From cd09b54ac4dd2d2ed86769011ebbbd0224d78d73 Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Mon, 8 May 2023 14:16:08 +0530 Subject: [PATCH] merges with latest --- .gitignore | 3 +- CHANGELOG.md | 346 + coreDriverInterfaceSupported.json | 2 +- docs/.nojekyll | 1 - docs/assets/highlight.css | 113 - docs/assets/icons.css | 1043 - docs/assets/icons.png | Bin 9615 -> 0 bytes docs/assets/icons@2x.png | Bin 28144 -> 0 bytes docs/assets/main.js | 52 - docs/assets/search.js | 1 - docs/assets/style.css | 1413 -- docs/assets/widgets.png | Bin 480 -> 0 bytes docs/assets/widgets@2x.png | Bin 855 -> 0 bytes docs/classes/framework.BaseRequest.html | 5 - docs/classes/framework.BaseResponse.html | 5 - docs/classes/index.default.html | 5 - .../ingredients_emaildelivery.default.html | 5 - .../ingredients_smsdelivery.default.html | 5 - docs/classes/recipe_dashboard.default.html | 5 - .../classes/recipe_emailpassword.default.html | 5 - .../recipe_emailverification.default.html | 5 - docs/classes/recipe_jwt.default.html | 5 - docs/classes/recipe_openid.default.html | 5 - docs/classes/recipe_passwordless.default.html | 5 - docs/classes/recipe_session.default.html | 5 - docs/classes/recipe_thirdparty.default.html | 5 - ...ecipe_thirdpartyemailpassword.default.html | 5 - ...recipe_thirdpartypasswordless.default.html | 5 - docs/classes/recipe_usermetadata.default.html | 5 - docs/classes/recipe_userroles.default.html | 5 - docs/index.html | 38 - .../framework_awsLambda.SessionEvent.html | 5 - .../framework_awsLambda.SessionEventV2.html | 5 - .../framework_express.SessionRequest.html | 487 - .../framework_fastify.SessionRequest.html | 8 - .../framework_hapi.SessionRequest.html | 245 - .../framework_koa.SessionContext.html | 250 - .../framework_loopback.SessionContext.html | 431 - .../recipe_session.SessionContainer.html | 7 - .../recipe_session.VerifySessionOptions.html | 5 - .../recipe_usermetadata.JSONObject.html | 1 - docs/modules.html | 1 - docs/modules/framework.html | 5 - docs/modules/framework_awsLambda.html | 5 - docs/modules/framework_express.html | 5 - docs/modules/framework_fastify.html | 5 - docs/modules/framework_hapi.html | 5 - docs/modules/framework_koa.html | 5 - docs/modules/framework_loopback.html | 5 - docs/modules/index.html | 5 - docs/modules/ingredients_emaildelivery.html | 1 - docs/modules/ingredients_smsdelivery.html | 1 - docs/modules/recipe_dashboard.html | 5 - docs/modules/recipe_emailpassword.html | 5 - docs/modules/recipe_emailverification.html | 5 - docs/modules/recipe_jwt.html | 5 - docs/modules/recipe_openid.html | 5 - docs/modules/recipe_passwordless.html | 5 - docs/modules/recipe_session.html | 30 - docs/modules/recipe_thirdparty.html | 5 - .../recipe_thirdpartyemailpassword.html | 5 - .../recipe_thirdpartypasswordless.html | 5 - docs/modules/recipe_usermetadata.html | 18 - docs/modules/recipe_userroles.html | 5 - .../with-thirdpartyemailpassword/index.js | 2 + lib/build/framework/awsLambda/framework.js | 10 +- lib/build/framework/fastify/framework.js | 2 +- lib/build/framework/utils.js | 57 +- lib/build/index.d.ts | 2 + lib/build/processState.d.ts | 6 +- lib/build/processState.js | 7 +- lib/build/querier.d.ts | 5 +- lib/build/querier.js | 17 +- lib/build/recipe/dashboard/api/analytics.d.ts | 6 + lib/build/recipe/dashboard/api/analytics.js | 124 + .../recipe/dashboard/api/implementation.js | 13 + .../recipe/dashboard/api/search/tagsGet.d.ts | 8 + .../recipe/dashboard/api/search/tagsGet.js | 62 + lib/build/recipe/dashboard/api/signIn.d.ts | 3 + lib/build/recipe/dashboard/api/signIn.js | 84 + lib/build/recipe/dashboard/api/signOut.d.ts | 3 + lib/build/recipe/dashboard/api/signOut.js | 77 + .../api/userdetails/userPasswordPut.js | 26 +- .../dashboard/api/userdetails/userPut.d.ts | 4 + .../dashboard/api/userdetails/userPut.js | 15 +- .../api/userdetails/userSessionsGet.js | 4 +- lib/build/recipe/dashboard/api/usersGet.d.ts | 5 + lib/build/recipe/dashboard/api/usersGet.js | 16 + lib/build/recipe/dashboard/api/validateKey.js | 10 +- lib/build/recipe/dashboard/constants.d.ts | 4 + lib/build/recipe/dashboard/constants.js | 6 +- lib/build/recipe/dashboard/recipe.d.ts | 4 +- lib/build/recipe/dashboard/recipe.js | 179 +- .../recipe/dashboard/recipeImplementation.js | 34 +- lib/build/recipe/dashboard/types.d.ts | 6 +- lib/build/recipe/dashboard/utils.d.ts | 10 +- lib/build/recipe/dashboard/utils.js | 38 +- .../emailpassword/api/implementation.js | 8 +- .../recipe/emailpassword/api/passwordReset.js | 14 + .../services/smtp/passwordReset.js | 1 - lib/build/recipe/emailpassword/index.d.ts | 5 + lib/build/recipe/emailpassword/recipe.js | 6 +- .../emailpassword/recipeImplementation.d.ts | 7 +- .../emailpassword/recipeImplementation.js | 19 +- lib/build/recipe/emailpassword/types.d.ts | 9 + .../services/smtp/emailVerify.js | 3 +- lib/build/recipe/jwt/api/getJWKS.js | 6 +- lib/build/recipe/jwt/index.d.ts | 2 +- lib/build/recipe/jwt/index.js | 3 +- lib/build/recipe/jwt/recipeImplementation.js | 5 +- lib/build/recipe/jwt/types.d.ts | 3 +- lib/build/recipe/openid/index.d.ts | 2 +- lib/build/recipe/openid/index.js | 3 +- .../recipe/openid/recipeImplementation.js | 3 +- lib/build/recipe/openid/types.d.ts | 2 +- .../services/smtp/passwordlessLogin.js | 3 - lib/build/recipe/session/accessToken.d.ts | 5 +- lib/build/recipe/session/accessToken.js | 158 +- .../recipe/session/api/implementation.js | 25 +- lib/build/recipe/session/api/signout.js | 5 +- lib/build/recipe/session/constants.d.ts | 1 + lib/build/recipe/session/constants.js | 3 +- .../recipe/session/cookieAndHeaders.d.ts | 8 +- lib/build/recipe/session/cookieAndHeaders.js | 15 +- lib/build/recipe/session/index.d.ts | 105 +- lib/build/recipe/session/index.js | 172 +- lib/build/recipe/session/jwt.d.ts | 3 +- lib/build/recipe/session/jwt.js | 74 +- lib/build/recipe/session/recipe.d.ts | 2 +- lib/build/recipe/session/recipe.js | 69 +- .../recipe/session/recipeImplementation.d.ts | 25 +- .../recipe/session/recipeImplementation.js | 506 +- lib/build/recipe/session/sessionClass.d.ts | 35 +- lib/build/recipe/session/sessionClass.js | 179 +- .../recipe/session/sessionFunctions.d.ts | 14 +- lib/build/recipe/session/sessionFunctions.js | 231 +- .../session/sessionRequestFunctions.d.ts | 55 + .../recipe/session/sessionRequestFunctions.js | 395 + lib/build/recipe/session/types.d.ts | 107 +- lib/build/recipe/session/utils.d.ts | 8 +- lib/build/recipe/session/utils.js | 77 +- .../recipe/session/with-jwt/constants.d.ts | 3 - .../recipe/session/with-jwt/constants.js | 41 - lib/build/recipe/session/with-jwt/index.d.ts | 3 - lib/build/recipe/session/with-jwt/index.js | 23 - .../with-jwt/recipeImplementation.d.ts | 10 - .../session/with-jwt/recipeImplementation.js | 243 - .../recipe/session/with-jwt/sessionClass.d.ts | 36 - .../recipe/session/with-jwt/sessionClass.js | 237 - lib/build/recipe/session/with-jwt/utils.d.ts | 17 - lib/build/recipe/session/with-jwt/utils.js | 109 - lib/build/recipe/thirdparty/index.d.ts | 4 + lib/build/recipe/thirdparty/index.js | 6 +- .../thirdparty/providers/bitbucket.d.ts | 15 + .../recipe/thirdparty/providers/bitbucket.js | 147 + .../recipe/thirdparty/providers/gitlab.d.ts | 16 + .../recipe/thirdparty/providers/gitlab.js | 138 + .../recipe/thirdparty/providers/index.d.ts | 4 + .../recipe/thirdparty/providers/index.js | 6 +- .../recipe/thirdpartyemailpassword/index.d.ts | 11 +- .../recipe/thirdpartyemailpassword/index.js | 6 +- .../recipe/thirdpartyemailpassword/recipe.js | 2 + .../recipeImplementation/index.d.ts | 7 +- .../recipeImplementation/index.js | 7 +- .../recipe/thirdpartyemailpassword/types.d.ts | 9 + .../recipe/thirdpartypasswordless/index.d.ts | 4 + .../recipe/thirdpartypasswordless/index.js | 6 +- lib/build/supertokens.d.ts | 2 +- lib/build/supertokens.js | 41 +- lib/build/utils.d.ts | 2 + lib/build/utils.js | 29 +- lib/build/version.d.ts | 4 +- lib/build/version.js | 6 +- lib/ts/framework/awsLambda/framework.ts | 12 +- lib/ts/framework/fastify/framework.ts | 4 +- lib/ts/framework/utils.ts | 57 +- lib/ts/index.ts | 2 + lib/ts/processState.ts | 2 +- lib/ts/querier.ts | 23 +- lib/ts/recipe/dashboard/api/analytics.ts | 98 + lib/ts/recipe/dashboard/api/implementation.ts | 15 +- .../api/search/tagsGet.ts} | 15 +- lib/ts/recipe/dashboard/api/signIn.ts | 56 + lib/ts/recipe/dashboard/api/signOut.ts | 35 + .../api/userdetails/userPasswordPut.ts | 24 +- .../dashboard/api/userdetails/userPut.ts | 24 +- .../api/userdetails/userSessionsGet.ts | 6 +- lib/ts/recipe/dashboard/api/usersGet.ts | 15 + lib/ts/recipe/dashboard/api/validateKey.ts | 16 +- lib/ts/recipe/dashboard/constants.ts | 4 + lib/ts/recipe/dashboard/recipe.ts | 152 +- .../recipe/dashboard/recipeImplementation.ts | 25 +- lib/ts/recipe/dashboard/types.ts | 7 +- lib/ts/recipe/dashboard/utils.ts | 48 +- .../emailpassword/api/implementation.ts | 10 +- .../recipe/emailpassword/api/passwordReset.ts | 15 + .../services/smtp/passwordReset.ts | 1 - lib/ts/recipe/emailpassword/index.ts | 8 +- lib/ts/recipe/emailpassword/recipe.ts | 5 +- .../emailpassword/recipeImplementation.ts | 24 +- lib/ts/recipe/emailpassword/types.ts | 3 + .../services/smtp/emailVerify.ts | 3 +- lib/ts/recipe/jwt/api/getJWKS.ts | 6 +- lib/ts/recipe/jwt/api/implementation.ts | 2 +- lib/ts/recipe/jwt/index.ts | 3 +- lib/ts/recipe/jwt/recipeImplementation.ts | 7 +- lib/ts/recipe/jwt/types.ts | 4 +- lib/ts/recipe/openid/index.ts | 3 +- lib/ts/recipe/openid/recipeImplementation.ts | 5 +- lib/ts/recipe/openid/types.ts | 2 +- .../services/smtp/passwordlessLogin.ts | 3 - lib/ts/recipe/session/accessToken.ts | 65 +- lib/ts/recipe/session/api/implementation.ts | 25 +- lib/ts/recipe/session/api/signout.ts | 5 +- lib/ts/recipe/session/constants.ts | 2 + lib/ts/recipe/session/cookieAndHeaders.ts | 13 +- lib/ts/recipe/session/index.ts | 233 +- lib/ts/recipe/session/jwt.ts | 40 +- lib/ts/recipe/session/recipe.ts | 72 +- lib/ts/recipe/session/recipeImplementation.ts | 534 +- lib/ts/recipe/session/sessionClass.ts | 161 +- lib/ts/recipe/session/sessionFunctions.ts | 245 +- .../recipe/session/sessionRequestFunctions.ts | 420 + lib/ts/recipe/session/types.ts | 115 +- lib/ts/recipe/session/utils.ts | 73 +- lib/ts/recipe/session/with-jwt/constants.ts | 38 - .../session/with-jwt/recipeImplementation.ts | 259 - .../recipe/session/with-jwt/sessionClass.ts | 175 - lib/ts/recipe/session/with-jwt/utils.ts | 85 - lib/ts/recipe/thirdparty/index.ts | 8 + .../recipe/thirdparty/providers/bitbucket.ts | 133 + lib/ts/recipe/thirdparty/providers/gitlab.ts | 122 + lib/ts/recipe/thirdparty/providers/index.ts | 4 + .../recipe/thirdpartyemailpassword/index.ts | 20 +- .../recipe/thirdpartyemailpassword/recipe.ts | 2 + .../emailPasswordRecipeImplementation.ts | 2 + .../recipeImplementation/index.ts | 6 +- .../recipe/thirdpartyemailpassword/types.ts | 3 + lib/ts/recipe/thirdpartypasswordless/index.ts | 8 + lib/ts/supertokens.ts | 45 +- lib/ts/utils.ts | 32 +- lib/ts/version.ts | 6 +- package-lock.json | 17489 ---------------- package.json | 5 +- test/auth-react-server/index.js | 6 +- test/config.test.js | 203 +- test/emailpassword/signoutFeature.test.js | 4 +- test/emailpassword/updateEmailPass.test.js | 157 + test/emailpassword/users.test.js | 79 + test/framework/awsLambda.test.js | 609 + test/framework/fastify.test.js | 583 +- test/framework/hapi.test.js | 652 +- test/framework/koa.test.js | 669 +- test/framework/loopback.test.js | 575 + test/frontendIntegration/index.js | 136 +- test/handshake.test.js | 151 - test/import.test.js | 43 + test/jwt/override.test.js | 4 +- test/middleware.test.js | 20 +- test/nextjs.test.js | 773 +- test/session.test.js | 165 +- test/session/accessTokenVersions.test.js | 876 + test/session/claims/assertClaims.test.js | 20 +- test/session/claims/createNewSession.test.js | 45 +- test/session/claims/fetchAndSetClaim.test.js | 4 +- test/session/claims/removeClaim.test.js | 11 +- test/session/claims/setClaimValue.test.js | 11 +- test/session/claims/verifySession.test.js | 4 +- test/session/claims/withJWT.test.js | 145 - ...ssTokenToFrontendInCookieBasedAuth.test.js | 328 + .../sessionHandlingFuncsWithoutReq.test.js | 381 + test/session/with-jwt/jwt.override.test.js | 214 - test/session/with-jwt/jwtFunctions.test.js | 169 - .../session/with-jwt/session.override.test.js | 689 - test/session/with-jwt/sessionClass.test.js | 558 - test/session/with-jwt/withjwt.test.js | 2334 --- ...sessionAccessTokenSigningKeyUpdate.test.js | 179 +- test/sessionExpress.test.js | 148 +- .../signupFeature.test.js | 23 + test/userContext.test.js | 7 +- test/userroles/claims.test.js | 13 +- test/users.json | 147 + test/utils.js | 54 + test/utils.test.js | 20 + test/with-typescript/index.ts | 238 +- 285 files changed, 11253 insertions(+), 30489 deletions(-) delete mode 100644 docs/.nojekyll delete mode 100644 docs/assets/highlight.css delete mode 100644 docs/assets/icons.css delete mode 100644 docs/assets/icons.png delete mode 100644 docs/assets/icons@2x.png delete mode 100644 docs/assets/main.js delete mode 100644 docs/assets/search.js delete mode 100644 docs/assets/style.css delete mode 100644 docs/assets/widgets.png delete mode 100644 docs/assets/widgets@2x.png delete mode 100644 docs/classes/framework.BaseRequest.html delete mode 100644 docs/classes/framework.BaseResponse.html delete mode 100644 docs/classes/index.default.html delete mode 100644 docs/classes/ingredients_emaildelivery.default.html delete mode 100644 docs/classes/ingredients_smsdelivery.default.html delete mode 100644 docs/classes/recipe_dashboard.default.html delete mode 100644 docs/classes/recipe_emailpassword.default.html delete mode 100644 docs/classes/recipe_emailverification.default.html delete mode 100644 docs/classes/recipe_jwt.default.html delete mode 100644 docs/classes/recipe_openid.default.html delete mode 100644 docs/classes/recipe_passwordless.default.html delete mode 100644 docs/classes/recipe_session.default.html delete mode 100644 docs/classes/recipe_thirdparty.default.html delete mode 100644 docs/classes/recipe_thirdpartyemailpassword.default.html delete mode 100644 docs/classes/recipe_thirdpartypasswordless.default.html delete mode 100644 docs/classes/recipe_usermetadata.default.html delete mode 100644 docs/classes/recipe_userroles.default.html delete mode 100644 docs/index.html delete mode 100644 docs/interfaces/framework_awsLambda.SessionEvent.html delete mode 100644 docs/interfaces/framework_awsLambda.SessionEventV2.html delete mode 100644 docs/interfaces/framework_express.SessionRequest.html delete mode 100644 docs/interfaces/framework_fastify.SessionRequest.html delete mode 100644 docs/interfaces/framework_hapi.SessionRequest.html delete mode 100644 docs/interfaces/framework_koa.SessionContext.html delete mode 100644 docs/interfaces/framework_loopback.SessionContext.html delete mode 100644 docs/interfaces/recipe_session.SessionContainer.html delete mode 100644 docs/interfaces/recipe_session.VerifySessionOptions.html delete mode 100644 docs/interfaces/recipe_usermetadata.JSONObject.html delete mode 100644 docs/modules.html delete mode 100644 docs/modules/framework.html delete mode 100644 docs/modules/framework_awsLambda.html delete mode 100644 docs/modules/framework_express.html delete mode 100644 docs/modules/framework_fastify.html delete mode 100644 docs/modules/framework_hapi.html delete mode 100644 docs/modules/framework_koa.html delete mode 100644 docs/modules/framework_loopback.html delete mode 100644 docs/modules/index.html delete mode 100644 docs/modules/ingredients_emaildelivery.html delete mode 100644 docs/modules/ingredients_smsdelivery.html delete mode 100644 docs/modules/recipe_dashboard.html delete mode 100644 docs/modules/recipe_emailpassword.html delete mode 100644 docs/modules/recipe_emailverification.html delete mode 100644 docs/modules/recipe_jwt.html delete mode 100644 docs/modules/recipe_openid.html delete mode 100644 docs/modules/recipe_passwordless.html delete mode 100644 docs/modules/recipe_session.html delete mode 100644 docs/modules/recipe_thirdparty.html delete mode 100644 docs/modules/recipe_thirdpartyemailpassword.html delete mode 100644 docs/modules/recipe_thirdpartypasswordless.html delete mode 100644 docs/modules/recipe_usermetadata.html delete mode 100644 docs/modules/recipe_userroles.html create mode 100644 lib/build/recipe/dashboard/api/analytics.d.ts create mode 100644 lib/build/recipe/dashboard/api/analytics.js create mode 100644 lib/build/recipe/dashboard/api/search/tagsGet.d.ts create mode 100644 lib/build/recipe/dashboard/api/search/tagsGet.js create mode 100644 lib/build/recipe/dashboard/api/signIn.d.ts create mode 100644 lib/build/recipe/dashboard/api/signIn.js create mode 100644 lib/build/recipe/dashboard/api/signOut.d.ts create mode 100644 lib/build/recipe/dashboard/api/signOut.js create mode 100644 lib/build/recipe/session/sessionRequestFunctions.d.ts create mode 100644 lib/build/recipe/session/sessionRequestFunctions.js delete mode 100644 lib/build/recipe/session/with-jwt/constants.d.ts delete mode 100644 lib/build/recipe/session/with-jwt/constants.js delete mode 100644 lib/build/recipe/session/with-jwt/index.d.ts delete mode 100644 lib/build/recipe/session/with-jwt/index.js delete mode 100644 lib/build/recipe/session/with-jwt/recipeImplementation.d.ts delete mode 100644 lib/build/recipe/session/with-jwt/recipeImplementation.js delete mode 100644 lib/build/recipe/session/with-jwt/sessionClass.d.ts delete mode 100644 lib/build/recipe/session/with-jwt/sessionClass.js delete mode 100644 lib/build/recipe/session/with-jwt/utils.d.ts delete mode 100644 lib/build/recipe/session/with-jwt/utils.js create mode 100644 lib/build/recipe/thirdparty/providers/bitbucket.d.ts create mode 100644 lib/build/recipe/thirdparty/providers/bitbucket.js create mode 100644 lib/build/recipe/thirdparty/providers/gitlab.d.ts create mode 100644 lib/build/recipe/thirdparty/providers/gitlab.js create mode 100644 lib/ts/recipe/dashboard/api/analytics.ts rename lib/ts/recipe/{session/with-jwt/index.ts => dashboard/api/search/tagsGet.ts} (51%) create mode 100644 lib/ts/recipe/dashboard/api/signIn.ts create mode 100644 lib/ts/recipe/dashboard/api/signOut.ts create mode 100644 lib/ts/recipe/session/sessionRequestFunctions.ts delete mode 100644 lib/ts/recipe/session/with-jwt/constants.ts delete mode 100644 lib/ts/recipe/session/with-jwt/recipeImplementation.ts delete mode 100644 lib/ts/recipe/session/with-jwt/sessionClass.ts delete mode 100644 lib/ts/recipe/session/with-jwt/utils.ts create mode 100644 lib/ts/recipe/thirdparty/providers/bitbucket.ts create mode 100644 lib/ts/recipe/thirdparty/providers/gitlab.ts delete mode 100644 package-lock.json delete mode 100644 test/handshake.test.js create mode 100644 test/import.test.js create mode 100644 test/session/accessTokenVersions.test.js delete mode 100644 test/session/claims/withJWT.test.js create mode 100644 test/session/exposeAccessTokenToFrontendInCookieBasedAuth.test.js create mode 100644 test/session/sessionHandlingFuncsWithoutReq.test.js delete mode 100644 test/session/with-jwt/jwt.override.test.js delete mode 100644 test/session/with-jwt/jwtFunctions.test.js delete mode 100644 test/session/with-jwt/session.override.test.js delete mode 100644 test/session/with-jwt/sessionClass.test.js delete mode 100644 test/session/with-jwt/withjwt.test.js create mode 100644 test/users.json create mode 100644 test/utils.test.js diff --git a/.gitignore b/.gitignore index eec512c0e..4b6f0072c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ coverage .vscode apiPassword releasePassword -.tmp \ No newline at end of file +.tmp +.idea diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cc984909..d44ea549d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,352 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - For EmailPassword recipe input, resetPasswordUsingTokenFeature user input removed +## [14.0.0] - 2023-05-04 + +### Breaking Changes + +- Added support for CDI version `2.21` +- Dropped support for CDI version `2.8`-`2.20` +- Changed the interface and configuration of the Session recipe, see below for details. If you do not use the Session recipe directly and do not provide custom configuration, then no migration is necessary. +- `getAccessTokenPayload` will now return standard (`sub`, `iat`, `exp`) claims and some SuperTokens specific claims along the user defined ones in `getAccessTokenPayload`. +- Some claim names are now prohibited in the root level of the access token payload + - They are: `sub`, `iat`, `exp`, `sessionHandle`, `parentRefreshTokenHash1`, `refreshTokenHash1`, `antiCsrfToken` + - If you used these in the root level of the access token payload, then you'll need to migrate your sessions or they will be logged out during the next refresh + - These props should be renamed (e.g., by adding a prefix) or moved inside an object in the access token payload + - You can migrate these sessions by updating their payload to match your new structure, by calling `mergeIntoAccessTokenPayload` +- New access tokens are valid JWTs now + - They can be used directly (i.e.: by calling `getAccessToken` on the session) if you need a JWT + - The `jwt` prop in the access token payload is removed +- Changed the Session recipe interface - createNewSession, getSession and refreshSession overrides now do not take response and request and return status instead of throwing +- Renamed `accessTokenPayload` to `customClaimsInAccessTokenPayload` in `SessionInformation` (the return value of `getSessionInformation`). This reflects the fact that it doesn't contain some default claims (`sub`, `iat`, etc.) + +### Configuration changes + +- Added `useDynamicAccessTokenSigningKey` (defaults to `true`) option to the Session recipe config +- Added `exposeAccessTokenToFrontendInCookieBasedAuth` (defaults to `false`) option to the Session recipe config +- JWT and OpenId related configuration has been removed from the Session recipe config. If necessary, they can be added by initializing the OpenId recipe before the Session recipe. + +### Interface changes + +- Renamed `getSessionData` to `getSessionDataFromDatabase` to clarify that it always hits the DB +- Renamed `updateSessionData` to `updateSessionDataInDatabase` +- Renamed `sessionData` to `sessionDataInDatabase` in `SessionInformation` and the input to `createNewSession` +- Added new `checkDatabase` param to `verifySession` and `getSession` +- Removed `status` from `getJWKS` output (function & API) +- Added new optional `useStaticSigningKey` param to `createJWT` +- Removed deprecated `updateAccessTokenPayload` and `regenerateAccessToken` from the Session recipe interface +- Removed `getAccessTokenLifeTimeMS` and `getRefreshTokenLifeTimeMS` functions + +## Changes + +- The Session recipe now always initializes the OpenID recipe if it hasn't been initialized. +- Refactored how access token validation is done +- Removed the handshake call to improve start-up times +- Added support for new access token version +- Added optional password policy check in `updateEmailOrPassword` + +### Added + +- Added `createNewSessionWithoutRequestResponse`, `getSessionWithoutRequestResponse`, `refreshSessionWithoutRequestResponse` to the Session recipe. +- Added `getAllSessionTokensDangerously` to session objects (`SessionContainerInterface`) +- Added `attachToRequestResponse` to session objects (`SessionContainerInterface`) + +### Migration + +#### If self-hosting core + +1. You need to update the core version +2. There are manual migration steps needed. Check out the core changelogs for more details. + +#### If you used the jwt feature of the session recipe + +1. Add `exposeAccessTokenToFrontendInCookieBasedAuth: true` to the Session recipe config on the backend if you need to access the JWT on the frontend. +2. On the frontend where you accessed the JWT before by: `(await Session.getAccessTokenPayloadSecurely()).jwt` update to: + +```tsx +let jwt = null; +const accessTokenPayload = await Session.getAccessTokenPayloadSecurely(); +if (accessTokenPayload.jwt === undefined) { + jwt = await Session.getAccessToken(); +} else { + // This branch is only required if there are valid access tokens created before the update + // It can be removed after the validity period ends + jwt = accessTokenPayload.jwt; +} +``` + +3. On the backend if you accessed the JWT before by `session.getAccessTokenPayload().jwt` please update to: + +```tsx +let jwt = null; +const accessTokenPayload = await session.getAccessTokenPayload(); +if (accessTokenPayload.jwt === undefined) { + jwt = await session.getAccessToken(); +} else { + // This branch is only required if there are valid access tokens created before the update + // It can be removed after the validity period ends + jwt = accessTokenPayload.jwt; +} +``` + +#### If you used to set an issuer in the session recipe `jwt` configuration + +- You can add an issuer claim to access tokens by overriding the `createNewSession` function in the session recipe init. + - Check out https://supertokens.com/docs/passwordless/common-customizations/sessions/claims/access-token-payload#during-session-creation for more information +- You can add an issuer claim to JWTs created by the JWT recipe by passing the `iss` claim as part of the payload. +- You can set the OpenId discovery configuration as follows: + +Before: + +```tsx +import SuperTokens from "supertokens-node"; +import Session from "supertokens-node/recipe/session"; + +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "...", + }, + recipeList: [ + Session.init({ + jwt: { + enable: true, + issuer: "...", + }, + }), + ], +}); +``` + +After: + +```tsx +import SuperTokens from "supertokens-node"; +import Session from "supertokens-node/recipe/session"; + +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "...", + }, + recipeList: [ + Session.init({ + getTokenTransferMethod: () => "header", + override: { + openIdFeature: { + functions: originalImplementation => ({ + ...originalImplementation, + getOpenIdDiscoveryConfiguration: async (input) => ({ + issuer: "your issuer", + jwks_uri: "https://your.api.domain/auth/jwt/jwks.json", + status: "OK" + }), + }) + } + } + }); + ], +}); +``` + +#### If you used `sessionData` (not `accessTokenPayload`) + +Related functions/prop names have changes (`sessionData` became `sessionDataFromDatabase`): + +- Renamed `getSessionData` to `getSessionDataFromDatabase` to clarify that it always hits the DB +- Renamed `updateSessionData` to `updateSessionDataInDatabase` +- Renamed `sessionData` to `sessionDataInDatabase` in `SessionInformation` and the input to `createNewSession` + +#### If you used to set `access_token_blacklisting` in the core config + +- You should now set `checkDatabase` to true in the verifySession params. + +#### If you used to set `access_token_signing_key_dynamic` in the core config + +- You should now set `useDynamicAccessTokenSigningKey` in the Session recipe config. + +#### If you used to use standard/protected props in the access token payload root: + +1. Update you application logic to rename those props (e.g., by adding a prefix) +2. Update the session recipe config (in this example `sub` is the protected property we are updating by adding the `app` prefix): + +Before: + +```tsx +Session.init({ + override: { + functions: (oI) => ({ + ...oI, + createNewSession: async (input) => { + return oI.createNewSession({ + ...input, + accessTokenPayload: { + ...input.accessTokenPayload, + sub: input.userId + "!!!", + }, + }); + }, + }), + }, +}); +``` + +After: + +```tsx +Session.init({ + override: { + functions: (oI) => ({ + ...oI, + getSession: async (input) => { + const result = await oI.getSession(input); + if (result) { + const origPayload = result.getAccessTokenPayload(); + if (origPayload.appSub === undefined) { + await result.mergeIntoAccessTokenPayload({ appSub: origPayload.sub, sub: null }); + } + } + return result; + }, + createNewSession: async (input) => { + return oI.createNewSession({ + ...input, + accessTokenPayload: { + ...input.accessTokenPayload, + appSub: input.userId + "!!!", + }, + }); + }, + }), + }, +}); +``` + +#### If you added an override for `createNewSession`/`refreshSession`/`getSession`: + +This example uses `getSession`, but the changes required for the other ones are very similar. Before: + +```tsx +Session.init({ + override: { + functions: (oI) => ({ + ...oI, + getSession: async (input) => { + const req = input.req; + console.log(req); + + try { + const session = await oI.getSession(input); + console.log(session); + return session; + } catch (error) { + console.log(error); + throw error; + } + }, + }), + }, +}); +``` + +After: + +```tsx +Session.init({ + override: { + functions: (oI) => ({ + ...oI, + getSession: async (input) => { + const req = input.userContext._default.request; + console.log(req); + + const resp = await oI.getSession(input); + + if (resp.status === "OK") { + console.log(resp.session); + } else { + console.log(resp.status); + console.log(resp.error); + } + + return resp; + }, + }), + }, +}); +``` + +## [13.6.0] - 2023-04-26 + +- Added missing arguments from `getUsersNewestFirst` and `getUsersOldestFirst` + +## [13.5.0] - 2023-04-22 + +- Adds new config to change the access token's path + +## [13.4.2] - 2023-04-11 + +- Modified email templates to make them render fine in gmail. + +## [13.4.1] - 2023-04-11 + +- Modified email templates to make them render fine in outlook. + +## [13.4.0] - 2023-03-31 + +- Adds APIs to enable search functionality to the dashboard recipe + +## [13.3.0] - 2023-03-30 + +### Added + +- Adds a telemetry API to the dashboard recipe + +## [13.2.0] - 2023-03-29 + +### Changed + +- Updates the example app to also initialise the dashboard + +### Added + +- Login with bitbucket and gitlab (single tenant only) + +## [13.1.5] - 2023-03-17 + +### Fixes + +- Fixed an issue where BaseRequest implmentations for frameworks such as AWS Lambda would not consider case sensitivity when fetching request headers +- Fixes an issue where dashboard recipe APIs would return 404 for Hapi + +## [13.1.4] - 2023-03-16 + +### Fixes + +- Fixes an issue where importing recipes without importing the package index file would cause crashes + +## [13.1.3] - 2023-03-08 + +### Changed + +- The dashboard recipe is no longer intialised automatically + +## [13.1.2] - 2023-02-27 + +### Fixes + +- Fixed request parsing issue during third-party (Apple) sign in in NextJS + +## [13.1.1] - 2023-02-24 + +- Refactor dashboard recipe to use auth mode instead of manually checking for api key + +## [13.1.0] - 2023-02-22 + +- Adds APIs and logic to the dashboard recipe to enable email password based login + ## [13.0.2] - 2023-02-10 - Package version update for twilio to ^4.7.2 and verify-apple-id-token to ^3.0.1 diff --git a/coreDriverInterfaceSupported.json b/coreDriverInterfaceSupported.json index 61938b1bb..f5d376bc6 100644 --- a/coreDriverInterfaceSupported.json +++ b/coreDriverInterfaceSupported.json @@ -1,4 +1,4 @@ { "_comment": "contains a list of core-driver interfaces branch names that this core supports", - "versions": ["2.8", "2.9", "2.10", "2.11", "2.12", "2.13", "2.14", "2.15"] + "versions": ["2.21"] } diff --git a/docs/.nojekyll b/docs/.nojekyll deleted file mode 100644 index e2ac6616a..000000000 --- a/docs/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/assets/highlight.css b/docs/assets/highlight.css deleted file mode 100644 index dd760c444..000000000 --- a/docs/assets/highlight.css +++ /dev/null @@ -1,113 +0,0 @@ -:root { - --light-hl-0: #0000FF; - --dark-hl-0: #569CD6; - --light-hl-1: #000000; - --dark-hl-1: #D4D4D4; - --light-hl-2: #0070C1; - --dark-hl-2: #4FC1FF; - --light-hl-3: #001080; - --dark-hl-3: #9CDCFE; - --light-hl-4: #795E26; - --dark-hl-4: #DCDCAA; - --light-hl-5: #A31515; - --dark-hl-5: #CE9178; - --light-hl-6: #098658; - --dark-hl-6: #B5CEA8; - --light-hl-7: #AF00DB; - --dark-hl-7: #C586C0; - --light-hl-8: #008000; - --dark-hl-8: #6A9955; - --light-hl-9: #267F99; - --dark-hl-9: #4EC9B0; - --light-hl-10: #000000FF; - --dark-hl-10: #D4D4D4; - --light-hl-11: #811F3F; - --dark-hl-11: #D16969; - --light-hl-12: #EE0000; - --dark-hl-12: #D7BA7D; - --light-code-background: #F5F5F5; - --dark-code-background: #1E1E1E; -} - -@media (prefers-color-scheme: light) { :root { - --hl-0: var(--light-hl-0); - --hl-1: var(--light-hl-1); - --hl-2: var(--light-hl-2); - --hl-3: var(--light-hl-3); - --hl-4: var(--light-hl-4); - --hl-5: var(--light-hl-5); - --hl-6: var(--light-hl-6); - --hl-7: var(--light-hl-7); - --hl-8: var(--light-hl-8); - --hl-9: var(--light-hl-9); - --hl-10: var(--light-hl-10); - --hl-11: var(--light-hl-11); - --hl-12: var(--light-hl-12); - --code-background: var(--light-code-background); -} } - -@media (prefers-color-scheme: dark) { :root { - --hl-0: var(--dark-hl-0); - --hl-1: var(--dark-hl-1); - --hl-2: var(--dark-hl-2); - --hl-3: var(--dark-hl-3); - --hl-4: var(--dark-hl-4); - --hl-5: var(--dark-hl-5); - --hl-6: var(--dark-hl-6); - --hl-7: var(--dark-hl-7); - --hl-8: var(--dark-hl-8); - --hl-9: var(--dark-hl-9); - --hl-10: var(--dark-hl-10); - --hl-11: var(--dark-hl-11); - --hl-12: var(--dark-hl-12); - --code-background: var(--dark-code-background); -} } - -body.light { - --hl-0: var(--light-hl-0); - --hl-1: var(--light-hl-1); - --hl-2: var(--light-hl-2); - --hl-3: var(--light-hl-3); - --hl-4: var(--light-hl-4); - --hl-5: var(--light-hl-5); - --hl-6: var(--light-hl-6); - --hl-7: var(--light-hl-7); - --hl-8: var(--light-hl-8); - --hl-9: var(--light-hl-9); - --hl-10: var(--light-hl-10); - --hl-11: var(--light-hl-11); - --hl-12: var(--light-hl-12); - --code-background: var(--light-code-background); -} - -body.dark { - --hl-0: var(--dark-hl-0); - --hl-1: var(--dark-hl-1); - --hl-2: var(--dark-hl-2); - --hl-3: var(--dark-hl-3); - --hl-4: var(--dark-hl-4); - --hl-5: var(--dark-hl-5); - --hl-6: var(--dark-hl-6); - --hl-7: var(--dark-hl-7); - --hl-8: var(--dark-hl-8); - --hl-9: var(--dark-hl-9); - --hl-10: var(--dark-hl-10); - --hl-11: var(--dark-hl-11); - --hl-12: var(--dark-hl-12); - --code-background: var(--dark-code-background); -} - -.hl-0 { color: var(--hl-0); } -.hl-1 { color: var(--hl-1); } -.hl-2 { color: var(--hl-2); } -.hl-3 { color: var(--hl-3); } -.hl-4 { color: var(--hl-4); } -.hl-5 { color: var(--hl-5); } -.hl-6 { color: var(--hl-6); } -.hl-7 { color: var(--hl-7); } -.hl-8 { color: var(--hl-8); } -.hl-9 { color: var(--hl-9); } -.hl-10 { color: var(--hl-10); } -.hl-11 { color: var(--hl-11); } -.hl-12 { color: var(--hl-12); } -pre, code { background: var(--code-background); } diff --git a/docs/assets/icons.css b/docs/assets/icons.css deleted file mode 100644 index 776a3562d..000000000 --- a/docs/assets/icons.css +++ /dev/null @@ -1,1043 +0,0 @@ -.tsd-kind-icon { - display: block; - position: relative; - padding-left: 20px; - text-indent: -20px; -} -.tsd-kind-icon:before { - content: ""; - display: inline-block; - vertical-align: middle; - width: 17px; - height: 17px; - margin: 0 3px 2px 0; - background-image: url(./icons.png); -} -@media (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 144dpi) { - .tsd-kind-icon:before { - background-image: url(./icons@2x.png); - background-size: 238px 204px; - } -} - -.tsd-signature.tsd-kind-icon:before { - background-position: 0 -153px; -} - -.tsd-kind-object-literal > .tsd-kind-icon:before { - background-position: 0px -17px; -} -.tsd-kind-object-literal.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -17px; -} -.tsd-kind-object-literal.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -17px; -} - -.tsd-kind-class > .tsd-kind-icon:before { - background-position: 0px -34px; -} -.tsd-kind-class.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -34px; -} -.tsd-kind-class.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -34px; -} - -.tsd-kind-class.tsd-has-type-parameter > .tsd-kind-icon:before { - background-position: 0px -51px; -} -.tsd-kind-class.tsd-has-type-parameter.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -17px -51px; -} -.tsd-kind-class.tsd-has-type-parameter.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -51px; -} - -.tsd-kind-interface > .tsd-kind-icon:before { - background-position: 0px -68px; -} -.tsd-kind-interface.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -68px; -} -.tsd-kind-interface.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -68px; -} - -.tsd-kind-interface.tsd-has-type-parameter > .tsd-kind-icon:before { - background-position: 0px -85px; -} -.tsd-kind-interface.tsd-has-type-parameter.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -17px -85px; -} -.tsd-kind-interface.tsd-has-type-parameter.tsd-is-private - > .tsd-kind-icon:before { - background-position: -34px -85px; -} - -.tsd-kind-namespace > .tsd-kind-icon:before { - background-position: 0px -102px; -} -.tsd-kind-namespace.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -102px; -} -.tsd-kind-namespace.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -102px; -} - -.tsd-kind-module > .tsd-kind-icon:before { - background-position: 0px -102px; -} -.tsd-kind-module.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -102px; -} -.tsd-kind-module.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -102px; -} - -.tsd-kind-enum > .tsd-kind-icon:before { - background-position: 0px -119px; -} -.tsd-kind-enum.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -119px; -} -.tsd-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -119px; -} - -.tsd-kind-enum-member > .tsd-kind-icon:before { - background-position: 0px -136px; -} -.tsd-kind-enum-member.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -136px; -} -.tsd-kind-enum-member.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -136px; -} - -.tsd-kind-signature > .tsd-kind-icon:before { - background-position: 0px -153px; -} -.tsd-kind-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -153px; -} -.tsd-kind-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -153px; -} - -.tsd-kind-type-alias > .tsd-kind-icon:before { - background-position: 0px -170px; -} -.tsd-kind-type-alias.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -170px; -} -.tsd-kind-type-alias.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -170px; -} - -.tsd-kind-type-alias.tsd-has-type-parameter > .tsd-kind-icon:before { - background-position: 0px -187px; -} -.tsd-kind-type-alias.tsd-has-type-parameter.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -17px -187px; -} -.tsd-kind-type-alias.tsd-has-type-parameter.tsd-is-private - > .tsd-kind-icon:before { - background-position: -34px -187px; -} - -.tsd-kind-variable > .tsd-kind-icon:before { - background-position: -136px -0px; -} -.tsd-kind-variable.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -0px; -} -.tsd-kind-variable.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-variable.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -0px; -} -.tsd-kind-variable.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -0px; -} -.tsd-kind-variable.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -0px; -} -.tsd-kind-variable.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -0px; -} -.tsd-kind-variable.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-variable.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -0px; -} -.tsd-kind-variable.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -0px; -} -.tsd-kind-variable.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-variable.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -0px; -} -.tsd-kind-variable.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -0px; -} - -.tsd-kind-property > .tsd-kind-icon:before { - background-position: -136px -0px; -} -.tsd-kind-property.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -0px; -} -.tsd-kind-property.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-property.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -0px; -} -.tsd-kind-property.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -0px; -} -.tsd-kind-property.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -0px; -} -.tsd-kind-property.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -0px; -} -.tsd-kind-property.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-property.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -0px; -} -.tsd-kind-property.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -0px; -} -.tsd-kind-property.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-property.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -0px; -} -.tsd-kind-property.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -0px; -} - -.tsd-kind-get-signature > .tsd-kind-icon:before { - background-position: -136px -17px; -} -.tsd-kind-get-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -17px; -} -.tsd-kind-get-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -17px; -} - -.tsd-kind-set-signature > .tsd-kind-icon:before { - background-position: -136px -34px; -} -.tsd-kind-set-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -34px; -} -.tsd-kind-set-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -34px; -} - -.tsd-kind-accessor > .tsd-kind-icon:before { - background-position: -136px -51px; -} -.tsd-kind-accessor.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -51px; -} -.tsd-kind-accessor.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -51px; -} - -.tsd-kind-function > .tsd-kind-icon:before { - background-position: -136px -68px; -} -.tsd-kind-function.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -68px; -} -.tsd-kind-function.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-function.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -68px; -} -.tsd-kind-function.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -68px; -} -.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -68px; -} -.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -68px; -} -.tsd-kind-function.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-function.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -68px; -} -.tsd-kind-function.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -68px; -} -.tsd-kind-function.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-function.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -68px; -} -.tsd-kind-function.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -68px; -} - -.tsd-kind-method > .tsd-kind-icon:before { - background-position: -136px -68px; -} -.tsd-kind-method.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -68px; -} -.tsd-kind-method.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-method.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -68px; -} -.tsd-kind-method.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -68px; -} -.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -68px; -} -.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -68px; -} -.tsd-kind-method.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-method.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -68px; -} -.tsd-kind-method.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { - background-position: -187px -68px; -} -.tsd-kind-method.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-method.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -68px; -} -.tsd-kind-method.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -68px; -} - -.tsd-kind-call-signature > .tsd-kind-icon:before { - background-position: -136px -68px; -} -.tsd-kind-call-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -68px; -} -.tsd-kind-call-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -68px; -} - -.tsd-kind-function.tsd-has-type-parameter > .tsd-kind-icon:before { - background-position: -136px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -153px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class - > .tsd-kind-icon:before { - background-position: -51px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-enum - > .tsd-kind-icon:before { - background-position: -170px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -85px; -} - -.tsd-kind-method.tsd-has-type-parameter > .tsd-kind-icon:before { - background-position: -136px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -153px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class - > .tsd-kind-icon:before { - background-position: -51px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-enum - > .tsd-kind-icon:before { - background-position: -170px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -85px; -} - -.tsd-kind-constructor > .tsd-kind-icon:before { - background-position: -136px -102px; -} -.tsd-kind-constructor.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -102px; -} -.tsd-kind-constructor.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -102px; -} - -.tsd-kind-constructor-signature > .tsd-kind-icon:before { - background-position: -136px -102px; -} -.tsd-kind-constructor-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -102px; -} -.tsd-kind-constructor-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -102px; -} - -.tsd-kind-index-signature > .tsd-kind-icon:before { - background-position: -136px -119px; -} -.tsd-kind-index-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -119px; -} -.tsd-kind-index-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -119px; -} - -.tsd-kind-event > .tsd-kind-icon:before { - background-position: -136px -136px; -} -.tsd-kind-event.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -136px; -} -.tsd-kind-event.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -136px; -} -.tsd-kind-event.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -136px; -} -.tsd-kind-event.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { - background-position: -68px -136px; -} -.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { - background-position: -85px -136px; -} -.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -136px; -} -.tsd-kind-event.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -136px; -} -.tsd-kind-event.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -136px; -} -.tsd-kind-event.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { - background-position: -187px -136px; -} -.tsd-kind-event.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -136px; -} -.tsd-kind-event.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -136px; -} -.tsd-kind-event.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -136px; -} - -.tsd-is-static > .tsd-kind-icon:before { - background-position: -136px -153px; -} -.tsd-is-static.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -153px; -} -.tsd-is-static.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -153px; -} -.tsd-is-static.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -153px; -} -.tsd-is-static.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { - background-position: -68px -153px; -} -.tsd-is-static.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { - background-position: -85px -153px; -} -.tsd-is-static.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -153px; -} -.tsd-is-static.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -153px; -} -.tsd-is-static.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -153px; -} -.tsd-is-static.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { - background-position: -187px -153px; -} -.tsd-is-static.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -153px; -} -.tsd-is-static.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -153px; -} -.tsd-is-static.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -153px; -} - -.tsd-is-static.tsd-kind-function > .tsd-kind-icon:before { - background-position: -136px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -170px; -} - -.tsd-is-static.tsd-kind-method > .tsd-kind-icon:before { - background-position: -136px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -170px; -} - -.tsd-is-static.tsd-kind-call-signature > .tsd-kind-icon:before { - background-position: -136px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -153px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class - > .tsd-kind-icon:before { - background-position: -51px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-enum - > .tsd-kind-icon:before { - background-position: -170px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -170px; -} - -.tsd-is-static.tsd-kind-event > .tsd-kind-icon:before { - background-position: -136px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -187px; -} diff --git a/docs/assets/icons.png b/docs/assets/icons.png deleted file mode 100644 index 3836d5fe46e48bbe186116855aae879c23935327..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9615 zcmZ{Kc_36>+`rwViHMAd#!?~-${LfgP1$7)F~(N1WKRsT#$-?;yNq3ylq}iztr1xY z8DtsBI<`UHtDfii{r-60Kg@OSJ?GqW=bZ2NvwY{NzOLpergKbGR8*&KBGn9m;|lQC z2Vwv|y`nSufCHVQijE2uRauuTeKZL;=kiiF^SbTk;N^?*u%}Y7bF;O-aMK0lXm4nb zvU~Kf+x|Kgl@Ro%nu?L%x8-yetd((kCqY|t;-%}@Y3Ez_m(HTRt=ekeUQ2n4-aRvJ zrlKaWct8JSc8Kxl4KHu+3VW1L`9%n~_KC5}g6&tFXqyKT-}R0?EdkYqCmQot47^9Z z6;opqR@7Nq-s|6=e6*0^`}+X1kg>CpuGnbpL7{xFTa|8nymC0{xgx*tI7n4mTKZNA znsd@3eVsV>YhATuv~+5(^Vu4j?)Tn`{x@8ijIA;wdf`+0P3$vnSrcWFXXc{Lx`1Z7 z%-n(BM(owD$7LzqJx)(f^Cusecq>OW z=h6n4YzSVM-V!-DK(sLT`!W~}($=O$9|ie`>_fpH0=1G1tiIFw($?~{5T>`74|p0H z``5=UydE)!CiFvmECW|s^TzG9*7pN|KknkVm3C{fEu30gffX&8iCm? zTFPm6*k%Hog`Q6JGj@dg9Z5nlAc6ApUe>;6xauB0-u!?wMU92jVL|3EcP9gEu5^wH z%tXRy#>HCEs*?KgMf73UcJ!lJ?x<6+)eJ{mEIS|HMDP7(7!(< z@X;?ACT8mncW9*XIaiJPW}Mw@b0W||)!sYnLw)0j4&-rXQgJhnQ2?frg1Nfk&JpmV8F=dDZl)e%#Grs|&0th7_o) z?7hQn<1078qcq?#;)CH=2kBBiGt37EtcXfpTXtHB59dr9=B~jI`yPm-Q?(ys=ajAu zGY;eS^z&WFvztZI3I~}*l}_lI^}6D<&CZ94;|&G9_pMx!C~$~EL4^8`QjT#|tqxxk zhl4CdxppbDiOk!Ht#SVAK4gf6Cr#=U&1sVxZ`y-X zTSi#@wHf(?(Dd6ypNOyshRZ*tneVP^W?y?$ur_!9iD-vY{&Q5(ooX2;`SkUjwEYA~ zwGcylCT4_`MZobm(0v$U(IhfYXxyjNJ@ztpH0sDmfpn|LMp3eM(R4uqKi_q1=D1-d z%GdV<&2+_9k@sc44xhIjqktRA2!Su|vzM0R-@#MK&{RdLoU#$Hc?{{JItvX{hKCtc zQNqZpkfG^@LGJRZM4H_>`F=N;O*+_`>M_ko_XWCgu@}ntqLX8VSeZQ_25Z8|^!d?o z$~}~9|`ZW9d_o<=8&K^~;Cr08b;qgq{(*e*sNt00lO2lZ;m-b<`Rl}=Lr6iQ8+$&br z!RLn{5a}j1Dh^|_1)Q?<;iBSrS0V|c_D@3}mc2d!%tV1VN?BC@clkFdx?HB&9KOTF z)9eHpmUEYsCqx^%JHuNdwY zz9P3oPYuTAXZVY}LRp&2qNl$pbsXL1GJ@wx?@CTO!acs+OFfW_U6?&As-(GJED}RR zO}B+Kxph7aUUm>i3rbPZQGXN}oQq;u`yTnFDAJ*d$4gjEJH!JPyt6V{cOUp*Jbyol zE$8wh)T=vpJOWRbv}HvR(cUSlO}ePIPdJ`J@yp=IC&E6K%r?QfW7F&%p!H~@?%yj5 z&MpiV!hyfukD56A097f!0+ANt`JSB~oLak75oKQN7FH=rQbX#Eak37|4&mqp@S~TA zOo51)xQxX}5NQ(3I_UeR4B;P0Q#x$_lDce78ET`Blo;`Hj*R;b8slZS7Oak(LjDuE z3z?-~-U@vWe*cEOsf^9|duH9};Pe)!=Ky+QQ!jr2VV-jMUH-F>oB>Ds zDJw}jm%V?OT^fu1y`$`yRdaW03L?)6vmInxhAsGrPhWIP8?=speMFf9Inn4^t zs$!88*B~c1A2J6t0~hgK2BJ_Pl23l=oeQQqjI2(4Mcv6U_#9#$PEN|qz36rCZ5$@I zNF1LpRe%ZG4qwuYr7ZdaynrPs?spt;9VbQM$462zbksMVhAOqPunrR7@Nbv#5;VKk zJB7xC?~QXd(e9REiLixHxRGhLcKR#0va}|LMS`AXKGOIGFKQv?=+>zf^ zN5XLjX6^`zh*%1UG_QV1H`@z!HZgC+OT2`+_B( z)J95hk;3C+K4XCswSP}au;fx=47~*$k`RAaYEU-qb03y0#x|&>LAeiXgri5E(!h9k z|9OVt@sk1-4+>0?ELyw|zs`~<95M=%o?Gix$?8z4Gz3Kpw|b>?BcD&s{X)-aXg!GJ zyq&`ZEP{K^u7ActXP$gGnO#F0Sr+QUZe0&d5*Yhw9A?C4(Sx2j3QKAlUpkQz7nji^ z%y8F|W{ypj(T%Bf#Wgyvq4szMo?*U-;3IGBRg1fK9!h-=YRsZ_+t~2!-)=pr;)Vnk zmt95&wMb02toOf`I9>M^Kv3LqKb_-#jauF&cGrWsCnMt?p7*uh zevugda={D04DB#7wR375=1i5}Z9fi3r)!F#7qmX9`SjppE&%8l8bKt+ADRMTWRv21 z4L&PldV8YpHw3b^`p0uWlIm#J&K65-y4lQW0VzZR!4#gfeT{b#fL1e*)Z*Ux}M^}bO%OM7uXip_4! zL@yo@q{utZeVV?3CtXs}i>nI|%26fwuzt0f#96fQ!{=dEX^YKnvIk*D%y9Cin;9R) zi{?)baJhgFs$1$SOZESTpldw2H&FD=v*v@1cA!`|s;avDKHa>Q+uJ8qhy!9%C4&lJSTN4OeydYOm4S?Bj7*e{xRYbU9Xos)R7qZT3dBBD5{ zo+(E3pR{>>)}hFhE+}!yYP0V+CVhyAq+RV{^X`XA3{iXj(ir$k@u|t8ZJ1ZnHq2dd zD$0RHmGJ=!?T5`*T2zOEJ~y}Nsyt7O)%+!0ulRQdsopJJxoznfpusv=2@zLXIq@^& z>0T5k4lzGCG(DnltLIe@6=ZOG@C(dvmYXfh4IhJfMfY8S?KkT znb7~EDE}Yhg$J1LxB7m`L4VMS(+(SXTQvh_mz!x&M3-6Z zFRB*a%_gVEqI^mL5|c%V=l_oi%|~h>gL0SB4QH5uonWd#={KPg6}6ES)zk0~#3^KJ zJq@{iqbHe3gyC))jeQ`W;(u3|q)JxuF24|GMsh%v5>>VY-bok%* z1Yl@(5G2UCK=fQck}pAyWV0n{`ML|rsl_N7vmW|frii__zB;ozrQ7{z)y}M^Sg@m_ z;+?{q3sUZs3WxnBbp~CyyL(TA?C*0KIeDPp7w0$!Ijd+M8#}r~vYW)NB*$mG*7-vH z@s^wK07OMxq>WveCEQFQ*p&2gjD1j%i+#G9z##Th`gew>H5=`RwyfPDg2G%f>x3@c z14Oy}pQK?(i06GWLWu%4cGjDoE-tTEI$`9^E?nLT663vu_>6K1e!N>A-^q&tfl$0& zy&>w~+yUelAa!c@xd8iyt^`B^$cj+}h}0i!40K2Ve1KFCDezBzZO8@=k&r)`TNTJ* zzF4Pim>SYL^=~7kW>EyiVHXNMT2)8l#v^IW!pLB_8ZvVfK&m8QHkjsZ)mvd?o$VYG zX#HiWwWlW>N{D85URJ-d)}_3h73|)X=E(6hFzi#TF{$4aSka4TeY>1a_(RIkFBL#O zE0_FoSQI)}+si51ufAqRHhDU=actTRQl@y#2h}xaDv-A&GP&0Qu9V4ED5aWnX z1E#mRT1QSvL!4~%Ozt84nP{&F>VIm6w2q!EPhh^BF-94$4JhCTcrdbDXA3Q&8mPTh zqdPv|X}??B?bIZPpl}z%(zr<8U-NoXjb*L#xyqHHfpIGAgN$5i(E9#rYPYq_tISC4 z2TDkd*uZ;CIhVI2o!||T)Kz`ER@%rTf-&SfmJFF>;d(RW(B6k!1<)uxHM_1G+9BWe zc)k`gBxYMcztqY5@jccaU)CqQ@^G5TBVx(nNf2}D@);3+{D)GzyT{>%dO6ibggS({N!!=P4=M8J}5R*&fgd(w36z0M0D$ z(SN5a`i%sZ9vmaEjiC4)DF}ix&`?mc-vYwK@+}8Gqzj6r6y)lT|Iqwlpj(LXqvh;- zb>jECiiOZ%&Q7gQg7(ix-?-RE*c(O6NG0F-+VCr;701@%L~fyfHnU<;Vk`m3A2{1MSmpii@G*k?KDq0GdZ)|hd`8OHep z8@6wv_|9NKNpe*sc#?zZ1S#}*qk{k<(I99u6(QT#>wf9w^u9~9_>;2d20T=^g-;b5 ze9x~fHZ-JL=J`hq-;W{2SgN)&m9RsVo=%?`JYp`pxEA_>`18Y>XA$rfWm^pQfG3MQ zxT^I1*({tZz2}+!5$AyNUE*jiYwu_S8v<#qZS4e!bGGBdY`3RkgLMf%Kz8s-;7PF+ z6w#-FwV#)PiKGR79miXmrDyv=ZTjc)j>N=&h4F+#G;unBZhhZz?a*;8@bi5`fV4)O zuU5pCs;tvRzbV@P5%W5xLI4I+w*^KExeVlzP4kNRGp-wi3g$lf-I|(o`JQ|u^XfkP zcik+g-5~2lG*oHfjLCpfNalFwz=4ZY>$Rc-QGpws&tCfFZUuJDL)3et%ap*$Q=-v0 zgLfsn-&%#+wnox~@)6ppx30sK(UJg1dCAvQF&}DkoPI+uX_wH))iaYvWtl}BtVKpU&MN= z0GdENbhdLgIwL-#_phGK;mZRlk4zq8*)akvV5zRX@jFUmvcr#3p99P@4z@m|bz-)^ zbZl8Wt?hR*z(sEZl;2PaILIG#835i@YoZQ@EwrD9IOBl7BpJX(ilLgcd)KCZAzo^b z6Z{|~=H;$D2dD53tejr_jx7^y-zT{SNZpNjn4+wJQX~K#LcrlKOv=D5xk%QXD{tg; z+xh`PvMV*HC*rF?xyjK5@KsMl5*w`r@wL#r13uFpso~#^oYIFc^&gGNS825eqFttU2_sG%_ z;X8VXD#Ol4X&$2B_Z$*&-)ZIUXf9I%mOOXJ3O%GbGpJfl+9(jY^fF_(b!Gt{{HAA3 zusUOCPDHYT@&*H~7a050c7r-_CaFACp$BXx)5==@fC11Gn|n~~+u@6N-}lvdyl3&6 z<#c_zm0Xp1F!8o2OBbFfgzzC4vno}9XEf40dGaVo;jiwiazo8hZ~iPVD(re=5k;H| zotm286$6nnTeIw>1FY$Ri|t{Lp?o(Fg3g_>|y~Z+16tvyLc@r?t9g7 zBuXyVuu9bC#q`?@OFIhgS)6v^XP@H0ukl2X!RPMsg%`YHMGad z4{VsgxaprFss3X%HbZablb6IdaNdbISVWp7yQXPPn=s7?J9qLEH{4>XAv8}%h&TDg zs()1sh}4at3nL3^%q!?P9BbW80e*ZwU63}CV7pt}gVu;~V6c$9p+*wfhw!zeE-z|V z=k{Ksec2)$Hu&?pRh;*TPk0T$Fc~^oAoBT4q?-Q}Y&3DluXeoMQ0LesTk}pVlf5(I z$dl8;zA0&=L&z*F*H>W7IeiPhTo@P0VTB~vyC2Bm7lCN}t7@NNlKFSHGKkh?z_qij zoYju!#D4b28cdslLdIM5Cmqe&!v^IcRr=qq^?l+P^n@6}fh@)IS81hx)SPAY7osk0)^ulqC1F*{hBNQl+Y}b>XjVXnS_Cc!L zIZ@Jq#mp^E&fKT~t4DM_^S17R@YJ@`(7;zv1mz_Y=~q*Gdg#*yXGxotY=#F|lvhPM zjlE)VHS=8=)njE^c7M|ZiBqARx>9Ib!y91$70iC8jPi$c+ysP}5Q3s`ti&1sx>~oG zI^>^1onS%G`mtq&)cZ15dZ{X^#MOfatyH0I=l%Q)n z7*@kZtC_3?=J_}?_G@?F?UK<0_AhYFclyrS-PkfYhAeVHcF z16x+quy10*2V$A%p_|@C(vlf}j3uY83h(#TSr$(;^8(I={_=YQQWmA9-IlwJv>tQm z=vN-I{TO7X`;qBxwb5w$91YLV?ZD5}pddq(7IdMCH zi>`qAn|#FITi!L5;K!(tYm9r416}Wof}P8~?R9I9Gp(?VA;uQg19MO47*gS7fH*&jBO!+ zA*<^BMccHjJIvGHguBb4a`X z3aZw#!c&Xr8&szD1+gu&;vYfoWo>0Pxfr2%m34tC33fmRbzWF9I_Pqb9nNK@N##9_ z7K)v)des!^owH`MoXY_O?|;^9;comiPx0e78xhnnVvTYt+t+cU1rn_>gaFJsL-iPn)?<9P9cF#4)7q&v+d&6|3G@s-AcJy+m zE&u*GUaMK|x|4GmT(CgBICk`2BP@3rqtjKIRD#uBy}y*d;<>`?W&mGsG;i*_}V&^tlP`%;=g39@jxP z+3lrtg*!i6N;irOpUfKcd;iDl5a`<#kr8RwFm9=^m+ouwwjcXmTB}w5V#9IF^&Bl$ zr1$Ly#cQ<3u86>am9}pk&i%nxu(W&s@>qEDtn_xVtH-_EiQ}iAK4Ssfsdn&L9t=)d z`XOQN7*J)g$Jrtq0=-yeLnHg*23LxYA7$cxz^Yc)I6E-!;{LQwu_wfGw4&MYy7{n< z@{g0Hf)N5gAJKQ1Z&HGPn9x9B7U(m(9K&=+LHAc_D{YdMBZs~x)u1Y8|Oq!`C4(3_9<&$ddi6>R$Nsz z*ti?=jA-Sr_97V}feo+}Lq3-cfpgWR;PLI8s{ve9@?e;2o}0MpquOucipz^DrT}QH z*(<{nLb4h9799hx4&%I8KPj}xcQ}llgcaG1!nRb(PP?m)=CzA4v%6>oOe96H9 zv4mUhw`>V$29k?)$Co>qIqq(~3w4jJ;Hv5(RxjB-j_iEhlF;&|DDC|I8IcT>Vn;RY zhtw5mT0ygXAu=M%{^;GqYuYIMu4H;Mj--5CL}|zMEhOum_o51Y7i|D>$XmUFoe;@1 z%GsTUsKgF4w%-Cr3lg#~h)8;Lk%WQTLBS8r*sE{YBUDw4HU#o}E)8pVIEfWv&14?U z-+Za${OFm=>IA358en)nB5Iaqxw&Xi*ty@uDOX8o2c0tq0^sX>ZXD+Hn|;KY!Omm1 z^%wgf&Zy9Azd?vmU`~zuOOA0{TZ*mAC!_>|avcN83F#c+sFn_6tGo!v?95IUR2bL$ zlO(OlhszqAgy)mNt8PRulC#6u^SL#z-O&@{=_!AzBZ>T4ROorj%fx$A;u8u>saum0ha7p zeHRX-z)PW*@v9bruyAtVI@)PhaEs5kp`xyxTQ`U9$Whwz#z$=U$V|&0w@EfCUS!Ob zACSTE{VeC-0V~ZCpkKq~P4CLgdOeBy>vB+0ZxIt_Cp4aa%vI#LS^K}ui07WNo}5r0 zagMHmq-jqTf-OD<kAvu_ob1mUP%1jxeKqB!1&-)_hP{p74hHE%WM!atyx68j5b zSqwh8aKo|NIOL<2_eiX+iOsRP`{MUt{0iQetB*SL!F_8)_;0f$iJ4(o__4KWuvy_! z8TZ{dTb*rL6VmuN-yl2Z>0glL84u^jAH^DQl}VRI=x0CnuF*|;|My-5aPI;>(mo+m z`nyEOe&k$RG11$vEdDPG7^raBCw|#C*4#pIUoZJNx?4|ZC{)l>+jaSiiJ`GBKf}l) zUk1>%A61hqy!KvfRsM^|u6vwbH5WpfH(I5AdpBAg%rar%zW}nccGxfgRV4&v`tEoGyBq!uz^f zVqWEtxn%j&+Q2Fi$rL)H`M_HExP+?mFyN^){c{JXs{IM}f}p>7lfD zLZ;s)%6a(Ow@`(jP}k~pn@!dv6JhJkZf5UoumHv`g-tcCs)w* z#0sc%t9@Li{p}f*$vg$UiQ*RGZUr=ykDIaxRDU_(QfcURuYrpX*7IQcS$(Buw%VW7 zxaffDgn{-=K@iEh)LlPc3MPzc+qM^>RXr6Y8ASnP&dr6fqmwYILTpmh$E%{Iz%Qz( NZmR35l_G4O{0}dcmS_L~ diff --git a/docs/assets/icons@2x.png b/docs/assets/icons@2x.png deleted file mode 100644 index 5a209e2f6d7f915cc9cb6fe7a4264c8be4db87b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28144 zcmeFZcUTka`>%_-5TzIqq$xo`r3nZ`iiBRG(z{ZnN$)K|ii-3S5u{fmRRNLEoAh2n z@4X|01dtAA(50@mzH5K?{+)CF+}EWTz2eMdW-{;n-p}WG1C$hCWW;pD1Ox#ad~k9g4`y4!oVfq@3c(iW~uhy*`T7_0aH7`>`EnYuXVq#+YC==3#rnNM4TqqzM zpi2Elr!3hl!ZdK#y0bV+yVc8rwFEtAX3=QlvJ&e-EsBp)Q`0yKXbNuf-yYw7kh0CD z|Flk1UuHgvoR+*QR0ee&IDUfUzE7*`A=P$6nC;BPI@VJs|F#`Xc>X!`<6%M7XXNok zw^unt1h0m>-&2{GiIGsByulr92XZRrazZs&&M3jJintF7A}cE^uW4zt_r81yHt1I! z6-_gmO@78G3$})kfyhR0^qk?zev_%4R$qSjQI3MAg0)9EM#TOAD=_tf(*)S$7yiiR z&5v>wk3Bn**iD9S_I#2%^vi(^O+gpv2i^A);6^AcH%VC>0nH8|O!jN*L<#RtT z@aF9HMNu*d(BdiZq(LBO%(qsjSot+ZXQd{zLYh#CvOrK(?#u+|XYRylqcXOLk=m!) zBp`~~1dg7kF(Q#m)I8ZHMOD5%m&U)5jGOW@7+sm1N+O~^j*zRG;e4x@OteV=T4yo9 zSG`^0j^S)ZYp2DT>}AR|n$S)4FPI#8#(R~;Y**AZ9`&yqT;p`rks7Nhz;)dn-TgXU zw!^Bo@W6|jfp@}ijsSEFo#x3LnG;`o_yXK@2KuG8cTv&K@=dU?_PK*6=YU9!Ix8l;<_!y*Qc2phVpLM}&t|CuHBv&{M$K?VXtTabi(7kUMwV zl!>5cDNNqK6`Br*B~EcVh#5Z!FgiJZBN5nzpC7?UdAc+&AT0ivd;DA2$@YXMPK6=< z+#U~?*!R0i`3uu|#zDrRRN&j-j>ZOu#h-n#7WO^)@0> zCT6a$LGWwFLcPfN=(3#6`*UIS%uIT=LIXV-RbGE&!!+8)q~dkx`l{aKCe1`{J<5&< zlhRo;JX-UC>5)X;mwR+W96`@&ucHp$jIb~B_w_=mH>In?BLume!Wta=`ca+&7~pek zBVD?f5{nelCaje~EtZn+g3%5GJF}R_b`q}IH$Iom2IRD$^h*R)Cid8Q5~4Dzm!P&Q z<`iI)4wA#l@TwjPL)*9k5Vc!!;`9;bf?HRMm86wi9LI8A%*NGep3g11H{aP)>%l2Q zRMMQU!*0J$hJI5Qs3b=6?}qR7O;BU%Yzufc*ZKBV`}ro7zm=C?OY6Vlabc^r6r7P> z?1c^jD{e4n*Ou441V=Pd1eE8utX@)G5gq72HQAXLZ4l2wKd@yIYC+s) z-mu`E`kj=B!)a^B;pecv4W5oh>_tpj>^NU8L*eH4EhcOxQ|);$x(z(Yb5^tudSptV z%8z{(h@_t`chWkvFX=r!p~Vjhf1AdM>uGK05$1fyLb5D7m0!MUKW=JTZv)bXz9~*F z$yP@U3UE0=$;yjWr8b7C(1^oNDMZVxYYeMtL}ZnvQDkm>S0)=r_ugabEZ}AJ<<_Fu z{I^KKIz+V8K|pK811W5r##z8^S*2fr9Ln zlRG?Zzz8;xu9VSE8s+=(!^TGi1P2hC7%7MUqF=cZqFBtJNW9BROV ziv0cjsUmVvsU^X!`1UivK|dy+fSG$3YH8W0`q${`)taBT9jV{Hfh|&RIaJVvqRIFh zC*Rmvl&3*;XcMiJZ-+Mvfe0xN4N?AvJeABnNdgs(BYb!fK5<1)5UvM!Tz4_aojmUX z#Ymoh)m%fN(>6|#*RP~Lxt1?5);w}yT_lftje3sidO&MxNgcMg9@S+>M%s~y)0i`8 zT_+7LrZ~d<7V^K^C^~ast~@nM04^c5dw*&660^p%^R>n4xzd&jo)Y@ z1r=F09>jFOr%wsj^a3;>N!{rvf(qpkAdWM*5IYCsuwNwoJh7;9I$#`T6-NUIEKsiS;OylQ(XY zQtCiR1dyEGJV=~|zaFOEveB&szAVx*wsyuY?hiBGWR{h0!D zv;G`;F9cnib*YxugasrI^%uy@i)>BvC4V8@! zwy5#iHC#Qar(i0EPA3CuMQbaKy4m$CLjLSNwJs!13b%h{&x7479bv{SjC&3?SO&)3 z6q4nRRP(zOfw-mQrmx@Z64~o}GNXa9YCE$vD-(CLseaF%6HH+WZz4 zbRiJ~zAtA6*i9;z!+zZ?9~V0Lr66|Ae;}U1e#6D^hMhB6XJNHZi{t>DgU&jb=#rPK z@s04Hr_SOr%UCRY_SdDuSw^D*Rzre~4PCqgc)DBYam}@G^TxsTqX%w-yWtYU-Q2IX-a2Z4Kz_-yIe`m;x2bY1F?XZoIH=`uW{$R)ICXxqU$- zG#M6s!fDZwUOA_cs|PXe1T@XN3^UdYyR*t}943A1dTvXp!=%8c%)(s)5y@OJ@@%1a ztlq}Uvhfo3^ZO>ZO|NKfu37JMRRmXfJ_*VOBVnxFFmbq!zc%A+R+w|={11?sJpmca zCeCi;;-*yO)ywzKxa#q?E%@U-+LGH4{=2|reRd-Kz*Ps1$u6sPFO>{K9^k2Y!@=h7rZt472^BCU& z|0MZmbh1HlC3#bcjoX#m73R?H>6oW=45{gu0$S>j`v?``ch#0kGur}QbO_gO3XrB- zS4pz-Yrnqqt-k_LE-&~ox9gd#^n&HE%Z~grM;N@Das8-#U304PA$v*rj36j~qQzYN zsX>8?%q9DhpxrWR@M>30YI^WUDh4bcn+*bYn;~zt_g`$3{#G+=lBmWE;j}5e&vlDa zjsdE(Xg^o(Z|3$Tx>~-q5NrZ}^$y0eMd|h`7Y4OWkgF0(Cu&CfJV03AKfzSGBhMU4bqd4kc`qE!CH4Q^FdOCtUHaZW3R&>S}$! zhk=OYL~3fch$-?wa0)OEkynDzJR=vc^vuUQ$hF(>E(q3{7{4uhC^f@bzHUZT>k%%R zsekA}E`OlGE(x+lP1smp0;Ba7{C$F=@Pp~i$AsJkc)x+3Vf9xQB=aSN>D!T;Y5iU~39#6yoQuj6Bj%kdYC z`72YjnSoF_A)d#@S`|;~F|6TOn%b{4?MWJC4uG&NK=D zqd0rU$A@62MtWD$=Gg>TgO6)b6Vf41#Au&Zq<@p1RG!t}NG8kv#>%{bHuCdAeIao2 zkWX{dyO`XCdv`FlK?jS{48~Uaz;oD6PtoFF0u6HBTHCHh<)5wP<r?9UIw%{psu)`l~*PK0?1^oH}d{D_wF{En-ejdBHTK|(*2$K?xVkG zwYXl8^HAjVOqKQj0f6s~O`)Slp+alXd8@#4Iw?pHys|MW1|l%ipCPeN)|fLB$Dc(9s}LNw@?8G{ zU>U(Vid5}ltIy~zNv>o09)rC()g8O`<5~!qF*Z_?L;+2Sy!WSv=}|67mnOPb!A*2; z^f>okkk+f3+9?Tg&6NBMX%;BtB3Ds#(PZ6E4`X0e`~amc=9QGw3J-$!nw6)l1A8;m zFdl>D?g@J3P-41+3N`R32d*Hq0GWj!{3n&rVA)dpcB+|5`XZFFZI1bKA7d;-x=0wt zy;$6nvCJ$_&JDjWa%`LQYq&(6LqBP7G_+`+4$|qk7IlS4wK{qnP-3!yFO%_fw(8(Q(#|htD?ECEYPeT&anf%0GjGQC<0)vR3x=4pq`@gX z{0?*O(e3p_zu@N9G2O%!F8j&|FRhF(c@BWMxZTpdW0xv^K!`2L39%+Hs0#R>a@n-J#u*kF6~?DIhPrUi@$pR0tS?5wF%PE z(-eYCc#{7tVRzd>j~xO&LBPK62xxwmxrdd{N6!G1hfD0H?fV)_B^PBIm|@~CZXnpdaM=<+?&D8Md^RL00JfP zK|cm@`4bB6muuN!Zck2>k+wh^8kM73#1(%6#^TG;42H{?eTC(h^zB32g{Skc%t3Dn zcHX3$TQhR}n9xXCd$?igvlBH@ZU~p4OO*Gf=$@=w?9vYs)!RYa9V@}xVt8Sr4y_!< zGjn5?gnlSKhqS-YW^o#@NScez6I3x{ zv>meTLLYSK!pa+|kqQI8rWST7_)jL~mqQ}Ou*!V2U-g|ZR+pB%Z@w|HnZrV~uY*w?_gMhSp+4fY?hMmdNXYD(iruAlj0&qga8nQ1=c#y* zgYc@oWp>=|LQ+s})zQ5kv*UF?QMJ2|FN1CzjX$x&TwGJ!4VjOiZxVDVz#r28{^WRn z{o1SYRs*^Nt9(ZX`wad=44v--X~h#aROW$yKE=n-VWRfhI&wn|_X6(` z_WPK(bt4Q8gxJ=b%BW_nNj&h;H;2z`{vi`~)tCBk(zGYBp?f;(Ua+^@+rKm53ld9S zPP#A^Wv7>F7c36IAp7(%S716|mr9fnL?n&Q*?OcmX7>@shP*98yVXmJ{1{z!s;@_D zt0}M~j-0t@?)wY>a9PxzCVtBiTKiS1<;-&hv5CHiv=8d$IOnl?aI_>zR3eW}l*}`T zd7%jWK1w(iqAjU37u~dz-4@O^=PWhD7_yL+z1;-hnPx|je;QFR?I_x6McEg|;`Zuf z_}_7>V@hb=%%^H&>8W{N&Ud5bKD%p(B6#&l@nN^wOdQizb`@g}g1c|qGqGr^c>a1w z|5;G!BbS8(8#mlqM+re6&;L0Ba$evPxRGW!koG@-z@*c+8&^U^7Q+0jgUtgB$)Bh)OGD5oa(ju zL&w{}@q-4qVXtvRtXul%gWH0DxXe$&?MN>z2jh1!ElU%a2;fz@xaTyfs`lnr<` zLv5teGAw`KJIh))Wg8JzoRNMyP>X1rhr)=#Y8O6Nf7>}xLS8!@+&6k0h#H>Nn{`&~ z<h^0MI*wtWWT)UGMw#$-to|sCF?yXL$;_=8T>RsAI7ks*W{$R-UI&M5a3{Gda?9J z3PeWSws3vp1$(`F*+<1X7B6hG<6u)lqr|?N&1Up;Si*MeoRFeRNGZa1=`C?4ZaPvJ zuHL9EQ^d$jd1pu9n6iBgWPMtJyxmfJGQf{a*eag-%E@KZ$^*2_&F#h|LL)2_l*QS9(#5T>)&wtE8a=@FF+vG8N zk>*kU^97;}tRP6EGf5HKhlr6@^Nb7N1`_>QnnYF9-8tncspx59kcfE)TtFun#cCjn zEU2;}6Xu~xx+Bv+O;tKLcuo?~kQbcPghcWdz4-^H!wQOhQukRZRMRk>kfMa~V;A;p zSqpR3D87(4X}j4Awfr<~7h4dgK)pzpZf{bn z^yt`yH4+85n%*$3rL0fWi>l^4|J{Qess(a2+0W-O>gl%xIaVi`l9N3Nq}{$Q?o$#6 zP(6};On20~O*x}!V+=9YO)zz4yeTv@_04tEzA@Muc((5aTR+rHpa6@RymHX{a%Ss{ z+ZVey@TSCpCZq6G3WNWPfd3Z(|HlaUnQ37#)!hnd5VH}%lQbK+^qVrFox87bV{eTd zMjY@0wT+?ndYzV$vST&K{gWpow&Zbq;%=a$(B%@MLh@v!P|L4U zgM9JBN_Gb)g+}3@K$8-*b+GGuC&@6v)Fomd?4){kVQ)620*%U<8saNfLM+ndN~1z> zV$;~rU}Fc&M@|;i!@q(ZqbHdoB(EYYOs>u5jd5A-M`}}pr;g+_B5o2kj-|Pa zF8qc!e5d+kUV>;ih=57(*r24g=6@)>+c%LfGLw_-Bbm7r_`az+tag}5rqG&jrg(-W~CJFkaxZTf@_Ofx@ zzxqF#<4|HKKBpc&B9R1r8t{!k_=WNfzbR?aogs939=bT|!c4N>91ai-wsc4|JdG9y zGpB1A4i1ueuSS{R3h}0^YLpx`pB;Ok2-R5 zZzHya))4+|xc0QJ*&1>3;@0$RcgE3M_rt55cZ9<51j!pV&i`8js3v%e$CG{I{X+yj zruhC$iN%UA-Y%u_?FQq!rBg;{`8h`ZCg^bG&OC=733*%4cUW`DPGqp|OgNy?)-Lky zuY7>yw$@M~Jl&X?9MI2RqOdsWZwzFd6{P)UF5-=GVh z;$}}BvAUMs#V{T@TweGxI7dhuIzFqotm&oQreos6)^Nt1G4l8ce%&u1F<%WFM9t;W zBAEtq#1FS}e7Gq{9nzJ-0@1fhx^+w)&5)h+@I@?kv+h4xs>`xqTMB()kR)QH0W6ODL=b|ea)CmcTzPItT=KH66{L4@p}bW9=F z=+(cM#QUgiq$M^X08=_kUPU7sf!8j#4rN7NO0#TX0-;8=ySO&T7v$C}*`++cHZu0; zRv+{Je*j9;z>+TGv1i76Qc^1lu^>XXp&w}t;MzI_nTpY_m?O?J|UF!?x>j)zIZZ*}uTg|S?56^~@P4iEAwq#7&c^D#OmVAeT^&ib{UcAER@k$$X; zQdR$NNz=G^;6|aY!VuP>0e2>_I^ymyjmC*~Oj(aU>lb7XxoNc&mR~HbdffiYw#m3DLJ)nb-vczmSGI=PaP=yOJ4mrW01pSsP02=(ym z!R+#8VFsL>Puje-hBZZ0gY`?oFt44R6Z--pJ~w8q7te$W<+z`WB)mKtrOR>%f~{*2 z8>hh;3|%NPQq8-xDbWw`*n5*Ni7GB0zr7D?q`b1s^a4*X%Jk>EYA*r$va{t*S$Wk8 zL^lqaL9$a?PVadKA#e`-ocbsFKC1awpXsVmMxs^Fnz9Tb*6tD1sa`;k~@OqRo@ub(|hVwu)j^O#EQmIetE!ma(-|!O<`ZRqJb<$^dia$W5ARK;F@n)=G zXY|L|OhQ88G?ay6&;=(qqYF;O$NJ7x1?PPHYJC`UButfql;CF9^Z@N$9e`rgvKY7- zzkY{r^gSjplQ4S;+v7}YOOB)q;im)xJ8Tb}^>Fe{+E{o<&QW1zc~g`vO5=ii`UUW? zZp)~%d!YRLs1P5Gsp1zs3gc8)u&mU&?P*XcG+Tr-__K7L+$}7WQfV_Ngi(tq_9feK zK+m&sYg9Dt?NYYIX6$uOy3OW4i<~fWv+Cf(7LSO2Cy{IK;1#Y8C_5@I{l+TY*=I|v zB849$N`$Qn3)Wezrk#N{(Sj^ujO*o{#sa4oD_O8zmLim4B{5HQWLd}YpB(b z4G-q~15C`KQcuBSO|^7AHPTM2RneHT?`cv7UxhiJ{_{;Q;kGe05x5xg&K3|_>$pD_a&U>aXaI13$(JL50d8Z5nu7>Swu zA*$V;mYnn2)kI5c`a29y*`L60#8U8YzlVb^NVbZO*AIlUcC6{g-vYStoB)oYa(>HrRpU$_+Fu$?E^-+?mgq9i+l>lZ?b zT6(Rs*ytr2RlqzPAC<(}aFaO~EuqFiP9Nk%5YV?9#t-?A=4jtCuRhpfZRc5{uXo+q z=LI8vUYPpMT}NAmAiT1T|Lra-gEjft1a;1k`{Oe~KvJy%Wz~FR@vzsl)Hj`G)zsap zD0(^YuCzHguv&0Ryn%gl!eek+ywQej&`(Qef(ql7EcAYQoG}tAUY=Ns0uhUO05V)*ND z@*NLrHqhR{%JlU-nMJbBbn#Q$0gDOt;1glG|M6dhX@zoq#PRvcMk<`}n-dBYPlDbf zY2&o+<&J4^>4Q557tWSxa)1M;mS}X$!JFe6+N_0AI?erp9CdjDGuyvnelpc04y2u#n8-PU5wo6P&9?ZpnONA+t}Ucy z&nD(V>H%M8avRC7jdV$uW8n|L5W6kw7|(e8$j>_ZLqe`6y!1fWM}{tJ3t7HmzB894QuSOpNj=&WDT3e5Or0)3wFwasb4%9_M@6)K z&l3J-@<{!8U7lZ%P!XZsO|ejU04NSjBEBESP4Ff6+T}!&pxTCxBG{W z{I$5gyC-P##k--2l=5r77AsRg@o4?Q7zqe%7Y9-kbSnK|KDcKK;nZqb@o$i(QzUtW z4FlkIku@T67|OO;)}XWaHSwT$i->~}#O|Bld^q?M%%`d*s2x9BKP zZo$OD?q27J1NAg#Nd(Fn?4I|PbI>nwdR&!F6YOHC^L#n$QG{zQGnjL8QL{~TyS%sy zMT%4c%BbJPXL6?WNg|O1-c<>qUm^=RW`+5)eH2jAI{T^M6-_natW57V(D?*MKT4n;I#vjkQ1Y~X{0hj4% zF}qYRzy8zJX(%d$`X$XgPvDafqM65Qw_;|~(JO*m8-*q1ir0~W4cd`@#KX3_GEp5t z5?rPAGz%$L?%(5dRFgw~R^|tdxXDGF>^=J2drvtC0;nBNt)$2d+>6A}c}i_~ef`fu zywIKq{Tp+H@09h2i{+Dn7?p7~8D%gZ+<(bq<1f|tL;Qy~w3}O7WX))3Ej+(psj!1- zrlt&tNKU|u?sySN{!ByuYY@P5bL5@7&Uld^k~iLzJaP7WDAI|JZrsHHT>hmAC?xw& zC!c!IBNTzL7K;wAXR3vVTe1i(oYdqoy3H0Zw{@>?*4UcFaMCNHwib2efs0(Ync=2q zwM72#(Cn=nv2ablw^j({)fdng^E-(uP|5UD8@CzqpKlZ^=HH}?5{kmM7vLAoAatc; zwH5KZJkkdhh8C1p5+HZgC}LE+Xu}KIn7|*#?;j-8^-VaZ5jOW{JA#*;g5p`(xTiDd zKkPnW*IU@QEsE%-JWbaZU2+aF3<-bfklBU}TCC{E-~c1suP&!}=v`e&X_xF{wro+L zcgxt?1af+ArOGprbI<(>!E99@GkN&7?#q=uz{(bMN@|0qqxcTr07b2;i>k6W8Za(r zOGe?77{mF3SVV_<+hIDRNdbE)(lSDJU|Bf|swOh*8)pQ6AizER8M>1xnN1+Qcqhg$ z&ak{6PD5v75^-mAcvoOH6*!9Hkzpt)*#Ip_vNoGk)^|nj*9+w7+7R(=j4q>aw<4Wc z=nBx)kd4$ER29&>bnknJ`n4)pOczJMPJ! z0)p$AgO&S=`T1(PYN?P}4cSJ%&R?iNexQp^N$*`-AbTP7WfZIW#P4d}}S2|=#O7ke0mzh*aEWQE)y!|#~iGCKXe zpzrFFL$pk!^d8pUI(IfGO<%TTQHsrDXLDNnMC6*d0wT9m7x6Ft7V=_OlTqkuj{x>p z;1kpB_NxE04RdYk)Y!laqUU=rfZJ$T5)`7`QV?5(Ltg_xlECcjtEa{J!@6Brx);>b zl?P)xrifEIfWi;~!Hgrq*7bz~i3BH#^2_mOIb$vnOz3yqef|S?NrX2~aMzcrlIGhJ zJ57YYnbrjk0gMXNJsZ;3!GV3+U0eN7l{dNPN>2^D{M%{F_n#@Jh)M2G9pb6tlT&F# zzc){OFWO&LCDH1cNMGR@X9VA+vt>EiQ|#sD{Y6sIh0eE(T5g#Bhn{L{CgdEL#dtrL zC>~e(BtwcN6QdM$0h>v5cu{@BvleO1d{z*-w8N(k$wHP$AXwvfT1)EL-?E&6nLdTq zFA@*HmwLR__b301zkRRgd(MeG6hCvppG6OwFv=2NKQVx_rQX$Z3q-DFDcOMHtbuC2 zb}=nSGqv$BlXjj(ahhid7ECVPglKaK;z#;LgZZ+OisWYuKBPX7xpErFk*@EYkKqg2 ze61oYkPXBN#&}jK`c6OUoF{pGlCOmyvi0VbqIH)+GaMDJ>Eg{$20?GwP~=nbph7n3wT-iS@IWTjG!q<-}5nJdNKFs75SDJ`2N60FM#00h+c!NU0ufy*_DlHj73t z5%X`Hqe$xxtHUL9%+{FK#XTYqf1a`&Lh=``4pOX3cy239FO^N zfStakz4XYa-?AppcGY?%Pj@WYmLvxBlKhq06UyFTy`Dj|YO2D`3uG#B$$f7PEjp~U zN;XAx*Xx;j?A}%@n)?=Uw67Bf^MPlLUonDdnT0whr^OXyCbtVRp^N&tL4I{~Dg4l+ zvxK9}?_3)Y$>n?i!054VsQ<#MMZ=Q@luen-sz=N_VC}l?`zNJtA`krH?K@>?REBq0S+(}^2UlFWDqHi30Pa~uu05d$T+-JrcJV1?aXOg(}Rs zl`@li5%>|PHxJjZT#h6)u5#ukqU%dvk;$HYi|x;L7naNA&)c1zj7(iIm+BYA&tK7r zwW0zwzaX`x0|CVQVi4}J(N#ScVIBUXBSyY%CN{!aH)SJ(GEwpFU}-yF{d#w05hL=m zqA}!Sf^U&%EPmu~34)ZMEMWZ|Z{ zf+Da%zhehlo-wY?=x^Nensm)O!dR`~B96^wloNE6>dRY#u#pQB(ftm&2{0{aPw);3 zLS~XJegtuFdsZ#-4}Yw<2z1ya*ZublDU*Ut>&i)(l$<$AW-E7gWuf>Kh>nR@=~Jgg zYVeI|2kH%1E@)ScwTRMO*HTWJ!AcdT*o-xoiH_PF%JHNE29RfRx{{W~Mn)HwZeR53 z{~74suQ)4?@;WN79bIYU3yi%hNhnxTu7in4w>kOLA9 z^_cPfyxl`BO^Jaqzdl`|Ez%y3HTE#{dbqX?j$5k&zQxN?z*CZw+vAZV-WEk=-9oI^ zi>;EFv9pBIbUMsM{{@)yaWwa#nUxs`jEZa5y%dJ~ZYpxpbwF;r5KM9NBrtI6bS49Z z{7GcMaXGAxDfXDD;60Li!JF~fHPwUU&ynr@B*@3ChF52>+Zzj(2PL6C2Mor0xpcaX zJz8ihH2PY@>!))WZIW^vV%K*vW$Xw?vcF2|dP9n=qCP9;7B^IZhW=jxJ&T%Ztkc=ADNzA zsx*6uOG(O5$(&<*ti|J7dW)DtZjKZ4%;`A)POZf?A4Jh3X-N5M*8W<2T>+@m+RM zso4=f_o0cfhnM$+auk~mI=kVgHZ;l-+V`UB8DLApLi~fqxxCu82ZpTHwuvkJ zMaL0c$(fK#3^%@^>W3#TVHR`5ZG3y0Clb5K47#1K#yLmQyhW_55~ZZn&H*`)Kcz#xCRQCFdlucHx%dY1wZPf=tL$KK^-_TTkBlg%SX#-AMe8 zDRJaA`0SE_!0FPPn@x{0rimZQd9k+}88MLx`S?6fu6=l1Y@h3fs<=&*q;z=urTS=C zK%}u|(8k5e&Y-zSmoYb|zD$^cY}p6(t?!f9J6m?2>Tc-Xy34Rp*Ug6P;_=3oS~ z%u;Q7%I5MiGqZ{d!-pEl{0|+1NTm+haNN1M^6$Gh!|V@!B;}D{h3pn(C{xBk%}#IR zO1TK6*^j5|!U4^zB>Fw$Ab?>qDPT1M^Jx#~^C&2cPdIB_0;KSVNk9r$##HLTSD_Z& zz)jE%*Gj)7d9uVMl=+HdJ8%e}9%lwaY;_kEvV>UsLHx;mMC@f3lzq5Iv&y8{w)@Z#?E z$bXT?tyF)?<3bugVVY6(e@Vg`2i>|)$^m~$WioLwW}oXXZ}=w;=N0{LOx0{9*as^Bb{)>T@3m+vEip|GPIJDHTEO0j?I58}) z3~@%Q(7?0uCeHM#BsO=kytmWFVcmtD#HF#V$&{e5iF)nW6D|+WjJvd;&5ukcPLykI zL)z_SO#T-IEgtk{E$oT_$8EEJI%wS_Y2C(F)`01pzGC)%N-d}qrB@+6yelt`_?uuN zPMGYZCo678{Kdb+IPo{#IN(js1Ummj@!l19H8oPMb}r|M+d{D&z2T^r|!8rbRwlE=7j zz{QM`99y%o-F!wvWl#jR$l|ML^ohwPPlBQ~Vi{{yBOjvrhl~uf zK5Vk45;70o*YhtM&7#Sc2dfA3wZq@0ZZ6N~v6zg&MzJl<$ZNrwqf-$TiT@#W`2x6Mt;TiS4huyA5^}YIPTFF^l19VciDe9QgSuo770l zz$Fvs?0FY@_UtE2YE##{%dGmgZHHfzsU_`V*H`P4*F`ul(sYs9Jq*h6rbk1>eD34Z{2K;_cLbZ46halLc ze2%NUKU&GA!WwUqG&=coFm>87tCT*F4xGxo74O@5Y3xJVE!8F_1FP%~BdC2FS9Isf zXuW-CnGh!{^D*Drcrxc3Y`W9=5ZVYqn-rEs?8_&q}IoEx+VFS zRga(VCYV$<=Zq#wk?;b+las#o#HsNw*`FGFDeA^*xQuB(cE3~CcEUYt6MjgdL|p=P z2+pPgOZ0Zk#7FPiJV}Wb={;89-U46uTu_QI1&b)P=+se1|88_^!5Um>o)Nj!lfI}_ zA{$}3*734@W4yItj?m zLJCa$`Rn$L_lRPSglt!uro*Wg-e^WHi@NW8q5zxYdq%ULx=%RZ(Ry~zKFHmgD!x8n_+?xj`!7VyZLb@!Ht zcyvx*=Ox|L<#!iwxI;b}HqA-#(_&c7eI; zh0-~Nl>BWL;lGfbd$~ThM~0`;bnAxA&t^Bg46A9F67?ijVTmmSHXl37dKJH@X%pJ( zv;J34-$9e2BLwPjbgdS-#g6)O&a!wuZ-4?=C;(W1fb*oq3F7!&Q;TDT{dSIuAJ0r( zTYW}1z5Y^?(IYRkcvPK{&UNZ!DTD2NG^^l4v6pZ*x!@0~FW+zs*VWLZvD5?b&529v zzAIr#Blpmqud6Eze&qzM(zwET6WE`YFdmz$)SiInkY`uE9 z2W8d!Z|P-BLFnbp3rcnGlI9P_{}G(V#2CJpq^&-OF7u(-e@`ex!`4!J7AZxIWjne$ z*}p)Oo)D;<^YCfczySXZ)mxzJ%Trh$e@@Xs6YI$UjQXTpMM3=OD}yJh-k2t_G}69%^Fr!Z2HQA5*4M*x@spn| zrheG^IKj0ez3X@*QK}PLKen)$lLlOFZ8tSxuEOsfZ4ZBRv~f7a=7}eY0qYvDhVUkw zZOeCWJKZrO(yrm9v!+wYKhPp+8sVTN>nKBQt1)2z7ZTr41?oJxD3UIFa*^`;bD2FhRFQI1$)e-S7>YM&OE5M83i$Yg1gC4XbSB(3HY$XeKc0w~r|t-}85eyvq znGOcAFmP`I@uNFB6D-U3R7zi&HI?4$T$XBCYp7jyF2hIU++&75Z}~Yj0lG(o!Q{%x zle@H4z=iwQ^%fFV}$@P%l|Q*S||Fc=aU(OuYN7&dFa}V3Nc7J*3pGRNHysT zpl1qYqD}+z4udN>1yr0@uF3~3%~hGND|wBbU_IaPN$MmzOSBa(DV?!lmqJAFWhao7 z6XK-N{+v`HO%=al&V4z}>Sa|@+Qf8!nk9bZMS#vdzl+RDih{^-@~-07nqb7URdH*R+DD=7!&A9Oi{-a*?F%R^?_>z|&W zHQ+4C_b)3pp#^K(qJHO8s1UDOMw^aDYOOebgZD{HMbGVDVk$+=PF2;lVmdaX96DD( z2>^x9360&?xbJ=C?ww+GUzY7mi#yf$i@Zi^^Y}?DA8FLB1O|#d@$jX3gICv(QdzlV&8dxsHV(c+LsK>QTvzU6_ zYb0#5dCxZ%c~~}R7+|_=M1NiJ;GL(M6jlh!W$wT&BZz#^;TRxOvOoC5av{aK*jUdB zEJTT7g$OLq7j%VOxq7lBmjswrMs{Cq4i_QLuY?I-R*l_PX%)WEauEF6LE{{cM%g#Z zY=g9-pHTq4-?B_^ws)ot(CdUT(Q;?3ZgB%&0-LSJk}S~oODd0f;gmE$LNlWC)*SZw zTF2tWUDe>}3GAgFzfUW{@fr-5%+TXNF!#@u3xLK#M@{^pJ@RwHxR(mQv$rbM^u)yF zp7gc4+^-scO=w4GnLoUHm&|*G%B4)zdnT-@sLAXD{t?qVWoK?M#QmO7ZDZYumcROM zT0RXq?@|A$uOb2&0IX>Ab9ty?U)lM3)bo7LPM+d~0IDZ9U)9X4Pt|IhEccrc4$Yqg zxN&t9niz^0H@V{LX*57HW5=4LcVn`mZrtz!m-E4LWa#a&|ZE=ZeR z_be>uWC0uQotqmp(+ySAn|+s`Jh^?c#?)U-^^qVEROY9akEY4F$EfL{d=!)6%BG-- zzxb^*e?e$Rf1Wl1QT?k8F>OCoXwv?=Ung`f@oR`*z|{D)G%5h9(2EXaoVg^$f5Zm< zKZTunJXG!9$1R~Oja|ej${K1yXo$j8_FcA;rjQxV!J)?|Gj8yk6(bnRAXg-|KsQuFvOvU}1Q)$#BKFf7rFv3#c^C6nuM& zOO0Gft$Kq{^uZk+fBQMx4ywF#eZ10jN%@}^6Trc3hCtkr5v?qLPeTBZoa}i>5KfE4m^W45!H&tNIy2!R)_bi2pfs)oyorVbu+nl5 ziVqIJzcjU0;LWSXA>n4vmdvWwz`nJ(vB0=#2PO^BiHo&%ecgXrM@U_;#^7aMCflK* zu?J85J`Tl@CXG@Gz9}c1FQwCP4okOwbBpS37P8a>qfV`z9k+`X5YFPzTfu%UP!6y`Fvr_P9?4V5;X6Bf8{U9#rCkAZ zM&uVB!n66B@`9(+a&}!KKRfCf^oQNN+6$^tHoMIK!>*$7-0ZFr=x>*b-P5X-LgxBY zo2Ug*pNH%q>8qqJmtk=~7g&DYcueN3PcuE3&z~%j0gUYgSS9wn57tV0QdV~{+bxEnx{U^j4&k6Tg_t{mX$_Yq$xe=@q|jc4#`MB^ zJT!tidMB9LT+XqKk3JFN=!_dS0?dknKn##1>;EeT2o)}9LyEIBz=e4SFuw9d_vq)Y znKx|vFBXdWkaNz_)-AYMGNnQ9zLj_f%C}~7N!N>u)Lf+CfEIdIU7czh$QbcAide4T zZQJy*?<2fUv(SP%PV21I_X1kz7G8vO5oI)0xCIvcYt6{A`!}bwQlGSad^&0sE+dig ztCN-J!D2iYgG*FJ2{BPzy1^u&y=FXDd67a8y7BGP|L)Sh_Z*1ci7meUFD~utdnA|k z%FkshXa7&|yHfQ-cZaL9*88w++@nx&uAPsEVL*=wVw{~gi>(snR7!xUfN3m@nIRqe z$bxi@pG5F$L=in`nIEOo82`J5h_9j*7~_4)pr(1ea&G+SOCoJiMKDK#1^!`Tmo zu(KAj$s(@Ez}~eSFWD$y#q zslU<&-b60sArh0MhfMd8Ut(rM_CQZ8FfKQivy3;fi)0|#R9eO4o~zDAw8`&mCJBRl zL+V<9>B#dX+=Ch6E=t$PUla#aJlOiq<<`$o@7t~|m@_8YX~f5JPr8|q*x0k}KKaw) zlj4s{p!Bb0(O2I@&cJP`BT4v(=^IBCC}>G;6Pl`dvTGO(u1uHZFzBch#Oi5#?{oUA zMDhff&?FU9`${$qfOt^aXNUDLXp}!L8o++(*YdqI@rZ`e_9q$WGiZtk%BdwBGNUQLOvKhbHU?bZL0ypyF6t66gl zm;}?$LvW7=cpykxJulrHg1_Tybvk9?!FUgQFW7)ZjiG5RKh5P)A-N+a_IR~*prd%Jub(3dwV#iE zEZRnitmR!zrZDwcFZbI$fi zpQ#2NyF^|ZZxhg}_2{p|uY5RbnD8K6ZJ*(Qw2)?}wekp&yaRA|Qo#DxsS?SeI+jqSMG)is9$_pX3e;QRCk`w z6Eyf}-+>ptnm-5fB$ja02cI*FiDNlWz6!au(Hs}CGqc@Mmic~|=QFFJrG1@1hjtXy z4~e%c+1cVu*QrSvt}^-J7&3CYOFA(;0v#pDtP1!!v4p;BvW*`n{US>q(dX{NUrV`ti>sUd7L3MP0-oP`aRTgYw5brGKhov{JH8&ZnR)OJ2X6Hj z*N%E-g5%w9Tu(o3p@Ox209&F)dqM|)8ypzq@>_T7)U{4lXM#FbS?FxaC!G^bZMM9+ z4tmuQbQP|}fWbv^^L6{ks3C9Ej)`TTPs7Rx%f;*+b8A$!FHS$N0rHb7YlE-;Os=Pr zQ{twGcgc=sfxFbo@AZ<0v(i)mIIN>SayZmhz4f%!>5C|cW!)L%h17s1v)z*m@qbN( zLIG`HP@`-xc!<{bo61SZlQWVZ1OuYl!Sb-gF-ru;V-o?-65R4%f%6Z;4dlCb<*tm4 zT`7ejX`!VvI;>13$7YHQz%+8p7l(Tpo$_JB4f^W={o?Bv;zK3iLCjqj{gvE5lo;fd zHH{q|VzJ(ecLFb~dW44K((lhkhDQ$2inQ@ZcRq7Y>-^*1b>gOVEt)4}ovdHpbt^K@ z|3sf`Dm|bJwcZkK{pP34+PPS-&Y(HzYpQh%%*U0(ohJ^qYv&SPhZse79v3M#nTUb? zTTjUjU*9&)0S1{kUx6pKuPYG_c~z}evFZy5xUz{>?k8wd2OGRLnS6!W@2E;KWyJGkUt&UFTh*2NVjj=kW%jj~V001z!4 z=ACav4hf=_2vC25z)FK{a-HCIF%1b@(>NH^N7$**yWUBYO61yA32R`g-kGrQqT2&s zZ1aW~`>zx~03Uhl@0bL?Vul+mpc)cp64nzfU1rpi*eG&?8WU7Xl4Pf1!!_iKpK_${ zC;xLY0h})InNl8x8hkL6Jpz7odsa%}^mCw|17HWPhf{dC+kQ}x((i~n?<}jL=p9a@ z<9^KPtHyuVYuBL`*B7H;P2iVO8ICwx_P&$c40y;=GC7R)u@F`J-|`;#me&bZ9#xFU zJg^Th!=rFfc{Bw+ujIxWBM>U0T(6i0?6X&W^QWn?a#<*foA?<)RQJ+am_wkw5~pN- z7sfTpB>PChT4dEn1d;2VMl0o-hg^bZeAQZSZ%fT*?fK_jkzO;p1^Kn_+yjstFP#ra zNvx;BrMYSMj?`B;0sS zFuJaW4L~Ou?IWxSIxyrDP0$laaSx}5DtUOzHO?=y^m2JYfcOG)&~ws}entE=bCT7$ z=#rYt?lU1eR^i}WaqU8Z0rKPflqR^`l!q|k(Zo+khOK+ubx;hXEPh&3dhXVaKhK_5 zEWuW;iN*%L+&b5&xM}Dl-pY8w8~S%KsSYAxoEeE0RatjS6)vupzw^Mi4zR4J9^a9vEO zGsL1|=&T;B!-Hc|XANCOT4+&_Am}oQeN;)!5I#Ng%dGfD89Z`xzBJfQ5Uq?0g3AeUS9@IhE|>w~}OV)8>HvkoV#COPN{LT#vk8 zt2Z)j@{a(~lW*kv*4-rOL6sffa^(OAYdJ-0AsgF9gwSQe2wH&X@4yh*TSHt#%TNt1(?*1p$1*$&WoXj%(3D- zcQ5QJ#PkYUg9UjMs?vZCI$TX&{X=JmqECeM2>uCx|CpLx$`!gYuDe(vVX}YRkFG^k zURe>tw{_d=^mg9nvS?KtpkI=2?(iG$tPXR5QosdvzxGoCt z$$I=Gfzpq+2F3?10L^~%hk|tHo!byiu28i+0-PzrVDKCekd-_eW}(>Fp}Ancc191J z%LV{ozGVXd7!U|yD)X?cRj`u12B#u~Q22#>5x;tCwV54R+A8Kzk+(poe&f<5a*v*K zT2oU&Cy_LPGej(sedjw!v3{YylrY}sxYF)>cfp<-T!xEu)CFu&YJe?D)I%N!%*L!8 zEi#ZVi4r-oMksMF`zOoUUiq(+KVL}Vgk4zs|M2{i%LBzJSShuf5=6EJK+gfbJ})q= zG0GhyJ>s|)s`}>jgj5{06DiB8;CT5#UeEFuCDRNU65yFEh+SOUYPR?{idoz^hcctc z&442k_wYk5d(L7ZTKmy)4^n0o##7c6!_jl_B86&KbNSP0;&tq_AS1DeI66n%PR*pX zi2%0k-ZNP@3`AaRb)vJ?W}XEv*Z1a+PPd6tY;c0IY-s0=Iw-*C*soU) zC=bBofdMQRHt;f`m;%bDO+Q@6&hS8dvdDDe(V_H-k2t&!J`FL&9w2#0bHLqd5+>n8)4e;ua%TPUO&4#d!TjvD`IHe+m+wqABkj zoNs5r+GI!s>cQZx77EF%7%V;lk~d43R$%h9**@|sc6SSR>J07Anld(@sT0nyR>Qu_ zPhkc@Fj;M*AKsf3%f|p*H1HyY%3g7T%cCKt?y8k0=-`j0laL`{!mVH11jZ{=3)Zbo z21^05#asw*jiv?Hew&@KV*;teNz-jz?UZ2y0k!l8DBW^9Rj~0!uD>Ft|27Lg;_|N} z*?vvL_xnuig>$EG@^@kLoJ?zdbt0stXU1YVLJO_W zCv!h-*}a>}{Q3SZv`DX6-2%p&B;T>R%A72KsxXP5VK54m2trhI`mBmx(#zV{ zInu6zS{==2l?XBO^i7UsOK?Fk{?ekyEXECjxn| ze`kRpJim|8Q}?3d(XG1>vcoX%zs<(_g-QWYTElLe@&5AL%%^F!{2#PFiop zRz~d(ix56>b@e=g)qGNk>2`{de6Q_WxRCIF*6yQFR#bxy#Qy{EQ~~2n-V>tkL{`UY z&0Rmmuj2DpeT)jObl<7A@des_b`d1V25nwoq~e9M<^f>hHSU>co8g(*{m}-YwofiI z-mkS=3Wl~O+8MFVW{YqX8E6K**_pPc`QNK@m~X8Hg&Kle5qX4L!dd6!IWdLU*Nlkc zGiH(n$H6or(h^BfuCPB&?kP`30z;2(u1 zR+FQfD9dIbldYlRvSLo87bRrF5U656yei7F$Z+uFv&!-!9(3wD{QY)By0oUJmuQ{- zU}FV=;Y7LSZ1uxnRdzVY10dxWlIkcKoJet_HxrwC@n~W6^hFyQekJ5|pV<4XQj zka1?kZLfD%g`ld(`_Jln6>AAWt9jnwML-$NI@O($<9KJ{W`C%l?Zl4-L0J7Mr!-?21u}Dy5k;D zu}!eeZ*3?R;L}9xDghYu?{zNJxF-U5o>7it>+~T~$v2ua{;7P)^J*yJ6~TT02(a@l_L<@JIZo3wOYJ9t9BNNUnvpIZ184_1fah;Vh@r1saB z^4y@`7jq3dxmVlsiow+%)C~5)FovY6v>3pvw$J%t@r@7cp&Ec@j$@T1u-i81-!`X5 z*u0~!^hDZq+7k7};*;b~0?h1x(q(|(>8OIVD1hr(THoGWk=iwDyIPzQf69sA=(J+o zn#EcLV}QPlry2xM(Oe*&QuTxz|DO({_ui&T9ig&XSsUK?V&dy)5>MGnr6uw&*J)SR z4O5d0C2t!+(VG{Y3fFU3G4!F~;z`0^Zy$VT zlJGjGSF&$3BUtfc03n5Fp1KQfb~InA&8`q*1q&GG=||Hzpy6L2H1f*;LpyQht{w?} zDZ2kUk>FaSr)>&iD|Z|7sH6U!z%}z@JhB~OedrN<`}Lfq^UV}Y43>cn?*zZ0AOM2< zpX5w(`QSQaEYTvqHz~=NXHUjQf0o%dBkQfeAN31lR&xxOEgYHTdZp%bVXN280=Ana z^M=FH$n=5rl?&BI)^08Qe_`>YwGkkoEIR+Kv^%~Pb0k^b?3|sA#qp8cs#eTueeM2Q zRw=0&M&6mX$~YF!Y0ZBc@63#c7`f!9BKSXd@Voc{RoLU+XN*d^;RK${8T?=LBS%Bk z&gk{var Ce=Object.create;var J=Object.defineProperty;var Pe=Object.getOwnPropertyDescriptor;var Oe=Object.getOwnPropertyNames;var Re=Object.getPrototypeOf,_e=Object.prototype.hasOwnProperty;var Me=t=>J(t,"__esModule",{value:!0});var Fe=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var De=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Oe(e))!_e.call(t,i)&&(r||i!=="default")&&J(t,i,{get:()=>e[i],enumerable:!(n=Pe(e,i))||n.enumerable});return t},Ae=(t,e)=>De(Me(J(t!=null?Ce(Re(t)):{},"default",!e&&t&&t.__esModule?{get:()=>t.default,enumerable:!0}:{value:t,enumerable:!0})),t);var de=Fe((ce,he)=>{(function(){var t=function(e){var r=new t.Builder;return r.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),r.searchPipeline.add(t.stemmer),e.call(r,r),r.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(r){e.console&&console.warn&&console.warn(r)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var r=Object.create(null),n=Object.keys(e),i=0;i0){var h=t.utils.clone(r)||{};h.position=[a,l],h.index=s.length,s.push(new t.Token(n.slice(a,o),h))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,r){r in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+r),e.label=r,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var r=e.label&&e.label in this.registeredFunctions;r||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. -`,e)},t.Pipeline.load=function(e){var r=new t.Pipeline;return e.forEach(function(n){var i=t.Pipeline.registeredFunctions[n];if(i)r.add(i);else throw new Error("Cannot load unregistered function: "+n)}),r},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(r){t.Pipeline.warnIfFunctionNotRegistered(r),this._stack.push(r)},this)},t.Pipeline.prototype.after=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");n=n+1,this._stack.splice(n,0,r)},t.Pipeline.prototype.before=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");this._stack.splice(n,0,r)},t.Pipeline.prototype.remove=function(e){var r=this._stack.indexOf(e);r!=-1&&this._stack.splice(r,1)},t.Pipeline.prototype.run=function(e){for(var r=this._stack.length,n=0;n1&&(oe&&(n=s),o!=e);)i=n-r,s=r+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ou?h+=2:a==u&&(r+=n[l+1]*i[h+1],l+=2,h+=2);return r},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),r=1,n=0;r0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}if(s.str.length==0&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}s.str.length==1&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var h=s.str.charAt(0),p=s.str.charAt(1),v;p in s.node.edges?v=s.node.edges[p]:(v=new t.TokenSet,s.node.edges[p]=v),s.str.length==1&&(v.final=!0),i.push({node:v,editsRemaining:s.editsRemaining-1,str:h+s.str.slice(2)})}}}return n},t.TokenSet.fromString=function(e){for(var r=new t.TokenSet,n=r,i=0,s=e.length;i=e;r--){var n=this.uncheckedNodes[r],i=n.child.toString();i in this.minimizedNodes?n.parent.edges[n.char]=this.minimizedNodes[i]:(n.child._str=i,this.minimizedNodes[i]=n.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(r){var n=new t.QueryParser(e,r);n.parse()})},t.Index.prototype.query=function(e){for(var r=new t.Query(this.fields),n=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),u=0;u1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,r){var n=e[this._ref],i=Object.keys(this._fields);this._documents[n]=r||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,r;do e=this.next(),r=e.charCodeAt(0);while(r>47&&r<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var r=e.next();if(r==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(r.charCodeAt(0)==92){e.escapeCharacter();continue}if(r==":")return t.QueryLexer.lexField;if(r=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(r=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(r=="+"&&e.width()===1||r=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(r.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,r){this.lexer=new t.QueryLexer(e),this.query=r,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var r=e.peekLexeme();if(r!=null)switch(r.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expected either a field or a term, found "+r.type;throw r.str.length>=1&&(n+=" with value '"+r.str+"'"),new t.QueryParseError(n,r.start,r.end)}},t.QueryParser.parsePresence=function(e){var r=e.consumeLexeme();if(r!=null){switch(r.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var n="unrecognised presence operator'"+r.str+"'";throw new t.QueryParseError(n,r.start,r.end)}var i=e.peekLexeme();if(i==null){var n="expecting term or field, found nothing";throw new t.QueryParseError(n,r.start,r.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(n,i.start,i.end)}}},t.QueryParser.parseField=function(e){var r=e.consumeLexeme();if(r!=null){if(e.query.allFields.indexOf(r.str)==-1){var n=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+r.str+"', possible fields: "+n;throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.fields=[r.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,r.start,r.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var r=e.consumeLexeme();if(r!=null){e.currentClause.term=r.str.toLowerCase(),r.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var n=e.peekLexeme();if(n==null){e.nextClause();return}switch(n.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+n.type+"'";throw new t.QueryParseError(i,n.start,n.end)}}},t.QueryParser.parseEditDistance=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="edit distance must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.editDistance=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="boost must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.boost=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,r){typeof define=="function"&&define.amd?define(r):typeof ce=="object"?he.exports=r():e.lunr=r()}(this,function(){return t})})()});var le=[];function N(t,e){le.push({selector:e,constructor:t})}var X=class{constructor(){this.createComponents(document.body)}createComponents(e){le.forEach(r=>{e.querySelectorAll(r.selector).forEach(n=>{n.dataset.hasInstance||(new r.constructor({el:n}),n.dataset.hasInstance=String(!0))})})}};var Q=class{constructor(e){this.el=e.el}};var Z=class{constructor(){this.listeners={}}addEventListener(e,r){e in this.listeners||(this.listeners[e]=[]),this.listeners[e].push(r)}removeEventListener(e,r){if(!(e in this.listeners))return;let n=this.listeners[e];for(let i=0,s=n.length;i{let r=Date.now();return(...n)=>{r+e-Date.now()<0&&(t(...n),r=Date.now())}};var ee=class extends Z{constructor(){super();this.scrollTop=0;this.lastY=0;this.width=0;this.height=0;this.showToolbar=!0;this.toolbar=document.querySelector(".tsd-page-toolbar"),this.secondaryNav=document.querySelector(".tsd-navigation.secondary"),window.addEventListener("scroll",K(()=>this.onScroll(),10)),window.addEventListener("resize",K(()=>this.onResize(),10)),this.onResize(),this.onScroll()}triggerResize(){let e=new CustomEvent("resize",{detail:{width:this.width,height:this.height}});this.dispatchEvent(e)}onResize(){this.width=window.innerWidth||0,this.height=window.innerHeight||0;let e=new CustomEvent("resize",{detail:{width:this.width,height:this.height}});this.dispatchEvent(e)}onScroll(){this.scrollTop=window.scrollY||0;let e=new CustomEvent("scroll",{detail:{scrollTop:this.scrollTop}});this.dispatchEvent(e),this.hideShowToolbar()}hideShowToolbar(){var r;let e=this.showToolbar;this.showToolbar=this.lastY>=this.scrollTop||this.scrollTop<=0,e!==this.showToolbar&&(this.toolbar.classList.toggle("tsd-page-toolbar--hide"),(r=this.secondaryNav)==null||r.classList.toggle("tsd-navigation--toolbar-hide")),this.lastY=this.scrollTop}},I=ee;I.instance=new ee;var te=class extends Q{constructor(e){super(e);this.anchors=[];this.index=-1;I.instance.addEventListener("resize",()=>this.onResize()),I.instance.addEventListener("scroll",r=>this.onScroll(r)),this.createAnchors()}createAnchors(){let e=window.location.href;e.indexOf("#")!=-1&&(e=e.substr(0,e.indexOf("#"))),this.el.querySelectorAll("a").forEach(r=>{let n=r.href;if(n.indexOf("#")==-1||n.substr(0,e.length)!=e)return;let i=n.substr(n.indexOf("#")+1),s=document.querySelector("a.tsd-anchor[name="+i+"]"),o=r.parentNode;!s||!o||this.anchors.push({link:o,anchor:s,position:0})}),this.onResize()}onResize(){let e;for(let n=0,i=this.anchors.length;nn.position-i.position);let r=new CustomEvent("scroll",{detail:{scrollTop:I.instance.scrollTop}});this.onScroll(r)}onScroll(e){let r=e.detail.scrollTop+5,n=this.anchors,i=n.length-1,s=this.index;for(;s>-1&&n[s].position>r;)s-=1;for(;s-1&&this.anchors[this.index].link.classList.remove("focus"),this.index=s,this.index>-1&&this.anchors[this.index].link.classList.add("focus"))}};var ue=(t,e=100)=>{let r;return(...n)=>{clearTimeout(r),r=setTimeout(()=>t(n),e)}};var fe=Ae(de());function pe(){let t=document.getElementById("tsd-search");if(!t)return;let e=document.getElementById("search-script");t.classList.add("loading"),e&&(e.addEventListener("error",()=>{t.classList.remove("loading"),t.classList.add("failure")}),e.addEventListener("load",()=>{t.classList.remove("loading"),t.classList.add("ready")}),window.searchData&&t.classList.remove("loading"));let r=document.querySelector("#tsd-search input"),n=document.querySelector("#tsd-search .results");if(!r||!n)throw new Error("The input field or the result list wrapper was not found");let i=!1;n.addEventListener("mousedown",()=>i=!0),n.addEventListener("mouseup",()=>{i=!1,t.classList.remove("has-focus")}),r.addEventListener("focus",()=>t.classList.add("has-focus")),r.addEventListener("blur",()=>{i||(i=!1,t.classList.remove("has-focus"))});let s={base:t.dataset.base+"/"};Ve(t,n,r,s)}function Ve(t,e,r,n){r.addEventListener("input",ue(()=>{ze(t,e,r,n)},200));let i=!1;r.addEventListener("keydown",s=>{i=!0,s.key=="Enter"?Ne(e,r):s.key=="Escape"?r.blur():s.key=="ArrowUp"?me(e,-1):s.key==="ArrowDown"?me(e,1):i=!1}),r.addEventListener("keypress",s=>{i&&s.preventDefault()}),document.body.addEventListener("keydown",s=>{s.altKey||s.ctrlKey||s.metaKey||!r.matches(":focus")&&s.key==="/"&&(r.focus(),s.preventDefault())})}function He(t,e){t.index||window.searchData&&(e.classList.remove("loading"),e.classList.add("ready"),t.data=window.searchData,t.index=fe.Index.load(window.searchData.index))}function ze(t,e,r,n){if(He(n,t),!n.index||!n.data)return;e.textContent="";let i=r.value.trim(),s=n.index.search(`*${i}*`);for(let o=0,a=Math.min(10,s.length);o${ve(u.parent,i)}.${l}`);let h=document.createElement("li");h.classList.value=u.classes;let p=document.createElement("a");p.href=n.base+u.url,p.classList.add("tsd-kind-icon"),p.innerHTML=l,h.append(p),e.appendChild(h)}}function me(t,e){let r=t.querySelector(".current");if(!r)r=t.querySelector(e==1?"li:first-child":"li:last-child"),r&&r.classList.add("current");else{let n=r;if(e===1)do n=n.nextElementSibling;while(n instanceof HTMLElement&&n.offsetParent==null);else do n=n.previousElementSibling;while(n instanceof HTMLElement&&n.offsetParent==null);n&&(r.classList.remove("current"),n.classList.add("current"))}}function Ne(t,e){let r=t.querySelector(".current");if(r||(r=t.querySelector("li:first-child")),r){let n=r.querySelector("a");n&&(window.location.href=n.href),e.blur()}}function ve(t,e){if(e==="")return t;let r=t.toLocaleLowerCase(),n=e.toLocaleLowerCase(),i=[],s=0,o=r.indexOf(n);for(;o!=-1;)i.push(re(t.substring(s,o)),`${re(t.substring(o,o+n.length))}`),s=o+n.length,o=r.indexOf(n,s);return i.push(re(t.substring(s))),i.join("")}var je={"&":"&","<":"<",">":">","'":"'",'"':"""};function re(t){return t.replace(/[&<>"'"]/g,e=>je[e])}var ge=class{constructor(e,r){this.signature=e,this.description=r}addClass(e){return this.signature.classList.add(e),this.description.classList.add(e),this}removeClass(e){return this.signature.classList.remove(e),this.description.classList.remove(e),this}},ne=class extends Q{constructor(e){super(e);this.groups=[];this.index=-1;this.createGroups(),this.container&&(this.el.classList.add("active"),Array.from(this.el.children).forEach(r=>{r.addEventListener("touchstart",n=>this.onClick(n)),r.addEventListener("click",n=>this.onClick(n))}),this.container.classList.add("active"),this.setIndex(0))}setIndex(e){if(e<0&&(e=0),e>this.groups.length-1&&(e=this.groups.length-1),this.index==e)return;let r=this.groups[e];if(this.index>-1){let n=this.groups[this.index];n.removeClass("current").addClass("fade-out"),r.addClass("current"),r.addClass("fade-in"),I.instance.triggerResize(),setTimeout(()=>{n.removeClass("fade-out"),r.removeClass("fade-in")},300)}else r.addClass("current"),I.instance.triggerResize();this.index=e}createGroups(){let e=this.el.children;if(e.length<2)return;this.container=this.el.nextElementSibling;let r=this.container.children;this.groups=[];for(let n=0;n{r.signature===e.currentTarget&&this.setIndex(n)})}};var C="mousedown",ye="mousemove",_="mouseup",G={x:0,y:0},xe=!1,ie=!1,Be=!1,A=!1,Le=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(Le?"is-mobile":"not-mobile");Le&&"ontouchstart"in document.documentElement&&(Be=!0,C="touchstart",ye="touchmove",_="touchend");document.addEventListener(C,t=>{ie=!0,A=!1;let e=C=="touchstart"?t.targetTouches[0]:t;G.y=e.pageY||0,G.x=e.pageX||0});document.addEventListener(ye,t=>{if(!!ie&&!A){let e=C=="touchstart"?t.targetTouches[0]:t,r=G.x-(e.pageX||0),n=G.y-(e.pageY||0);A=Math.sqrt(r*r+n*n)>10}});document.addEventListener(_,()=>{ie=!1});document.addEventListener("click",t=>{xe&&(t.preventDefault(),t.stopImmediatePropagation(),xe=!1)});var se=class extends Q{constructor(e){super(e);this.className=this.el.dataset.toggle||"",this.el.addEventListener(_,r=>this.onPointerUp(r)),this.el.addEventListener("click",r=>r.preventDefault()),document.addEventListener(C,r=>this.onDocumentPointerDown(r)),document.addEventListener(_,r=>this.onDocumentPointerUp(r))}setActive(e){if(this.active==e)return;this.active=e,document.documentElement.classList.toggle("has-"+this.className,e),this.el.classList.toggle("active",e);let r=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(r),setTimeout(()=>document.documentElement.classList.remove(r),500)}onPointerUp(e){A||(this.setActive(!0),e.preventDefault())}onDocumentPointerDown(e){if(this.active){if(e.target.closest(".col-menu, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(e){if(!A&&this.active&&e.target.closest(".col-menu")){let r=e.target.closest("a");if(r){let n=window.location.href;n.indexOf("#")!=-1&&(n=n.substr(0,n.indexOf("#"))),r.href.substr(0,n.length)==n&&setTimeout(()=>this.setActive(!1),250)}}}};var oe=class{constructor(e,r){this.key=e,this.value=r,this.defaultValue=r,this.initialize(),window.localStorage[this.key]&&this.setValue(this.fromLocalStorage(window.localStorage[this.key]))}initialize(){}setValue(e){if(this.value==e)return;let r=this.value;this.value=e,window.localStorage[this.key]=this.toLocalStorage(e),this.handleValueChange(r,e)}},ae=class extends oe{initialize(){let e=document.querySelector("#tsd-filter-"+this.key);!e||(this.checkbox=e,this.checkbox.addEventListener("change",()=>{this.setValue(this.checkbox.checked)}))}handleValueChange(e,r){!this.checkbox||(this.checkbox.checked=this.value,document.documentElement.classList.toggle("toggle-"+this.key,this.value!=this.defaultValue))}fromLocalStorage(e){return e=="true"}toLocalStorage(e){return e?"true":"false"}},Ee=class extends oe{initialize(){document.documentElement.classList.add("toggle-"+this.key+this.value);let e=document.querySelector("#tsd-filter-"+this.key);if(!e)return;this.select=e;let r=()=>{this.select.classList.add("active")},n=()=>{this.select.classList.remove("active")};this.select.addEventListener(C,r),this.select.addEventListener("mouseover",r),this.select.addEventListener("mouseleave",n),this.select.querySelectorAll("li").forEach(i=>{i.addEventListener(_,s=>{e.classList.remove("active"),this.setValue(s.target.dataset.value||"")})}),document.addEventListener(C,i=>{this.select.contains(i.target)||this.select.classList.remove("active")})}handleValueChange(e,r){this.select.querySelectorAll("li.selected").forEach(s=>{s.classList.remove("selected")});let n=this.select.querySelector('li[data-value="'+r+'"]'),i=this.select.querySelector(".tsd-select-label");n&&i&&(n.classList.add("selected"),i.textContent=n.textContent),document.documentElement.classList.remove("toggle-"+e),document.documentElement.classList.add("toggle-"+r)}fromLocalStorage(e){return e}toLocalStorage(e){return e}},Y=class extends Q{constructor(e){super(e);this.optionVisibility=new Ee("visibility","private"),this.optionInherited=new ae("inherited",!0),this.optionExternals=new ae("externals",!0)}static isSupported(){try{return typeof window.localStorage!="undefined"}catch{return!1}}};function be(t){let e=localStorage.getItem("tsd-theme")||"os";t.value=e,we(e),t.addEventListener("change",()=>{localStorage.setItem("tsd-theme",t.value),we(t.value)})}function we(t){switch(t){case"os":document.body.classList.remove("light","dark");break;case"light":document.body.classList.remove("dark"),document.body.classList.add("light");break;case"dark":document.body.classList.remove("light"),document.body.classList.add("dark");break}}pe();N(te,".menu-highlight");N(ne,".tsd-signatures");N(se,"a[data-toggle]");Y.isSupported()?N(Y,"#tsd-filter"):document.documentElement.classList.add("no-filter");var Te=document.getElementById("theme");Te&&be(Te);var qe=new X;Object.defineProperty(window,"app",{value:qe});})(); -/*! - * lunr.Builder - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.Index - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.Pipeline - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.Set - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.TokenSet - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.Vector - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.stemmer - * Copyright (C) 2020 Oliver Nightingale - * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt - */ -/*! - * lunr.stopWordFilter - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.tokenizer - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.trimmer - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.utils - * Copyright (C) 2020 Oliver Nightingale - */ -/** - * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 - * Copyright (C) 2020 Oliver Nightingale - * @license MIT - */ diff --git a/docs/assets/search.js b/docs/assets/search.js deleted file mode 100644 index 3bdf1fc8c..000000000 --- a/docs/assets/search.js +++ /dev/null @@ -1 +0,0 @@ -window.searchData = JSON.parse("{\"kinds\":{\"2\":\"Module\",\"32\":\"Variable\",\"64\":\"Function\",\"128\":\"Class\",\"256\":\"Interface\",\"512\":\"Constructor\",\"1024\":\"Property\",\"2048\":\"Method\",\"65536\":\"Type literal\",\"4194304\":\"Type alias\",\"16777216\":\"Reference\"},\"rows\":[{\"id\":0,\"kind\":2,\"name\":\"index\",\"url\":\"modules/index.html\",\"classes\":\"tsd-kind-module\"},{\"id\":1,\"kind\":64,\"name\":\"init\",\"url\":\"modules/index.html#init\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"index\"},{\"id\":2,\"kind\":64,\"name\":\"getAllCORSHeaders\",\"url\":\"modules/index.html#getAllCORSHeaders\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"index\"},{\"id\":3,\"kind\":64,\"name\":\"getUserCount\",\"url\":\"modules/index.html#getUserCount\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"index\"},{\"id\":4,\"kind\":64,\"name\":\"getUsersOldestFirst\",\"url\":\"modules/index.html#getUsersOldestFirst\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"index\"},{\"id\":5,\"kind\":64,\"name\":\"getUsersNewestFirst\",\"url\":\"modules/index.html#getUsersNewestFirst\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"index\"},{\"id\":6,\"kind\":64,\"name\":\"deleteUser\",\"url\":\"modules/index.html#deleteUser\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"index\"},{\"id\":7,\"kind\":64,\"name\":\"createUserIdMapping\",\"url\":\"modules/index.html#createUserIdMapping\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"index\"},{\"id\":8,\"kind\":64,\"name\":\"getUserIdMapping\",\"url\":\"modules/index.html#getUserIdMapping\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"index\"},{\"id\":9,\"kind\":64,\"name\":\"deleteUserIdMapping\",\"url\":\"modules/index.html#deleteUserIdMapping\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"index\"},{\"id\":10,\"kind\":64,\"name\":\"updateOrDeleteUserIdMappingInfo\",\"url\":\"modules/index.html#updateOrDeleteUserIdMappingInfo\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"index\"},{\"id\":11,\"kind\":32,\"name\":\"Error\",\"url\":\"modules/index.html#Error\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"index\"},{\"id\":12,\"kind\":128,\"name\":\"default\",\"url\":\"classes/index.default.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"index\"},{\"id\":13,\"kind\":1024,\"name\":\"init\",\"url\":\"classes/index.default.html#init\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"index.default\"},{\"id\":14,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/index.default.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"index.default\"},{\"id\":15,\"kind\":1024,\"name\":\"Error\",\"url\":\"classes/index.default.html#Error\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"index.default\"},{\"id\":16,\"kind\":2048,\"name\":\"getAllCORSHeaders\",\"url\":\"classes/index.default.html#getAllCORSHeaders\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"index.default\"},{\"id\":17,\"kind\":2048,\"name\":\"getUserCount\",\"url\":\"classes/index.default.html#getUserCount\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"index.default\"},{\"id\":18,\"kind\":2048,\"name\":\"getUsersOldestFirst\",\"url\":\"classes/index.default.html#getUsersOldestFirst\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"index.default\"},{\"id\":19,\"kind\":2048,\"name\":\"getUsersNewestFirst\",\"url\":\"classes/index.default.html#getUsersNewestFirst\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"index.default\"},{\"id\":20,\"kind\":2048,\"name\":\"deleteUser\",\"url\":\"classes/index.default.html#deleteUser\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"index.default\"},{\"id\":21,\"kind\":2048,\"name\":\"createUserIdMapping\",\"url\":\"classes/index.default.html#createUserIdMapping\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"index.default\"},{\"id\":22,\"kind\":2048,\"name\":\"getUserIdMapping\",\"url\":\"classes/index.default.html#getUserIdMapping\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"index.default\"},{\"id\":23,\"kind\":2048,\"name\":\"deleteUserIdMapping\",\"url\":\"classes/index.default.html#deleteUserIdMapping\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"index.default\"},{\"id\":24,\"kind\":2048,\"name\":\"updateOrDeleteUserIdMappingInfo\",\"url\":\"classes/index.default.html#updateOrDeleteUserIdMappingInfo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"index.default\"},{\"id\":25,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/index.default.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"index.default\"},{\"id\":26,\"kind\":2,\"name\":\"framework\",\"url\":\"modules/framework.html\",\"classes\":\"tsd-kind-module\"},{\"id\":27,\"kind\":32,\"name\":\"express\",\"url\":\"modules/framework.html#express-1\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"framework\"},{\"id\":28,\"kind\":32,\"name\":\"fastify\",\"url\":\"modules/framework.html#fastify-1\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"framework\"},{\"id\":29,\"kind\":32,\"name\":\"hapi\",\"url\":\"modules/framework.html#hapi-1\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"framework\"},{\"id\":30,\"kind\":32,\"name\":\"loopback\",\"url\":\"modules/framework.html#loopback-1\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"framework\"},{\"id\":31,\"kind\":32,\"name\":\"koa\",\"url\":\"modules/framework.html#koa-1\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"framework\"},{\"id\":32,\"kind\":32,\"name\":\"awsLambda\",\"url\":\"modules/framework.html#awsLambda-1\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"framework\"},{\"id\":33,\"kind\":1024,\"name\":\"default\",\"url\":\"modules/framework.html#default\",\"classes\":\"tsd-kind-property tsd-parent-kind-module\",\"parent\":\"framework\"},{\"id\":34,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/framework.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-module\",\"parent\":\"framework\"},{\"id\":35,\"kind\":1024,\"name\":\"express\",\"url\":\"modules/framework.html#__type.express\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"framework.__type\"},{\"id\":36,\"kind\":1024,\"name\":\"fastify\",\"url\":\"modules/framework.html#__type.fastify\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"framework.__type\"},{\"id\":37,\"kind\":1024,\"name\":\"hapi\",\"url\":\"modules/framework.html#__type.hapi\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"framework.__type\"},{\"id\":38,\"kind\":1024,\"name\":\"loopback\",\"url\":\"modules/framework.html#__type.loopback\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"framework.__type\"},{\"id\":39,\"kind\":1024,\"name\":\"koa\",\"url\":\"modules/framework.html#__type.koa\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"framework.__type\"},{\"id\":40,\"kind\":1024,\"name\":\"awsLambda\",\"url\":\"modules/framework.html#__type.awsLambda\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"framework.__type\"},{\"id\":41,\"kind\":2,\"name\":\"framework/awsLambda\",\"url\":\"modules/framework_awsLambda.html\",\"classes\":\"tsd-kind-module\"},{\"id\":42,\"kind\":64,\"name\":\"middleware\",\"url\":\"modules/framework_awsLambda.html#middleware\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/awsLambda\"},{\"id\":43,\"kind\":64,\"name\":\"wrapRequest\",\"url\":\"modules/framework_awsLambda.html#wrapRequest\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/awsLambda\"},{\"id\":44,\"kind\":64,\"name\":\"wrapResponse\",\"url\":\"modules/framework_awsLambda.html#wrapResponse\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/awsLambda\"},{\"id\":45,\"kind\":2,\"name\":\"framework/express\",\"url\":\"modules/framework_express.html\",\"classes\":\"tsd-kind-module\"},{\"id\":46,\"kind\":64,\"name\":\"middleware\",\"url\":\"modules/framework_express.html#middleware\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/express\"},{\"id\":47,\"kind\":64,\"name\":\"errorHandler\",\"url\":\"modules/framework_express.html#errorHandler\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/express\"},{\"id\":48,\"kind\":64,\"name\":\"wrapRequest\",\"url\":\"modules/framework_express.html#wrapRequest\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/express\"},{\"id\":49,\"kind\":64,\"name\":\"wrapResponse\",\"url\":\"modules/framework_express.html#wrapResponse\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/express\"},{\"id\":50,\"kind\":2,\"name\":\"framework/fastify\",\"url\":\"modules/framework_fastify.html\",\"classes\":\"tsd-kind-module\"},{\"id\":51,\"kind\":64,\"name\":\"plugin\",\"url\":\"modules/framework_fastify.html#plugin\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/fastify\"},{\"id\":52,\"kind\":64,\"name\":\"errorHandler\",\"url\":\"modules/framework_fastify.html#errorHandler\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/fastify\"},{\"id\":53,\"kind\":64,\"name\":\"wrapRequest\",\"url\":\"modules/framework_fastify.html#wrapRequest\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/fastify\"},{\"id\":54,\"kind\":64,\"name\":\"wrapResponse\",\"url\":\"modules/framework_fastify.html#wrapResponse\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/fastify\"},{\"id\":55,\"kind\":2,\"name\":\"framework/hapi\",\"url\":\"modules/framework_hapi.html\",\"classes\":\"tsd-kind-module\"},{\"id\":56,\"kind\":32,\"name\":\"plugin\",\"url\":\"modules/framework_hapi.html#plugin\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"framework/hapi\"},{\"id\":57,\"kind\":64,\"name\":\"wrapRequest\",\"url\":\"modules/framework_hapi.html#wrapRequest\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/hapi\"},{\"id\":58,\"kind\":64,\"name\":\"wrapResponse\",\"url\":\"modules/framework_hapi.html#wrapResponse\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/hapi\"},{\"id\":59,\"kind\":2,\"name\":\"framework/koa\",\"url\":\"modules/framework_koa.html\",\"classes\":\"tsd-kind-module\"},{\"id\":60,\"kind\":64,\"name\":\"middleware\",\"url\":\"modules/framework_koa.html#middleware\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/koa\"},{\"id\":61,\"kind\":64,\"name\":\"wrapRequest\",\"url\":\"modules/framework_koa.html#wrapRequest\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/koa\"},{\"id\":62,\"kind\":64,\"name\":\"wrapResponse\",\"url\":\"modules/framework_koa.html#wrapResponse\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/koa\"},{\"id\":63,\"kind\":2,\"name\":\"framework/loopback\",\"url\":\"modules/framework_loopback.html\",\"classes\":\"tsd-kind-module\"},{\"id\":64,\"kind\":64,\"name\":\"middleware\",\"url\":\"modules/framework_loopback.html#middleware\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/loopback\"},{\"id\":65,\"kind\":64,\"name\":\"wrapRequest\",\"url\":\"modules/framework_loopback.html#wrapRequest\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/loopback\"},{\"id\":66,\"kind\":64,\"name\":\"wrapResponse\",\"url\":\"modules/framework_loopback.html#wrapResponse\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"framework/loopback\"},{\"id\":67,\"kind\":2,\"name\":\"ingredients/emaildelivery\",\"url\":\"modules/ingredients_emaildelivery.html\",\"classes\":\"tsd-kind-module\"},{\"id\":68,\"kind\":128,\"name\":\"default\",\"url\":\"classes/ingredients_emaildelivery.default.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module tsd-has-type-parameter\",\"parent\":\"ingredients/emaildelivery\"},{\"id\":69,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/ingredients_emaildelivery.default.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-has-type-parameter\",\"parent\":\"ingredients/emaildelivery.default\"},{\"id\":70,\"kind\":1024,\"name\":\"ingredientInterfaceImpl\",\"url\":\"classes/ingredients_emaildelivery.default.html#ingredientInterfaceImpl\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"ingredients/emaildelivery.default\"},{\"id\":71,\"kind\":2,\"name\":\"ingredients/smsdelivery\",\"url\":\"modules/ingredients_smsdelivery.html\",\"classes\":\"tsd-kind-module\"},{\"id\":72,\"kind\":128,\"name\":\"default\",\"url\":\"classes/ingredients_smsdelivery.default.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module tsd-has-type-parameter\",\"parent\":\"ingredients/smsdelivery\"},{\"id\":73,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/ingredients_smsdelivery.default.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-has-type-parameter\",\"parent\":\"ingredients/smsdelivery.default\"},{\"id\":74,\"kind\":1024,\"name\":\"ingredientInterfaceImpl\",\"url\":\"classes/ingredients_smsdelivery.default.html#ingredientInterfaceImpl\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"ingredients/smsdelivery.default\"},{\"id\":75,\"kind\":2,\"name\":\"recipe/dashboard\",\"url\":\"modules/recipe_dashboard.html\",\"classes\":\"tsd-kind-module\"},{\"id\":76,\"kind\":64,\"name\":\"init\",\"url\":\"modules/recipe_dashboard.html#init\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/dashboard\"},{\"id\":77,\"kind\":128,\"name\":\"default\",\"url\":\"classes/recipe_dashboard.default.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"recipe/dashboard\"},{\"id\":78,\"kind\":1024,\"name\":\"init\",\"url\":\"classes/recipe_dashboard.default.html#init\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/dashboard.default\"},{\"id\":79,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_dashboard.default.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/dashboard.default\"},{\"id\":80,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/recipe_dashboard.default.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"recipe/dashboard.default\"},{\"id\":81,\"kind\":2,\"name\":\"recipe/emailpassword\",\"url\":\"modules/recipe_emailpassword.html\",\"classes\":\"tsd-kind-module\"},{\"id\":82,\"kind\":64,\"name\":\"init\",\"url\":\"modules/recipe_emailpassword.html#init\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailpassword\"},{\"id\":83,\"kind\":32,\"name\":\"Error\",\"url\":\"modules/recipe_emailpassword.html#Error\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"recipe/emailpassword\"},{\"id\":84,\"kind\":64,\"name\":\"signUp\",\"url\":\"modules/recipe_emailpassword.html#signUp-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailpassword\"},{\"id\":85,\"kind\":64,\"name\":\"signIn\",\"url\":\"modules/recipe_emailpassword.html#signIn-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailpassword\"},{\"id\":86,\"kind\":64,\"name\":\"getUserById\",\"url\":\"modules/recipe_emailpassword.html#getUserById-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailpassword\"},{\"id\":87,\"kind\":64,\"name\":\"getUserByEmail\",\"url\":\"modules/recipe_emailpassword.html#getUserByEmail-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailpassword\"},{\"id\":88,\"kind\":64,\"name\":\"createResetPasswordToken\",\"url\":\"modules/recipe_emailpassword.html#createResetPasswordToken-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailpassword\"},{\"id\":89,\"kind\":64,\"name\":\"resetPasswordUsingToken\",\"url\":\"modules/recipe_emailpassword.html#resetPasswordUsingToken-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailpassword\"},{\"id\":90,\"kind\":64,\"name\":\"updateEmailOrPassword\",\"url\":\"modules/recipe_emailpassword.html#updateEmailOrPassword-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailpassword\"},{\"id\":91,\"kind\":64,\"name\":\"sendEmail\",\"url\":\"modules/recipe_emailpassword.html#sendEmail\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailpassword\"},{\"id\":92,\"kind\":128,\"name\":\"default\",\"url\":\"classes/recipe_emailpassword.default.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"recipe/emailpassword\"},{\"id\":93,\"kind\":1024,\"name\":\"init\",\"url\":\"classes/recipe_emailpassword.default.html#init\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailpassword.default\"},{\"id\":94,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_emailpassword.default.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/emailpassword.default\"},{\"id\":95,\"kind\":1024,\"name\":\"Error\",\"url\":\"classes/recipe_emailpassword.default.html#Error\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailpassword.default\"},{\"id\":96,\"kind\":2048,\"name\":\"signUp\",\"url\":\"classes/recipe_emailpassword.default.html#signUp\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailpassword.default\"},{\"id\":97,\"kind\":2048,\"name\":\"signIn\",\"url\":\"classes/recipe_emailpassword.default.html#signIn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailpassword.default\"},{\"id\":98,\"kind\":2048,\"name\":\"getUserById\",\"url\":\"classes/recipe_emailpassword.default.html#getUserById\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailpassword.default\"},{\"id\":99,\"kind\":2048,\"name\":\"getUserByEmail\",\"url\":\"classes/recipe_emailpassword.default.html#getUserByEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailpassword.default\"},{\"id\":100,\"kind\":2048,\"name\":\"createResetPasswordToken\",\"url\":\"classes/recipe_emailpassword.default.html#createResetPasswordToken\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailpassword.default\"},{\"id\":101,\"kind\":2048,\"name\":\"resetPasswordUsingToken\",\"url\":\"classes/recipe_emailpassword.default.html#resetPasswordUsingToken\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailpassword.default\"},{\"id\":102,\"kind\":2048,\"name\":\"updateEmailOrPassword\",\"url\":\"classes/recipe_emailpassword.default.html#updateEmailOrPassword\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailpassword.default\"},{\"id\":103,\"kind\":2048,\"name\":\"sendEmail\",\"url\":\"classes/recipe_emailpassword.default.html#sendEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailpassword.default\"},{\"id\":104,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/recipe_emailpassword.default.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"recipe/emailpassword.default\"},{\"id\":105,\"kind\":2,\"name\":\"recipe/emailverification\",\"url\":\"modules/recipe_emailverification.html\",\"classes\":\"tsd-kind-module\"},{\"id\":106,\"kind\":64,\"name\":\"init\",\"url\":\"modules/recipe_emailverification.html#init\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailverification\"},{\"id\":107,\"kind\":32,\"name\":\"Error\",\"url\":\"modules/recipe_emailverification.html#Error\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"recipe/emailverification\"},{\"id\":108,\"kind\":64,\"name\":\"createEmailVerificationToken\",\"url\":\"modules/recipe_emailverification.html#createEmailVerificationToken-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailverification\"},{\"id\":109,\"kind\":64,\"name\":\"verifyEmailUsingToken\",\"url\":\"modules/recipe_emailverification.html#verifyEmailUsingToken-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailverification\"},{\"id\":110,\"kind\":64,\"name\":\"isEmailVerified\",\"url\":\"modules/recipe_emailverification.html#isEmailVerified-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailverification\"},{\"id\":111,\"kind\":64,\"name\":\"revokeEmailVerificationTokens\",\"url\":\"modules/recipe_emailverification.html#revokeEmailVerificationTokens-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailverification\"},{\"id\":112,\"kind\":64,\"name\":\"unverifyEmail\",\"url\":\"modules/recipe_emailverification.html#unverifyEmail-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailverification\"},{\"id\":113,\"kind\":64,\"name\":\"sendEmail\",\"url\":\"modules/recipe_emailverification.html#sendEmail\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/emailverification\"},{\"id\":114,\"kind\":128,\"name\":\"default\",\"url\":\"classes/recipe_emailverification.default.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"recipe/emailverification\"},{\"id\":115,\"kind\":1024,\"name\":\"init\",\"url\":\"classes/recipe_emailverification.default.html#init\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailverification.default\"},{\"id\":116,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_emailverification.default.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/emailverification.default\"},{\"id\":117,\"kind\":1024,\"name\":\"Error\",\"url\":\"classes/recipe_emailverification.default.html#Error\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailverification.default\"},{\"id\":118,\"kind\":1024,\"name\":\"EmailVerificationClaim\",\"url\":\"classes/recipe_emailverification.default.html#EmailVerificationClaim\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailverification.default\"},{\"id\":119,\"kind\":2048,\"name\":\"createEmailVerificationToken\",\"url\":\"classes/recipe_emailverification.default.html#createEmailVerificationToken\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailverification.default\"},{\"id\":120,\"kind\":2048,\"name\":\"verifyEmailUsingToken\",\"url\":\"classes/recipe_emailverification.default.html#verifyEmailUsingToken\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailverification.default\"},{\"id\":121,\"kind\":2048,\"name\":\"isEmailVerified\",\"url\":\"classes/recipe_emailverification.default.html#isEmailVerified\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailverification.default\"},{\"id\":122,\"kind\":2048,\"name\":\"revokeEmailVerificationTokens\",\"url\":\"classes/recipe_emailverification.default.html#revokeEmailVerificationTokens\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailverification.default\"},{\"id\":123,\"kind\":2048,\"name\":\"unverifyEmail\",\"url\":\"classes/recipe_emailverification.default.html#unverifyEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailverification.default\"},{\"id\":124,\"kind\":2048,\"name\":\"sendEmail\",\"url\":\"classes/recipe_emailverification.default.html#sendEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/emailverification.default\"},{\"id\":125,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/recipe_emailverification.default.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"recipe/emailverification.default\"},{\"id\":126,\"kind\":2,\"name\":\"recipe/jwt\",\"url\":\"modules/recipe_jwt.html\",\"classes\":\"tsd-kind-module\"},{\"id\":127,\"kind\":64,\"name\":\"init\",\"url\":\"modules/recipe_jwt.html#init\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/jwt\"},{\"id\":128,\"kind\":64,\"name\":\"createJWT\",\"url\":\"modules/recipe_jwt.html#createJWT-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/jwt\"},{\"id\":129,\"kind\":64,\"name\":\"getJWKS\",\"url\":\"modules/recipe_jwt.html#getJWKS-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/jwt\"},{\"id\":130,\"kind\":128,\"name\":\"default\",\"url\":\"classes/recipe_jwt.default.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"recipe/jwt\"},{\"id\":131,\"kind\":1024,\"name\":\"init\",\"url\":\"classes/recipe_jwt.default.html#init\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/jwt.default\"},{\"id\":132,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_jwt.default.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/jwt.default\"},{\"id\":133,\"kind\":2048,\"name\":\"createJWT\",\"url\":\"classes/recipe_jwt.default.html#createJWT\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/jwt.default\"},{\"id\":134,\"kind\":2048,\"name\":\"getJWKS\",\"url\":\"classes/recipe_jwt.default.html#getJWKS\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/jwt.default\"},{\"id\":135,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/recipe_jwt.default.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"recipe/jwt.default\"},{\"id\":136,\"kind\":2,\"name\":\"recipe/openid\",\"url\":\"modules/recipe_openid.html\",\"classes\":\"tsd-kind-module\"},{\"id\":137,\"kind\":64,\"name\":\"init\",\"url\":\"modules/recipe_openid.html#init\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/openid\"},{\"id\":138,\"kind\":64,\"name\":\"getOpenIdDiscoveryConfiguration\",\"url\":\"modules/recipe_openid.html#getOpenIdDiscoveryConfiguration\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/openid\"},{\"id\":139,\"kind\":64,\"name\":\"createJWT\",\"url\":\"modules/recipe_openid.html#createJWT\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/openid\"},{\"id\":140,\"kind\":64,\"name\":\"getJWKS\",\"url\":\"modules/recipe_openid.html#getJWKS\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/openid\"},{\"id\":141,\"kind\":128,\"name\":\"default\",\"url\":\"classes/recipe_openid.default.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"recipe/openid\"},{\"id\":142,\"kind\":1024,\"name\":\"init\",\"url\":\"classes/recipe_openid.default.html#init\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/openid.default\"},{\"id\":143,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_openid.default.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/openid.default\"},{\"id\":144,\"kind\":2048,\"name\":\"getOpenIdDiscoveryConfiguration\",\"url\":\"classes/recipe_openid.default.html#getOpenIdDiscoveryConfiguration\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/openid.default\"},{\"id\":145,\"kind\":2048,\"name\":\"createJWT\",\"url\":\"classes/recipe_openid.default.html#createJWT\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/openid.default\"},{\"id\":146,\"kind\":2048,\"name\":\"getJWKS\",\"url\":\"classes/recipe_openid.default.html#getJWKS\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/openid.default\"},{\"id\":147,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/recipe_openid.default.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"recipe/openid.default\"},{\"id\":148,\"kind\":2,\"name\":\"recipe/passwordless\",\"url\":\"modules/recipe_passwordless.html\",\"classes\":\"tsd-kind-module\"},{\"id\":149,\"kind\":64,\"name\":\"init\",\"url\":\"modules/recipe_passwordless.html#init\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":150,\"kind\":32,\"name\":\"Error\",\"url\":\"modules/recipe_passwordless.html#Error\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":151,\"kind\":64,\"name\":\"createCode\",\"url\":\"modules/recipe_passwordless.html#createCode-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":152,\"kind\":64,\"name\":\"consumeCode\",\"url\":\"modules/recipe_passwordless.html#consumeCode-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":153,\"kind\":64,\"name\":\"getUserByEmail\",\"url\":\"modules/recipe_passwordless.html#getUserByEmail-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":154,\"kind\":64,\"name\":\"getUserById\",\"url\":\"modules/recipe_passwordless.html#getUserById-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":155,\"kind\":64,\"name\":\"getUserByPhoneNumber\",\"url\":\"modules/recipe_passwordless.html#getUserByPhoneNumber-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":156,\"kind\":64,\"name\":\"listCodesByDeviceId\",\"url\":\"modules/recipe_passwordless.html#listCodesByDeviceId-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":157,\"kind\":64,\"name\":\"listCodesByEmail\",\"url\":\"modules/recipe_passwordless.html#listCodesByEmail-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":158,\"kind\":64,\"name\":\"listCodesByPhoneNumber\",\"url\":\"modules/recipe_passwordless.html#listCodesByPhoneNumber-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":159,\"kind\":64,\"name\":\"listCodesByPreAuthSessionId\",\"url\":\"modules/recipe_passwordless.html#listCodesByPreAuthSessionId-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":160,\"kind\":64,\"name\":\"createNewCodeForDevice\",\"url\":\"modules/recipe_passwordless.html#createNewCodeForDevice-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":161,\"kind\":64,\"name\":\"updateUser\",\"url\":\"modules/recipe_passwordless.html#updateUser-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":162,\"kind\":64,\"name\":\"revokeAllCodes\",\"url\":\"modules/recipe_passwordless.html#revokeAllCodes-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":163,\"kind\":64,\"name\":\"revokeCode\",\"url\":\"modules/recipe_passwordless.html#revokeCode-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":164,\"kind\":64,\"name\":\"createMagicLink\",\"url\":\"modules/recipe_passwordless.html#createMagicLink\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":165,\"kind\":64,\"name\":\"signInUp\",\"url\":\"modules/recipe_passwordless.html#signInUp\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":166,\"kind\":64,\"name\":\"sendEmail\",\"url\":\"modules/recipe_passwordless.html#sendEmail\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":167,\"kind\":64,\"name\":\"sendSms\",\"url\":\"modules/recipe_passwordless.html#sendSms\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":168,\"kind\":128,\"name\":\"default\",\"url\":\"classes/recipe_passwordless.default.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":169,\"kind\":1024,\"name\":\"init\",\"url\":\"classes/recipe_passwordless.default.html#init\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":170,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_passwordless.default.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/passwordless.default\"},{\"id\":171,\"kind\":1024,\"name\":\"Error\",\"url\":\"classes/recipe_passwordless.default.html#Error\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":172,\"kind\":2048,\"name\":\"createCode\",\"url\":\"classes/recipe_passwordless.default.html#createCode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":173,\"kind\":2048,\"name\":\"createNewCodeForDevice\",\"url\":\"classes/recipe_passwordless.default.html#createNewCodeForDevice\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":174,\"kind\":2048,\"name\":\"consumeCode\",\"url\":\"classes/recipe_passwordless.default.html#consumeCode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":175,\"kind\":2048,\"name\":\"getUserById\",\"url\":\"classes/recipe_passwordless.default.html#getUserById\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":176,\"kind\":2048,\"name\":\"getUserByEmail\",\"url\":\"classes/recipe_passwordless.default.html#getUserByEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":177,\"kind\":2048,\"name\":\"getUserByPhoneNumber\",\"url\":\"classes/recipe_passwordless.default.html#getUserByPhoneNumber\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":178,\"kind\":2048,\"name\":\"updateUser\",\"url\":\"classes/recipe_passwordless.default.html#updateUser\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":179,\"kind\":2048,\"name\":\"revokeAllCodes\",\"url\":\"classes/recipe_passwordless.default.html#revokeAllCodes\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":180,\"kind\":2048,\"name\":\"revokeCode\",\"url\":\"classes/recipe_passwordless.default.html#revokeCode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":181,\"kind\":2048,\"name\":\"listCodesByEmail\",\"url\":\"classes/recipe_passwordless.default.html#listCodesByEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":182,\"kind\":2048,\"name\":\"listCodesByPhoneNumber\",\"url\":\"classes/recipe_passwordless.default.html#listCodesByPhoneNumber\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":183,\"kind\":2048,\"name\":\"listCodesByDeviceId\",\"url\":\"classes/recipe_passwordless.default.html#listCodesByDeviceId\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":184,\"kind\":2048,\"name\":\"listCodesByPreAuthSessionId\",\"url\":\"classes/recipe_passwordless.default.html#listCodesByPreAuthSessionId\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":185,\"kind\":2048,\"name\":\"createMagicLink\",\"url\":\"classes/recipe_passwordless.default.html#createMagicLink\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":186,\"kind\":2048,\"name\":\"signInUp\",\"url\":\"classes/recipe_passwordless.default.html#signInUp\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":187,\"kind\":2048,\"name\":\"sendEmail\",\"url\":\"classes/recipe_passwordless.default.html#sendEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":188,\"kind\":2048,\"name\":\"sendSms\",\"url\":\"classes/recipe_passwordless.default.html#sendSms\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/passwordless.default\"},{\"id\":189,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/recipe_passwordless.default.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"recipe/passwordless.default\"},{\"id\":190,\"kind\":2,\"name\":\"recipe/session\",\"url\":\"modules/recipe_session.html\",\"classes\":\"tsd-kind-module\"},{\"id\":191,\"kind\":64,\"name\":\"init\",\"url\":\"modules/recipe_session.html#init\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":192,\"kind\":64,\"name\":\"createNewSession\",\"url\":\"modules/recipe_session.html#createNewSession-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":193,\"kind\":64,\"name\":\"getSession\",\"url\":\"modules/recipe_session.html#getSession-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":194,\"kind\":64,\"name\":\"getSessionInformation\",\"url\":\"modules/recipe_session.html#getSessionInformation-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":195,\"kind\":64,\"name\":\"refreshSession\",\"url\":\"modules/recipe_session.html#refreshSession-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":196,\"kind\":64,\"name\":\"revokeAllSessionsForUser\",\"url\":\"modules/recipe_session.html#revokeAllSessionsForUser-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":197,\"kind\":64,\"name\":\"getAllSessionHandlesForUser\",\"url\":\"modules/recipe_session.html#getAllSessionHandlesForUser-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":198,\"kind\":64,\"name\":\"revokeSession\",\"url\":\"modules/recipe_session.html#revokeSession-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":199,\"kind\":64,\"name\":\"revokeMultipleSessions\",\"url\":\"modules/recipe_session.html#revokeMultipleSessions-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":200,\"kind\":64,\"name\":\"updateSessionData\",\"url\":\"modules/recipe_session.html#updateSessionData-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":201,\"kind\":64,\"name\":\"updateAccessTokenPayload\",\"url\":\"modules/recipe_session.html#updateAccessTokenPayload-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":202,\"kind\":64,\"name\":\"mergeIntoAccessTokenPayload\",\"url\":\"modules/recipe_session.html#mergeIntoAccessTokenPayload-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":203,\"kind\":64,\"name\":\"fetchAndSetClaim\",\"url\":\"modules/recipe_session.html#fetchAndSetClaim-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":204,\"kind\":64,\"name\":\"setClaimValue\",\"url\":\"modules/recipe_session.html#setClaimValue-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module tsd-has-type-parameter\",\"parent\":\"recipe/session\"},{\"id\":205,\"kind\":64,\"name\":\"getClaimValue\",\"url\":\"modules/recipe_session.html#getClaimValue-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module tsd-has-type-parameter\",\"parent\":\"recipe/session\"},{\"id\":206,\"kind\":64,\"name\":\"removeClaim\",\"url\":\"modules/recipe_session.html#removeClaim-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":207,\"kind\":64,\"name\":\"validateClaimsInJWTPayload\",\"url\":\"modules/recipe_session.html#validateClaimsInJWTPayload-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":208,\"kind\":64,\"name\":\"validateClaimsForSessionHandle\",\"url\":\"modules/recipe_session.html#validateClaimsForSessionHandle\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":209,\"kind\":32,\"name\":\"Error\",\"url\":\"modules/recipe_session.html#Error\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":210,\"kind\":64,\"name\":\"createJWT\",\"url\":\"modules/recipe_session.html#createJWT\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":211,\"kind\":64,\"name\":\"getJWKS\",\"url\":\"modules/recipe_session.html#getJWKS\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":212,\"kind\":64,\"name\":\"getOpenIdDiscoveryConfiguration\",\"url\":\"modules/recipe_session.html#getOpenIdDiscoveryConfiguration\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":213,\"kind\":128,\"name\":\"default\",\"url\":\"classes/recipe_session.default.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":214,\"kind\":1024,\"name\":\"init\",\"url\":\"classes/recipe_session.default.html#init\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":215,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_session.default.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/session.default\"},{\"id\":216,\"kind\":1024,\"name\":\"Error\",\"url\":\"classes/recipe_session.default.html#Error\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":217,\"kind\":2048,\"name\":\"createNewSession\",\"url\":\"classes/recipe_session.default.html#createNewSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":218,\"kind\":2048,\"name\":\"validateClaimsForSessionHandle\",\"url\":\"classes/recipe_session.default.html#validateClaimsForSessionHandle\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":219,\"kind\":2048,\"name\":\"validateClaimsInJWTPayload\",\"url\":\"classes/recipe_session.default.html#validateClaimsInJWTPayload\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":220,\"kind\":2048,\"name\":\"getSession\",\"url\":\"classes/recipe_session.default.html#getSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":221,\"kind\":2048,\"name\":\"getSessionInformation\",\"url\":\"classes/recipe_session.default.html#getSessionInformation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":222,\"kind\":2048,\"name\":\"refreshSession\",\"url\":\"classes/recipe_session.default.html#refreshSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":223,\"kind\":2048,\"name\":\"revokeAllSessionsForUser\",\"url\":\"classes/recipe_session.default.html#revokeAllSessionsForUser\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":224,\"kind\":2048,\"name\":\"getAllSessionHandlesForUser\",\"url\":\"classes/recipe_session.default.html#getAllSessionHandlesForUser\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":225,\"kind\":2048,\"name\":\"revokeSession\",\"url\":\"classes/recipe_session.default.html#revokeSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":226,\"kind\":2048,\"name\":\"revokeMultipleSessions\",\"url\":\"classes/recipe_session.default.html#revokeMultipleSessions\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":227,\"kind\":2048,\"name\":\"updateSessionData\",\"url\":\"classes/recipe_session.default.html#updateSessionData\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":228,\"kind\":2048,\"name\":\"regenerateAccessToken\",\"url\":\"classes/recipe_session.default.html#regenerateAccessToken\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":229,\"kind\":2048,\"name\":\"updateAccessTokenPayload\",\"url\":\"classes/recipe_session.default.html#updateAccessTokenPayload\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":230,\"kind\":2048,\"name\":\"mergeIntoAccessTokenPayload\",\"url\":\"classes/recipe_session.default.html#mergeIntoAccessTokenPayload\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":231,\"kind\":2048,\"name\":\"createJWT\",\"url\":\"classes/recipe_session.default.html#createJWT\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":232,\"kind\":2048,\"name\":\"getJWKS\",\"url\":\"classes/recipe_session.default.html#getJWKS\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":233,\"kind\":2048,\"name\":\"getOpenIdDiscoveryConfiguration\",\"url\":\"classes/recipe_session.default.html#getOpenIdDiscoveryConfiguration\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":234,\"kind\":2048,\"name\":\"fetchAndSetClaim\",\"url\":\"classes/recipe_session.default.html#fetchAndSetClaim\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":235,\"kind\":2048,\"name\":\"setClaimValue\",\"url\":\"classes/recipe_session.default.html#setClaimValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-has-type-parameter tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":236,\"kind\":2048,\"name\":\"getClaimValue\",\"url\":\"classes/recipe_session.default.html#getClaimValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-has-type-parameter tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":237,\"kind\":2048,\"name\":\"removeClaim\",\"url\":\"classes/recipe_session.default.html#removeClaim\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/session.default\"},{\"id\":238,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/recipe_session.default.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"recipe/session.default\"},{\"id\":239,\"kind\":2,\"name\":\"recipe/thirdparty\",\"url\":\"modules/recipe_thirdparty.html\",\"classes\":\"tsd-kind-module\"},{\"id\":240,\"kind\":64,\"name\":\"init\",\"url\":\"modules/recipe_thirdparty.html#init\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":241,\"kind\":32,\"name\":\"Error\",\"url\":\"modules/recipe_thirdparty.html#Error\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":242,\"kind\":64,\"name\":\"signInUp\",\"url\":\"modules/recipe_thirdparty.html#signInUp-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":243,\"kind\":64,\"name\":\"getUserById\",\"url\":\"modules/recipe_thirdparty.html#getUserById-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":244,\"kind\":64,\"name\":\"getUsersByEmail\",\"url\":\"modules/recipe_thirdparty.html#getUsersByEmail-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":245,\"kind\":64,\"name\":\"getUserByThirdPartyInfo\",\"url\":\"modules/recipe_thirdparty.html#getUserByThirdPartyInfo-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":246,\"kind\":64,\"name\":\"Google\",\"url\":\"modules/recipe_thirdparty.html#Google\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":247,\"kind\":64,\"name\":\"Github\",\"url\":\"modules/recipe_thirdparty.html#Github\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":248,\"kind\":64,\"name\":\"Facebook\",\"url\":\"modules/recipe_thirdparty.html#Facebook\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":249,\"kind\":64,\"name\":\"Apple\",\"url\":\"modules/recipe_thirdparty.html#Apple\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":250,\"kind\":64,\"name\":\"Discord\",\"url\":\"modules/recipe_thirdparty.html#Discord\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":251,\"kind\":64,\"name\":\"GoogleWorkspaces\",\"url\":\"modules/recipe_thirdparty.html#GoogleWorkspaces\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":252,\"kind\":128,\"name\":\"default\",\"url\":\"classes/recipe_thirdparty.default.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":253,\"kind\":1024,\"name\":\"init\",\"url\":\"classes/recipe_thirdparty.default.html#init\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":254,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdparty.default.html#__type-6\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":255,\"kind\":1024,\"name\":\"Error\",\"url\":\"classes/recipe_thirdparty.default.html#Error\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":256,\"kind\":2048,\"name\":\"signInUp\",\"url\":\"classes/recipe_thirdparty.default.html#signInUp\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":257,\"kind\":2048,\"name\":\"getUserById\",\"url\":\"classes/recipe_thirdparty.default.html#getUserById\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":258,\"kind\":2048,\"name\":\"getUsersByEmail\",\"url\":\"classes/recipe_thirdparty.default.html#getUsersByEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":259,\"kind\":2048,\"name\":\"getUserByThirdPartyInfo\",\"url\":\"classes/recipe_thirdparty.default.html#getUserByThirdPartyInfo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":260,\"kind\":1024,\"name\":\"Google\",\"url\":\"classes/recipe_thirdparty.default.html#Google\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":261,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdparty.default.html#__type-4\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":262,\"kind\":1024,\"name\":\"Github\",\"url\":\"classes/recipe_thirdparty.default.html#Github\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":263,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdparty.default.html#__type-3\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":264,\"kind\":1024,\"name\":\"Facebook\",\"url\":\"classes/recipe_thirdparty.default.html#Facebook\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":265,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdparty.default.html#__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":266,\"kind\":1024,\"name\":\"Apple\",\"url\":\"classes/recipe_thirdparty.default.html#Apple\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":267,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdparty.default.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":268,\"kind\":1024,\"name\":\"Discord\",\"url\":\"classes/recipe_thirdparty.default.html#Discord\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":269,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdparty.default.html#__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":270,\"kind\":1024,\"name\":\"GoogleWorkspaces\",\"url\":\"classes/recipe_thirdparty.default.html#GoogleWorkspaces\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":271,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdparty.default.html#__type-5\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":272,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/recipe_thirdparty.default.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"recipe/thirdparty.default\"},{\"id\":273,\"kind\":2,\"name\":\"recipe/thirdpartyemailpassword\",\"url\":\"modules/recipe_thirdpartyemailpassword.html\",\"classes\":\"tsd-kind-module\"},{\"id\":274,\"kind\":64,\"name\":\"init\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#init\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":275,\"kind\":32,\"name\":\"Error\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#Error\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":276,\"kind\":64,\"name\":\"emailPasswordSignUp\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#emailPasswordSignUp-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":277,\"kind\":64,\"name\":\"emailPasswordSignIn\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#emailPasswordSignIn-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":278,\"kind\":64,\"name\":\"thirdPartySignInUp\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#thirdPartySignInUp-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":279,\"kind\":64,\"name\":\"getUserById\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#getUserById-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":280,\"kind\":64,\"name\":\"getUserByThirdPartyInfo\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#getUserByThirdPartyInfo-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":281,\"kind\":64,\"name\":\"getUsersByEmail\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#getUsersByEmail-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":282,\"kind\":64,\"name\":\"createResetPasswordToken\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#createResetPasswordToken-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":283,\"kind\":64,\"name\":\"resetPasswordUsingToken\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#resetPasswordUsingToken-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":284,\"kind\":64,\"name\":\"updateEmailOrPassword\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#updateEmailOrPassword-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":285,\"kind\":64,\"name\":\"Google\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#Google\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":286,\"kind\":64,\"name\":\"Github\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#Github\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":287,\"kind\":64,\"name\":\"Facebook\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#Facebook\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":288,\"kind\":64,\"name\":\"Apple\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#Apple\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":289,\"kind\":64,\"name\":\"Discord\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#Discord\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":290,\"kind\":64,\"name\":\"GoogleWorkspaces\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#GoogleWorkspaces\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":291,\"kind\":64,\"name\":\"sendEmail\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#sendEmail\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":292,\"kind\":128,\"name\":\"default\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":293,\"kind\":1024,\"name\":\"init\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#init\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":294,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#__type-6\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":295,\"kind\":1024,\"name\":\"Error\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#Error\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":296,\"kind\":2048,\"name\":\"thirdPartySignInUp\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#thirdPartySignInUp\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":297,\"kind\":2048,\"name\":\"getUserByThirdPartyInfo\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#getUserByThirdPartyInfo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":298,\"kind\":2048,\"name\":\"emailPasswordSignUp\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#emailPasswordSignUp\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":299,\"kind\":2048,\"name\":\"emailPasswordSignIn\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#emailPasswordSignIn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":300,\"kind\":2048,\"name\":\"getUserById\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#getUserById\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":301,\"kind\":2048,\"name\":\"getUsersByEmail\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#getUsersByEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":302,\"kind\":2048,\"name\":\"createResetPasswordToken\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#createResetPasswordToken\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":303,\"kind\":2048,\"name\":\"resetPasswordUsingToken\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#resetPasswordUsingToken\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":304,\"kind\":2048,\"name\":\"updateEmailOrPassword\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#updateEmailOrPassword\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":305,\"kind\":1024,\"name\":\"Google\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#Google\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":306,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#__type-4\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":307,\"kind\":1024,\"name\":\"Github\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#Github\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":308,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#__type-3\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":309,\"kind\":1024,\"name\":\"Facebook\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#Facebook\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":310,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":311,\"kind\":1024,\"name\":\"Apple\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#Apple\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":312,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":313,\"kind\":1024,\"name\":\"Discord\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#Discord\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":314,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":315,\"kind\":1024,\"name\":\"GoogleWorkspaces\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#GoogleWorkspaces\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":316,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#__type-5\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":317,\"kind\":2048,\"name\":\"sendEmail\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#sendEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":318,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/recipe_thirdpartyemailpassword.default.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartyemailpassword.default\"},{\"id\":319,\"kind\":2,\"name\":\"recipe/thirdpartypasswordless\",\"url\":\"modules/recipe_thirdpartypasswordless.html\",\"classes\":\"tsd-kind-module\"},{\"id\":320,\"kind\":64,\"name\":\"init\",\"url\":\"modules/recipe_thirdpartypasswordless.html#init\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":321,\"kind\":32,\"name\":\"Error\",\"url\":\"modules/recipe_thirdpartypasswordless.html#Error\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":322,\"kind\":64,\"name\":\"thirdPartySignInUp\",\"url\":\"modules/recipe_thirdpartypasswordless.html#thirdPartySignInUp-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":323,\"kind\":64,\"name\":\"passwordlessSignInUp\",\"url\":\"modules/recipe_thirdpartypasswordless.html#passwordlessSignInUp\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":324,\"kind\":64,\"name\":\"getUserById\",\"url\":\"modules/recipe_thirdpartypasswordless.html#getUserById-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":325,\"kind\":64,\"name\":\"getUserByThirdPartyInfo\",\"url\":\"modules/recipe_thirdpartypasswordless.html#getUserByThirdPartyInfo-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":326,\"kind\":64,\"name\":\"getUsersByEmail\",\"url\":\"modules/recipe_thirdpartypasswordless.html#getUsersByEmail-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":327,\"kind\":64,\"name\":\"createCode\",\"url\":\"modules/recipe_thirdpartypasswordless.html#createCode-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":328,\"kind\":64,\"name\":\"consumeCode\",\"url\":\"modules/recipe_thirdpartypasswordless.html#consumeCode-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":329,\"kind\":64,\"name\":\"getUserByPhoneNumber\",\"url\":\"modules/recipe_thirdpartypasswordless.html#getUserByPhoneNumber-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":330,\"kind\":64,\"name\":\"listCodesByDeviceId\",\"url\":\"modules/recipe_thirdpartypasswordless.html#listCodesByDeviceId-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":331,\"kind\":64,\"name\":\"listCodesByEmail\",\"url\":\"modules/recipe_thirdpartypasswordless.html#listCodesByEmail-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":332,\"kind\":64,\"name\":\"listCodesByPhoneNumber\",\"url\":\"modules/recipe_thirdpartypasswordless.html#listCodesByPhoneNumber-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":333,\"kind\":64,\"name\":\"listCodesByPreAuthSessionId\",\"url\":\"modules/recipe_thirdpartypasswordless.html#listCodesByPreAuthSessionId-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":334,\"kind\":64,\"name\":\"createNewCodeForDevice\",\"url\":\"modules/recipe_thirdpartypasswordless.html#createNewCodeForDevice-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":335,\"kind\":64,\"name\":\"updatePasswordlessUser\",\"url\":\"modules/recipe_thirdpartypasswordless.html#updatePasswordlessUser-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":336,\"kind\":64,\"name\":\"revokeAllCodes\",\"url\":\"modules/recipe_thirdpartypasswordless.html#revokeAllCodes-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":337,\"kind\":64,\"name\":\"revokeCode\",\"url\":\"modules/recipe_thirdpartypasswordless.html#revokeCode-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":338,\"kind\":64,\"name\":\"createMagicLink\",\"url\":\"modules/recipe_thirdpartypasswordless.html#createMagicLink\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":339,\"kind\":64,\"name\":\"Google\",\"url\":\"modules/recipe_thirdpartypasswordless.html#Google\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":340,\"kind\":64,\"name\":\"Github\",\"url\":\"modules/recipe_thirdpartypasswordless.html#Github\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":341,\"kind\":64,\"name\":\"Facebook\",\"url\":\"modules/recipe_thirdpartypasswordless.html#Facebook\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":342,\"kind\":64,\"name\":\"Apple\",\"url\":\"modules/recipe_thirdpartypasswordless.html#Apple\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":343,\"kind\":64,\"name\":\"Discord\",\"url\":\"modules/recipe_thirdpartypasswordless.html#Discord\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":344,\"kind\":64,\"name\":\"GoogleWorkspaces\",\"url\":\"modules/recipe_thirdpartypasswordless.html#GoogleWorkspaces\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":345,\"kind\":64,\"name\":\"sendEmail\",\"url\":\"modules/recipe_thirdpartypasswordless.html#sendEmail\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":346,\"kind\":64,\"name\":\"sendSms\",\"url\":\"modules/recipe_thirdpartypasswordless.html#sendSms\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":347,\"kind\":128,\"name\":\"default\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":348,\"kind\":1024,\"name\":\"init\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#init\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":349,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#__type-6\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":350,\"kind\":1024,\"name\":\"Error\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#Error\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":351,\"kind\":2048,\"name\":\"thirdPartySignInUp\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#thirdPartySignInUp\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":352,\"kind\":2048,\"name\":\"getUserByThirdPartyInfo\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#getUserByThirdPartyInfo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":353,\"kind\":2048,\"name\":\"getUserById\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#getUserById\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":354,\"kind\":2048,\"name\":\"getUsersByEmail\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#getUsersByEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":355,\"kind\":2048,\"name\":\"createCode\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#createCode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":356,\"kind\":2048,\"name\":\"createNewCodeForDevice\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#createNewCodeForDevice\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":357,\"kind\":2048,\"name\":\"consumeCode\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#consumeCode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":358,\"kind\":2048,\"name\":\"getUserByPhoneNumber\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#getUserByPhoneNumber\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":359,\"kind\":2048,\"name\":\"updatePasswordlessUser\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#updatePasswordlessUser\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":360,\"kind\":2048,\"name\":\"revokeAllCodes\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#revokeAllCodes\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":361,\"kind\":2048,\"name\":\"revokeCode\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#revokeCode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":362,\"kind\":2048,\"name\":\"listCodesByEmail\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#listCodesByEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":363,\"kind\":2048,\"name\":\"listCodesByPhoneNumber\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#listCodesByPhoneNumber\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":364,\"kind\":2048,\"name\":\"listCodesByDeviceId\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#listCodesByDeviceId\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":365,\"kind\":2048,\"name\":\"listCodesByPreAuthSessionId\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#listCodesByPreAuthSessionId\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":366,\"kind\":2048,\"name\":\"createMagicLink\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#createMagicLink\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":367,\"kind\":2048,\"name\":\"passwordlessSignInUp\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#passwordlessSignInUp\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":368,\"kind\":1024,\"name\":\"Google\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#Google\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":369,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#__type-4\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":370,\"kind\":1024,\"name\":\"Github\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#Github\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":371,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#__type-3\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":372,\"kind\":1024,\"name\":\"Facebook\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#Facebook\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":373,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":374,\"kind\":1024,\"name\":\"Apple\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#Apple\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":375,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":376,\"kind\":1024,\"name\":\"Discord\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#Discord\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":377,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":378,\"kind\":1024,\"name\":\"GoogleWorkspaces\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#GoogleWorkspaces\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":379,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#__type-5\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":380,\"kind\":2048,\"name\":\"sendEmail\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#sendEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":381,\"kind\":2048,\"name\":\"sendSms\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#sendSms\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":382,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/recipe_thirdpartypasswordless.default.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"recipe/thirdpartypasswordless.default\"},{\"id\":383,\"kind\":2,\"name\":\"recipe/usermetadata\",\"url\":\"modules/recipe_usermetadata.html\",\"classes\":\"tsd-kind-module\"},{\"id\":384,\"kind\":64,\"name\":\"init\",\"url\":\"modules/recipe_usermetadata.html#init\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/usermetadata\"},{\"id\":385,\"kind\":64,\"name\":\"getUserMetadata\",\"url\":\"modules/recipe_usermetadata.html#getUserMetadata-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/usermetadata\"},{\"id\":386,\"kind\":64,\"name\":\"updateUserMetadata\",\"url\":\"modules/recipe_usermetadata.html#updateUserMetadata-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/usermetadata\"},{\"id\":387,\"kind\":64,\"name\":\"clearUserMetadata\",\"url\":\"modules/recipe_usermetadata.html#clearUserMetadata-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/usermetadata\"},{\"id\":388,\"kind\":128,\"name\":\"default\",\"url\":\"classes/recipe_usermetadata.default.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"recipe/usermetadata\"},{\"id\":389,\"kind\":1024,\"name\":\"init\",\"url\":\"classes/recipe_usermetadata.default.html#init\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/usermetadata.default\"},{\"id\":390,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_usermetadata.default.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/usermetadata.default\"},{\"id\":391,\"kind\":2048,\"name\":\"getUserMetadata\",\"url\":\"classes/recipe_usermetadata.default.html#getUserMetadata\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/usermetadata.default\"},{\"id\":392,\"kind\":2048,\"name\":\"updateUserMetadata\",\"url\":\"classes/recipe_usermetadata.default.html#updateUserMetadata\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/usermetadata.default\"},{\"id\":393,\"kind\":2048,\"name\":\"clearUserMetadata\",\"url\":\"classes/recipe_usermetadata.default.html#clearUserMetadata\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/usermetadata.default\"},{\"id\":394,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/recipe_usermetadata.default.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"recipe/usermetadata.default\"},{\"id\":395,\"kind\":2,\"name\":\"recipe/userroles\",\"url\":\"modules/recipe_userroles.html\",\"classes\":\"tsd-kind-module\"},{\"id\":396,\"kind\":64,\"name\":\"init\",\"url\":\"modules/recipe_userroles.html#init\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/userroles\"},{\"id\":397,\"kind\":64,\"name\":\"addRoleToUser\",\"url\":\"modules/recipe_userroles.html#addRoleToUser-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/userroles\"},{\"id\":398,\"kind\":64,\"name\":\"removeUserRole\",\"url\":\"modules/recipe_userroles.html#removeUserRole-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/userroles\"},{\"id\":399,\"kind\":64,\"name\":\"getRolesForUser\",\"url\":\"modules/recipe_userroles.html#getRolesForUser-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/userroles\"},{\"id\":400,\"kind\":64,\"name\":\"getUsersThatHaveRole\",\"url\":\"modules/recipe_userroles.html#getUsersThatHaveRole-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/userroles\"},{\"id\":401,\"kind\":64,\"name\":\"createNewRoleOrAddPermissions\",\"url\":\"modules/recipe_userroles.html#createNewRoleOrAddPermissions-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/userroles\"},{\"id\":402,\"kind\":64,\"name\":\"getPermissionsForRole\",\"url\":\"modules/recipe_userroles.html#getPermissionsForRole-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/userroles\"},{\"id\":403,\"kind\":64,\"name\":\"removePermissionsFromRole\",\"url\":\"modules/recipe_userroles.html#removePermissionsFromRole-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/userroles\"},{\"id\":404,\"kind\":64,\"name\":\"getRolesThatHavePermission\",\"url\":\"modules/recipe_userroles.html#getRolesThatHavePermission-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/userroles\"},{\"id\":405,\"kind\":64,\"name\":\"deleteRole\",\"url\":\"modules/recipe_userroles.html#deleteRole-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/userroles\"},{\"id\":406,\"kind\":64,\"name\":\"getAllRoles\",\"url\":\"modules/recipe_userroles.html#getAllRoles-1\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"recipe/userroles\"},{\"id\":407,\"kind\":128,\"name\":\"default\",\"url\":\"classes/recipe_userroles.default.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"recipe/userroles\"},{\"id\":408,\"kind\":1024,\"name\":\"init\",\"url\":\"classes/recipe_userroles.default.html#init\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/userroles.default\"},{\"id\":409,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/recipe_userroles.default.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"recipe/userroles.default\"},{\"id\":410,\"kind\":1024,\"name\":\"PermissionClaim\",\"url\":\"classes/recipe_userroles.default.html#PermissionClaim\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/userroles.default\"},{\"id\":411,\"kind\":1024,\"name\":\"UserRoleClaim\",\"url\":\"classes/recipe_userroles.default.html#UserRoleClaim\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/userroles.default\"},{\"id\":412,\"kind\":2048,\"name\":\"addRoleToUser\",\"url\":\"classes/recipe_userroles.default.html#addRoleToUser\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/userroles.default\"},{\"id\":413,\"kind\":2048,\"name\":\"removeUserRole\",\"url\":\"classes/recipe_userroles.default.html#removeUserRole\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/userroles.default\"},{\"id\":414,\"kind\":2048,\"name\":\"getRolesForUser\",\"url\":\"classes/recipe_userroles.default.html#getRolesForUser\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/userroles.default\"},{\"id\":415,\"kind\":2048,\"name\":\"getUsersThatHaveRole\",\"url\":\"classes/recipe_userroles.default.html#getUsersThatHaveRole\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/userroles.default\"},{\"id\":416,\"kind\":2048,\"name\":\"createNewRoleOrAddPermissions\",\"url\":\"classes/recipe_userroles.default.html#createNewRoleOrAddPermissions\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/userroles.default\"},{\"id\":417,\"kind\":2048,\"name\":\"getPermissionsForRole\",\"url\":\"classes/recipe_userroles.default.html#getPermissionsForRole\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/userroles.default\"},{\"id\":418,\"kind\":2048,\"name\":\"removePermissionsFromRole\",\"url\":\"classes/recipe_userroles.default.html#removePermissionsFromRole\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/userroles.default\"},{\"id\":419,\"kind\":2048,\"name\":\"getRolesThatHavePermission\",\"url\":\"classes/recipe_userroles.default.html#getRolesThatHavePermission\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/userroles.default\"},{\"id\":420,\"kind\":2048,\"name\":\"deleteRole\",\"url\":\"classes/recipe_userroles.default.html#deleteRole\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/userroles.default\"},{\"id\":421,\"kind\":2048,\"name\":\"getAllRoles\",\"url\":\"classes/recipe_userroles.default.html#getAllRoles\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"recipe/userroles.default\"},{\"id\":422,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/recipe_userroles.default.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"recipe/userroles.default\"},{\"id\":423,\"kind\":128,\"name\":\"BaseRequest\",\"url\":\"classes/framework.BaseRequest.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"framework\"},{\"id\":424,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/framework.BaseRequest.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":425,\"kind\":1024,\"name\":\"wrapperUsed\",\"url\":\"classes/framework.BaseRequest.html#wrapperUsed\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":426,\"kind\":1024,\"name\":\"original\",\"url\":\"classes/framework.BaseRequest.html#original\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":427,\"kind\":1024,\"name\":\"getKeyValueFromQuery\",\"url\":\"classes/framework.BaseRequest.html#getKeyValueFromQuery\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":428,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/framework.BaseRequest.html#__type-4\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":429,\"kind\":1024,\"name\":\"getJSONBody\",\"url\":\"classes/framework.BaseRequest.html#getJSONBody\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":430,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/framework.BaseRequest.html#__type-3\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":431,\"kind\":1024,\"name\":\"getMethod\",\"url\":\"classes/framework.BaseRequest.html#getMethod\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":432,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/framework.BaseRequest.html#__type-5\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":433,\"kind\":1024,\"name\":\"getCookieValue\",\"url\":\"classes/framework.BaseRequest.html#getCookieValue\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":434,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/framework.BaseRequest.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":435,\"kind\":1024,\"name\":\"getHeaderValue\",\"url\":\"classes/framework.BaseRequest.html#getHeaderValue\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":436,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/framework.BaseRequest.html#__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":437,\"kind\":1024,\"name\":\"getOriginalURL\",\"url\":\"classes/framework.BaseRequest.html#getOriginalURL\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":438,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/framework.BaseRequest.html#__type-6\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":439,\"kind\":1024,\"name\":\"getFormData\",\"url\":\"classes/framework.BaseRequest.html#getFormData\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":440,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/framework.BaseRequest.html#__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"framework.BaseRequest\"},{\"id\":441,\"kind\":128,\"name\":\"BaseResponse\",\"url\":\"classes/framework.BaseResponse.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"framework\"},{\"id\":442,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/framework.BaseResponse.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"framework.BaseResponse\"},{\"id\":443,\"kind\":1024,\"name\":\"wrapperUsed\",\"url\":\"classes/framework.BaseResponse.html#wrapperUsed\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseResponse\"},{\"id\":444,\"kind\":1024,\"name\":\"original\",\"url\":\"classes/framework.BaseResponse.html#original\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseResponse\"},{\"id\":445,\"kind\":1024,\"name\":\"setHeader\",\"url\":\"classes/framework.BaseResponse.html#setHeader\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseResponse\"},{\"id\":446,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/framework.BaseResponse.html#__type-4\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"framework.BaseResponse\"},{\"id\":447,\"kind\":1024,\"name\":\"removeHeader\",\"url\":\"classes/framework.BaseResponse.html#removeHeader\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseResponse\"},{\"id\":448,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/framework.BaseResponse.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"framework.BaseResponse\"},{\"id\":449,\"kind\":1024,\"name\":\"setCookie\",\"url\":\"classes/framework.BaseResponse.html#setCookie\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseResponse\"},{\"id\":450,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/framework.BaseResponse.html#__type-3\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"framework.BaseResponse\"},{\"id\":451,\"kind\":1024,\"name\":\"setStatusCode\",\"url\":\"classes/framework.BaseResponse.html#setStatusCode\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseResponse\"},{\"id\":452,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/framework.BaseResponse.html#__type-5\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"framework.BaseResponse\"},{\"id\":453,\"kind\":1024,\"name\":\"sendJSONResponse\",\"url\":\"classes/framework.BaseResponse.html#sendJSONResponse\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseResponse\"},{\"id\":454,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/framework.BaseResponse.html#__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"framework.BaseResponse\"},{\"id\":455,\"kind\":1024,\"name\":\"sendHTMLResponse\",\"url\":\"classes/framework.BaseResponse.html#sendHTMLResponse\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"framework.BaseResponse\"},{\"id\":456,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/framework.BaseResponse.html#__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"framework.BaseResponse\"},{\"id\":457,\"kind\":256,\"name\":\"SessionEvent\",\"url\":\"interfaces/framework_awsLambda.SessionEvent.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"framework/awsLambda\"},{\"id\":458,\"kind\":1024,\"name\":\"session\",\"url\":\"interfaces/framework_awsLambda.SessionEvent.html#session\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"framework/awsLambda.SessionEvent\"},{\"id\":459,\"kind\":1024,\"name\":\"supertokens\",\"url\":\"interfaces/framework_awsLambda.SessionEvent.html#supertokens\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface tsd-is-inherited\",\"parent\":\"framework/awsLambda.SessionEvent\"},{\"id\":460,\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/framework_awsLambda.SessionEvent.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-interface\",\"parent\":\"framework/awsLambda.SessionEvent\"},{\"id\":461,\"kind\":1024,\"name\":\"response\",\"url\":\"interfaces/framework_awsLambda.SessionEvent.html#__type.response\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"framework/awsLambda.SessionEvent.__type\"},{\"id\":462,\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/framework_awsLambda.SessionEvent.html#__type.__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-literal\",\"parent\":\"framework/awsLambda.SessionEvent.__type\"},{\"id\":463,\"kind\":1024,\"name\":\"headers\",\"url\":\"interfaces/framework_awsLambda.SessionEvent.html#__type.__type-1.headers-1\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"framework/awsLambda.SessionEvent.__type.__type\"},{\"id\":464,\"kind\":1024,\"name\":\"cookies\",\"url\":\"interfaces/framework_awsLambda.SessionEvent.html#__type.__type-1.cookies\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"framework/awsLambda.SessionEvent.__type.__type\"},{\"id\":465,\"kind\":256,\"name\":\"SessionEventV2\",\"url\":\"interfaces/framework_awsLambda.SessionEventV2.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"framework/awsLambda\"},{\"id\":466,\"kind\":1024,\"name\":\"session\",\"url\":\"interfaces/framework_awsLambda.SessionEventV2.html#session\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"framework/awsLambda.SessionEventV2\"},{\"id\":467,\"kind\":1024,\"name\":\"supertokens\",\"url\":\"interfaces/framework_awsLambda.SessionEventV2.html#supertokens\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface tsd-is-inherited\",\"parent\":\"framework/awsLambda.SessionEventV2\"},{\"id\":468,\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/framework_awsLambda.SessionEventV2.html#__type-5\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-interface\",\"parent\":\"framework/awsLambda.SessionEventV2\"},{\"id\":469,\"kind\":1024,\"name\":\"response\",\"url\":\"interfaces/framework_awsLambda.SessionEventV2.html#__type-5.response\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"framework/awsLambda.SessionEventV2.__type\"},{\"id\":470,\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/framework_awsLambda.SessionEventV2.html#__type-5.__type-6\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-literal\",\"parent\":\"framework/awsLambda.SessionEventV2.__type\"},{\"id\":471,\"kind\":1024,\"name\":\"headers\",\"url\":\"interfaces/framework_awsLambda.SessionEventV2.html#__type-5.__type-6.headers-1\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"framework/awsLambda.SessionEventV2.__type.__type\"},{\"id\":472,\"kind\":1024,\"name\":\"cookies\",\"url\":\"interfaces/framework_awsLambda.SessionEventV2.html#__type-5.__type-6.cookies-1\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"framework/awsLambda.SessionEventV2.__type.__type\"},{\"id\":473,\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/framework_awsLambda.SessionEventV2.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-interface\",\"parent\":\"framework/awsLambda.SessionEventV2\"},{\"id\":474,\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/framework_awsLambda.SessionEventV2.html#__type.__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-literal\",\"parent\":\"framework/awsLambda.SessionEventV2.__type\"},{\"id\":475,\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/framework_awsLambda.SessionEventV2.html#__type.__type-1.__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-literal\",\"parent\":\"framework/awsLambda.SessionEventV2.__type.__type\"},{\"id\":476,\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/framework_awsLambda.SessionEventV2.html#__type.__type-1.__type-2.__type-3\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-literal\",\"parent\":\"framework/awsLambda.SessionEventV2.__type.__type.__type\"},{\"id\":477,\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/framework_awsLambda.SessionEventV2.html#__type.__type-4\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-literal\",\"parent\":\"framework/awsLambda.SessionEventV2.__type\"},{\"id\":478,\"kind\":256,\"name\":\"SessionRequest\",\"url\":\"interfaces/framework_express.SessionRequest.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"framework/express\"},{\"id\":479,\"kind\":1024,\"name\":\"session\",\"url\":\"interfaces/framework_express.SessionRequest.html#session\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"framework/express.SessionRequest\"},{\"id\":480,\"kind\":256,\"name\":\"SessionRequest\",\"url\":\"interfaces/framework_fastify.SessionRequest.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"framework/fastify\"},{\"id\":481,\"kind\":1024,\"name\":\"session\",\"url\":\"interfaces/framework_fastify.SessionRequest.html#session\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"framework/fastify.SessionRequest\"},{\"id\":482,\"kind\":256,\"name\":\"SessionRequest\",\"url\":\"interfaces/framework_hapi.SessionRequest.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"framework/hapi\"},{\"id\":483,\"kind\":1024,\"name\":\"session\",\"url\":\"interfaces/framework_hapi.SessionRequest.html#session\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"framework/hapi.SessionRequest\"},{\"id\":484,\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/framework_hapi.SessionRequest.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-interface\",\"parent\":\"framework/hapi.SessionRequest\"},{\"id\":485,\"kind\":256,\"name\":\"SessionContext\",\"url\":\"interfaces/framework_koa.SessionContext.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"framework/koa\"},{\"id\":486,\"kind\":1024,\"name\":\"session\",\"url\":\"interfaces/framework_koa.SessionContext.html#session\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"framework/koa.SessionContext\"},{\"id\":487,\"kind\":256,\"name\":\"SessionContext\",\"url\":\"interfaces/framework_loopback.SessionContext.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"framework/loopback\"},{\"id\":488,\"kind\":1024,\"name\":\"session\",\"url\":\"interfaces/framework_loopback.SessionContext.html#session\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"framework/loopback.SessionContext\"},{\"id\":489,\"kind\":4194304,\"name\":\"RecipeInterface\",\"url\":\"modules/recipe_dashboard.html#RecipeInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/dashboard\"},{\"id\":490,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_dashboard.html#RecipeInterface.__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/dashboard.RecipeInterface\"},{\"id\":491,\"kind\":2048,\"name\":\"getDashboardBundleLocation\",\"url\":\"modules/recipe_dashboard.html#RecipeInterface.__type-2.getDashboardBundleLocation\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/dashboard.RecipeInterface.__type\"},{\"id\":492,\"kind\":2048,\"name\":\"shouldAllowAccess\",\"url\":\"modules/recipe_dashboard.html#RecipeInterface.__type-2.shouldAllowAccess\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/dashboard.RecipeInterface.__type\"},{\"id\":493,\"kind\":4194304,\"name\":\"APIOptions\",\"url\":\"modules/recipe_dashboard.html#APIOptions\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/dashboard\"},{\"id\":494,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_dashboard.html#APIOptions.__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/dashboard.APIOptions\"},{\"id\":495,\"kind\":1024,\"name\":\"recipeImplementation\",\"url\":\"modules/recipe_dashboard.html#APIOptions.__type-1.recipeImplementation\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/dashboard.APIOptions.__type\"},{\"id\":496,\"kind\":1024,\"name\":\"config\",\"url\":\"modules/recipe_dashboard.html#APIOptions.__type-1.config\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/dashboard.APIOptions.__type\"},{\"id\":497,\"kind\":1024,\"name\":\"recipeId\",\"url\":\"modules/recipe_dashboard.html#APIOptions.__type-1.recipeId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/dashboard.APIOptions.__type\"},{\"id\":498,\"kind\":1024,\"name\":\"req\",\"url\":\"modules/recipe_dashboard.html#APIOptions.__type-1.req\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/dashboard.APIOptions.__type\"},{\"id\":499,\"kind\":1024,\"name\":\"res\",\"url\":\"modules/recipe_dashboard.html#APIOptions.__type-1.res\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/dashboard.APIOptions.__type\"},{\"id\":500,\"kind\":1024,\"name\":\"isInServerlessEnv\",\"url\":\"modules/recipe_dashboard.html#APIOptions.__type-1.isInServerlessEnv\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/dashboard.APIOptions.__type\"},{\"id\":501,\"kind\":1024,\"name\":\"appInfo\",\"url\":\"modules/recipe_dashboard.html#APIOptions.__type-1.appInfo\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/dashboard.APIOptions.__type\"},{\"id\":502,\"kind\":4194304,\"name\":\"APIInterface\",\"url\":\"modules/recipe_dashboard.html#APIInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/dashboard\"},{\"id\":503,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_dashboard.html#APIInterface.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/dashboard.APIInterface\"},{\"id\":504,\"kind\":1024,\"name\":\"dashboardGET\",\"url\":\"modules/recipe_dashboard.html#APIInterface.__type.dashboardGET\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/dashboard.APIInterface.__type\"},{\"id\":505,\"kind\":4194304,\"name\":\"RecipeInterface\",\"url\":\"modules/recipe_emailpassword.html#RecipeInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/emailpassword\"},{\"id\":506,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_emailpassword.html#RecipeInterface.__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/emailpassword.RecipeInterface\"},{\"id\":507,\"kind\":2048,\"name\":\"signUp\",\"url\":\"modules/recipe_emailpassword.html#RecipeInterface.__type-2.signUp\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.RecipeInterface.__type\"},{\"id\":508,\"kind\":2048,\"name\":\"signIn\",\"url\":\"modules/recipe_emailpassword.html#RecipeInterface.__type-2.signIn\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.RecipeInterface.__type\"},{\"id\":509,\"kind\":2048,\"name\":\"getUserById\",\"url\":\"modules/recipe_emailpassword.html#RecipeInterface.__type-2.getUserById\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.RecipeInterface.__type\"},{\"id\":510,\"kind\":2048,\"name\":\"getUserByEmail\",\"url\":\"modules/recipe_emailpassword.html#RecipeInterface.__type-2.getUserByEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.RecipeInterface.__type\"},{\"id\":511,\"kind\":2048,\"name\":\"createResetPasswordToken\",\"url\":\"modules/recipe_emailpassword.html#RecipeInterface.__type-2.createResetPasswordToken\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.RecipeInterface.__type\"},{\"id\":512,\"kind\":2048,\"name\":\"resetPasswordUsingToken\",\"url\":\"modules/recipe_emailpassword.html#RecipeInterface.__type-2.resetPasswordUsingToken\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.RecipeInterface.__type\"},{\"id\":513,\"kind\":2048,\"name\":\"updateEmailOrPassword\",\"url\":\"modules/recipe_emailpassword.html#RecipeInterface.__type-2.updateEmailOrPassword\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.RecipeInterface.__type\"},{\"id\":514,\"kind\":4194304,\"name\":\"User\",\"url\":\"modules/recipe_emailpassword.html#User\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/emailpassword\"},{\"id\":515,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_emailpassword.html#User.__type-3\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/emailpassword.User\"},{\"id\":516,\"kind\":1024,\"name\":\"id\",\"url\":\"modules/recipe_emailpassword.html#User.__type-3.id\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.User.__type\"},{\"id\":517,\"kind\":1024,\"name\":\"email\",\"url\":\"modules/recipe_emailpassword.html#User.__type-3.email\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.User.__type\"},{\"id\":518,\"kind\":1024,\"name\":\"timeJoined\",\"url\":\"modules/recipe_emailpassword.html#User.__type-3.timeJoined\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.User.__type\"},{\"id\":519,\"kind\":4194304,\"name\":\"APIOptions\",\"url\":\"modules/recipe_emailpassword.html#APIOptions\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/emailpassword\"},{\"id\":520,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_emailpassword.html#APIOptions.__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/emailpassword.APIOptions\"},{\"id\":521,\"kind\":1024,\"name\":\"recipeImplementation\",\"url\":\"modules/recipe_emailpassword.html#APIOptions.__type-1.recipeImplementation\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.APIOptions.__type\"},{\"id\":522,\"kind\":1024,\"name\":\"appInfo\",\"url\":\"modules/recipe_emailpassword.html#APIOptions.__type-1.appInfo\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.APIOptions.__type\"},{\"id\":523,\"kind\":1024,\"name\":\"config\",\"url\":\"modules/recipe_emailpassword.html#APIOptions.__type-1.config\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.APIOptions.__type\"},{\"id\":524,\"kind\":1024,\"name\":\"recipeId\",\"url\":\"modules/recipe_emailpassword.html#APIOptions.__type-1.recipeId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.APIOptions.__type\"},{\"id\":525,\"kind\":1024,\"name\":\"isInServerlessEnv\",\"url\":\"modules/recipe_emailpassword.html#APIOptions.__type-1.isInServerlessEnv\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.APIOptions.__type\"},{\"id\":526,\"kind\":1024,\"name\":\"req\",\"url\":\"modules/recipe_emailpassword.html#APIOptions.__type-1.req\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.APIOptions.__type\"},{\"id\":527,\"kind\":1024,\"name\":\"res\",\"url\":\"modules/recipe_emailpassword.html#APIOptions.__type-1.res\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.APIOptions.__type\"},{\"id\":528,\"kind\":1024,\"name\":\"emailDelivery\",\"url\":\"modules/recipe_emailpassword.html#APIOptions.__type-1.emailDelivery\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.APIOptions.__type\"},{\"id\":529,\"kind\":4194304,\"name\":\"APIInterface\",\"url\":\"modules/recipe_emailpassword.html#APIInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/emailpassword\"},{\"id\":530,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_emailpassword.html#APIInterface.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/emailpassword.APIInterface\"},{\"id\":531,\"kind\":1024,\"name\":\"emailExistsGET\",\"url\":\"modules/recipe_emailpassword.html#APIInterface.__type.emailExistsGET\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.APIInterface.__type\"},{\"id\":532,\"kind\":1024,\"name\":\"generatePasswordResetTokenPOST\",\"url\":\"modules/recipe_emailpassword.html#APIInterface.__type.generatePasswordResetTokenPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.APIInterface.__type\"},{\"id\":533,\"kind\":1024,\"name\":\"passwordResetPOST\",\"url\":\"modules/recipe_emailpassword.html#APIInterface.__type.passwordResetPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.APIInterface.__type\"},{\"id\":534,\"kind\":1024,\"name\":\"signInPOST\",\"url\":\"modules/recipe_emailpassword.html#APIInterface.__type.signInPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.APIInterface.__type\"},{\"id\":535,\"kind\":1024,\"name\":\"signUpPOST\",\"url\":\"modules/recipe_emailpassword.html#APIInterface.__type.signUpPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailpassword.APIInterface.__type\"},{\"id\":536,\"kind\":4194304,\"name\":\"RecipeInterface\",\"url\":\"modules/recipe_emailverification.html#RecipeInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/emailverification\"},{\"id\":537,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_emailverification.html#RecipeInterface.__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/emailverification.RecipeInterface\"},{\"id\":538,\"kind\":2048,\"name\":\"createEmailVerificationToken\",\"url\":\"modules/recipe_emailverification.html#RecipeInterface.__type-2.createEmailVerificationToken\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.RecipeInterface.__type\"},{\"id\":539,\"kind\":2048,\"name\":\"verifyEmailUsingToken\",\"url\":\"modules/recipe_emailverification.html#RecipeInterface.__type-2.verifyEmailUsingToken\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.RecipeInterface.__type\"},{\"id\":540,\"kind\":2048,\"name\":\"isEmailVerified\",\"url\":\"modules/recipe_emailverification.html#RecipeInterface.__type-2.isEmailVerified\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.RecipeInterface.__type\"},{\"id\":541,\"kind\":2048,\"name\":\"revokeEmailVerificationTokens\",\"url\":\"modules/recipe_emailverification.html#RecipeInterface.__type-2.revokeEmailVerificationTokens\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.RecipeInterface.__type\"},{\"id\":542,\"kind\":2048,\"name\":\"unverifyEmail\",\"url\":\"modules/recipe_emailverification.html#RecipeInterface.__type-2.unverifyEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.RecipeInterface.__type\"},{\"id\":543,\"kind\":4194304,\"name\":\"APIOptions\",\"url\":\"modules/recipe_emailverification.html#APIOptions\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/emailverification\"},{\"id\":544,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_emailverification.html#APIOptions.__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/emailverification.APIOptions\"},{\"id\":545,\"kind\":1024,\"name\":\"recipeImplementation\",\"url\":\"modules/recipe_emailverification.html#APIOptions.__type-1.recipeImplementation\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.APIOptions.__type\"},{\"id\":546,\"kind\":1024,\"name\":\"appInfo\",\"url\":\"modules/recipe_emailverification.html#APIOptions.__type-1.appInfo\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.APIOptions.__type\"},{\"id\":547,\"kind\":1024,\"name\":\"config\",\"url\":\"modules/recipe_emailverification.html#APIOptions.__type-1.config\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.APIOptions.__type\"},{\"id\":548,\"kind\":1024,\"name\":\"recipeId\",\"url\":\"modules/recipe_emailverification.html#APIOptions.__type-1.recipeId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.APIOptions.__type\"},{\"id\":549,\"kind\":1024,\"name\":\"isInServerlessEnv\",\"url\":\"modules/recipe_emailverification.html#APIOptions.__type-1.isInServerlessEnv\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.APIOptions.__type\"},{\"id\":550,\"kind\":1024,\"name\":\"req\",\"url\":\"modules/recipe_emailverification.html#APIOptions.__type-1.req\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.APIOptions.__type\"},{\"id\":551,\"kind\":1024,\"name\":\"res\",\"url\":\"modules/recipe_emailverification.html#APIOptions.__type-1.res\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.APIOptions.__type\"},{\"id\":552,\"kind\":1024,\"name\":\"emailDelivery\",\"url\":\"modules/recipe_emailverification.html#APIOptions.__type-1.emailDelivery\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.APIOptions.__type\"},{\"id\":553,\"kind\":4194304,\"name\":\"APIInterface\",\"url\":\"modules/recipe_emailverification.html#APIInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/emailverification\"},{\"id\":554,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_emailverification.html#APIInterface.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/emailverification.APIInterface\"},{\"id\":555,\"kind\":1024,\"name\":\"verifyEmailPOST\",\"url\":\"modules/recipe_emailverification.html#APIInterface.__type.verifyEmailPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.APIInterface.__type\"},{\"id\":556,\"kind\":1024,\"name\":\"isEmailVerifiedGET\",\"url\":\"modules/recipe_emailverification.html#APIInterface.__type.isEmailVerifiedGET\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.APIInterface.__type\"},{\"id\":557,\"kind\":1024,\"name\":\"generateEmailVerifyTokenPOST\",\"url\":\"modules/recipe_emailverification.html#APIInterface.__type.generateEmailVerifyTokenPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.APIInterface.__type\"},{\"id\":558,\"kind\":4194304,\"name\":\"User\",\"url\":\"modules/recipe_emailverification.html#User\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/emailverification\"},{\"id\":559,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_emailverification.html#User.__type-3\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/emailverification.User\"},{\"id\":560,\"kind\":1024,\"name\":\"id\",\"url\":\"modules/recipe_emailverification.html#User.__type-3.id\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.User.__type\"},{\"id\":561,\"kind\":1024,\"name\":\"email\",\"url\":\"modules/recipe_emailverification.html#User.__type-3.email\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/emailverification.User.__type\"},{\"id\":562,\"kind\":32,\"name\":\"EmailVerificationClaim\",\"url\":\"modules/recipe_emailverification.html#EmailVerificationClaim\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"recipe/emailverification\"},{\"id\":563,\"kind\":4194304,\"name\":\"APIInterface\",\"url\":\"modules/recipe_jwt.html#APIInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/jwt\"},{\"id\":564,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_jwt.html#APIInterface.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/jwt.APIInterface\"},{\"id\":565,\"kind\":1024,\"name\":\"getJWKSGET\",\"url\":\"modules/recipe_jwt.html#APIInterface.__type.getJWKSGET\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/jwt.APIInterface.__type\"},{\"id\":566,\"kind\":4194304,\"name\":\"APIOptions\",\"url\":\"modules/recipe_jwt.html#APIOptions\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/jwt\"},{\"id\":567,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_jwt.html#APIOptions.__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/jwt.APIOptions\"},{\"id\":568,\"kind\":1024,\"name\":\"recipeImplementation\",\"url\":\"modules/recipe_jwt.html#APIOptions.__type-1.recipeImplementation\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/jwt.APIOptions.__type\"},{\"id\":569,\"kind\":1024,\"name\":\"config\",\"url\":\"modules/recipe_jwt.html#APIOptions.__type-1.config\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/jwt.APIOptions.__type\"},{\"id\":570,\"kind\":1024,\"name\":\"recipeId\",\"url\":\"modules/recipe_jwt.html#APIOptions.__type-1.recipeId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/jwt.APIOptions.__type\"},{\"id\":571,\"kind\":1024,\"name\":\"isInServerlessEnv\",\"url\":\"modules/recipe_jwt.html#APIOptions.__type-1.isInServerlessEnv\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/jwt.APIOptions.__type\"},{\"id\":572,\"kind\":1024,\"name\":\"req\",\"url\":\"modules/recipe_jwt.html#APIOptions.__type-1.req\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/jwt.APIOptions.__type\"},{\"id\":573,\"kind\":1024,\"name\":\"res\",\"url\":\"modules/recipe_jwt.html#APIOptions.__type-1.res\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/jwt.APIOptions.__type\"},{\"id\":574,\"kind\":4194304,\"name\":\"RecipeInterface\",\"url\":\"modules/recipe_jwt.html#RecipeInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/jwt\"},{\"id\":575,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_jwt.html#RecipeInterface.__type-3\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/jwt.RecipeInterface\"},{\"id\":576,\"kind\":2048,\"name\":\"createJWT\",\"url\":\"modules/recipe_jwt.html#RecipeInterface.__type-3.createJWT\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/jwt.RecipeInterface.__type\"},{\"id\":577,\"kind\":2048,\"name\":\"getJWKS\",\"url\":\"modules/recipe_jwt.html#RecipeInterface.__type-3.getJWKS\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/jwt.RecipeInterface.__type\"},{\"id\":578,\"kind\":4194304,\"name\":\"JsonWebKey\",\"url\":\"modules/recipe_jwt.html#JsonWebKey\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/jwt\"},{\"id\":579,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_jwt.html#JsonWebKey.__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/jwt.JsonWebKey\"},{\"id\":580,\"kind\":1024,\"name\":\"kty\",\"url\":\"modules/recipe_jwt.html#JsonWebKey.__type-2.kty\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/jwt.JsonWebKey.__type\"},{\"id\":581,\"kind\":1024,\"name\":\"kid\",\"url\":\"modules/recipe_jwt.html#JsonWebKey.__type-2.kid\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/jwt.JsonWebKey.__type\"},{\"id\":582,\"kind\":1024,\"name\":\"n\",\"url\":\"modules/recipe_jwt.html#JsonWebKey.__type-2.n\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/jwt.JsonWebKey.__type\"},{\"id\":583,\"kind\":1024,\"name\":\"e\",\"url\":\"modules/recipe_jwt.html#JsonWebKey.__type-2.e\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/jwt.JsonWebKey.__type\"},{\"id\":584,\"kind\":1024,\"name\":\"alg\",\"url\":\"modules/recipe_jwt.html#JsonWebKey.__type-2.alg\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/jwt.JsonWebKey.__type\"},{\"id\":585,\"kind\":1024,\"name\":\"use\",\"url\":\"modules/recipe_jwt.html#JsonWebKey.__type-2.use\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/jwt.JsonWebKey.__type\"},{\"id\":586,\"kind\":4194304,\"name\":\"RecipeInterface\",\"url\":\"modules/recipe_passwordless.html#RecipeInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":587,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_passwordless.html#RecipeInterface.__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/passwordless.RecipeInterface\"},{\"id\":588,\"kind\":2048,\"name\":\"createCode\",\"url\":\"modules/recipe_passwordless.html#RecipeInterface.__type-2.createCode\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.RecipeInterface.__type\"},{\"id\":589,\"kind\":2048,\"name\":\"createNewCodeForDevice\",\"url\":\"modules/recipe_passwordless.html#RecipeInterface.__type-2.createNewCodeForDevice\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.RecipeInterface.__type\"},{\"id\":590,\"kind\":2048,\"name\":\"consumeCode\",\"url\":\"modules/recipe_passwordless.html#RecipeInterface.__type-2.consumeCode\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.RecipeInterface.__type\"},{\"id\":591,\"kind\":2048,\"name\":\"getUserById\",\"url\":\"modules/recipe_passwordless.html#RecipeInterface.__type-2.getUserById\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.RecipeInterface.__type\"},{\"id\":592,\"kind\":2048,\"name\":\"getUserByEmail\",\"url\":\"modules/recipe_passwordless.html#RecipeInterface.__type-2.getUserByEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.RecipeInterface.__type\"},{\"id\":593,\"kind\":2048,\"name\":\"getUserByPhoneNumber\",\"url\":\"modules/recipe_passwordless.html#RecipeInterface.__type-2.getUserByPhoneNumber\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.RecipeInterface.__type\"},{\"id\":594,\"kind\":2048,\"name\":\"updateUser\",\"url\":\"modules/recipe_passwordless.html#RecipeInterface.__type-2.updateUser\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.RecipeInterface.__type\"},{\"id\":595,\"kind\":2048,\"name\":\"revokeAllCodes\",\"url\":\"modules/recipe_passwordless.html#RecipeInterface.__type-2.revokeAllCodes\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.RecipeInterface.__type\"},{\"id\":596,\"kind\":2048,\"name\":\"revokeCode\",\"url\":\"modules/recipe_passwordless.html#RecipeInterface.__type-2.revokeCode\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.RecipeInterface.__type\"},{\"id\":597,\"kind\":2048,\"name\":\"listCodesByEmail\",\"url\":\"modules/recipe_passwordless.html#RecipeInterface.__type-2.listCodesByEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.RecipeInterface.__type\"},{\"id\":598,\"kind\":2048,\"name\":\"listCodesByPhoneNumber\",\"url\":\"modules/recipe_passwordless.html#RecipeInterface.__type-2.listCodesByPhoneNumber\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.RecipeInterface.__type\"},{\"id\":599,\"kind\":2048,\"name\":\"listCodesByDeviceId\",\"url\":\"modules/recipe_passwordless.html#RecipeInterface.__type-2.listCodesByDeviceId\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.RecipeInterface.__type\"},{\"id\":600,\"kind\":2048,\"name\":\"listCodesByPreAuthSessionId\",\"url\":\"modules/recipe_passwordless.html#RecipeInterface.__type-2.listCodesByPreAuthSessionId\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.RecipeInterface.__type\"},{\"id\":601,\"kind\":4194304,\"name\":\"User\",\"url\":\"modules/recipe_passwordless.html#User\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":602,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_passwordless.html#User.__type-3\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/passwordless.User\"},{\"id\":603,\"kind\":1024,\"name\":\"id\",\"url\":\"modules/recipe_passwordless.html#User.__type-3.id\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.User.__type\"},{\"id\":604,\"kind\":1024,\"name\":\"email\",\"url\":\"modules/recipe_passwordless.html#User.__type-3.email\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.User.__type\"},{\"id\":605,\"kind\":1024,\"name\":\"phoneNumber\",\"url\":\"modules/recipe_passwordless.html#User.__type-3.phoneNumber\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.User.__type\"},{\"id\":606,\"kind\":1024,\"name\":\"timeJoined\",\"url\":\"modules/recipe_passwordless.html#User.__type-3.timeJoined\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.User.__type\"},{\"id\":607,\"kind\":4194304,\"name\":\"APIOptions\",\"url\":\"modules/recipe_passwordless.html#APIOptions\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":608,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_passwordless.html#APIOptions.__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/passwordless.APIOptions\"},{\"id\":609,\"kind\":1024,\"name\":\"recipeImplementation\",\"url\":\"modules/recipe_passwordless.html#APIOptions.__type-1.recipeImplementation\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.APIOptions.__type\"},{\"id\":610,\"kind\":1024,\"name\":\"appInfo\",\"url\":\"modules/recipe_passwordless.html#APIOptions.__type-1.appInfo\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.APIOptions.__type\"},{\"id\":611,\"kind\":1024,\"name\":\"config\",\"url\":\"modules/recipe_passwordless.html#APIOptions.__type-1.config\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.APIOptions.__type\"},{\"id\":612,\"kind\":1024,\"name\":\"recipeId\",\"url\":\"modules/recipe_passwordless.html#APIOptions.__type-1.recipeId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.APIOptions.__type\"},{\"id\":613,\"kind\":1024,\"name\":\"isInServerlessEnv\",\"url\":\"modules/recipe_passwordless.html#APIOptions.__type-1.isInServerlessEnv\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.APIOptions.__type\"},{\"id\":614,\"kind\":1024,\"name\":\"req\",\"url\":\"modules/recipe_passwordless.html#APIOptions.__type-1.req\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.APIOptions.__type\"},{\"id\":615,\"kind\":1024,\"name\":\"res\",\"url\":\"modules/recipe_passwordless.html#APIOptions.__type-1.res\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.APIOptions.__type\"},{\"id\":616,\"kind\":1024,\"name\":\"emailDelivery\",\"url\":\"modules/recipe_passwordless.html#APIOptions.__type-1.emailDelivery\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.APIOptions.__type\"},{\"id\":617,\"kind\":1024,\"name\":\"smsDelivery\",\"url\":\"modules/recipe_passwordless.html#APIOptions.__type-1.smsDelivery\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.APIOptions.__type\"},{\"id\":618,\"kind\":4194304,\"name\":\"APIInterface\",\"url\":\"modules/recipe_passwordless.html#APIInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/passwordless\"},{\"id\":619,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_passwordless.html#APIInterface.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/passwordless.APIInterface\"},{\"id\":620,\"kind\":2048,\"name\":\"createCodePOST\",\"url\":\"modules/recipe_passwordless.html#APIInterface.__type.createCodePOST\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.APIInterface.__type\"},{\"id\":621,\"kind\":2048,\"name\":\"resendCodePOST\",\"url\":\"modules/recipe_passwordless.html#APIInterface.__type.resendCodePOST\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.APIInterface.__type\"},{\"id\":622,\"kind\":2048,\"name\":\"consumeCodePOST\",\"url\":\"modules/recipe_passwordless.html#APIInterface.__type.consumeCodePOST\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.APIInterface.__type\"},{\"id\":623,\"kind\":2048,\"name\":\"emailExistsGET\",\"url\":\"modules/recipe_passwordless.html#APIInterface.__type.emailExistsGET\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.APIInterface.__type\"},{\"id\":624,\"kind\":2048,\"name\":\"phoneNumberExistsGET\",\"url\":\"modules/recipe_passwordless.html#APIInterface.__type.phoneNumberExistsGET\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/passwordless.APIInterface.__type\"},{\"id\":625,\"kind\":256,\"name\":\"VerifySessionOptions\",\"url\":\"interfaces/recipe_session.VerifySessionOptions.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":626,\"kind\":1024,\"name\":\"antiCsrfCheck\",\"url\":\"interfaces/recipe_session.VerifySessionOptions.html#antiCsrfCheck\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"recipe/session.VerifySessionOptions\"},{\"id\":627,\"kind\":1024,\"name\":\"sessionRequired\",\"url\":\"interfaces/recipe_session.VerifySessionOptions.html#sessionRequired\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"recipe/session.VerifySessionOptions\"},{\"id\":628,\"kind\":2048,\"name\":\"overrideGlobalClaimValidators\",\"url\":\"interfaces/recipe_session.VerifySessionOptions.html#overrideGlobalClaimValidators\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"recipe/session.VerifySessionOptions\"},{\"id\":629,\"kind\":4194304,\"name\":\"RecipeInterface\",\"url\":\"modules/recipe_session.html#RecipeInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":630,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/session.RecipeInterface\"},{\"id\":631,\"kind\":2048,\"name\":\"createNewSession\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.createNewSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":632,\"kind\":2048,\"name\":\"getGlobalClaimValidators\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.getGlobalClaimValidators\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":633,\"kind\":2048,\"name\":\"getSession\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.getSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":634,\"kind\":2048,\"name\":\"refreshSession\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.refreshSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":635,\"kind\":2048,\"name\":\"getSessionInformation\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.getSessionInformation\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":636,\"kind\":2048,\"name\":\"revokeAllSessionsForUser\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.revokeAllSessionsForUser\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":637,\"kind\":2048,\"name\":\"getAllSessionHandlesForUser\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.getAllSessionHandlesForUser\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":638,\"kind\":2048,\"name\":\"revokeSession\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.revokeSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":639,\"kind\":2048,\"name\":\"revokeMultipleSessions\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.revokeMultipleSessions\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":640,\"kind\":2048,\"name\":\"updateSessionData\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.updateSessionData\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":641,\"kind\":2048,\"name\":\"updateAccessTokenPayload\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.updateAccessTokenPayload\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":642,\"kind\":2048,\"name\":\"mergeIntoAccessTokenPayload\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.mergeIntoAccessTokenPayload\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":643,\"kind\":2048,\"name\":\"regenerateAccessToken\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.regenerateAccessToken\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":644,\"kind\":2048,\"name\":\"getAccessTokenLifeTimeMS\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.getAccessTokenLifeTimeMS\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":645,\"kind\":2048,\"name\":\"getRefreshTokenLifeTimeMS\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.getRefreshTokenLifeTimeMS\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":646,\"kind\":2048,\"name\":\"validateClaims\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.validateClaims\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":647,\"kind\":2048,\"name\":\"validateClaimsInJWTPayload\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.validateClaimsInJWTPayload\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":648,\"kind\":2048,\"name\":\"fetchAndSetClaim\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.fetchAndSetClaim\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":649,\"kind\":2048,\"name\":\"setClaimValue\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.setClaimValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal tsd-has-type-parameter\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":650,\"kind\":2048,\"name\":\"getClaimValue\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.getClaimValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal tsd-has-type-parameter\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":651,\"kind\":2048,\"name\":\"removeClaim\",\"url\":\"modules/recipe_session.html#RecipeInterface.__type-2.removeClaim\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.RecipeInterface.__type\"},{\"id\":652,\"kind\":256,\"name\":\"SessionContainer\",\"url\":\"interfaces/recipe_session.SessionContainer.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":653,\"kind\":2048,\"name\":\"revokeSession\",\"url\":\"interfaces/recipe_session.SessionContainer.html#revokeSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":654,\"kind\":2048,\"name\":\"getSessionData\",\"url\":\"interfaces/recipe_session.SessionContainer.html#getSessionData\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":655,\"kind\":2048,\"name\":\"updateSessionData\",\"url\":\"interfaces/recipe_session.SessionContainer.html#updateSessionData\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":656,\"kind\":2048,\"name\":\"getUserId\",\"url\":\"interfaces/recipe_session.SessionContainer.html#getUserId\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":657,\"kind\":2048,\"name\":\"getAccessTokenPayload\",\"url\":\"interfaces/recipe_session.SessionContainer.html#getAccessTokenPayload\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":658,\"kind\":2048,\"name\":\"getHandle\",\"url\":\"interfaces/recipe_session.SessionContainer.html#getHandle\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":659,\"kind\":2048,\"name\":\"getAccessToken\",\"url\":\"interfaces/recipe_session.SessionContainer.html#getAccessToken\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":660,\"kind\":2048,\"name\":\"updateAccessTokenPayload\",\"url\":\"interfaces/recipe_session.SessionContainer.html#updateAccessTokenPayload\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":661,\"kind\":2048,\"name\":\"mergeIntoAccessTokenPayload\",\"url\":\"interfaces/recipe_session.SessionContainer.html#mergeIntoAccessTokenPayload\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":662,\"kind\":2048,\"name\":\"getTimeCreated\",\"url\":\"interfaces/recipe_session.SessionContainer.html#getTimeCreated\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":663,\"kind\":2048,\"name\":\"getExpiry\",\"url\":\"interfaces/recipe_session.SessionContainer.html#getExpiry\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":664,\"kind\":2048,\"name\":\"assertClaims\",\"url\":\"interfaces/recipe_session.SessionContainer.html#assertClaims\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":665,\"kind\":2048,\"name\":\"fetchAndSetClaim\",\"url\":\"interfaces/recipe_session.SessionContainer.html#fetchAndSetClaim\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface tsd-has-type-parameter\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":666,\"kind\":2048,\"name\":\"setClaimValue\",\"url\":\"interfaces/recipe_session.SessionContainer.html#setClaimValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface tsd-has-type-parameter\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":667,\"kind\":2048,\"name\":\"getClaimValue\",\"url\":\"interfaces/recipe_session.SessionContainer.html#getClaimValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface tsd-has-type-parameter\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":668,\"kind\":2048,\"name\":\"removeClaim\",\"url\":\"interfaces/recipe_session.SessionContainer.html#removeClaim\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"recipe/session.SessionContainer\"},{\"id\":669,\"kind\":4194304,\"name\":\"APIInterface\",\"url\":\"modules/recipe_session.html#APIInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":670,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_session.html#APIInterface.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/session.APIInterface\"},{\"id\":671,\"kind\":1024,\"name\":\"refreshPOST\",\"url\":\"modules/recipe_session.html#APIInterface.__type.refreshPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.APIInterface.__type\"},{\"id\":672,\"kind\":1024,\"name\":\"signOutPOST\",\"url\":\"modules/recipe_session.html#APIInterface.__type.signOutPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.APIInterface.__type\"},{\"id\":673,\"kind\":2048,\"name\":\"verifySession\",\"url\":\"modules/recipe_session.html#APIInterface.__type.verifySession\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.APIInterface.__type\"},{\"id\":674,\"kind\":4194304,\"name\":\"APIOptions\",\"url\":\"modules/recipe_session.html#APIOptions\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":675,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_session.html#APIOptions.__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/session.APIOptions\"},{\"id\":676,\"kind\":1024,\"name\":\"recipeImplementation\",\"url\":\"modules/recipe_session.html#APIOptions.__type-1.recipeImplementation\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.APIOptions.__type\"},{\"id\":677,\"kind\":1024,\"name\":\"config\",\"url\":\"modules/recipe_session.html#APIOptions.__type-1.config\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.APIOptions.__type\"},{\"id\":678,\"kind\":1024,\"name\":\"recipeId\",\"url\":\"modules/recipe_session.html#APIOptions.__type-1.recipeId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.APIOptions.__type\"},{\"id\":679,\"kind\":1024,\"name\":\"isInServerlessEnv\",\"url\":\"modules/recipe_session.html#APIOptions.__type-1.isInServerlessEnv\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.APIOptions.__type\"},{\"id\":680,\"kind\":1024,\"name\":\"req\",\"url\":\"modules/recipe_session.html#APIOptions.__type-1.req\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.APIOptions.__type\"},{\"id\":681,\"kind\":1024,\"name\":\"res\",\"url\":\"modules/recipe_session.html#APIOptions.__type-1.res\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.APIOptions.__type\"},{\"id\":682,\"kind\":4194304,\"name\":\"SessionInformation\",\"url\":\"modules/recipe_session.html#SessionInformation\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":683,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_session.html#SessionInformation.__type-3\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/session.SessionInformation\"},{\"id\":684,\"kind\":1024,\"name\":\"sessionHandle\",\"url\":\"modules/recipe_session.html#SessionInformation.__type-3.sessionHandle\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.SessionInformation.__type\"},{\"id\":685,\"kind\":1024,\"name\":\"userId\",\"url\":\"modules/recipe_session.html#SessionInformation.__type-3.userId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.SessionInformation.__type\"},{\"id\":686,\"kind\":1024,\"name\":\"sessionData\",\"url\":\"modules/recipe_session.html#SessionInformation.__type-3.sessionData\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.SessionInformation.__type\"},{\"id\":687,\"kind\":1024,\"name\":\"expiry\",\"url\":\"modules/recipe_session.html#SessionInformation.__type-3.expiry\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.SessionInformation.__type\"},{\"id\":688,\"kind\":1024,\"name\":\"accessTokenPayload\",\"url\":\"modules/recipe_session.html#SessionInformation.__type-3.accessTokenPayload\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.SessionInformation.__type\"},{\"id\":689,\"kind\":1024,\"name\":\"timeCreated\",\"url\":\"modules/recipe_session.html#SessionInformation.__type-3.timeCreated\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/session.SessionInformation.__type\"},{\"id\":690,\"kind\":4194304,\"name\":\"SessionClaimValidator\",\"url\":\"modules/recipe_session.html#SessionClaimValidator\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/session\"},{\"id\":691,\"kind\":4194304,\"name\":\"RecipeInterface\",\"url\":\"modules/recipe_thirdparty.html#RecipeInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":692,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_thirdparty.html#RecipeInterface.__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/thirdparty.RecipeInterface\"},{\"id\":693,\"kind\":2048,\"name\":\"getUserById\",\"url\":\"modules/recipe_thirdparty.html#RecipeInterface.__type-2.getUserById\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.RecipeInterface.__type\"},{\"id\":694,\"kind\":2048,\"name\":\"getUsersByEmail\",\"url\":\"modules/recipe_thirdparty.html#RecipeInterface.__type-2.getUsersByEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.RecipeInterface.__type\"},{\"id\":695,\"kind\":2048,\"name\":\"getUserByThirdPartyInfo\",\"url\":\"modules/recipe_thirdparty.html#RecipeInterface.__type-2.getUserByThirdPartyInfo\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.RecipeInterface.__type\"},{\"id\":696,\"kind\":2048,\"name\":\"signInUp\",\"url\":\"modules/recipe_thirdparty.html#RecipeInterface.__type-2.signInUp\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.RecipeInterface.__type\"},{\"id\":697,\"kind\":4194304,\"name\":\"User\",\"url\":\"modules/recipe_thirdparty.html#User\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":698,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_thirdparty.html#User.__type-4\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/thirdparty.User\"},{\"id\":699,\"kind\":1024,\"name\":\"id\",\"url\":\"modules/recipe_thirdparty.html#User.__type-4.id-1\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.User.__type\"},{\"id\":700,\"kind\":1024,\"name\":\"timeJoined\",\"url\":\"modules/recipe_thirdparty.html#User.__type-4.timeJoined\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.User.__type\"},{\"id\":701,\"kind\":1024,\"name\":\"email\",\"url\":\"modules/recipe_thirdparty.html#User.__type-4.email\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.User.__type\"},{\"id\":702,\"kind\":1024,\"name\":\"thirdParty\",\"url\":\"modules/recipe_thirdparty.html#User.__type-4.thirdParty\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.User.__type\"},{\"id\":703,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_thirdparty.html#User.__type-4.__type-5\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.User.__type\"},{\"id\":704,\"kind\":1024,\"name\":\"id\",\"url\":\"modules/recipe_thirdparty.html#User.__type-4.__type-5.id-2\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.User.__type.__type\"},{\"id\":705,\"kind\":1024,\"name\":\"userId\",\"url\":\"modules/recipe_thirdparty.html#User.__type-4.__type-5.userId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.User.__type.__type\"},{\"id\":706,\"kind\":4194304,\"name\":\"APIInterface\",\"url\":\"modules/recipe_thirdparty.html#APIInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":707,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_thirdparty.html#APIInterface.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/thirdparty.APIInterface\"},{\"id\":708,\"kind\":1024,\"name\":\"authorisationUrlGET\",\"url\":\"modules/recipe_thirdparty.html#APIInterface.__type.authorisationUrlGET\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.APIInterface.__type\"},{\"id\":709,\"kind\":1024,\"name\":\"signInUpPOST\",\"url\":\"modules/recipe_thirdparty.html#APIInterface.__type.signInUpPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.APIInterface.__type\"},{\"id\":710,\"kind\":1024,\"name\":\"appleRedirectHandlerPOST\",\"url\":\"modules/recipe_thirdparty.html#APIInterface.__type.appleRedirectHandlerPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.APIInterface.__type\"},{\"id\":711,\"kind\":4194304,\"name\":\"APIOptions\",\"url\":\"modules/recipe_thirdparty.html#APIOptions\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":712,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_thirdparty.html#APIOptions.__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/thirdparty.APIOptions\"},{\"id\":713,\"kind\":1024,\"name\":\"recipeImplementation\",\"url\":\"modules/recipe_thirdparty.html#APIOptions.__type-1.recipeImplementation\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.APIOptions.__type\"},{\"id\":714,\"kind\":1024,\"name\":\"config\",\"url\":\"modules/recipe_thirdparty.html#APIOptions.__type-1.config\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.APIOptions.__type\"},{\"id\":715,\"kind\":1024,\"name\":\"recipeId\",\"url\":\"modules/recipe_thirdparty.html#APIOptions.__type-1.recipeId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.APIOptions.__type\"},{\"id\":716,\"kind\":1024,\"name\":\"isInServerlessEnv\",\"url\":\"modules/recipe_thirdparty.html#APIOptions.__type-1.isInServerlessEnv\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.APIOptions.__type\"},{\"id\":717,\"kind\":1024,\"name\":\"providers\",\"url\":\"modules/recipe_thirdparty.html#APIOptions.__type-1.providers\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.APIOptions.__type\"},{\"id\":718,\"kind\":1024,\"name\":\"req\",\"url\":\"modules/recipe_thirdparty.html#APIOptions.__type-1.req\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.APIOptions.__type\"},{\"id\":719,\"kind\":1024,\"name\":\"res\",\"url\":\"modules/recipe_thirdparty.html#APIOptions.__type-1.res\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.APIOptions.__type\"},{\"id\":720,\"kind\":1024,\"name\":\"appInfo\",\"url\":\"modules/recipe_thirdparty.html#APIOptions.__type-1.appInfo\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.APIOptions.__type\"},{\"id\":721,\"kind\":4194304,\"name\":\"TypeProvider\",\"url\":\"modules/recipe_thirdparty.html#TypeProvider\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/thirdparty\"},{\"id\":722,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_thirdparty.html#TypeProvider.__type-3\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/thirdparty.TypeProvider\"},{\"id\":723,\"kind\":1024,\"name\":\"id\",\"url\":\"modules/recipe_thirdparty.html#TypeProvider.__type-3.id\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.TypeProvider.__type\"},{\"id\":724,\"kind\":2048,\"name\":\"get\",\"url\":\"modules/recipe_thirdparty.html#TypeProvider.__type-3.get\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.TypeProvider.__type\"},{\"id\":725,\"kind\":1024,\"name\":\"isDefault\",\"url\":\"modules/recipe_thirdparty.html#TypeProvider.__type-3.isDefault\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdparty.TypeProvider.__type\"},{\"id\":726,\"kind\":4194304,\"name\":\"RecipeInterface\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#RecipeInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":727,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#RecipeInterface.__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/thirdpartyemailpassword.RecipeInterface\"},{\"id\":728,\"kind\":2048,\"name\":\"getUserById\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#RecipeInterface.__type-1.getUserById\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.RecipeInterface.__type\"},{\"id\":729,\"kind\":2048,\"name\":\"getUsersByEmail\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#RecipeInterface.__type-1.getUsersByEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.RecipeInterface.__type\"},{\"id\":730,\"kind\":2048,\"name\":\"getUserByThirdPartyInfo\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#RecipeInterface.__type-1.getUserByThirdPartyInfo\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.RecipeInterface.__type\"},{\"id\":731,\"kind\":2048,\"name\":\"thirdPartySignInUp\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#RecipeInterface.__type-1.thirdPartySignInUp\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.RecipeInterface.__type\"},{\"id\":732,\"kind\":2048,\"name\":\"emailPasswordSignUp\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#RecipeInterface.__type-1.emailPasswordSignUp\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.RecipeInterface.__type\"},{\"id\":733,\"kind\":2048,\"name\":\"emailPasswordSignIn\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#RecipeInterface.__type-1.emailPasswordSignIn\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.RecipeInterface.__type\"},{\"id\":734,\"kind\":2048,\"name\":\"createResetPasswordToken\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#RecipeInterface.__type-1.createResetPasswordToken\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.RecipeInterface.__type\"},{\"id\":735,\"kind\":2048,\"name\":\"resetPasswordUsingToken\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#RecipeInterface.__type-1.resetPasswordUsingToken\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.RecipeInterface.__type\"},{\"id\":736,\"kind\":2048,\"name\":\"updateEmailOrPassword\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#RecipeInterface.__type-1.updateEmailOrPassword\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.RecipeInterface.__type\"},{\"id\":737,\"kind\":16777216,\"name\":\"TypeProvider\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#TypeProvider\",\"classes\":\"tsd-kind-reference tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":738,\"kind\":4194304,\"name\":\"User\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#User\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":739,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#User.__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/thirdpartyemailpassword.User\"},{\"id\":740,\"kind\":1024,\"name\":\"id\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#User.__type-2.id\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.User.__type\"},{\"id\":741,\"kind\":1024,\"name\":\"timeJoined\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#User.__type-2.timeJoined\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.User.__type\"},{\"id\":742,\"kind\":1024,\"name\":\"email\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#User.__type-2.email\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.User.__type\"},{\"id\":743,\"kind\":1024,\"name\":\"thirdParty\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#User.__type-2.thirdParty\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.User.__type\"},{\"id\":744,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#User.__type-2.__type-3\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.User.__type\"},{\"id\":745,\"kind\":1024,\"name\":\"id\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#User.__type-2.__type-3.id-1\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.User.__type.__type\"},{\"id\":746,\"kind\":1024,\"name\":\"userId\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#User.__type-2.__type-3.userId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.User.__type.__type\"},{\"id\":747,\"kind\":4194304,\"name\":\"APIInterface\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#APIInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":748,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#APIInterface.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/thirdpartyemailpassword.APIInterface\"},{\"id\":749,\"kind\":1024,\"name\":\"authorisationUrlGET\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#APIInterface.__type.authorisationUrlGET\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.APIInterface.__type\"},{\"id\":750,\"kind\":1024,\"name\":\"emailPasswordEmailExistsGET\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#APIInterface.__type.emailPasswordEmailExistsGET\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.APIInterface.__type\"},{\"id\":751,\"kind\":1024,\"name\":\"generatePasswordResetTokenPOST\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#APIInterface.__type.generatePasswordResetTokenPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.APIInterface.__type\"},{\"id\":752,\"kind\":1024,\"name\":\"passwordResetPOST\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#APIInterface.__type.passwordResetPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.APIInterface.__type\"},{\"id\":753,\"kind\":1024,\"name\":\"thirdPartySignInUpPOST\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#APIInterface.__type.thirdPartySignInUpPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.APIInterface.__type\"},{\"id\":754,\"kind\":1024,\"name\":\"emailPasswordSignInPOST\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#APIInterface.__type.emailPasswordSignInPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.APIInterface.__type\"},{\"id\":755,\"kind\":1024,\"name\":\"emailPasswordSignUpPOST\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#APIInterface.__type.emailPasswordSignUpPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.APIInterface.__type\"},{\"id\":756,\"kind\":1024,\"name\":\"appleRedirectHandlerPOST\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#APIInterface.__type.appleRedirectHandlerPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartyemailpassword.APIInterface.__type\"},{\"id\":757,\"kind\":4194304,\"name\":\"EmailPasswordAPIOptions\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#EmailPasswordAPIOptions\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":758,\"kind\":4194304,\"name\":\"ThirdPartyAPIOptions\",\"url\":\"modules/recipe_thirdpartyemailpassword.html#ThirdPartyAPIOptions\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartyemailpassword\"},{\"id\":759,\"kind\":4194304,\"name\":\"RecipeInterface\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":760,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface\"},{\"id\":761,\"kind\":2048,\"name\":\"getUserById\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1.getUserById\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface.__type\"},{\"id\":762,\"kind\":2048,\"name\":\"getUsersByEmail\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1.getUsersByEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface.__type\"},{\"id\":763,\"kind\":2048,\"name\":\"getUserByPhoneNumber\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1.getUserByPhoneNumber\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface.__type\"},{\"id\":764,\"kind\":2048,\"name\":\"getUserByThirdPartyInfo\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1.getUserByThirdPartyInfo\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface.__type\"},{\"id\":765,\"kind\":2048,\"name\":\"thirdPartySignInUp\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1.thirdPartySignInUp\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface.__type\"},{\"id\":766,\"kind\":2048,\"name\":\"createCode\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1.createCode\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface.__type\"},{\"id\":767,\"kind\":2048,\"name\":\"createNewCodeForDevice\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1.createNewCodeForDevice\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface.__type\"},{\"id\":768,\"kind\":2048,\"name\":\"consumeCode\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1.consumeCode\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface.__type\"},{\"id\":769,\"kind\":2048,\"name\":\"updatePasswordlessUser\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1.updatePasswordlessUser\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface.__type\"},{\"id\":770,\"kind\":2048,\"name\":\"revokeAllCodes\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1.revokeAllCodes\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface.__type\"},{\"id\":771,\"kind\":2048,\"name\":\"revokeCode\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1.revokeCode\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface.__type\"},{\"id\":772,\"kind\":2048,\"name\":\"listCodesByEmail\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1.listCodesByEmail\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface.__type\"},{\"id\":773,\"kind\":2048,\"name\":\"listCodesByPhoneNumber\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1.listCodesByPhoneNumber\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface.__type\"},{\"id\":774,\"kind\":2048,\"name\":\"listCodesByDeviceId\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1.listCodesByDeviceId\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface.__type\"},{\"id\":775,\"kind\":2048,\"name\":\"listCodesByPreAuthSessionId\",\"url\":\"modules/recipe_thirdpartypasswordless.html#RecipeInterface.__type-1.listCodesByPreAuthSessionId\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.RecipeInterface.__type\"},{\"id\":776,\"kind\":16777216,\"name\":\"TypeProvider\",\"url\":\"modules/recipe_thirdpartypasswordless.html#TypeProvider\",\"classes\":\"tsd-kind-reference tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":777,\"kind\":4194304,\"name\":\"User\",\"url\":\"modules/recipe_thirdpartypasswordless.html#User\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":778,\"kind\":4194304,\"name\":\"APIInterface\",\"url\":\"modules/recipe_thirdpartypasswordless.html#APIInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":779,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_thirdpartypasswordless.html#APIInterface.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/thirdpartypasswordless.APIInterface\"},{\"id\":780,\"kind\":1024,\"name\":\"authorisationUrlGET\",\"url\":\"modules/recipe_thirdpartypasswordless.html#APIInterface.__type.authorisationUrlGET\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.APIInterface.__type\"},{\"id\":781,\"kind\":1024,\"name\":\"thirdPartySignInUpPOST\",\"url\":\"modules/recipe_thirdpartypasswordless.html#APIInterface.__type.thirdPartySignInUpPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.APIInterface.__type\"},{\"id\":782,\"kind\":1024,\"name\":\"appleRedirectHandlerPOST\",\"url\":\"modules/recipe_thirdpartypasswordless.html#APIInterface.__type.appleRedirectHandlerPOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.APIInterface.__type\"},{\"id\":783,\"kind\":1024,\"name\":\"createCodePOST\",\"url\":\"modules/recipe_thirdpartypasswordless.html#APIInterface.__type.createCodePOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.APIInterface.__type\"},{\"id\":784,\"kind\":1024,\"name\":\"resendCodePOST\",\"url\":\"modules/recipe_thirdpartypasswordless.html#APIInterface.__type.resendCodePOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.APIInterface.__type\"},{\"id\":785,\"kind\":1024,\"name\":\"consumeCodePOST\",\"url\":\"modules/recipe_thirdpartypasswordless.html#APIInterface.__type.consumeCodePOST\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.APIInterface.__type\"},{\"id\":786,\"kind\":1024,\"name\":\"passwordlessUserEmailExistsGET\",\"url\":\"modules/recipe_thirdpartypasswordless.html#APIInterface.__type.passwordlessUserEmailExistsGET\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.APIInterface.__type\"},{\"id\":787,\"kind\":1024,\"name\":\"passwordlessUserPhoneNumberExistsGET\",\"url\":\"modules/recipe_thirdpartypasswordless.html#APIInterface.__type.passwordlessUserPhoneNumberExistsGET\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"recipe/thirdpartypasswordless.APIInterface.__type\"},{\"id\":788,\"kind\":4194304,\"name\":\"PasswordlessAPIOptions\",\"url\":\"modules/recipe_thirdpartypasswordless.html#PasswordlessAPIOptions\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":789,\"kind\":4194304,\"name\":\"ThirdPartyAPIOptions\",\"url\":\"modules/recipe_thirdpartypasswordless.html#ThirdPartyAPIOptions\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/thirdpartypasswordless\"},{\"id\":790,\"kind\":4194304,\"name\":\"RecipeInterface\",\"url\":\"modules/recipe_usermetadata.html#RecipeInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/usermetadata\"},{\"id\":791,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_usermetadata.html#RecipeInterface.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/usermetadata.RecipeInterface\"},{\"id\":792,\"kind\":2048,\"name\":\"getUserMetadata\",\"url\":\"modules/recipe_usermetadata.html#RecipeInterface.__type.getUserMetadata\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/usermetadata.RecipeInterface.__type\"},{\"id\":793,\"kind\":2048,\"name\":\"updateUserMetadata\",\"url\":\"modules/recipe_usermetadata.html#RecipeInterface.__type.updateUserMetadata\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/usermetadata.RecipeInterface.__type\"},{\"id\":794,\"kind\":2048,\"name\":\"clearUserMetadata\",\"url\":\"modules/recipe_usermetadata.html#RecipeInterface.__type.clearUserMetadata\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/usermetadata.RecipeInterface.__type\"},{\"id\":795,\"kind\":256,\"name\":\"JSONObject\",\"url\":\"interfaces/recipe_usermetadata.JSONObject.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"recipe/usermetadata\"},{\"id\":796,\"kind\":32,\"name\":\"UserRoleClaim\",\"url\":\"modules/recipe_userroles.html#UserRoleClaim\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"recipe/userroles\"},{\"id\":797,\"kind\":32,\"name\":\"PermissionClaim\",\"url\":\"modules/recipe_userroles.html#PermissionClaim\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"recipe/userroles\"},{\"id\":798,\"kind\":4194304,\"name\":\"RecipeInterface\",\"url\":\"modules/recipe_userroles.html#RecipeInterface\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"recipe/userroles\"},{\"id\":799,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules/recipe_userroles.html#RecipeInterface.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"recipe/userroles.RecipeInterface\"},{\"id\":800,\"kind\":2048,\"name\":\"addRoleToUser\",\"url\":\"modules/recipe_userroles.html#RecipeInterface.__type.addRoleToUser\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/userroles.RecipeInterface.__type\"},{\"id\":801,\"kind\":2048,\"name\":\"removeUserRole\",\"url\":\"modules/recipe_userroles.html#RecipeInterface.__type.removeUserRole\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/userroles.RecipeInterface.__type\"},{\"id\":802,\"kind\":2048,\"name\":\"getRolesForUser\",\"url\":\"modules/recipe_userroles.html#RecipeInterface.__type.getRolesForUser\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/userroles.RecipeInterface.__type\"},{\"id\":803,\"kind\":2048,\"name\":\"getUsersThatHaveRole\",\"url\":\"modules/recipe_userroles.html#RecipeInterface.__type.getUsersThatHaveRole\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/userroles.RecipeInterface.__type\"},{\"id\":804,\"kind\":2048,\"name\":\"createNewRoleOrAddPermissions\",\"url\":\"modules/recipe_userroles.html#RecipeInterface.__type.createNewRoleOrAddPermissions\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/userroles.RecipeInterface.__type\"},{\"id\":805,\"kind\":2048,\"name\":\"getPermissionsForRole\",\"url\":\"modules/recipe_userroles.html#RecipeInterface.__type.getPermissionsForRole\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/userroles.RecipeInterface.__type\"},{\"id\":806,\"kind\":2048,\"name\":\"removePermissionsFromRole\",\"url\":\"modules/recipe_userroles.html#RecipeInterface.__type.removePermissionsFromRole\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/userroles.RecipeInterface.__type\"},{\"id\":807,\"kind\":2048,\"name\":\"getRolesThatHavePermission\",\"url\":\"modules/recipe_userroles.html#RecipeInterface.__type.getRolesThatHavePermission\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/userroles.RecipeInterface.__type\"},{\"id\":808,\"kind\":2048,\"name\":\"deleteRole\",\"url\":\"modules/recipe_userroles.html#RecipeInterface.__type.deleteRole\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/userroles.RecipeInterface.__type\"},{\"id\":809,\"kind\":2048,\"name\":\"getAllRoles\",\"url\":\"modules/recipe_userroles.html#RecipeInterface.__type.getAllRoles\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"recipe/userroles.RecipeInterface.__type\"}],\"index\":{\"version\":\"2.3.9\",\"fields\":[\"name\",\"parent\"],\"fieldVectors\":[[\"name/0\",[0,40.956]],[\"parent/0\",[]],[\"name/1\",[1,34.211]],[\"parent/1\",[0,4.049]],[\"name/2\",[2,57.82]],[\"parent/2\",[0,4.049]],[\"name/3\",[3,57.82]],[\"parent/3\",[0,4.049]],[\"name/4\",[4,57.82]],[\"parent/4\",[0,4.049]],[\"name/5\",[5,57.82]],[\"parent/5\",[0,4.049]],[\"name/6\",[6,57.82]],[\"parent/6\",[0,4.049]],[\"name/7\",[7,57.82]],[\"parent/7\",[0,4.049]],[\"name/8\",[8,57.82]],[\"parent/8\",[0,4.049]],[\"name/9\",[9,57.82]],[\"parent/9\",[0,4.049]],[\"name/10\",[10,57.82]],[\"parent/10\",[0,4.049]],[\"name/11\",[11,38.949]],[\"parent/11\",[0,4.049]],[\"name/12\",[12,38.949]],[\"parent/12\",[0,4.049]],[\"name/13\",[1,34.211]],[\"parent/13\",[13,4.049]],[\"name/14\",[14,21.711]],[\"parent/14\",[13,4.049]],[\"name/15\",[11,38.949]],[\"parent/15\",[13,4.049]],[\"name/16\",[2,57.82]],[\"parent/16\",[13,4.049]],[\"name/17\",[3,57.82]],[\"parent/17\",[13,4.049]],[\"name/18\",[4,57.82]],[\"parent/18\",[13,4.049]],[\"name/19\",[5,57.82]],[\"parent/19\",[13,4.049]],[\"name/20\",[6,57.82]],[\"parent/20\",[13,4.049]],[\"name/21\",[7,57.82]],[\"parent/21\",[13,4.049]],[\"name/22\",[8,57.82]],[\"parent/22\",[13,4.049]],[\"name/23\",[9,57.82]],[\"parent/23\",[13,4.049]],[\"name/24\",[10,57.82]],[\"parent/24\",[13,4.049]],[\"name/25\",[15,38.361]],[\"parent/25\",[13,4.049]],[\"name/26\",[16,42.559]],[\"parent/26\",[]],[\"name/27\",[17,57.82]],[\"parent/27\",[16,4.208]],[\"name/28\",[18,57.82]],[\"parent/28\",[16,4.208]],[\"name/29\",[19,57.82]],[\"parent/29\",[16,4.208]],[\"name/30\",[20,57.82]],[\"parent/30\",[16,4.208]],[\"name/31\",[21,57.82]],[\"parent/31\",[16,4.208]],[\"name/32\",[22,57.82]],[\"parent/32\",[16,4.208]],[\"name/33\",[12,38.949]],[\"parent/33\",[16,4.208]],[\"name/34\",[14,21.711]],[\"parent/34\",[16,4.208]],[\"name/35\",[17,57.82]],[\"parent/35\",[23,4.772]],[\"name/36\",[18,57.82]],[\"parent/36\",[23,4.772]],[\"name/37\",[19,57.82]],[\"parent/37\",[23,4.772]],[\"name/38\",[20,57.82]],[\"parent/38\",[23,4.772]],[\"name/39\",[21,57.82]],[\"parent/39\",[23,4.772]],[\"name/40\",[22,57.82]],[\"parent/40\",[23,4.772]],[\"name/41\",[24,48.265]],[\"parent/41\",[]],[\"name/42\",[25,51.942]],[\"parent/42\",[24,4.772]],[\"name/43\",[26,48.265]],[\"parent/43\",[24,4.772]],[\"name/44\",[27,48.265]],[\"parent/44\",[24,4.772]],[\"name/45\",[28,48.265]],[\"parent/45\",[]],[\"name/46\",[25,51.942]],[\"parent/46\",[28,4.772]],[\"name/47\",[29,57.82]],[\"parent/47\",[28,4.772]],[\"name/48\",[26,48.265]],[\"parent/48\",[28,4.772]],[\"name/49\",[27,48.265]],[\"parent/49\",[28,4.772]],[\"name/50\",[30,48.265]],[\"parent/50\",[]],[\"name/51\",[31,57.82]],[\"parent/51\",[30,4.772]],[\"name/52\",[29,57.82]],[\"parent/52\",[30,4.772]],[\"name/53\",[26,48.265]],[\"parent/53\",[30,4.772]],[\"name/54\",[27,48.265]],[\"parent/54\",[30,4.772]],[\"name/55\",[32,49.935]],[\"parent/55\",[]],[\"name/56\",[31,57.82]],[\"parent/56\",[32,4.937]],[\"name/57\",[26,48.265]],[\"parent/57\",[32,4.937]],[\"name/58\",[27,48.265]],[\"parent/58\",[32,4.937]],[\"name/59\",[33,49.935]],[\"parent/59\",[]],[\"name/60\",[25,51.942]],[\"parent/60\",[33,4.937]],[\"name/61\",[26,48.265]],[\"parent/61\",[33,4.937]],[\"name/62\",[27,48.265]],[\"parent/62\",[33,4.937]],[\"name/63\",[34,49.935]],[\"parent/63\",[]],[\"name/64\",[25,51.942]],[\"parent/64\",[34,4.937]],[\"name/65\",[26,48.265]],[\"parent/65\",[34,4.937]],[\"name/66\",[27,48.265]],[\"parent/66\",[34,4.937]],[\"name/67\",[35,57.82]],[\"parent/67\",[]],[\"name/68\",[12,38.949]],[\"parent/68\",[35,5.717]],[\"name/69\",[15,38.361]],[\"parent/69\",[36,5.717]],[\"name/70\",[37,57.82]],[\"parent/70\",[36,5.717]],[\"name/71\",[38,57.82]],[\"parent/71\",[]],[\"name/72\",[12,38.949]],[\"parent/72\",[38,5.717]],[\"name/73\",[15,38.361]],[\"parent/73\",[39,5.717]],[\"name/74\",[37,57.82]],[\"parent/74\",[39,5.717]],[\"name/75\",[40,48.265]],[\"parent/75\",[]],[\"name/76\",[1,34.211]],[\"parent/76\",[40,4.772]],[\"name/77\",[12,38.949]],[\"parent/77\",[40,4.772]],[\"name/78\",[1,34.211]],[\"parent/78\",[41,5.384]],[\"name/79\",[14,21.711]],[\"parent/79\",[41,5.384]],[\"name/80\",[15,38.361]],[\"parent/80\",[41,5.384]],[\"name/81\",[42,38.949]],[\"parent/81\",[]],[\"name/82\",[1,34.211]],[\"parent/82\",[42,3.851]],[\"name/83\",[11,38.949]],[\"parent/83\",[42,3.851]],[\"name/84\",[43,54.455]],[\"parent/84\",[42,3.851]],[\"name/85\",[44,54.455]],[\"parent/85\",[42,3.851]],[\"name/86\",[45,39.574]],[\"parent/86\",[42,3.851]],[\"name/87\",[46,48.265]],[\"parent/87\",[42,3.851]],[\"name/88\",[47,48.265]],[\"parent/88\",[42,3.851]],[\"name/89\",[48,48.265]],[\"parent/89\",[42,3.851]],[\"name/90\",[49,48.265]],[\"parent/90\",[42,3.851]],[\"name/91\",[50,43.469]],[\"parent/91\",[42,3.851]],[\"name/92\",[12,38.949]],[\"parent/92\",[42,3.851]],[\"name/93\",[1,34.211]],[\"parent/93\",[51,4.125]],[\"name/94\",[14,21.711]],[\"parent/94\",[51,4.125]],[\"name/95\",[11,38.949]],[\"parent/95\",[51,4.125]],[\"name/96\",[43,54.455]],[\"parent/96\",[51,4.125]],[\"name/97\",[44,54.455]],[\"parent/97\",[51,4.125]],[\"name/98\",[45,39.574]],[\"parent/98\",[51,4.125]],[\"name/99\",[46,48.265]],[\"parent/99\",[51,4.125]],[\"name/100\",[47,48.265]],[\"parent/100\",[51,4.125]],[\"name/101\",[48,48.265]],[\"parent/101\",[51,4.125]],[\"name/102\",[49,48.265]],[\"parent/102\",[51,4.125]],[\"name/103\",[50,43.469]],[\"parent/103\",[51,4.125]],[\"name/104\",[15,38.361]],[\"parent/104\",[51,4.125]],[\"name/105\",[52,39.574]],[\"parent/105\",[]],[\"name/106\",[1,34.211]],[\"parent/106\",[52,3.913]],[\"name/107\",[11,38.949]],[\"parent/107\",[52,3.913]],[\"name/108\",[53,54.455]],[\"parent/108\",[52,3.913]],[\"name/109\",[54,54.455]],[\"parent/109\",[52,3.913]],[\"name/110\",[55,54.455]],[\"parent/110\",[52,3.913]],[\"name/111\",[56,54.455]],[\"parent/111\",[52,3.913]],[\"name/112\",[57,54.455]],[\"parent/112\",[52,3.913]],[\"name/113\",[50,43.469]],[\"parent/113\",[52,3.913]],[\"name/114\",[12,38.949]],[\"parent/114\",[52,3.913]],[\"name/115\",[1,34.211]],[\"parent/115\",[58,4.208]],[\"name/116\",[14,21.711]],[\"parent/116\",[58,4.208]],[\"name/117\",[11,38.949]],[\"parent/117\",[58,4.208]],[\"name/118\",[59,57.82]],[\"parent/118\",[58,4.208]],[\"name/119\",[53,54.455]],[\"parent/119\",[58,4.208]],[\"name/120\",[54,54.455]],[\"parent/120\",[58,4.208]],[\"name/121\",[55,54.455]],[\"parent/121\",[58,4.208]],[\"name/122\",[56,54.455]],[\"parent/122\",[58,4.208]],[\"name/123\",[57,54.455]],[\"parent/123\",[58,4.208]],[\"name/124\",[50,43.469]],[\"parent/124\",[58,4.208]],[\"name/125\",[15,38.361]],[\"parent/125\",[58,4.208]],[\"name/126\",[60,44.47]],[\"parent/126\",[]],[\"name/127\",[1,34.211]],[\"parent/127\",[60,4.397]],[\"name/128\",[61,46.834]],[\"parent/128\",[60,4.397]],[\"name/129\",[62,46.834]],[\"parent/129\",[60,4.397]],[\"name/130\",[12,38.949]],[\"parent/130\",[60,4.397]],[\"name/131\",[1,34.211]],[\"parent/131\",[63,4.937]],[\"name/132\",[14,21.711]],[\"parent/132\",[63,4.937]],[\"name/133\",[61,46.834]],[\"parent/133\",[63,4.937]],[\"name/134\",[62,46.834]],[\"parent/134\",[63,4.937]],[\"name/135\",[15,38.361]],[\"parent/135\",[63,4.937]],[\"name/136\",[64,48.265]],[\"parent/136\",[]],[\"name/137\",[1,34.211]],[\"parent/137\",[64,4.772]],[\"name/138\",[65,51.942]],[\"parent/138\",[64,4.772]],[\"name/139\",[61,46.834]],[\"parent/139\",[64,4.772]],[\"name/140\",[62,46.834]],[\"parent/140\",[64,4.772]],[\"name/141\",[12,38.949]],[\"parent/141\",[64,4.772]],[\"name/142\",[1,34.211]],[\"parent/142\",[66,4.772]],[\"name/143\",[14,21.711]],[\"parent/143\",[66,4.772]],[\"name/144\",[65,51.942]],[\"parent/144\",[66,4.772]],[\"name/145\",[61,46.834]],[\"parent/145\",[66,4.772]],[\"name/146\",[62,46.834]],[\"parent/146\",[66,4.772]],[\"name/147\",[15,38.361]],[\"parent/147\",[66,4.772]],[\"name/148\",[67,34.596]],[\"parent/148\",[]],[\"name/149\",[1,34.211]],[\"parent/149\",[67,3.421]],[\"name/150\",[11,38.949]],[\"parent/150\",[67,3.421]],[\"name/151\",[68,48.265]],[\"parent/151\",[67,3.421]],[\"name/152\",[69,48.265]],[\"parent/152\",[67,3.421]],[\"name/153\",[46,48.265]],[\"parent/153\",[67,3.421]],[\"name/154\",[45,39.574]],[\"parent/154\",[67,3.421]],[\"name/155\",[70,48.265]],[\"parent/155\",[67,3.421]],[\"name/156\",[71,48.265]],[\"parent/156\",[67,3.421]],[\"name/157\",[72,48.265]],[\"parent/157\",[67,3.421]],[\"name/158\",[73,48.265]],[\"parent/158\",[67,3.421]],[\"name/159\",[74,48.265]],[\"parent/159\",[67,3.421]],[\"name/160\",[75,48.265]],[\"parent/160\",[67,3.421]],[\"name/161\",[76,54.455]],[\"parent/161\",[67,3.421]],[\"name/162\",[77,48.265]],[\"parent/162\",[67,3.421]],[\"name/163\",[78,48.265]],[\"parent/163\",[67,3.421]],[\"name/164\",[79,51.942]],[\"parent/164\",[67,3.421]],[\"name/165\",[80,49.935]],[\"parent/165\",[67,3.421]],[\"name/166\",[50,43.469]],[\"parent/166\",[67,3.421]],[\"name/167\",[81,51.942]],[\"parent/167\",[67,3.421]],[\"name/168\",[12,38.949]],[\"parent/168\",[67,3.421]],[\"name/169\",[1,34.211]],[\"parent/169\",[82,3.589]],[\"name/170\",[14,21.711]],[\"parent/170\",[82,3.589]],[\"name/171\",[11,38.949]],[\"parent/171\",[82,3.589]],[\"name/172\",[68,48.265]],[\"parent/172\",[82,3.589]],[\"name/173\",[75,48.265]],[\"parent/173\",[82,3.589]],[\"name/174\",[69,48.265]],[\"parent/174\",[82,3.589]],[\"name/175\",[45,39.574]],[\"parent/175\",[82,3.589]],[\"name/176\",[46,48.265]],[\"parent/176\",[82,3.589]],[\"name/177\",[70,48.265]],[\"parent/177\",[82,3.589]],[\"name/178\",[76,54.455]],[\"parent/178\",[82,3.589]],[\"name/179\",[77,48.265]],[\"parent/179\",[82,3.589]],[\"name/180\",[78,48.265]],[\"parent/180\",[82,3.589]],[\"name/181\",[72,48.265]],[\"parent/181\",[82,3.589]],[\"name/182\",[73,48.265]],[\"parent/182\",[82,3.589]],[\"name/183\",[71,48.265]],[\"parent/183\",[82,3.589]],[\"name/184\",[74,48.265]],[\"parent/184\",[82,3.589]],[\"name/185\",[79,51.942]],[\"parent/185\",[82,3.589]],[\"name/186\",[80,49.935]],[\"parent/186\",[82,3.589]],[\"name/187\",[50,43.469]],[\"parent/187\",[82,3.589]],[\"name/188\",[81,51.942]],[\"parent/188\",[82,3.589]],[\"name/189\",[15,38.361]],[\"parent/189\",[82,3.589]],[\"name/190\",[83,32.483]],[\"parent/190\",[]],[\"name/191\",[1,34.211]],[\"parent/191\",[83,3.212]],[\"name/192\",[84,54.455]],[\"parent/192\",[83,3.212]],[\"name/193\",[85,54.455]],[\"parent/193\",[83,3.212]],[\"name/194\",[86,54.455]],[\"parent/194\",[83,3.212]],[\"name/195\",[87,54.455]],[\"parent/195\",[83,3.212]],[\"name/196\",[88,54.455]],[\"parent/196\",[83,3.212]],[\"name/197\",[89,54.455]],[\"parent/197\",[83,3.212]],[\"name/198\",[90,51.942]],[\"parent/198\",[83,3.212]],[\"name/199\",[91,54.455]],[\"parent/199\",[83,3.212]],[\"name/200\",[92,51.942]],[\"parent/200\",[83,3.212]],[\"name/201\",[93,51.942]],[\"parent/201\",[83,3.212]],[\"name/202\",[94,51.942]],[\"parent/202\",[83,3.212]],[\"name/203\",[95,51.942]],[\"parent/203\",[83,3.212]],[\"name/204\",[96,51.942]],[\"parent/204\",[83,3.212]],[\"name/205\",[97,51.942]],[\"parent/205\",[83,3.212]],[\"name/206\",[98,51.942]],[\"parent/206\",[83,3.212]],[\"name/207\",[99,54.455]],[\"parent/207\",[83,3.212]],[\"name/208\",[100,57.82]],[\"parent/208\",[83,3.212]],[\"name/209\",[11,38.949]],[\"parent/209\",[83,3.212]],[\"name/210\",[61,46.834]],[\"parent/210\",[83,3.212]],[\"name/211\",[62,46.834]],[\"parent/211\",[83,3.212]],[\"name/212\",[65,51.942]],[\"parent/212\",[83,3.212]],[\"name/213\",[12,38.949]],[\"parent/213\",[83,3.212]],[\"name/214\",[1,34.211]],[\"parent/214\",[101,3.421]],[\"name/215\",[14,21.711]],[\"parent/215\",[101,3.421]],[\"name/216\",[11,38.949]],[\"parent/216\",[101,3.421]],[\"name/217\",[84,54.455]],[\"parent/217\",[101,3.421]],[\"name/218\",[100,57.82]],[\"parent/218\",[101,3.421]],[\"name/219\",[99,54.455]],[\"parent/219\",[101,3.421]],[\"name/220\",[85,54.455]],[\"parent/220\",[101,3.421]],[\"name/221\",[86,54.455]],[\"parent/221\",[101,3.421]],[\"name/222\",[87,54.455]],[\"parent/222\",[101,3.421]],[\"name/223\",[88,54.455]],[\"parent/223\",[101,3.421]],[\"name/224\",[89,54.455]],[\"parent/224\",[101,3.421]],[\"name/225\",[90,51.942]],[\"parent/225\",[101,3.421]],[\"name/226\",[91,54.455]],[\"parent/226\",[101,3.421]],[\"name/227\",[92,51.942]],[\"parent/227\",[101,3.421]],[\"name/228\",[102,57.82]],[\"parent/228\",[101,3.421]],[\"name/229\",[93,51.942]],[\"parent/229\",[101,3.421]],[\"name/230\",[94,51.942]],[\"parent/230\",[101,3.421]],[\"name/231\",[61,46.834]],[\"parent/231\",[101,3.421]],[\"name/232\",[62,46.834]],[\"parent/232\",[101,3.421]],[\"name/233\",[65,51.942]],[\"parent/233\",[101,3.421]],[\"name/234\",[95,51.942]],[\"parent/234\",[101,3.421]],[\"name/235\",[96,51.942]],[\"parent/235\",[101,3.421]],[\"name/236\",[97,51.942]],[\"parent/236\",[101,3.421]],[\"name/237\",[98,51.942]],[\"parent/237\",[101,3.421]],[\"name/238\",[15,38.361]],[\"parent/238\",[101,3.421]],[\"name/239\",[103,37.279]],[\"parent/239\",[]],[\"name/240\",[1,34.211]],[\"parent/240\",[103,3.686]],[\"name/241\",[11,38.949]],[\"parent/241\",[103,3.686]],[\"name/242\",[80,49.935]],[\"parent/242\",[103,3.686]],[\"name/243\",[45,39.574]],[\"parent/243\",[103,3.686]],[\"name/244\",[104,44.47]],[\"parent/244\",[103,3.686]],[\"name/245\",[105,44.47]],[\"parent/245\",[103,3.686]],[\"name/246\",[106,48.265]],[\"parent/246\",[103,3.686]],[\"name/247\",[107,48.265]],[\"parent/247\",[103,3.686]],[\"name/248\",[108,48.265]],[\"parent/248\",[103,3.686]],[\"name/249\",[109,48.265]],[\"parent/249\",[103,3.686]],[\"name/250\",[110,48.265]],[\"parent/250\",[103,3.686]],[\"name/251\",[111,48.265]],[\"parent/251\",[103,3.686]],[\"name/252\",[12,38.949]],[\"parent/252\",[103,3.686]],[\"name/253\",[1,34.211]],[\"parent/253\",[112,3.636]],[\"name/254\",[14,21.711]],[\"parent/254\",[112,3.636]],[\"name/255\",[11,38.949]],[\"parent/255\",[112,3.636]],[\"name/256\",[80,49.935]],[\"parent/256\",[112,3.636]],[\"name/257\",[45,39.574]],[\"parent/257\",[112,3.636]],[\"name/258\",[104,44.47]],[\"parent/258\",[112,3.636]],[\"name/259\",[105,44.47]],[\"parent/259\",[112,3.636]],[\"name/260\",[106,48.265]],[\"parent/260\",[112,3.636]],[\"name/261\",[14,21.711]],[\"parent/261\",[112,3.636]],[\"name/262\",[107,48.265]],[\"parent/262\",[112,3.636]],[\"name/263\",[14,21.711]],[\"parent/263\",[112,3.636]],[\"name/264\",[108,48.265]],[\"parent/264\",[112,3.636]],[\"name/265\",[14,21.711]],[\"parent/265\",[112,3.636]],[\"name/266\",[109,48.265]],[\"parent/266\",[112,3.636]],[\"name/267\",[14,21.711]],[\"parent/267\",[112,3.636]],[\"name/268\",[110,48.265]],[\"parent/268\",[112,3.636]],[\"name/269\",[14,21.711]],[\"parent/269\",[112,3.636]],[\"name/270\",[111,48.265]],[\"parent/270\",[112,3.636]],[\"name/271\",[14,21.711]],[\"parent/271\",[112,3.636]],[\"name/272\",[15,38.361]],[\"parent/272\",[112,3.636]],[\"name/273\",[113,34.211]],[\"parent/273\",[]],[\"name/274\",[1,34.211]],[\"parent/274\",[113,3.382]],[\"name/275\",[11,38.949]],[\"parent/275\",[113,3.382]],[\"name/276\",[114,54.455]],[\"parent/276\",[113,3.382]],[\"name/277\",[115,54.455]],[\"parent/277\",[113,3.382]],[\"name/278\",[116,48.265]],[\"parent/278\",[113,3.382]],[\"name/279\",[45,39.574]],[\"parent/279\",[113,3.382]],[\"name/280\",[105,44.47]],[\"parent/280\",[113,3.382]],[\"name/281\",[104,44.47]],[\"parent/281\",[113,3.382]],[\"name/282\",[47,48.265]],[\"parent/282\",[113,3.382]],[\"name/283\",[48,48.265]],[\"parent/283\",[113,3.382]],[\"name/284\",[49,48.265]],[\"parent/284\",[113,3.382]],[\"name/285\",[106,48.265]],[\"parent/285\",[113,3.382]],[\"name/286\",[107,48.265]],[\"parent/286\",[113,3.382]],[\"name/287\",[108,48.265]],[\"parent/287\",[113,3.382]],[\"name/288\",[109,48.265]],[\"parent/288\",[113,3.382]],[\"name/289\",[110,48.265]],[\"parent/289\",[113,3.382]],[\"name/290\",[111,48.265]],[\"parent/290\",[113,3.382]],[\"name/291\",[50,43.469]],[\"parent/291\",[113,3.382]],[\"name/292\",[12,38.949]],[\"parent/292\",[113,3.382]],[\"name/293\",[1,34.211]],[\"parent/293\",[117,3.382]],[\"name/294\",[14,21.711]],[\"parent/294\",[117,3.382]],[\"name/295\",[11,38.949]],[\"parent/295\",[117,3.382]],[\"name/296\",[116,48.265]],[\"parent/296\",[117,3.382]],[\"name/297\",[105,44.47]],[\"parent/297\",[117,3.382]],[\"name/298\",[114,54.455]],[\"parent/298\",[117,3.382]],[\"name/299\",[115,54.455]],[\"parent/299\",[117,3.382]],[\"name/300\",[45,39.574]],[\"parent/300\",[117,3.382]],[\"name/301\",[104,44.47]],[\"parent/301\",[117,3.382]],[\"name/302\",[47,48.265]],[\"parent/302\",[117,3.382]],[\"name/303\",[48,48.265]],[\"parent/303\",[117,3.382]],[\"name/304\",[49,48.265]],[\"parent/304\",[117,3.382]],[\"name/305\",[106,48.265]],[\"parent/305\",[117,3.382]],[\"name/306\",[14,21.711]],[\"parent/306\",[117,3.382]],[\"name/307\",[107,48.265]],[\"parent/307\",[117,3.382]],[\"name/308\",[14,21.711]],[\"parent/308\",[117,3.382]],[\"name/309\",[108,48.265]],[\"parent/309\",[117,3.382]],[\"name/310\",[14,21.711]],[\"parent/310\",[117,3.382]],[\"name/311\",[109,48.265]],[\"parent/311\",[117,3.382]],[\"name/312\",[14,21.711]],[\"parent/312\",[117,3.382]],[\"name/313\",[110,48.265]],[\"parent/313\",[117,3.382]],[\"name/314\",[14,21.711]],[\"parent/314\",[117,3.382]],[\"name/315\",[111,48.265]],[\"parent/315\",[117,3.382]],[\"name/316\",[14,21.711]],[\"parent/316\",[117,3.382]],[\"name/317\",[50,43.469]],[\"parent/317\",[117,3.382]],[\"name/318\",[15,38.361]],[\"parent/318\",[117,3.382]],[\"name/319\",[118,31.287]],[\"parent/319\",[]],[\"name/320\",[1,34.211]],[\"parent/320\",[118,3.093]],[\"name/321\",[11,38.949]],[\"parent/321\",[118,3.093]],[\"name/322\",[116,48.265]],[\"parent/322\",[118,3.093]],[\"name/323\",[119,57.82]],[\"parent/323\",[118,3.093]],[\"name/324\",[45,39.574]],[\"parent/324\",[118,3.093]],[\"name/325\",[105,44.47]],[\"parent/325\",[118,3.093]],[\"name/326\",[104,44.47]],[\"parent/326\",[118,3.093]],[\"name/327\",[68,48.265]],[\"parent/327\",[118,3.093]],[\"name/328\",[69,48.265]],[\"parent/328\",[118,3.093]],[\"name/329\",[70,48.265]],[\"parent/329\",[118,3.093]],[\"name/330\",[71,48.265]],[\"parent/330\",[118,3.093]],[\"name/331\",[72,48.265]],[\"parent/331\",[118,3.093]],[\"name/332\",[73,48.265]],[\"parent/332\",[118,3.093]],[\"name/333\",[74,48.265]],[\"parent/333\",[118,3.093]],[\"name/334\",[75,48.265]],[\"parent/334\",[118,3.093]],[\"name/335\",[120,54.455]],[\"parent/335\",[118,3.093]],[\"name/336\",[77,48.265]],[\"parent/336\",[118,3.093]],[\"name/337\",[78,48.265]],[\"parent/337\",[118,3.093]],[\"name/338\",[79,51.942]],[\"parent/338\",[118,3.093]],[\"name/339\",[106,48.265]],[\"parent/339\",[118,3.093]],[\"name/340\",[107,48.265]],[\"parent/340\",[118,3.093]],[\"name/341\",[108,48.265]],[\"parent/341\",[118,3.093]],[\"name/342\",[109,48.265]],[\"parent/342\",[118,3.093]],[\"name/343\",[110,48.265]],[\"parent/343\",[118,3.093]],[\"name/344\",[111,48.265]],[\"parent/344\",[118,3.093]],[\"name/345\",[50,43.469]],[\"parent/345\",[118,3.093]],[\"name/346\",[81,51.942]],[\"parent/346\",[118,3.093]],[\"name/347\",[12,38.949]],[\"parent/347\",[118,3.093]],[\"name/348\",[1,34.211]],[\"parent/348\",[121,3.093]],[\"name/349\",[14,21.711]],[\"parent/349\",[121,3.093]],[\"name/350\",[11,38.949]],[\"parent/350\",[121,3.093]],[\"name/351\",[116,48.265]],[\"parent/351\",[121,3.093]],[\"name/352\",[105,44.47]],[\"parent/352\",[121,3.093]],[\"name/353\",[45,39.574]],[\"parent/353\",[121,3.093]],[\"name/354\",[104,44.47]],[\"parent/354\",[121,3.093]],[\"name/355\",[68,48.265]],[\"parent/355\",[121,3.093]],[\"name/356\",[75,48.265]],[\"parent/356\",[121,3.093]],[\"name/357\",[69,48.265]],[\"parent/357\",[121,3.093]],[\"name/358\",[70,48.265]],[\"parent/358\",[121,3.093]],[\"name/359\",[120,54.455]],[\"parent/359\",[121,3.093]],[\"name/360\",[77,48.265]],[\"parent/360\",[121,3.093]],[\"name/361\",[78,48.265]],[\"parent/361\",[121,3.093]],[\"name/362\",[72,48.265]],[\"parent/362\",[121,3.093]],[\"name/363\",[73,48.265]],[\"parent/363\",[121,3.093]],[\"name/364\",[71,48.265]],[\"parent/364\",[121,3.093]],[\"name/365\",[74,48.265]],[\"parent/365\",[121,3.093]],[\"name/366\",[79,51.942]],[\"parent/366\",[121,3.093]],[\"name/367\",[119,57.82]],[\"parent/367\",[121,3.093]],[\"name/368\",[106,48.265]],[\"parent/368\",[121,3.093]],[\"name/369\",[14,21.711]],[\"parent/369\",[121,3.093]],[\"name/370\",[107,48.265]],[\"parent/370\",[121,3.093]],[\"name/371\",[14,21.711]],[\"parent/371\",[121,3.093]],[\"name/372\",[108,48.265]],[\"parent/372\",[121,3.093]],[\"name/373\",[14,21.711]],[\"parent/373\",[121,3.093]],[\"name/374\",[109,48.265]],[\"parent/374\",[121,3.093]],[\"name/375\",[14,21.711]],[\"parent/375\",[121,3.093]],[\"name/376\",[110,48.265]],[\"parent/376\",[121,3.093]],[\"name/377\",[14,21.711]],[\"parent/377\",[121,3.093]],[\"name/378\",[111,48.265]],[\"parent/378\",[121,3.093]],[\"name/379\",[14,21.711]],[\"parent/379\",[121,3.093]],[\"name/380\",[50,43.469]],[\"parent/380\",[121,3.093]],[\"name/381\",[81,51.942]],[\"parent/381\",[121,3.093]],[\"name/382\",[15,38.361]],[\"parent/382\",[121,3.093]],[\"name/383\",[122,45.582]],[\"parent/383\",[]],[\"name/384\",[1,34.211]],[\"parent/384\",[122,4.507]],[\"name/385\",[123,54.455]],[\"parent/385\",[122,4.507]],[\"name/386\",[124,54.455]],[\"parent/386\",[122,4.507]],[\"name/387\",[125,54.455]],[\"parent/387\",[122,4.507]],[\"name/388\",[12,38.949]],[\"parent/388\",[122,4.507]],[\"name/389\",[1,34.211]],[\"parent/389\",[126,4.772]],[\"name/390\",[14,21.711]],[\"parent/390\",[126,4.772]],[\"name/391\",[123,54.455]],[\"parent/391\",[126,4.772]],[\"name/392\",[124,54.455]],[\"parent/392\",[126,4.772]],[\"name/393\",[125,54.455]],[\"parent/393\",[126,4.772]],[\"name/394\",[15,38.361]],[\"parent/394\",[126,4.772]],[\"name/395\",[127,38.949]],[\"parent/395\",[]],[\"name/396\",[1,34.211]],[\"parent/396\",[127,3.851]],[\"name/397\",[128,54.455]],[\"parent/397\",[127,3.851]],[\"name/398\",[129,54.455]],[\"parent/398\",[127,3.851]],[\"name/399\",[130,54.455]],[\"parent/399\",[127,3.851]],[\"name/400\",[131,54.455]],[\"parent/400\",[127,3.851]],[\"name/401\",[132,54.455]],[\"parent/401\",[127,3.851]],[\"name/402\",[133,54.455]],[\"parent/402\",[127,3.851]],[\"name/403\",[134,54.455]],[\"parent/403\",[127,3.851]],[\"name/404\",[135,54.455]],[\"parent/404\",[127,3.851]],[\"name/405\",[136,54.455]],[\"parent/405\",[127,3.851]],[\"name/406\",[137,54.455]],[\"parent/406\",[127,3.851]],[\"name/407\",[12,38.949]],[\"parent/407\",[127,3.851]],[\"name/408\",[1,34.211]],[\"parent/408\",[138,3.913]],[\"name/409\",[14,21.711]],[\"parent/409\",[138,3.913]],[\"name/410\",[139,57.82]],[\"parent/410\",[138,3.913]],[\"name/411\",[140,57.82]],[\"parent/411\",[138,3.913]],[\"name/412\",[128,54.455]],[\"parent/412\",[138,3.913]],[\"name/413\",[129,54.455]],[\"parent/413\",[138,3.913]],[\"name/414\",[130,54.455]],[\"parent/414\",[138,3.913]],[\"name/415\",[131,54.455]],[\"parent/415\",[138,3.913]],[\"name/416\",[132,54.455]],[\"parent/416\",[138,3.913]],[\"name/417\",[133,54.455]],[\"parent/417\",[138,3.913]],[\"name/418\",[134,54.455]],[\"parent/418\",[138,3.913]],[\"name/419\",[135,54.455]],[\"parent/419\",[138,3.913]],[\"name/420\",[136,54.455]],[\"parent/420\",[138,3.913]],[\"name/421\",[137,54.455]],[\"parent/421\",[138,3.913]],[\"name/422\",[15,38.361]],[\"parent/422\",[138,3.913]],[\"name/423\",[141,62.928]],[\"parent/423\",[16,4.208]],[\"name/424\",[15,38.361]],[\"parent/424\",[142,3.793]],[\"name/425\",[143,57.82]],[\"parent/425\",[142,3.793]],[\"name/426\",[144,57.82]],[\"parent/426\",[142,3.793]],[\"name/427\",[145,62.928]],[\"parent/427\",[142,3.793]],[\"name/428\",[14,21.711]],[\"parent/428\",[142,3.793]],[\"name/429\",[146,62.928]],[\"parent/429\",[142,3.793]],[\"name/430\",[14,21.711]],[\"parent/430\",[142,3.793]],[\"name/431\",[147,62.928]],[\"parent/431\",[142,3.793]],[\"name/432\",[14,21.711]],[\"parent/432\",[142,3.793]],[\"name/433\",[148,62.928]],[\"parent/433\",[142,3.793]],[\"name/434\",[14,21.711]],[\"parent/434\",[142,3.793]],[\"name/435\",[149,62.928]],[\"parent/435\",[142,3.793]],[\"name/436\",[14,21.711]],[\"parent/436\",[142,3.793]],[\"name/437\",[150,62.928]],[\"parent/437\",[142,3.793]],[\"name/438\",[14,21.711]],[\"parent/438\",[142,3.793]],[\"name/439\",[151,62.928]],[\"parent/439\",[142,3.793]],[\"name/440\",[14,21.711]],[\"parent/440\",[142,3.793]],[\"name/441\",[152,62.928]],[\"parent/441\",[16,4.208]],[\"name/442\",[15,38.361]],[\"parent/442\",[153,3.913]],[\"name/443\",[143,57.82]],[\"parent/443\",[153,3.913]],[\"name/444\",[144,57.82]],[\"parent/444\",[153,3.913]],[\"name/445\",[154,62.928]],[\"parent/445\",[153,3.913]],[\"name/446\",[14,21.711]],[\"parent/446\",[153,3.913]],[\"name/447\",[155,62.928]],[\"parent/447\",[153,3.913]],[\"name/448\",[14,21.711]],[\"parent/448\",[153,3.913]],[\"name/449\",[156,62.928]],[\"parent/449\",[153,3.913]],[\"name/450\",[14,21.711]],[\"parent/450\",[153,3.913]],[\"name/451\",[157,62.928]],[\"parent/451\",[153,3.913]],[\"name/452\",[14,21.711]],[\"parent/452\",[153,3.913]],[\"name/453\",[158,62.928]],[\"parent/453\",[153,3.913]],[\"name/454\",[14,21.711]],[\"parent/454\",[153,3.913]],[\"name/455\",[159,62.928]],[\"parent/455\",[153,3.913]],[\"name/456\",[14,21.711]],[\"parent/456\",[153,3.913]],[\"name/457\",[160,62.928]],[\"parent/457\",[24,4.772]],[\"name/458\",[161,46.834]],[\"parent/458\",[162,5.384]],[\"name/459\",[163,57.82]],[\"parent/459\",[162,5.384]],[\"name/460\",[14,21.711]],[\"parent/460\",[162,5.384]],[\"name/461\",[164,57.82]],[\"parent/461\",[165,5.717]],[\"name/462\",[14,21.711]],[\"parent/462\",[165,5.717]],[\"name/463\",[166,57.82]],[\"parent/463\",[167,5.717]],[\"name/464\",[168,57.82]],[\"parent/464\",[167,5.717]],[\"name/465\",[169,62.928]],[\"parent/465\",[24,4.772]],[\"name/466\",[161,46.834]],[\"parent/466\",[170,5.136]],[\"name/467\",[163,57.82]],[\"parent/467\",[170,5.136]],[\"name/468\",[14,21.711]],[\"parent/468\",[170,5.136]],[\"name/469\",[164,57.82]],[\"parent/469\",[171,5.136]],[\"name/470\",[14,21.711]],[\"parent/470\",[171,5.136]],[\"name/471\",[166,57.82]],[\"parent/471\",[172,5.384]],[\"name/472\",[168,57.82]],[\"parent/472\",[172,5.384]],[\"name/473\",[14,21.711]],[\"parent/473\",[170,5.136]],[\"name/474\",[14,21.711]],[\"parent/474\",[171,5.136]],[\"name/475\",[14,21.711]],[\"parent/475\",[172,5.384]],[\"name/476\",[14,21.711]],[\"parent/476\",[173,6.222]],[\"name/477\",[14,21.711]],[\"parent/477\",[171,5.136]],[\"name/478\",[174,54.455]],[\"parent/478\",[28,4.772]],[\"name/479\",[161,46.834]],[\"parent/479\",[175,6.222]],[\"name/480\",[174,54.455]],[\"parent/480\",[30,4.772]],[\"name/481\",[161,46.834]],[\"parent/481\",[176,6.222]],[\"name/482\",[174,54.455]],[\"parent/482\",[32,4.937]],[\"name/483\",[161,46.834]],[\"parent/483\",[177,5.717]],[\"name/484\",[14,21.711]],[\"parent/484\",[177,5.717]],[\"name/485\",[178,57.82]],[\"parent/485\",[33,4.937]],[\"name/486\",[161,46.834]],[\"parent/486\",[179,6.222]],[\"name/487\",[178,57.82]],[\"parent/487\",[34,4.937]],[\"name/488\",[161,46.834]],[\"parent/488\",[180,6.222]],[\"name/489\",[181,42.559]],[\"parent/489\",[40,4.772]],[\"name/490\",[14,21.711]],[\"parent/490\",[182,6.222]],[\"name/491\",[183,62.928]],[\"parent/491\",[184,5.717]],[\"name/492\",[185,62.928]],[\"parent/492\",[184,5.717]],[\"name/493\",[186,46.834]],[\"parent/493\",[40,4.772]],[\"name/494\",[14,21.711]],[\"parent/494\",[187,6.222]],[\"name/495\",[188,46.834]],[\"parent/495\",[189,4.63]],[\"name/496\",[190,46.834]],[\"parent/496\",[189,4.63]],[\"name/497\",[191,46.834]],[\"parent/497\",[189,4.63]],[\"name/498\",[192,46.834]],[\"parent/498\",[189,4.63]],[\"name/499\",[193,46.834]],[\"parent/499\",[189,4.63]],[\"name/500\",[194,46.834]],[\"parent/500\",[189,4.63]],[\"name/501\",[195,49.935]],[\"parent/501\",[189,4.63]],[\"name/502\",[196,44.47]],[\"parent/502\",[40,4.772]],[\"name/503\",[14,21.711]],[\"parent/503\",[197,6.222]],[\"name/504\",[198,62.928]],[\"parent/504\",[199,6.222]],[\"name/505\",[181,42.559]],[\"parent/505\",[42,3.851]],[\"name/506\",[14,21.711]],[\"parent/506\",[200,6.222]],[\"name/507\",[43,54.455]],[\"parent/507\",[201,4.63]],[\"name/508\",[44,54.455]],[\"parent/508\",[201,4.63]],[\"name/509\",[45,39.574]],[\"parent/509\",[201,4.63]],[\"name/510\",[46,48.265]],[\"parent/510\",[201,4.63]],[\"name/511\",[47,48.265]],[\"parent/511\",[201,4.63]],[\"name/512\",[48,48.265]],[\"parent/512\",[201,4.63]],[\"name/513\",[49,48.265]],[\"parent/513\",[201,4.63]],[\"name/514\",[202,48.265]],[\"parent/514\",[42,3.851]],[\"name/515\",[14,21.711]],[\"parent/515\",[203,6.222]],[\"name/516\",[204,45.582]],[\"parent/516\",[205,5.384]],[\"name/517\",[206,49.935]],[\"parent/517\",[205,5.384]],[\"name/518\",[207,51.942]],[\"parent/518\",[205,5.384]],[\"name/519\",[186,46.834]],[\"parent/519\",[42,3.851]],[\"name/520\",[14,21.711]],[\"parent/520\",[208,6.222]],[\"name/521\",[188,46.834]],[\"parent/521\",[209,4.507]],[\"name/522\",[195,49.935]],[\"parent/522\",[209,4.507]],[\"name/523\",[190,46.834]],[\"parent/523\",[209,4.507]],[\"name/524\",[191,46.834]],[\"parent/524\",[209,4.507]],[\"name/525\",[194,46.834]],[\"parent/525\",[209,4.507]],[\"name/526\",[192,46.834]],[\"parent/526\",[209,4.507]],[\"name/527\",[193,46.834]],[\"parent/527\",[209,4.507]],[\"name/528\",[210,54.455]],[\"parent/528\",[209,4.507]],[\"name/529\",[196,44.47]],[\"parent/529\",[42,3.851]],[\"name/530\",[14,21.711]],[\"parent/530\",[211,6.222]],[\"name/531\",[212,57.82]],[\"parent/531\",[213,4.937]],[\"name/532\",[214,57.82]],[\"parent/532\",[213,4.937]],[\"name/533\",[215,57.82]],[\"parent/533\",[213,4.937]],[\"name/534\",[216,62.928]],[\"parent/534\",[213,4.937]],[\"name/535\",[217,62.928]],[\"parent/535\",[213,4.937]],[\"name/536\",[181,42.559]],[\"parent/536\",[52,3.913]],[\"name/537\",[14,21.711]],[\"parent/537\",[218,6.222]],[\"name/538\",[53,54.455]],[\"parent/538\",[219,4.937]],[\"name/539\",[54,54.455]],[\"parent/539\",[219,4.937]],[\"name/540\",[55,54.455]],[\"parent/540\",[219,4.937]],[\"name/541\",[56,54.455]],[\"parent/541\",[219,4.937]],[\"name/542\",[57,54.455]],[\"parent/542\",[219,4.937]],[\"name/543\",[186,46.834]],[\"parent/543\",[52,3.913]],[\"name/544\",[14,21.711]],[\"parent/544\",[220,6.222]],[\"name/545\",[188,46.834]],[\"parent/545\",[221,4.507]],[\"name/546\",[195,49.935]],[\"parent/546\",[221,4.507]],[\"name/547\",[190,46.834]],[\"parent/547\",[221,4.507]],[\"name/548\",[191,46.834]],[\"parent/548\",[221,4.507]],[\"name/549\",[194,46.834]],[\"parent/549\",[221,4.507]],[\"name/550\",[192,46.834]],[\"parent/550\",[221,4.507]],[\"name/551\",[193,46.834]],[\"parent/551\",[221,4.507]],[\"name/552\",[210,54.455]],[\"parent/552\",[221,4.507]],[\"name/553\",[196,44.47]],[\"parent/553\",[52,3.913]],[\"name/554\",[14,21.711]],[\"parent/554\",[222,6.222]],[\"name/555\",[223,62.928]],[\"parent/555\",[224,5.384]],[\"name/556\",[225,62.928]],[\"parent/556\",[224,5.384]],[\"name/557\",[226,62.928]],[\"parent/557\",[224,5.384]],[\"name/558\",[202,48.265]],[\"parent/558\",[52,3.913]],[\"name/559\",[14,21.711]],[\"parent/559\",[227,6.222]],[\"name/560\",[204,45.582]],[\"parent/560\",[228,5.717]],[\"name/561\",[206,49.935]],[\"parent/561\",[228,5.717]],[\"name/562\",[59,57.82]],[\"parent/562\",[52,3.913]],[\"name/563\",[196,44.47]],[\"parent/563\",[60,4.397]],[\"name/564\",[14,21.711]],[\"parent/564\",[229,6.222]],[\"name/565\",[230,62.928]],[\"parent/565\",[231,6.222]],[\"name/566\",[186,46.834]],[\"parent/566\",[60,4.397]],[\"name/567\",[14,21.711]],[\"parent/567\",[232,6.222]],[\"name/568\",[188,46.834]],[\"parent/568\",[233,4.772]],[\"name/569\",[190,46.834]],[\"parent/569\",[233,4.772]],[\"name/570\",[191,46.834]],[\"parent/570\",[233,4.772]],[\"name/571\",[194,46.834]],[\"parent/571\",[233,4.772]],[\"name/572\",[192,46.834]],[\"parent/572\",[233,4.772]],[\"name/573\",[193,46.834]],[\"parent/573\",[233,4.772]],[\"name/574\",[181,42.559]],[\"parent/574\",[60,4.397]],[\"name/575\",[14,21.711]],[\"parent/575\",[234,6.222]],[\"name/576\",[61,46.834]],[\"parent/576\",[235,5.717]],[\"name/577\",[62,46.834]],[\"parent/577\",[235,5.717]],[\"name/578\",[236,62.928]],[\"parent/578\",[60,4.397]],[\"name/579\",[14,21.711]],[\"parent/579\",[237,6.222]],[\"name/580\",[238,62.928]],[\"parent/580\",[239,4.772]],[\"name/581\",[240,62.928]],[\"parent/581\",[239,4.772]],[\"name/582\",[241,62.928]],[\"parent/582\",[239,4.772]],[\"name/583\",[242,62.928]],[\"parent/583\",[239,4.772]],[\"name/584\",[243,62.928]],[\"parent/584\",[239,4.772]],[\"name/585\",[244,62.928]],[\"parent/585\",[239,4.772]],[\"name/586\",[181,42.559]],[\"parent/586\",[67,3.421]],[\"name/587\",[14,21.711]],[\"parent/587\",[245,6.222]],[\"name/588\",[68,48.265]],[\"parent/588\",[246,4.049]],[\"name/589\",[75,48.265]],[\"parent/589\",[246,4.049]],[\"name/590\",[69,48.265]],[\"parent/590\",[246,4.049]],[\"name/591\",[45,39.574]],[\"parent/591\",[246,4.049]],[\"name/592\",[46,48.265]],[\"parent/592\",[246,4.049]],[\"name/593\",[70,48.265]],[\"parent/593\",[246,4.049]],[\"name/594\",[76,54.455]],[\"parent/594\",[246,4.049]],[\"name/595\",[77,48.265]],[\"parent/595\",[246,4.049]],[\"name/596\",[78,48.265]],[\"parent/596\",[246,4.049]],[\"name/597\",[72,48.265]],[\"parent/597\",[246,4.049]],[\"name/598\",[73,48.265]],[\"parent/598\",[246,4.049]],[\"name/599\",[71,48.265]],[\"parent/599\",[246,4.049]],[\"name/600\",[74,48.265]],[\"parent/600\",[246,4.049]],[\"name/601\",[202,48.265]],[\"parent/601\",[67,3.421]],[\"name/602\",[14,21.711]],[\"parent/602\",[247,6.222]],[\"name/603\",[204,45.582]],[\"parent/603\",[248,5.136]],[\"name/604\",[206,49.935]],[\"parent/604\",[248,5.136]],[\"name/605\",[249,62.928]],[\"parent/605\",[248,5.136]],[\"name/606\",[207,51.942]],[\"parent/606\",[248,5.136]],[\"name/607\",[186,46.834]],[\"parent/607\",[67,3.421]],[\"name/608\",[14,21.711]],[\"parent/608\",[250,6.222]],[\"name/609\",[188,46.834]],[\"parent/609\",[251,4.397]],[\"name/610\",[195,49.935]],[\"parent/610\",[251,4.397]],[\"name/611\",[190,46.834]],[\"parent/611\",[251,4.397]],[\"name/612\",[191,46.834]],[\"parent/612\",[251,4.397]],[\"name/613\",[194,46.834]],[\"parent/613\",[251,4.397]],[\"name/614\",[192,46.834]],[\"parent/614\",[251,4.397]],[\"name/615\",[193,46.834]],[\"parent/615\",[251,4.397]],[\"name/616\",[210,54.455]],[\"parent/616\",[251,4.397]],[\"name/617\",[252,62.928]],[\"parent/617\",[251,4.397]],[\"name/618\",[196,44.47]],[\"parent/618\",[67,3.421]],[\"name/619\",[14,21.711]],[\"parent/619\",[253,6.222]],[\"name/620\",[254,57.82]],[\"parent/620\",[255,4.937]],[\"name/621\",[256,57.82]],[\"parent/621\",[255,4.937]],[\"name/622\",[257,57.82]],[\"parent/622\",[255,4.937]],[\"name/623\",[212,57.82]],[\"parent/623\",[255,4.937]],[\"name/624\",[258,62.928]],[\"parent/624\",[255,4.937]],[\"name/625\",[259,62.928]],[\"parent/625\",[83,3.212]],[\"name/626\",[260,62.928]],[\"parent/626\",[261,5.384]],[\"name/627\",[262,62.928]],[\"parent/627\",[261,5.384]],[\"name/628\",[263,62.928]],[\"parent/628\",[261,5.384]],[\"name/629\",[181,42.559]],[\"parent/629\",[83,3.212]],[\"name/630\",[14,21.711]],[\"parent/630\",[264,6.222]],[\"name/631\",[84,54.455]],[\"parent/631\",[265,3.589]],[\"name/632\",[266,62.928]],[\"parent/632\",[265,3.589]],[\"name/633\",[85,54.455]],[\"parent/633\",[265,3.589]],[\"name/634\",[87,54.455]],[\"parent/634\",[265,3.589]],[\"name/635\",[86,54.455]],[\"parent/635\",[265,3.589]],[\"name/636\",[88,54.455]],[\"parent/636\",[265,3.589]],[\"name/637\",[89,54.455]],[\"parent/637\",[265,3.589]],[\"name/638\",[90,51.942]],[\"parent/638\",[265,3.589]],[\"name/639\",[91,54.455]],[\"parent/639\",[265,3.589]],[\"name/640\",[92,51.942]],[\"parent/640\",[265,3.589]],[\"name/641\",[93,51.942]],[\"parent/641\",[265,3.589]],[\"name/642\",[94,51.942]],[\"parent/642\",[265,3.589]],[\"name/643\",[102,57.82]],[\"parent/643\",[265,3.589]],[\"name/644\",[267,62.928]],[\"parent/644\",[265,3.589]],[\"name/645\",[268,62.928]],[\"parent/645\",[265,3.589]],[\"name/646\",[269,62.928]],[\"parent/646\",[265,3.589]],[\"name/647\",[99,54.455]],[\"parent/647\",[265,3.589]],[\"name/648\",[95,51.942]],[\"parent/648\",[265,3.589]],[\"name/649\",[96,51.942]],[\"parent/649\",[265,3.589]],[\"name/650\",[97,51.942]],[\"parent/650\",[265,3.589]],[\"name/651\",[98,51.942]],[\"parent/651\",[265,3.589]],[\"name/652\",[270,62.928]],[\"parent/652\",[83,3.212]],[\"name/653\",[90,51.942]],[\"parent/653\",[271,3.851]],[\"name/654\",[272,62.928]],[\"parent/654\",[271,3.851]],[\"name/655\",[92,51.942]],[\"parent/655\",[271,3.851]],[\"name/656\",[273,62.928]],[\"parent/656\",[271,3.851]],[\"name/657\",[274,62.928]],[\"parent/657\",[271,3.851]],[\"name/658\",[275,62.928]],[\"parent/658\",[271,3.851]],[\"name/659\",[276,62.928]],[\"parent/659\",[271,3.851]],[\"name/660\",[93,51.942]],[\"parent/660\",[271,3.851]],[\"name/661\",[94,51.942]],[\"parent/661\",[271,3.851]],[\"name/662\",[277,62.928]],[\"parent/662\",[271,3.851]],[\"name/663\",[278,62.928]],[\"parent/663\",[271,3.851]],[\"name/664\",[279,62.928]],[\"parent/664\",[271,3.851]],[\"name/665\",[95,51.942]],[\"parent/665\",[271,3.851]],[\"name/666\",[96,51.942]],[\"parent/666\",[271,3.851]],[\"name/667\",[97,51.942]],[\"parent/667\",[271,3.851]],[\"name/668\",[98,51.942]],[\"parent/668\",[271,3.851]],[\"name/669\",[196,44.47]],[\"parent/669\",[83,3.212]],[\"name/670\",[14,21.711]],[\"parent/670\",[280,6.222]],[\"name/671\",[281,62.928]],[\"parent/671\",[282,5.384]],[\"name/672\",[283,62.928]],[\"parent/672\",[282,5.384]],[\"name/673\",[284,62.928]],[\"parent/673\",[282,5.384]],[\"name/674\",[186,46.834]],[\"parent/674\",[83,3.212]],[\"name/675\",[14,21.711]],[\"parent/675\",[285,6.222]],[\"name/676\",[188,46.834]],[\"parent/676\",[286,4.772]],[\"name/677\",[190,46.834]],[\"parent/677\",[286,4.772]],[\"name/678\",[191,46.834]],[\"parent/678\",[286,4.772]],[\"name/679\",[194,46.834]],[\"parent/679\",[286,4.772]],[\"name/680\",[192,46.834]],[\"parent/680\",[286,4.772]],[\"name/681\",[193,46.834]],[\"parent/681\",[286,4.772]],[\"name/682\",[287,62.928]],[\"parent/682\",[83,3.212]],[\"name/683\",[14,21.711]],[\"parent/683\",[288,6.222]],[\"name/684\",[289,62.928]],[\"parent/684\",[290,4.772]],[\"name/685\",[291,54.455]],[\"parent/685\",[290,4.772]],[\"name/686\",[292,62.928]],[\"parent/686\",[290,4.772]],[\"name/687\",[293,62.928]],[\"parent/687\",[290,4.772]],[\"name/688\",[294,62.928]],[\"parent/688\",[290,4.772]],[\"name/689\",[295,62.928]],[\"parent/689\",[290,4.772]],[\"name/690\",[296,62.928]],[\"parent/690\",[83,3.212]],[\"name/691\",[181,42.559]],[\"parent/691\",[103,3.686]],[\"name/692\",[14,21.711]],[\"parent/692\",[297,6.222]],[\"name/693\",[45,39.574]],[\"parent/693\",[298,5.136]],[\"name/694\",[104,44.47]],[\"parent/694\",[298,5.136]],[\"name/695\",[105,44.47]],[\"parent/695\",[298,5.136]],[\"name/696\",[80,49.935]],[\"parent/696\",[298,5.136]],[\"name/697\",[202,48.265]],[\"parent/697\",[103,3.686]],[\"name/698\",[14,21.711]],[\"parent/698\",[299,6.222]],[\"name/699\",[204,45.582]],[\"parent/699\",[300,4.937]],[\"name/700\",[207,51.942]],[\"parent/700\",[300,4.937]],[\"name/701\",[206,49.935]],[\"parent/701\",[300,4.937]],[\"name/702\",[301,57.82]],[\"parent/702\",[300,4.937]],[\"name/703\",[14,21.711]],[\"parent/703\",[300,4.937]],[\"name/704\",[204,45.582]],[\"parent/704\",[302,5.717]],[\"name/705\",[291,54.455]],[\"parent/705\",[302,5.717]],[\"name/706\",[196,44.47]],[\"parent/706\",[103,3.686]],[\"name/707\",[14,21.711]],[\"parent/707\",[303,6.222]],[\"name/708\",[304,54.455]],[\"parent/708\",[305,5.384]],[\"name/709\",[306,62.928]],[\"parent/709\",[305,5.384]],[\"name/710\",[307,54.455]],[\"parent/710\",[305,5.384]],[\"name/711\",[186,46.834]],[\"parent/711\",[103,3.686]],[\"name/712\",[14,21.711]],[\"parent/712\",[308,6.222]],[\"name/713\",[188,46.834]],[\"parent/713\",[309,4.507]],[\"name/714\",[190,46.834]],[\"parent/714\",[309,4.507]],[\"name/715\",[191,46.834]],[\"parent/715\",[309,4.507]],[\"name/716\",[194,46.834]],[\"parent/716\",[309,4.507]],[\"name/717\",[310,62.928]],[\"parent/717\",[309,4.507]],[\"name/718\",[192,46.834]],[\"parent/718\",[309,4.507]],[\"name/719\",[193,46.834]],[\"parent/719\",[309,4.507]],[\"name/720\",[195,49.935]],[\"parent/720\",[309,4.507]],[\"name/721\",[311,54.455]],[\"parent/721\",[103,3.686]],[\"name/722\",[14,21.711]],[\"parent/722\",[312,6.222]],[\"name/723\",[204,45.582]],[\"parent/723\",[313,5.384]],[\"name/724\",[314,62.928]],[\"parent/724\",[313,5.384]],[\"name/725\",[315,62.928]],[\"parent/725\",[313,5.384]],[\"name/726\",[181,42.559]],[\"parent/726\",[113,3.382]],[\"name/727\",[14,21.711]],[\"parent/727\",[316,6.222]],[\"name/728\",[45,39.574]],[\"parent/728\",[317,4.397]],[\"name/729\",[104,44.47]],[\"parent/729\",[317,4.397]],[\"name/730\",[105,44.47]],[\"parent/730\",[317,4.397]],[\"name/731\",[116,48.265]],[\"parent/731\",[317,4.397]],[\"name/732\",[114,54.455]],[\"parent/732\",[317,4.397]],[\"name/733\",[115,54.455]],[\"parent/733\",[317,4.397]],[\"name/734\",[47,48.265]],[\"parent/734\",[317,4.397]],[\"name/735\",[48,48.265]],[\"parent/735\",[317,4.397]],[\"name/736\",[49,48.265]],[\"parent/736\",[317,4.397]],[\"name/737\",[311,54.455]],[\"parent/737\",[113,3.382]],[\"name/738\",[202,48.265]],[\"parent/738\",[113,3.382]],[\"name/739\",[14,21.711]],[\"parent/739\",[318,6.222]],[\"name/740\",[204,45.582]],[\"parent/740\",[319,4.937]],[\"name/741\",[207,51.942]],[\"parent/741\",[319,4.937]],[\"name/742\",[206,49.935]],[\"parent/742\",[319,4.937]],[\"name/743\",[301,57.82]],[\"parent/743\",[319,4.937]],[\"name/744\",[14,21.711]],[\"parent/744\",[319,4.937]],[\"name/745\",[204,45.582]],[\"parent/745\",[320,5.717]],[\"name/746\",[291,54.455]],[\"parent/746\",[320,5.717]],[\"name/747\",[196,44.47]],[\"parent/747\",[113,3.382]],[\"name/748\",[14,21.711]],[\"parent/748\",[321,6.222]],[\"name/749\",[304,54.455]],[\"parent/749\",[322,4.507]],[\"name/750\",[323,62.928]],[\"parent/750\",[322,4.507]],[\"name/751\",[214,57.82]],[\"parent/751\",[322,4.507]],[\"name/752\",[215,57.82]],[\"parent/752\",[322,4.507]],[\"name/753\",[324,57.82]],[\"parent/753\",[322,4.507]],[\"name/754\",[325,62.928]],[\"parent/754\",[322,4.507]],[\"name/755\",[326,62.928]],[\"parent/755\",[322,4.507]],[\"name/756\",[307,54.455]],[\"parent/756\",[322,4.507]],[\"name/757\",[327,62.928]],[\"parent/757\",[113,3.382]],[\"name/758\",[328,57.82]],[\"parent/758\",[113,3.382]],[\"name/759\",[181,42.559]],[\"parent/759\",[118,3.093]],[\"name/760\",[14,21.711]],[\"parent/760\",[329,6.222]],[\"name/761\",[45,39.574]],[\"parent/761\",[330,3.913]],[\"name/762\",[104,44.47]],[\"parent/762\",[330,3.913]],[\"name/763\",[70,48.265]],[\"parent/763\",[330,3.913]],[\"name/764\",[105,44.47]],[\"parent/764\",[330,3.913]],[\"name/765\",[116,48.265]],[\"parent/765\",[330,3.913]],[\"name/766\",[68,48.265]],[\"parent/766\",[330,3.913]],[\"name/767\",[75,48.265]],[\"parent/767\",[330,3.913]],[\"name/768\",[69,48.265]],[\"parent/768\",[330,3.913]],[\"name/769\",[120,54.455]],[\"parent/769\",[330,3.913]],[\"name/770\",[77,48.265]],[\"parent/770\",[330,3.913]],[\"name/771\",[78,48.265]],[\"parent/771\",[330,3.913]],[\"name/772\",[72,48.265]],[\"parent/772\",[330,3.913]],[\"name/773\",[73,48.265]],[\"parent/773\",[330,3.913]],[\"name/774\",[71,48.265]],[\"parent/774\",[330,3.913]],[\"name/775\",[74,48.265]],[\"parent/775\",[330,3.913]],[\"name/776\",[311,54.455]],[\"parent/776\",[118,3.093]],[\"name/777\",[202,48.265]],[\"parent/777\",[118,3.093]],[\"name/778\",[196,44.47]],[\"parent/778\",[118,3.093]],[\"name/779\",[14,21.711]],[\"parent/779\",[331,6.222]],[\"name/780\",[304,54.455]],[\"parent/780\",[332,4.507]],[\"name/781\",[324,57.82]],[\"parent/781\",[332,4.507]],[\"name/782\",[307,54.455]],[\"parent/782\",[332,4.507]],[\"name/783\",[254,57.82]],[\"parent/783\",[332,4.507]],[\"name/784\",[256,57.82]],[\"parent/784\",[332,4.507]],[\"name/785\",[257,57.82]],[\"parent/785\",[332,4.507]],[\"name/786\",[333,62.928]],[\"parent/786\",[332,4.507]],[\"name/787\",[334,62.928]],[\"parent/787\",[332,4.507]],[\"name/788\",[335,62.928]],[\"parent/788\",[118,3.093]],[\"name/789\",[328,57.82]],[\"parent/789\",[118,3.093]],[\"name/790\",[181,42.559]],[\"parent/790\",[122,4.507]],[\"name/791\",[14,21.711]],[\"parent/791\",[336,6.222]],[\"name/792\",[123,54.455]],[\"parent/792\",[337,5.384]],[\"name/793\",[124,54.455]],[\"parent/793\",[337,5.384]],[\"name/794\",[125,54.455]],[\"parent/794\",[337,5.384]],[\"name/795\",[338,62.928]],[\"parent/795\",[122,4.507]],[\"name/796\",[140,57.82]],[\"parent/796\",[127,3.851]],[\"name/797\",[139,57.82]],[\"parent/797\",[127,3.851]],[\"name/798\",[181,42.559]],[\"parent/798\",[127,3.851]],[\"name/799\",[14,21.711]],[\"parent/799\",[339,6.222]],[\"name/800\",[128,54.455]],[\"parent/800\",[340,4.298]],[\"name/801\",[129,54.455]],[\"parent/801\",[340,4.298]],[\"name/802\",[130,54.455]],[\"parent/802\",[340,4.298]],[\"name/803\",[131,54.455]],[\"parent/803\",[340,4.298]],[\"name/804\",[132,54.455]],[\"parent/804\",[340,4.298]],[\"name/805\",[133,54.455]],[\"parent/805\",[340,4.298]],[\"name/806\",[134,54.455]],[\"parent/806\",[340,4.298]],[\"name/807\",[135,54.455]],[\"parent/807\",[340,4.298]],[\"name/808\",[136,54.455]],[\"parent/808\",[340,4.298]],[\"name/809\",[137,54.455]],[\"parent/809\",[340,4.298]]],\"invertedIndex\":[[\"__type\",{\"_index\":14,\"name\":{\"14\":{},\"34\":{},\"79\":{},\"94\":{},\"116\":{},\"132\":{},\"143\":{},\"170\":{},\"215\":{},\"254\":{},\"261\":{},\"263\":{},\"265\":{},\"267\":{},\"269\":{},\"271\":{},\"294\":{},\"306\":{},\"308\":{},\"310\":{},\"312\":{},\"314\":{},\"316\":{},\"349\":{},\"369\":{},\"371\":{},\"373\":{},\"375\":{},\"377\":{},\"379\":{},\"390\":{},\"409\":{},\"428\":{},\"430\":{},\"432\":{},\"434\":{},\"436\":{},\"438\":{},\"440\":{},\"446\":{},\"448\":{},\"450\":{},\"452\":{},\"454\":{},\"456\":{},\"460\":{},\"462\":{},\"468\":{},\"470\":{},\"473\":{},\"474\":{},\"475\":{},\"476\":{},\"477\":{},\"484\":{},\"490\":{},\"494\":{},\"503\":{},\"506\":{},\"515\":{},\"520\":{},\"530\":{},\"537\":{},\"544\":{},\"554\":{},\"559\":{},\"564\":{},\"567\":{},\"575\":{},\"579\":{},\"587\":{},\"602\":{},\"608\":{},\"619\":{},\"630\":{},\"670\":{},\"675\":{},\"683\":{},\"692\":{},\"698\":{},\"703\":{},\"707\":{},\"712\":{},\"722\":{},\"727\":{},\"739\":{},\"744\":{},\"748\":{},\"760\":{},\"779\":{},\"791\":{},\"799\":{}},\"parent\":{}}],[\"accesstokenpayload\",{\"_index\":294,\"name\":{\"688\":{}},\"parent\":{}}],[\"addroletouser\",{\"_index\":128,\"name\":{\"397\":{},\"412\":{},\"800\":{}},\"parent\":{}}],[\"alg\",{\"_index\":243,\"name\":{\"584\":{}},\"parent\":{}}],[\"anticsrfcheck\",{\"_index\":260,\"name\":{\"626\":{}},\"parent\":{}}],[\"apiinterface\",{\"_index\":196,\"name\":{\"502\":{},\"529\":{},\"553\":{},\"563\":{},\"618\":{},\"669\":{},\"706\":{},\"747\":{},\"778\":{}},\"parent\":{}}],[\"apioptions\",{\"_index\":186,\"name\":{\"493\":{},\"519\":{},\"543\":{},\"566\":{},\"607\":{},\"674\":{},\"711\":{}},\"parent\":{}}],[\"appinfo\",{\"_index\":195,\"name\":{\"501\":{},\"522\":{},\"546\":{},\"610\":{},\"720\":{}},\"parent\":{}}],[\"apple\",{\"_index\":109,\"name\":{\"249\":{},\"266\":{},\"288\":{},\"311\":{},\"342\":{},\"374\":{}},\"parent\":{}}],[\"appleredirecthandlerpost\",{\"_index\":307,\"name\":{\"710\":{},\"756\":{},\"782\":{}},\"parent\":{}}],[\"assertclaims\",{\"_index\":279,\"name\":{\"664\":{}},\"parent\":{}}],[\"authorisationurlget\",{\"_index\":304,\"name\":{\"708\":{},\"749\":{},\"780\":{}},\"parent\":{}}],[\"awslambda\",{\"_index\":22,\"name\":{\"32\":{},\"40\":{}},\"parent\":{}}],[\"baserequest\",{\"_index\":141,\"name\":{\"423\":{}},\"parent\":{}}],[\"baseresponse\",{\"_index\":152,\"name\":{\"441\":{}},\"parent\":{}}],[\"clearusermetadata\",{\"_index\":125,\"name\":{\"387\":{},\"393\":{},\"794\":{}},\"parent\":{}}],[\"config\",{\"_index\":190,\"name\":{\"496\":{},\"523\":{},\"547\":{},\"569\":{},\"611\":{},\"677\":{},\"714\":{}},\"parent\":{}}],[\"constructor\",{\"_index\":15,\"name\":{\"25\":{},\"69\":{},\"73\":{},\"80\":{},\"104\":{},\"125\":{},\"135\":{},\"147\":{},\"189\":{},\"238\":{},\"272\":{},\"318\":{},\"382\":{},\"394\":{},\"422\":{},\"424\":{},\"442\":{}},\"parent\":{}}],[\"consumecode\",{\"_index\":69,\"name\":{\"152\":{},\"174\":{},\"328\":{},\"357\":{},\"590\":{},\"768\":{}},\"parent\":{}}],[\"consumecodepost\",{\"_index\":257,\"name\":{\"622\":{},\"785\":{}},\"parent\":{}}],[\"cookies\",{\"_index\":168,\"name\":{\"464\":{},\"472\":{}},\"parent\":{}}],[\"createcode\",{\"_index\":68,\"name\":{\"151\":{},\"172\":{},\"327\":{},\"355\":{},\"588\":{},\"766\":{}},\"parent\":{}}],[\"createcodepost\",{\"_index\":254,\"name\":{\"620\":{},\"783\":{}},\"parent\":{}}],[\"createemailverificationtoken\",{\"_index\":53,\"name\":{\"108\":{},\"119\":{},\"538\":{}},\"parent\":{}}],[\"createjwt\",{\"_index\":61,\"name\":{\"128\":{},\"133\":{},\"139\":{},\"145\":{},\"210\":{},\"231\":{},\"576\":{}},\"parent\":{}}],[\"createmagiclink\",{\"_index\":79,\"name\":{\"164\":{},\"185\":{},\"338\":{},\"366\":{}},\"parent\":{}}],[\"createnewcodefordevice\",{\"_index\":75,\"name\":{\"160\":{},\"173\":{},\"334\":{},\"356\":{},\"589\":{},\"767\":{}},\"parent\":{}}],[\"createnewroleoraddpermissions\",{\"_index\":132,\"name\":{\"401\":{},\"416\":{},\"804\":{}},\"parent\":{}}],[\"createnewsession\",{\"_index\":84,\"name\":{\"192\":{},\"217\":{},\"631\":{}},\"parent\":{}}],[\"createresetpasswordtoken\",{\"_index\":47,\"name\":{\"88\":{},\"100\":{},\"282\":{},\"302\":{},\"511\":{},\"734\":{}},\"parent\":{}}],[\"createuseridmapping\",{\"_index\":7,\"name\":{\"7\":{},\"21\":{}},\"parent\":{}}],[\"dashboardget\",{\"_index\":198,\"name\":{\"504\":{}},\"parent\":{}}],[\"default\",{\"_index\":12,\"name\":{\"12\":{},\"33\":{},\"68\":{},\"72\":{},\"77\":{},\"92\":{},\"114\":{},\"130\":{},\"141\":{},\"168\":{},\"213\":{},\"252\":{},\"292\":{},\"347\":{},\"388\":{},\"407\":{}},\"parent\":{}}],[\"deleterole\",{\"_index\":136,\"name\":{\"405\":{},\"420\":{},\"808\":{}},\"parent\":{}}],[\"deleteuser\",{\"_index\":6,\"name\":{\"6\":{},\"20\":{}},\"parent\":{}}],[\"deleteuseridmapping\",{\"_index\":9,\"name\":{\"9\":{},\"23\":{}},\"parent\":{}}],[\"discord\",{\"_index\":110,\"name\":{\"250\":{},\"268\":{},\"289\":{},\"313\":{},\"343\":{},\"376\":{}},\"parent\":{}}],[\"e\",{\"_index\":242,\"name\":{\"583\":{}},\"parent\":{}}],[\"email\",{\"_index\":206,\"name\":{\"517\":{},\"561\":{},\"604\":{},\"701\":{},\"742\":{}},\"parent\":{}}],[\"emaildelivery\",{\"_index\":210,\"name\":{\"528\":{},\"552\":{},\"616\":{}},\"parent\":{}}],[\"emailexistsget\",{\"_index\":212,\"name\":{\"531\":{},\"623\":{}},\"parent\":{}}],[\"emailpasswordapioptions\",{\"_index\":327,\"name\":{\"757\":{}},\"parent\":{}}],[\"emailpasswordemailexistsget\",{\"_index\":323,\"name\":{\"750\":{}},\"parent\":{}}],[\"emailpasswordsignin\",{\"_index\":115,\"name\":{\"277\":{},\"299\":{},\"733\":{}},\"parent\":{}}],[\"emailpasswordsigninpost\",{\"_index\":325,\"name\":{\"754\":{}},\"parent\":{}}],[\"emailpasswordsignup\",{\"_index\":114,\"name\":{\"276\":{},\"298\":{},\"732\":{}},\"parent\":{}}],[\"emailpasswordsignuppost\",{\"_index\":326,\"name\":{\"755\":{}},\"parent\":{}}],[\"emailverificationclaim\",{\"_index\":59,\"name\":{\"118\":{},\"562\":{}},\"parent\":{}}],[\"error\",{\"_index\":11,\"name\":{\"11\":{},\"15\":{},\"83\":{},\"95\":{},\"107\":{},\"117\":{},\"150\":{},\"171\":{},\"209\":{},\"216\":{},\"241\":{},\"255\":{},\"275\":{},\"295\":{},\"321\":{},\"350\":{}},\"parent\":{}}],[\"errorhandler\",{\"_index\":29,\"name\":{\"47\":{},\"52\":{}},\"parent\":{}}],[\"expiry\",{\"_index\":293,\"name\":{\"687\":{}},\"parent\":{}}],[\"express\",{\"_index\":17,\"name\":{\"27\":{},\"35\":{}},\"parent\":{}}],[\"facebook\",{\"_index\":108,\"name\":{\"248\":{},\"264\":{},\"287\":{},\"309\":{},\"341\":{},\"372\":{}},\"parent\":{}}],[\"fastify\",{\"_index\":18,\"name\":{\"28\":{},\"36\":{}},\"parent\":{}}],[\"fetchandsetclaim\",{\"_index\":95,\"name\":{\"203\":{},\"234\":{},\"648\":{},\"665\":{}},\"parent\":{}}],[\"framework\",{\"_index\":16,\"name\":{\"26\":{}},\"parent\":{\"27\":{},\"28\":{},\"29\":{},\"30\":{},\"31\":{},\"32\":{},\"33\":{},\"34\":{},\"423\":{},\"441\":{}}}],[\"framework.__type\",{\"_index\":23,\"name\":{},\"parent\":{\"35\":{},\"36\":{},\"37\":{},\"38\":{},\"39\":{},\"40\":{}}}],[\"framework.baserequest\",{\"_index\":142,\"name\":{},\"parent\":{\"424\":{},\"425\":{},\"426\":{},\"427\":{},\"428\":{},\"429\":{},\"430\":{},\"431\":{},\"432\":{},\"433\":{},\"434\":{},\"435\":{},\"436\":{},\"437\":{},\"438\":{},\"439\":{},\"440\":{}}}],[\"framework.baseresponse\",{\"_index\":153,\"name\":{},\"parent\":{\"442\":{},\"443\":{},\"444\":{},\"445\":{},\"446\":{},\"447\":{},\"448\":{},\"449\":{},\"450\":{},\"451\":{},\"452\":{},\"453\":{},\"454\":{},\"455\":{},\"456\":{}}}],[\"framework/awslambda\",{\"_index\":24,\"name\":{\"41\":{}},\"parent\":{\"42\":{},\"43\":{},\"44\":{},\"457\":{},\"465\":{}}}],[\"framework/awslambda.sessionevent\",{\"_index\":162,\"name\":{},\"parent\":{\"458\":{},\"459\":{},\"460\":{}}}],[\"framework/awslambda.sessionevent.__type\",{\"_index\":165,\"name\":{},\"parent\":{\"461\":{},\"462\":{}}}],[\"framework/awslambda.sessionevent.__type.__type\",{\"_index\":167,\"name\":{},\"parent\":{\"463\":{},\"464\":{}}}],[\"framework/awslambda.sessioneventv2\",{\"_index\":170,\"name\":{},\"parent\":{\"466\":{},\"467\":{},\"468\":{},\"473\":{}}}],[\"framework/awslambda.sessioneventv2.__type\",{\"_index\":171,\"name\":{},\"parent\":{\"469\":{},\"470\":{},\"474\":{},\"477\":{}}}],[\"framework/awslambda.sessioneventv2.__type.__type\",{\"_index\":172,\"name\":{},\"parent\":{\"471\":{},\"472\":{},\"475\":{}}}],[\"framework/awslambda.sessioneventv2.__type.__type.__type\",{\"_index\":173,\"name\":{},\"parent\":{\"476\":{}}}],[\"framework/express\",{\"_index\":28,\"name\":{\"45\":{}},\"parent\":{\"46\":{},\"47\":{},\"48\":{},\"49\":{},\"478\":{}}}],[\"framework/express.sessionrequest\",{\"_index\":175,\"name\":{},\"parent\":{\"479\":{}}}],[\"framework/fastify\",{\"_index\":30,\"name\":{\"50\":{}},\"parent\":{\"51\":{},\"52\":{},\"53\":{},\"54\":{},\"480\":{}}}],[\"framework/fastify.sessionrequest\",{\"_index\":176,\"name\":{},\"parent\":{\"481\":{}}}],[\"framework/hapi\",{\"_index\":32,\"name\":{\"55\":{}},\"parent\":{\"56\":{},\"57\":{},\"58\":{},\"482\":{}}}],[\"framework/hapi.sessionrequest\",{\"_index\":177,\"name\":{},\"parent\":{\"483\":{},\"484\":{}}}],[\"framework/koa\",{\"_index\":33,\"name\":{\"59\":{}},\"parent\":{\"60\":{},\"61\":{},\"62\":{},\"485\":{}}}],[\"framework/koa.sessioncontext\",{\"_index\":179,\"name\":{},\"parent\":{\"486\":{}}}],[\"framework/loopback\",{\"_index\":34,\"name\":{\"63\":{}},\"parent\":{\"64\":{},\"65\":{},\"66\":{},\"487\":{}}}],[\"framework/loopback.sessioncontext\",{\"_index\":180,\"name\":{},\"parent\":{\"488\":{}}}],[\"generateemailverifytokenpost\",{\"_index\":226,\"name\":{\"557\":{}},\"parent\":{}}],[\"generatepasswordresettokenpost\",{\"_index\":214,\"name\":{\"532\":{},\"751\":{}},\"parent\":{}}],[\"get\",{\"_index\":314,\"name\":{\"724\":{}},\"parent\":{}}],[\"getaccesstoken\",{\"_index\":276,\"name\":{\"659\":{}},\"parent\":{}}],[\"getaccesstokenlifetimems\",{\"_index\":267,\"name\":{\"644\":{}},\"parent\":{}}],[\"getaccesstokenpayload\",{\"_index\":274,\"name\":{\"657\":{}},\"parent\":{}}],[\"getallcorsheaders\",{\"_index\":2,\"name\":{\"2\":{},\"16\":{}},\"parent\":{}}],[\"getallroles\",{\"_index\":137,\"name\":{\"406\":{},\"421\":{},\"809\":{}},\"parent\":{}}],[\"getallsessionhandlesforuser\",{\"_index\":89,\"name\":{\"197\":{},\"224\":{},\"637\":{}},\"parent\":{}}],[\"getclaimvalue\",{\"_index\":97,\"name\":{\"205\":{},\"236\":{},\"650\":{},\"667\":{}},\"parent\":{}}],[\"getcookievalue\",{\"_index\":148,\"name\":{\"433\":{}},\"parent\":{}}],[\"getdashboardbundlelocation\",{\"_index\":183,\"name\":{\"491\":{}},\"parent\":{}}],[\"getexpiry\",{\"_index\":278,\"name\":{\"663\":{}},\"parent\":{}}],[\"getformdata\",{\"_index\":151,\"name\":{\"439\":{}},\"parent\":{}}],[\"getglobalclaimvalidators\",{\"_index\":266,\"name\":{\"632\":{}},\"parent\":{}}],[\"gethandle\",{\"_index\":275,\"name\":{\"658\":{}},\"parent\":{}}],[\"getheadervalue\",{\"_index\":149,\"name\":{\"435\":{}},\"parent\":{}}],[\"getjsonbody\",{\"_index\":146,\"name\":{\"429\":{}},\"parent\":{}}],[\"getjwks\",{\"_index\":62,\"name\":{\"129\":{},\"134\":{},\"140\":{},\"146\":{},\"211\":{},\"232\":{},\"577\":{}},\"parent\":{}}],[\"getjwksget\",{\"_index\":230,\"name\":{\"565\":{}},\"parent\":{}}],[\"getkeyvaluefromquery\",{\"_index\":145,\"name\":{\"427\":{}},\"parent\":{}}],[\"getmethod\",{\"_index\":147,\"name\":{\"431\":{}},\"parent\":{}}],[\"getopeniddiscoveryconfiguration\",{\"_index\":65,\"name\":{\"138\":{},\"144\":{},\"212\":{},\"233\":{}},\"parent\":{}}],[\"getoriginalurl\",{\"_index\":150,\"name\":{\"437\":{}},\"parent\":{}}],[\"getpermissionsforrole\",{\"_index\":133,\"name\":{\"402\":{},\"417\":{},\"805\":{}},\"parent\":{}}],[\"getrefreshtokenlifetimems\",{\"_index\":268,\"name\":{\"645\":{}},\"parent\":{}}],[\"getrolesforuser\",{\"_index\":130,\"name\":{\"399\":{},\"414\":{},\"802\":{}},\"parent\":{}}],[\"getrolesthathavepermission\",{\"_index\":135,\"name\":{\"404\":{},\"419\":{},\"807\":{}},\"parent\":{}}],[\"getsession\",{\"_index\":85,\"name\":{\"193\":{},\"220\":{},\"633\":{}},\"parent\":{}}],[\"getsessiondata\",{\"_index\":272,\"name\":{\"654\":{}},\"parent\":{}}],[\"getsessioninformation\",{\"_index\":86,\"name\":{\"194\":{},\"221\":{},\"635\":{}},\"parent\":{}}],[\"gettimecreated\",{\"_index\":277,\"name\":{\"662\":{}},\"parent\":{}}],[\"getuserbyemail\",{\"_index\":46,\"name\":{\"87\":{},\"99\":{},\"153\":{},\"176\":{},\"510\":{},\"592\":{}},\"parent\":{}}],[\"getuserbyid\",{\"_index\":45,\"name\":{\"86\":{},\"98\":{},\"154\":{},\"175\":{},\"243\":{},\"257\":{},\"279\":{},\"300\":{},\"324\":{},\"353\":{},\"509\":{},\"591\":{},\"693\":{},\"728\":{},\"761\":{}},\"parent\":{}}],[\"getuserbyphonenumber\",{\"_index\":70,\"name\":{\"155\":{},\"177\":{},\"329\":{},\"358\":{},\"593\":{},\"763\":{}},\"parent\":{}}],[\"getuserbythirdpartyinfo\",{\"_index\":105,\"name\":{\"245\":{},\"259\":{},\"280\":{},\"297\":{},\"325\":{},\"352\":{},\"695\":{},\"730\":{},\"764\":{}},\"parent\":{}}],[\"getusercount\",{\"_index\":3,\"name\":{\"3\":{},\"17\":{}},\"parent\":{}}],[\"getuserid\",{\"_index\":273,\"name\":{\"656\":{}},\"parent\":{}}],[\"getuseridmapping\",{\"_index\":8,\"name\":{\"8\":{},\"22\":{}},\"parent\":{}}],[\"getusermetadata\",{\"_index\":123,\"name\":{\"385\":{},\"391\":{},\"792\":{}},\"parent\":{}}],[\"getusersbyemail\",{\"_index\":104,\"name\":{\"244\":{},\"258\":{},\"281\":{},\"301\":{},\"326\":{},\"354\":{},\"694\":{},\"729\":{},\"762\":{}},\"parent\":{}}],[\"getusersnewestfirst\",{\"_index\":5,\"name\":{\"5\":{},\"19\":{}},\"parent\":{}}],[\"getusersoldestfirst\",{\"_index\":4,\"name\":{\"4\":{},\"18\":{}},\"parent\":{}}],[\"getusersthathaverole\",{\"_index\":131,\"name\":{\"400\":{},\"415\":{},\"803\":{}},\"parent\":{}}],[\"github\",{\"_index\":107,\"name\":{\"247\":{},\"262\":{},\"286\":{},\"307\":{},\"340\":{},\"370\":{}},\"parent\":{}}],[\"google\",{\"_index\":106,\"name\":{\"246\":{},\"260\":{},\"285\":{},\"305\":{},\"339\":{},\"368\":{}},\"parent\":{}}],[\"googleworkspaces\",{\"_index\":111,\"name\":{\"251\":{},\"270\":{},\"290\":{},\"315\":{},\"344\":{},\"378\":{}},\"parent\":{}}],[\"hapi\",{\"_index\":19,\"name\":{\"29\":{},\"37\":{}},\"parent\":{}}],[\"headers\",{\"_index\":166,\"name\":{\"463\":{},\"471\":{}},\"parent\":{}}],[\"id\",{\"_index\":204,\"name\":{\"516\":{},\"560\":{},\"603\":{},\"699\":{},\"704\":{},\"723\":{},\"740\":{},\"745\":{}},\"parent\":{}}],[\"index\",{\"_index\":0,\"name\":{\"0\":{}},\"parent\":{\"1\":{},\"2\":{},\"3\":{},\"4\":{},\"5\":{},\"6\":{},\"7\":{},\"8\":{},\"9\":{},\"10\":{},\"11\":{},\"12\":{}}}],[\"index.default\",{\"_index\":13,\"name\":{},\"parent\":{\"13\":{},\"14\":{},\"15\":{},\"16\":{},\"17\":{},\"18\":{},\"19\":{},\"20\":{},\"21\":{},\"22\":{},\"23\":{},\"24\":{},\"25\":{}}}],[\"ingredientinterfaceimpl\",{\"_index\":37,\"name\":{\"70\":{},\"74\":{}},\"parent\":{}}],[\"ingredients/emaildelivery\",{\"_index\":35,\"name\":{\"67\":{}},\"parent\":{\"68\":{}}}],[\"ingredients/emaildelivery.default\",{\"_index\":36,\"name\":{},\"parent\":{\"69\":{},\"70\":{}}}],[\"ingredients/smsdelivery\",{\"_index\":38,\"name\":{\"71\":{}},\"parent\":{\"72\":{}}}],[\"ingredients/smsdelivery.default\",{\"_index\":39,\"name\":{},\"parent\":{\"73\":{},\"74\":{}}}],[\"init\",{\"_index\":1,\"name\":{\"1\":{},\"13\":{},\"76\":{},\"78\":{},\"82\":{},\"93\":{},\"106\":{},\"115\":{},\"127\":{},\"131\":{},\"137\":{},\"142\":{},\"149\":{},\"169\":{},\"191\":{},\"214\":{},\"240\":{},\"253\":{},\"274\":{},\"293\":{},\"320\":{},\"348\":{},\"384\":{},\"389\":{},\"396\":{},\"408\":{}},\"parent\":{}}],[\"isdefault\",{\"_index\":315,\"name\":{\"725\":{}},\"parent\":{}}],[\"isemailverified\",{\"_index\":55,\"name\":{\"110\":{},\"121\":{},\"540\":{}},\"parent\":{}}],[\"isemailverifiedget\",{\"_index\":225,\"name\":{\"556\":{}},\"parent\":{}}],[\"isinserverlessenv\",{\"_index\":194,\"name\":{\"500\":{},\"525\":{},\"549\":{},\"571\":{},\"613\":{},\"679\":{},\"716\":{}},\"parent\":{}}],[\"jsonobject\",{\"_index\":338,\"name\":{\"795\":{}},\"parent\":{}}],[\"jsonwebkey\",{\"_index\":236,\"name\":{\"578\":{}},\"parent\":{}}],[\"kid\",{\"_index\":240,\"name\":{\"581\":{}},\"parent\":{}}],[\"koa\",{\"_index\":21,\"name\":{\"31\":{},\"39\":{}},\"parent\":{}}],[\"kty\",{\"_index\":238,\"name\":{\"580\":{}},\"parent\":{}}],[\"listcodesbydeviceid\",{\"_index\":71,\"name\":{\"156\":{},\"183\":{},\"330\":{},\"364\":{},\"599\":{},\"774\":{}},\"parent\":{}}],[\"listcodesbyemail\",{\"_index\":72,\"name\":{\"157\":{},\"181\":{},\"331\":{},\"362\":{},\"597\":{},\"772\":{}},\"parent\":{}}],[\"listcodesbyphonenumber\",{\"_index\":73,\"name\":{\"158\":{},\"182\":{},\"332\":{},\"363\":{},\"598\":{},\"773\":{}},\"parent\":{}}],[\"listcodesbypreauthsessionid\",{\"_index\":74,\"name\":{\"159\":{},\"184\":{},\"333\":{},\"365\":{},\"600\":{},\"775\":{}},\"parent\":{}}],[\"loopback\",{\"_index\":20,\"name\":{\"30\":{},\"38\":{}},\"parent\":{}}],[\"mergeintoaccesstokenpayload\",{\"_index\":94,\"name\":{\"202\":{},\"230\":{},\"642\":{},\"661\":{}},\"parent\":{}}],[\"middleware\",{\"_index\":25,\"name\":{\"42\":{},\"46\":{},\"60\":{},\"64\":{}},\"parent\":{}}],[\"n\",{\"_index\":241,\"name\":{\"582\":{}},\"parent\":{}}],[\"original\",{\"_index\":144,\"name\":{\"426\":{},\"444\":{}},\"parent\":{}}],[\"overrideglobalclaimvalidators\",{\"_index\":263,\"name\":{\"628\":{}},\"parent\":{}}],[\"passwordlessapioptions\",{\"_index\":335,\"name\":{\"788\":{}},\"parent\":{}}],[\"passwordlesssigninup\",{\"_index\":119,\"name\":{\"323\":{},\"367\":{}},\"parent\":{}}],[\"passwordlessuseremailexistsget\",{\"_index\":333,\"name\":{\"786\":{}},\"parent\":{}}],[\"passwordlessuserphonenumberexistsget\",{\"_index\":334,\"name\":{\"787\":{}},\"parent\":{}}],[\"passwordresetpost\",{\"_index\":215,\"name\":{\"533\":{},\"752\":{}},\"parent\":{}}],[\"permissionclaim\",{\"_index\":139,\"name\":{\"410\":{},\"797\":{}},\"parent\":{}}],[\"phonenumber\",{\"_index\":249,\"name\":{\"605\":{}},\"parent\":{}}],[\"phonenumberexistsget\",{\"_index\":258,\"name\":{\"624\":{}},\"parent\":{}}],[\"plugin\",{\"_index\":31,\"name\":{\"51\":{},\"56\":{}},\"parent\":{}}],[\"providers\",{\"_index\":310,\"name\":{\"717\":{}},\"parent\":{}}],[\"recipe/dashboard\",{\"_index\":40,\"name\":{\"75\":{}},\"parent\":{\"76\":{},\"77\":{},\"489\":{},\"493\":{},\"502\":{}}}],[\"recipe/dashboard.apiinterface\",{\"_index\":197,\"name\":{},\"parent\":{\"503\":{}}}],[\"recipe/dashboard.apiinterface.__type\",{\"_index\":199,\"name\":{},\"parent\":{\"504\":{}}}],[\"recipe/dashboard.apioptions\",{\"_index\":187,\"name\":{},\"parent\":{\"494\":{}}}],[\"recipe/dashboard.apioptions.__type\",{\"_index\":189,\"name\":{},\"parent\":{\"495\":{},\"496\":{},\"497\":{},\"498\":{},\"499\":{},\"500\":{},\"501\":{}}}],[\"recipe/dashboard.default\",{\"_index\":41,\"name\":{},\"parent\":{\"78\":{},\"79\":{},\"80\":{}}}],[\"recipe/dashboard.recipeinterface\",{\"_index\":182,\"name\":{},\"parent\":{\"490\":{}}}],[\"recipe/dashboard.recipeinterface.__type\",{\"_index\":184,\"name\":{},\"parent\":{\"491\":{},\"492\":{}}}],[\"recipe/emailpassword\",{\"_index\":42,\"name\":{\"81\":{}},\"parent\":{\"82\":{},\"83\":{},\"84\":{},\"85\":{},\"86\":{},\"87\":{},\"88\":{},\"89\":{},\"90\":{},\"91\":{},\"92\":{},\"505\":{},\"514\":{},\"519\":{},\"529\":{}}}],[\"recipe/emailpassword.apiinterface\",{\"_index\":211,\"name\":{},\"parent\":{\"530\":{}}}],[\"recipe/emailpassword.apiinterface.__type\",{\"_index\":213,\"name\":{},\"parent\":{\"531\":{},\"532\":{},\"533\":{},\"534\":{},\"535\":{}}}],[\"recipe/emailpassword.apioptions\",{\"_index\":208,\"name\":{},\"parent\":{\"520\":{}}}],[\"recipe/emailpassword.apioptions.__type\",{\"_index\":209,\"name\":{},\"parent\":{\"521\":{},\"522\":{},\"523\":{},\"524\":{},\"525\":{},\"526\":{},\"527\":{},\"528\":{}}}],[\"recipe/emailpassword.default\",{\"_index\":51,\"name\":{},\"parent\":{\"93\":{},\"94\":{},\"95\":{},\"96\":{},\"97\":{},\"98\":{},\"99\":{},\"100\":{},\"101\":{},\"102\":{},\"103\":{},\"104\":{}}}],[\"recipe/emailpassword.recipeinterface\",{\"_index\":200,\"name\":{},\"parent\":{\"506\":{}}}],[\"recipe/emailpassword.recipeinterface.__type\",{\"_index\":201,\"name\":{},\"parent\":{\"507\":{},\"508\":{},\"509\":{},\"510\":{},\"511\":{},\"512\":{},\"513\":{}}}],[\"recipe/emailpassword.user\",{\"_index\":203,\"name\":{},\"parent\":{\"515\":{}}}],[\"recipe/emailpassword.user.__type\",{\"_index\":205,\"name\":{},\"parent\":{\"516\":{},\"517\":{},\"518\":{}}}],[\"recipe/emailverification\",{\"_index\":52,\"name\":{\"105\":{}},\"parent\":{\"106\":{},\"107\":{},\"108\":{},\"109\":{},\"110\":{},\"111\":{},\"112\":{},\"113\":{},\"114\":{},\"536\":{},\"543\":{},\"553\":{},\"558\":{},\"562\":{}}}],[\"recipe/emailverification.apiinterface\",{\"_index\":222,\"name\":{},\"parent\":{\"554\":{}}}],[\"recipe/emailverification.apiinterface.__type\",{\"_index\":224,\"name\":{},\"parent\":{\"555\":{},\"556\":{},\"557\":{}}}],[\"recipe/emailverification.apioptions\",{\"_index\":220,\"name\":{},\"parent\":{\"544\":{}}}],[\"recipe/emailverification.apioptions.__type\",{\"_index\":221,\"name\":{},\"parent\":{\"545\":{},\"546\":{},\"547\":{},\"548\":{},\"549\":{},\"550\":{},\"551\":{},\"552\":{}}}],[\"recipe/emailverification.default\",{\"_index\":58,\"name\":{},\"parent\":{\"115\":{},\"116\":{},\"117\":{},\"118\":{},\"119\":{},\"120\":{},\"121\":{},\"122\":{},\"123\":{},\"124\":{},\"125\":{}}}],[\"recipe/emailverification.recipeinterface\",{\"_index\":218,\"name\":{},\"parent\":{\"537\":{}}}],[\"recipe/emailverification.recipeinterface.__type\",{\"_index\":219,\"name\":{},\"parent\":{\"538\":{},\"539\":{},\"540\":{},\"541\":{},\"542\":{}}}],[\"recipe/emailverification.user\",{\"_index\":227,\"name\":{},\"parent\":{\"559\":{}}}],[\"recipe/emailverification.user.__type\",{\"_index\":228,\"name\":{},\"parent\":{\"560\":{},\"561\":{}}}],[\"recipe/jwt\",{\"_index\":60,\"name\":{\"126\":{}},\"parent\":{\"127\":{},\"128\":{},\"129\":{},\"130\":{},\"563\":{},\"566\":{},\"574\":{},\"578\":{}}}],[\"recipe/jwt.apiinterface\",{\"_index\":229,\"name\":{},\"parent\":{\"564\":{}}}],[\"recipe/jwt.apiinterface.__type\",{\"_index\":231,\"name\":{},\"parent\":{\"565\":{}}}],[\"recipe/jwt.apioptions\",{\"_index\":232,\"name\":{},\"parent\":{\"567\":{}}}],[\"recipe/jwt.apioptions.__type\",{\"_index\":233,\"name\":{},\"parent\":{\"568\":{},\"569\":{},\"570\":{},\"571\":{},\"572\":{},\"573\":{}}}],[\"recipe/jwt.default\",{\"_index\":63,\"name\":{},\"parent\":{\"131\":{},\"132\":{},\"133\":{},\"134\":{},\"135\":{}}}],[\"recipe/jwt.jsonwebkey\",{\"_index\":237,\"name\":{},\"parent\":{\"579\":{}}}],[\"recipe/jwt.jsonwebkey.__type\",{\"_index\":239,\"name\":{},\"parent\":{\"580\":{},\"581\":{},\"582\":{},\"583\":{},\"584\":{},\"585\":{}}}],[\"recipe/jwt.recipeinterface\",{\"_index\":234,\"name\":{},\"parent\":{\"575\":{}}}],[\"recipe/jwt.recipeinterface.__type\",{\"_index\":235,\"name\":{},\"parent\":{\"576\":{},\"577\":{}}}],[\"recipe/openid\",{\"_index\":64,\"name\":{\"136\":{}},\"parent\":{\"137\":{},\"138\":{},\"139\":{},\"140\":{},\"141\":{}}}],[\"recipe/openid.default\",{\"_index\":66,\"name\":{},\"parent\":{\"142\":{},\"143\":{},\"144\":{},\"145\":{},\"146\":{},\"147\":{}}}],[\"recipe/passwordless\",{\"_index\":67,\"name\":{\"148\":{}},\"parent\":{\"149\":{},\"150\":{},\"151\":{},\"152\":{},\"153\":{},\"154\":{},\"155\":{},\"156\":{},\"157\":{},\"158\":{},\"159\":{},\"160\":{},\"161\":{},\"162\":{},\"163\":{},\"164\":{},\"165\":{},\"166\":{},\"167\":{},\"168\":{},\"586\":{},\"601\":{},\"607\":{},\"618\":{}}}],[\"recipe/passwordless.apiinterface\",{\"_index\":253,\"name\":{},\"parent\":{\"619\":{}}}],[\"recipe/passwordless.apiinterface.__type\",{\"_index\":255,\"name\":{},\"parent\":{\"620\":{},\"621\":{},\"622\":{},\"623\":{},\"624\":{}}}],[\"recipe/passwordless.apioptions\",{\"_index\":250,\"name\":{},\"parent\":{\"608\":{}}}],[\"recipe/passwordless.apioptions.__type\",{\"_index\":251,\"name\":{},\"parent\":{\"609\":{},\"610\":{},\"611\":{},\"612\":{},\"613\":{},\"614\":{},\"615\":{},\"616\":{},\"617\":{}}}],[\"recipe/passwordless.default\",{\"_index\":82,\"name\":{},\"parent\":{\"169\":{},\"170\":{},\"171\":{},\"172\":{},\"173\":{},\"174\":{},\"175\":{},\"176\":{},\"177\":{},\"178\":{},\"179\":{},\"180\":{},\"181\":{},\"182\":{},\"183\":{},\"184\":{},\"185\":{},\"186\":{},\"187\":{},\"188\":{},\"189\":{}}}],[\"recipe/passwordless.recipeinterface\",{\"_index\":245,\"name\":{},\"parent\":{\"587\":{}}}],[\"recipe/passwordless.recipeinterface.__type\",{\"_index\":246,\"name\":{},\"parent\":{\"588\":{},\"589\":{},\"590\":{},\"591\":{},\"592\":{},\"593\":{},\"594\":{},\"595\":{},\"596\":{},\"597\":{},\"598\":{},\"599\":{},\"600\":{}}}],[\"recipe/passwordless.user\",{\"_index\":247,\"name\":{},\"parent\":{\"602\":{}}}],[\"recipe/passwordless.user.__type\",{\"_index\":248,\"name\":{},\"parent\":{\"603\":{},\"604\":{},\"605\":{},\"606\":{}}}],[\"recipe/session\",{\"_index\":83,\"name\":{\"190\":{}},\"parent\":{\"191\":{},\"192\":{},\"193\":{},\"194\":{},\"195\":{},\"196\":{},\"197\":{},\"198\":{},\"199\":{},\"200\":{},\"201\":{},\"202\":{},\"203\":{},\"204\":{},\"205\":{},\"206\":{},\"207\":{},\"208\":{},\"209\":{},\"210\":{},\"211\":{},\"212\":{},\"213\":{},\"625\":{},\"629\":{},\"652\":{},\"669\":{},\"674\":{},\"682\":{},\"690\":{}}}],[\"recipe/session.apiinterface\",{\"_index\":280,\"name\":{},\"parent\":{\"670\":{}}}],[\"recipe/session.apiinterface.__type\",{\"_index\":282,\"name\":{},\"parent\":{\"671\":{},\"672\":{},\"673\":{}}}],[\"recipe/session.apioptions\",{\"_index\":285,\"name\":{},\"parent\":{\"675\":{}}}],[\"recipe/session.apioptions.__type\",{\"_index\":286,\"name\":{},\"parent\":{\"676\":{},\"677\":{},\"678\":{},\"679\":{},\"680\":{},\"681\":{}}}],[\"recipe/session.default\",{\"_index\":101,\"name\":{},\"parent\":{\"214\":{},\"215\":{},\"216\":{},\"217\":{},\"218\":{},\"219\":{},\"220\":{},\"221\":{},\"222\":{},\"223\":{},\"224\":{},\"225\":{},\"226\":{},\"227\":{},\"228\":{},\"229\":{},\"230\":{},\"231\":{},\"232\":{},\"233\":{},\"234\":{},\"235\":{},\"236\":{},\"237\":{},\"238\":{}}}],[\"recipe/session.recipeinterface\",{\"_index\":264,\"name\":{},\"parent\":{\"630\":{}}}],[\"recipe/session.recipeinterface.__type\",{\"_index\":265,\"name\":{},\"parent\":{\"631\":{},\"632\":{},\"633\":{},\"634\":{},\"635\":{},\"636\":{},\"637\":{},\"638\":{},\"639\":{},\"640\":{},\"641\":{},\"642\":{},\"643\":{},\"644\":{},\"645\":{},\"646\":{},\"647\":{},\"648\":{},\"649\":{},\"650\":{},\"651\":{}}}],[\"recipe/session.sessioncontainer\",{\"_index\":271,\"name\":{},\"parent\":{\"653\":{},\"654\":{},\"655\":{},\"656\":{},\"657\":{},\"658\":{},\"659\":{},\"660\":{},\"661\":{},\"662\":{},\"663\":{},\"664\":{},\"665\":{},\"666\":{},\"667\":{},\"668\":{}}}],[\"recipe/session.sessioninformation\",{\"_index\":288,\"name\":{},\"parent\":{\"683\":{}}}],[\"recipe/session.sessioninformation.__type\",{\"_index\":290,\"name\":{},\"parent\":{\"684\":{},\"685\":{},\"686\":{},\"687\":{},\"688\":{},\"689\":{}}}],[\"recipe/session.verifysessionoptions\",{\"_index\":261,\"name\":{},\"parent\":{\"626\":{},\"627\":{},\"628\":{}}}],[\"recipe/thirdparty\",{\"_index\":103,\"name\":{\"239\":{}},\"parent\":{\"240\":{},\"241\":{},\"242\":{},\"243\":{},\"244\":{},\"245\":{},\"246\":{},\"247\":{},\"248\":{},\"249\":{},\"250\":{},\"251\":{},\"252\":{},\"691\":{},\"697\":{},\"706\":{},\"711\":{},\"721\":{}}}],[\"recipe/thirdparty.apiinterface\",{\"_index\":303,\"name\":{},\"parent\":{\"707\":{}}}],[\"recipe/thirdparty.apiinterface.__type\",{\"_index\":305,\"name\":{},\"parent\":{\"708\":{},\"709\":{},\"710\":{}}}],[\"recipe/thirdparty.apioptions\",{\"_index\":308,\"name\":{},\"parent\":{\"712\":{}}}],[\"recipe/thirdparty.apioptions.__type\",{\"_index\":309,\"name\":{},\"parent\":{\"713\":{},\"714\":{},\"715\":{},\"716\":{},\"717\":{},\"718\":{},\"719\":{},\"720\":{}}}],[\"recipe/thirdparty.default\",{\"_index\":112,\"name\":{},\"parent\":{\"253\":{},\"254\":{},\"255\":{},\"256\":{},\"257\":{},\"258\":{},\"259\":{},\"260\":{},\"261\":{},\"262\":{},\"263\":{},\"264\":{},\"265\":{},\"266\":{},\"267\":{},\"268\":{},\"269\":{},\"270\":{},\"271\":{},\"272\":{}}}],[\"recipe/thirdparty.recipeinterface\",{\"_index\":297,\"name\":{},\"parent\":{\"692\":{}}}],[\"recipe/thirdparty.recipeinterface.__type\",{\"_index\":298,\"name\":{},\"parent\":{\"693\":{},\"694\":{},\"695\":{},\"696\":{}}}],[\"recipe/thirdparty.typeprovider\",{\"_index\":312,\"name\":{},\"parent\":{\"722\":{}}}],[\"recipe/thirdparty.typeprovider.__type\",{\"_index\":313,\"name\":{},\"parent\":{\"723\":{},\"724\":{},\"725\":{}}}],[\"recipe/thirdparty.user\",{\"_index\":299,\"name\":{},\"parent\":{\"698\":{}}}],[\"recipe/thirdparty.user.__type\",{\"_index\":300,\"name\":{},\"parent\":{\"699\":{},\"700\":{},\"701\":{},\"702\":{},\"703\":{}}}],[\"recipe/thirdparty.user.__type.__type\",{\"_index\":302,\"name\":{},\"parent\":{\"704\":{},\"705\":{}}}],[\"recipe/thirdpartyemailpassword\",{\"_index\":113,\"name\":{\"273\":{}},\"parent\":{\"274\":{},\"275\":{},\"276\":{},\"277\":{},\"278\":{},\"279\":{},\"280\":{},\"281\":{},\"282\":{},\"283\":{},\"284\":{},\"285\":{},\"286\":{},\"287\":{},\"288\":{},\"289\":{},\"290\":{},\"291\":{},\"292\":{},\"726\":{},\"737\":{},\"738\":{},\"747\":{},\"757\":{},\"758\":{}}}],[\"recipe/thirdpartyemailpassword.apiinterface\",{\"_index\":321,\"name\":{},\"parent\":{\"748\":{}}}],[\"recipe/thirdpartyemailpassword.apiinterface.__type\",{\"_index\":322,\"name\":{},\"parent\":{\"749\":{},\"750\":{},\"751\":{},\"752\":{},\"753\":{},\"754\":{},\"755\":{},\"756\":{}}}],[\"recipe/thirdpartyemailpassword.default\",{\"_index\":117,\"name\":{},\"parent\":{\"293\":{},\"294\":{},\"295\":{},\"296\":{},\"297\":{},\"298\":{},\"299\":{},\"300\":{},\"301\":{},\"302\":{},\"303\":{},\"304\":{},\"305\":{},\"306\":{},\"307\":{},\"308\":{},\"309\":{},\"310\":{},\"311\":{},\"312\":{},\"313\":{},\"314\":{},\"315\":{},\"316\":{},\"317\":{},\"318\":{}}}],[\"recipe/thirdpartyemailpassword.recipeinterface\",{\"_index\":316,\"name\":{},\"parent\":{\"727\":{}}}],[\"recipe/thirdpartyemailpassword.recipeinterface.__type\",{\"_index\":317,\"name\":{},\"parent\":{\"728\":{},\"729\":{},\"730\":{},\"731\":{},\"732\":{},\"733\":{},\"734\":{},\"735\":{},\"736\":{}}}],[\"recipe/thirdpartyemailpassword.user\",{\"_index\":318,\"name\":{},\"parent\":{\"739\":{}}}],[\"recipe/thirdpartyemailpassword.user.__type\",{\"_index\":319,\"name\":{},\"parent\":{\"740\":{},\"741\":{},\"742\":{},\"743\":{},\"744\":{}}}],[\"recipe/thirdpartyemailpassword.user.__type.__type\",{\"_index\":320,\"name\":{},\"parent\":{\"745\":{},\"746\":{}}}],[\"recipe/thirdpartypasswordless\",{\"_index\":118,\"name\":{\"319\":{}},\"parent\":{\"320\":{},\"321\":{},\"322\":{},\"323\":{},\"324\":{},\"325\":{},\"326\":{},\"327\":{},\"328\":{},\"329\":{},\"330\":{},\"331\":{},\"332\":{},\"333\":{},\"334\":{},\"335\":{},\"336\":{},\"337\":{},\"338\":{},\"339\":{},\"340\":{},\"341\":{},\"342\":{},\"343\":{},\"344\":{},\"345\":{},\"346\":{},\"347\":{},\"759\":{},\"776\":{},\"777\":{},\"778\":{},\"788\":{},\"789\":{}}}],[\"recipe/thirdpartypasswordless.apiinterface\",{\"_index\":331,\"name\":{},\"parent\":{\"779\":{}}}],[\"recipe/thirdpartypasswordless.apiinterface.__type\",{\"_index\":332,\"name\":{},\"parent\":{\"780\":{},\"781\":{},\"782\":{},\"783\":{},\"784\":{},\"785\":{},\"786\":{},\"787\":{}}}],[\"recipe/thirdpartypasswordless.default\",{\"_index\":121,\"name\":{},\"parent\":{\"348\":{},\"349\":{},\"350\":{},\"351\":{},\"352\":{},\"353\":{},\"354\":{},\"355\":{},\"356\":{},\"357\":{},\"358\":{},\"359\":{},\"360\":{},\"361\":{},\"362\":{},\"363\":{},\"364\":{},\"365\":{},\"366\":{},\"367\":{},\"368\":{},\"369\":{},\"370\":{},\"371\":{},\"372\":{},\"373\":{},\"374\":{},\"375\":{},\"376\":{},\"377\":{},\"378\":{},\"379\":{},\"380\":{},\"381\":{},\"382\":{}}}],[\"recipe/thirdpartypasswordless.recipeinterface\",{\"_index\":329,\"name\":{},\"parent\":{\"760\":{}}}],[\"recipe/thirdpartypasswordless.recipeinterface.__type\",{\"_index\":330,\"name\":{},\"parent\":{\"761\":{},\"762\":{},\"763\":{},\"764\":{},\"765\":{},\"766\":{},\"767\":{},\"768\":{},\"769\":{},\"770\":{},\"771\":{},\"772\":{},\"773\":{},\"774\":{},\"775\":{}}}],[\"recipe/usermetadata\",{\"_index\":122,\"name\":{\"383\":{}},\"parent\":{\"384\":{},\"385\":{},\"386\":{},\"387\":{},\"388\":{},\"790\":{},\"795\":{}}}],[\"recipe/usermetadata.default\",{\"_index\":126,\"name\":{},\"parent\":{\"389\":{},\"390\":{},\"391\":{},\"392\":{},\"393\":{},\"394\":{}}}],[\"recipe/usermetadata.recipeinterface\",{\"_index\":336,\"name\":{},\"parent\":{\"791\":{}}}],[\"recipe/usermetadata.recipeinterface.__type\",{\"_index\":337,\"name\":{},\"parent\":{\"792\":{},\"793\":{},\"794\":{}}}],[\"recipe/userroles\",{\"_index\":127,\"name\":{\"395\":{}},\"parent\":{\"396\":{},\"397\":{},\"398\":{},\"399\":{},\"400\":{},\"401\":{},\"402\":{},\"403\":{},\"404\":{},\"405\":{},\"406\":{},\"407\":{},\"796\":{},\"797\":{},\"798\":{}}}],[\"recipe/userroles.default\",{\"_index\":138,\"name\":{},\"parent\":{\"408\":{},\"409\":{},\"410\":{},\"411\":{},\"412\":{},\"413\":{},\"414\":{},\"415\":{},\"416\":{},\"417\":{},\"418\":{},\"419\":{},\"420\":{},\"421\":{},\"422\":{}}}],[\"recipe/userroles.recipeinterface\",{\"_index\":339,\"name\":{},\"parent\":{\"799\":{}}}],[\"recipe/userroles.recipeinterface.__type\",{\"_index\":340,\"name\":{},\"parent\":{\"800\":{},\"801\":{},\"802\":{},\"803\":{},\"804\":{},\"805\":{},\"806\":{},\"807\":{},\"808\":{},\"809\":{}}}],[\"recipeid\",{\"_index\":191,\"name\":{\"497\":{},\"524\":{},\"548\":{},\"570\":{},\"612\":{},\"678\":{},\"715\":{}},\"parent\":{}}],[\"recipeimplementation\",{\"_index\":188,\"name\":{\"495\":{},\"521\":{},\"545\":{},\"568\":{},\"609\":{},\"676\":{},\"713\":{}},\"parent\":{}}],[\"recipeinterface\",{\"_index\":181,\"name\":{\"489\":{},\"505\":{},\"536\":{},\"574\":{},\"586\":{},\"629\":{},\"691\":{},\"726\":{},\"759\":{},\"790\":{},\"798\":{}},\"parent\":{}}],[\"refreshpost\",{\"_index\":281,\"name\":{\"671\":{}},\"parent\":{}}],[\"refreshsession\",{\"_index\":87,\"name\":{\"195\":{},\"222\":{},\"634\":{}},\"parent\":{}}],[\"regenerateaccesstoken\",{\"_index\":102,\"name\":{\"228\":{},\"643\":{}},\"parent\":{}}],[\"removeclaim\",{\"_index\":98,\"name\":{\"206\":{},\"237\":{},\"651\":{},\"668\":{}},\"parent\":{}}],[\"removeheader\",{\"_index\":155,\"name\":{\"447\":{}},\"parent\":{}}],[\"removepermissionsfromrole\",{\"_index\":134,\"name\":{\"403\":{},\"418\":{},\"806\":{}},\"parent\":{}}],[\"removeuserrole\",{\"_index\":129,\"name\":{\"398\":{},\"413\":{},\"801\":{}},\"parent\":{}}],[\"req\",{\"_index\":192,\"name\":{\"498\":{},\"526\":{},\"550\":{},\"572\":{},\"614\":{},\"680\":{},\"718\":{}},\"parent\":{}}],[\"res\",{\"_index\":193,\"name\":{\"499\":{},\"527\":{},\"551\":{},\"573\":{},\"615\":{},\"681\":{},\"719\":{}},\"parent\":{}}],[\"resendcodepost\",{\"_index\":256,\"name\":{\"621\":{},\"784\":{}},\"parent\":{}}],[\"resetpasswordusingtoken\",{\"_index\":48,\"name\":{\"89\":{},\"101\":{},\"283\":{},\"303\":{},\"512\":{},\"735\":{}},\"parent\":{}}],[\"response\",{\"_index\":164,\"name\":{\"461\":{},\"469\":{}},\"parent\":{}}],[\"revokeallcodes\",{\"_index\":77,\"name\":{\"162\":{},\"179\":{},\"336\":{},\"360\":{},\"595\":{},\"770\":{}},\"parent\":{}}],[\"revokeallsessionsforuser\",{\"_index\":88,\"name\":{\"196\":{},\"223\":{},\"636\":{}},\"parent\":{}}],[\"revokecode\",{\"_index\":78,\"name\":{\"163\":{},\"180\":{},\"337\":{},\"361\":{},\"596\":{},\"771\":{}},\"parent\":{}}],[\"revokeemailverificationtokens\",{\"_index\":56,\"name\":{\"111\":{},\"122\":{},\"541\":{}},\"parent\":{}}],[\"revokemultiplesessions\",{\"_index\":91,\"name\":{\"199\":{},\"226\":{},\"639\":{}},\"parent\":{}}],[\"revokesession\",{\"_index\":90,\"name\":{\"198\":{},\"225\":{},\"638\":{},\"653\":{}},\"parent\":{}}],[\"sendemail\",{\"_index\":50,\"name\":{\"91\":{},\"103\":{},\"113\":{},\"124\":{},\"166\":{},\"187\":{},\"291\":{},\"317\":{},\"345\":{},\"380\":{}},\"parent\":{}}],[\"sendhtmlresponse\",{\"_index\":159,\"name\":{\"455\":{}},\"parent\":{}}],[\"sendjsonresponse\",{\"_index\":158,\"name\":{\"453\":{}},\"parent\":{}}],[\"sendsms\",{\"_index\":81,\"name\":{\"167\":{},\"188\":{},\"346\":{},\"381\":{}},\"parent\":{}}],[\"session\",{\"_index\":161,\"name\":{\"458\":{},\"466\":{},\"479\":{},\"481\":{},\"483\":{},\"486\":{},\"488\":{}},\"parent\":{}}],[\"sessionclaimvalidator\",{\"_index\":296,\"name\":{\"690\":{}},\"parent\":{}}],[\"sessioncontainer\",{\"_index\":270,\"name\":{\"652\":{}},\"parent\":{}}],[\"sessioncontext\",{\"_index\":178,\"name\":{\"485\":{},\"487\":{}},\"parent\":{}}],[\"sessiondata\",{\"_index\":292,\"name\":{\"686\":{}},\"parent\":{}}],[\"sessionevent\",{\"_index\":160,\"name\":{\"457\":{}},\"parent\":{}}],[\"sessioneventv2\",{\"_index\":169,\"name\":{\"465\":{}},\"parent\":{}}],[\"sessionhandle\",{\"_index\":289,\"name\":{\"684\":{}},\"parent\":{}}],[\"sessioninformation\",{\"_index\":287,\"name\":{\"682\":{}},\"parent\":{}}],[\"sessionrequest\",{\"_index\":174,\"name\":{\"478\":{},\"480\":{},\"482\":{}},\"parent\":{}}],[\"sessionrequired\",{\"_index\":262,\"name\":{\"627\":{}},\"parent\":{}}],[\"setclaimvalue\",{\"_index\":96,\"name\":{\"204\":{},\"235\":{},\"649\":{},\"666\":{}},\"parent\":{}}],[\"setcookie\",{\"_index\":156,\"name\":{\"449\":{}},\"parent\":{}}],[\"setheader\",{\"_index\":154,\"name\":{\"445\":{}},\"parent\":{}}],[\"setstatuscode\",{\"_index\":157,\"name\":{\"451\":{}},\"parent\":{}}],[\"shouldallowaccess\",{\"_index\":185,\"name\":{\"492\":{}},\"parent\":{}}],[\"signin\",{\"_index\":44,\"name\":{\"85\":{},\"97\":{},\"508\":{}},\"parent\":{}}],[\"signinpost\",{\"_index\":216,\"name\":{\"534\":{}},\"parent\":{}}],[\"signinup\",{\"_index\":80,\"name\":{\"165\":{},\"186\":{},\"242\":{},\"256\":{},\"696\":{}},\"parent\":{}}],[\"signinuppost\",{\"_index\":306,\"name\":{\"709\":{}},\"parent\":{}}],[\"signoutpost\",{\"_index\":283,\"name\":{\"672\":{}},\"parent\":{}}],[\"signup\",{\"_index\":43,\"name\":{\"84\":{},\"96\":{},\"507\":{}},\"parent\":{}}],[\"signuppost\",{\"_index\":217,\"name\":{\"535\":{}},\"parent\":{}}],[\"smsdelivery\",{\"_index\":252,\"name\":{\"617\":{}},\"parent\":{}}],[\"supertokens\",{\"_index\":163,\"name\":{\"459\":{},\"467\":{}},\"parent\":{}}],[\"thirdparty\",{\"_index\":301,\"name\":{\"702\":{},\"743\":{}},\"parent\":{}}],[\"thirdpartyapioptions\",{\"_index\":328,\"name\":{\"758\":{},\"789\":{}},\"parent\":{}}],[\"thirdpartysigninup\",{\"_index\":116,\"name\":{\"278\":{},\"296\":{},\"322\":{},\"351\":{},\"731\":{},\"765\":{}},\"parent\":{}}],[\"thirdpartysigninuppost\",{\"_index\":324,\"name\":{\"753\":{},\"781\":{}},\"parent\":{}}],[\"timecreated\",{\"_index\":295,\"name\":{\"689\":{}},\"parent\":{}}],[\"timejoined\",{\"_index\":207,\"name\":{\"518\":{},\"606\":{},\"700\":{},\"741\":{}},\"parent\":{}}],[\"typeprovider\",{\"_index\":311,\"name\":{\"721\":{},\"737\":{},\"776\":{}},\"parent\":{}}],[\"unverifyemail\",{\"_index\":57,\"name\":{\"112\":{},\"123\":{},\"542\":{}},\"parent\":{}}],[\"updateaccesstokenpayload\",{\"_index\":93,\"name\":{\"201\":{},\"229\":{},\"641\":{},\"660\":{}},\"parent\":{}}],[\"updateemailorpassword\",{\"_index\":49,\"name\":{\"90\":{},\"102\":{},\"284\":{},\"304\":{},\"513\":{},\"736\":{}},\"parent\":{}}],[\"updateordeleteuseridmappinginfo\",{\"_index\":10,\"name\":{\"10\":{},\"24\":{}},\"parent\":{}}],[\"updatepasswordlessuser\",{\"_index\":120,\"name\":{\"335\":{},\"359\":{},\"769\":{}},\"parent\":{}}],[\"updatesessiondata\",{\"_index\":92,\"name\":{\"200\":{},\"227\":{},\"640\":{},\"655\":{}},\"parent\":{}}],[\"updateuser\",{\"_index\":76,\"name\":{\"161\":{},\"178\":{},\"594\":{}},\"parent\":{}}],[\"updateusermetadata\",{\"_index\":124,\"name\":{\"386\":{},\"392\":{},\"793\":{}},\"parent\":{}}],[\"use\",{\"_index\":244,\"name\":{\"585\":{}},\"parent\":{}}],[\"user\",{\"_index\":202,\"name\":{\"514\":{},\"558\":{},\"601\":{},\"697\":{},\"738\":{},\"777\":{}},\"parent\":{}}],[\"userid\",{\"_index\":291,\"name\":{\"685\":{},\"705\":{},\"746\":{}},\"parent\":{}}],[\"userroleclaim\",{\"_index\":140,\"name\":{\"411\":{},\"796\":{}},\"parent\":{}}],[\"validateclaims\",{\"_index\":269,\"name\":{\"646\":{}},\"parent\":{}}],[\"validateclaimsforsessionhandle\",{\"_index\":100,\"name\":{\"208\":{},\"218\":{}},\"parent\":{}}],[\"validateclaimsinjwtpayload\",{\"_index\":99,\"name\":{\"207\":{},\"219\":{},\"647\":{}},\"parent\":{}}],[\"verifyemailpost\",{\"_index\":223,\"name\":{\"555\":{}},\"parent\":{}}],[\"verifyemailusingtoken\",{\"_index\":54,\"name\":{\"109\":{},\"120\":{},\"539\":{}},\"parent\":{}}],[\"verifysession\",{\"_index\":284,\"name\":{\"673\":{}},\"parent\":{}}],[\"verifysessionoptions\",{\"_index\":259,\"name\":{\"625\":{}},\"parent\":{}}],[\"wrapperused\",{\"_index\":143,\"name\":{\"425\":{},\"443\":{}},\"parent\":{}}],[\"wraprequest\",{\"_index\":26,\"name\":{\"43\":{},\"48\":{},\"53\":{},\"57\":{},\"61\":{},\"65\":{}},\"parent\":{}}],[\"wrapresponse\",{\"_index\":27,\"name\":{\"44\":{},\"49\":{},\"54\":{},\"58\":{},\"62\":{},\"66\":{}},\"parent\":{}}]],\"pipeline\":[]}}"); \ No newline at end of file diff --git a/docs/assets/style.css b/docs/assets/style.css deleted file mode 100644 index a16ed029e..000000000 --- a/docs/assets/style.css +++ /dev/null @@ -1,1413 +0,0 @@ -@import url("./icons.css"); - -:root { - /* Light */ - --light-color-background: #fcfcfc; - --light-color-secondary-background: #fff; - --light-color-text: #222; - --light-color-text-aside: #707070; - --light-color-link: #4da6ff; - --light-color-menu-divider: #eee; - --light-color-menu-divider-focus: #000; - --light-color-menu-label: #707070; - --light-color-panel: var(--light-color-secondary-background); - --light-color-panel-divider: #eee; - --light-color-comment-tag: #707070; - --light-color-comment-tag-text: #fff; - --light-color-ts: #9600ff; - --light-color-ts-interface: #647f1b; - --light-color-ts-enum: #937210; - --light-color-ts-class: #0672de; - --light-color-ts-private: #707070; - --light-color-toolbar: #fff; - --light-color-toolbar-text: #333; - --light-icon-filter: invert(0); - --light-external-icon: url("data:image/svg+xml;utf8,"); - - /* Dark */ - --dark-color-background: #36393f; - --dark-color-secondary-background: #2f3136; - --dark-color-text: #ffffff; - --dark-color-text-aside: #e6e4e4; - --dark-color-link: #00aff4; - --dark-color-menu-divider: #eee; - --dark-color-menu-divider-focus: #000; - --dark-color-menu-label: #707070; - --dark-color-panel: var(--dark-color-secondary-background); - --dark-color-panel-divider: #818181; - --dark-color-comment-tag: #dcddde; - --dark-color-comment-tag-text: #2f3136; - --dark-color-ts: #c97dff; - --dark-color-ts-interface: #9cbe3c; - --dark-color-ts-enum: #d6ab29; - --dark-color-ts-class: #3695f3; - --dark-color-ts-private: #e2e2e2; - --dark-color-toolbar: #34373c; - --dark-color-toolbar-text: #ffffff; - --dark-icon-filter: invert(1); - --dark-external-icon: url("data:image/svg+xml;utf8,"); -} - -@media (prefers-color-scheme: light) { - :root { - --color-background: var(--light-color-background); - --color-secondary-background: var(--light-color-secondary-background); - --color-text: var(--light-color-text); - --color-text-aside: var(--light-color-text-aside); - --color-link: var(--light-color-link); - --color-menu-divider: var(--light-color-menu-divider); - --color-menu-divider-focus: var(--light-color-menu-divider-focus); - --color-menu-label: var(--light-color-menu-label); - --color-panel: var(--light-color-panel); - --color-panel-divider: var(--light-color-panel-divider); - --color-comment-tag: var(--light-color-comment-tag); - --color-comment-tag-text: var(--light-color-comment-tag-text); - --color-ts: var(--light-color-ts); - --color-ts-interface: var(--light-color-ts-interface); - --color-ts-enum: var(--light-color-ts-enum); - --color-ts-class: var(--light-color-ts-class); - --color-ts-private: var(--light-color-ts-private); - --color-toolbar: var(--light-color-toolbar); - --color-toolbar-text: var(--light-color-toolbar-text); - --icon-filter: var(--light-icon-filter); - --external-icon: var(--light-external-icon); - } -} - -@media (prefers-color-scheme: dark) { - :root { - --color-background: var(--dark-color-background); - --color-secondary-background: var(--dark-color-secondary-background); - --color-text: var(--dark-color-text); - --color-text-aside: var(--dark-color-text-aside); - --color-link: var(--dark-color-link); - --color-menu-divider: var(--dark-color-menu-divider); - --color-menu-divider-focus: var(--dark-color-menu-divider-focus); - --color-menu-label: var(--dark-color-menu-label); - --color-panel: var(--dark-color-panel); - --color-panel-divider: var(--dark-color-panel-divider); - --color-comment-tag: var(--dark-color-comment-tag); - --color-comment-tag-text: var(--dark-color-comment-tag-text); - --color-ts: var(--dark-color-ts); - --color-ts-interface: var(--dark-color-ts-interface); - --color-ts-enum: var(--dark-color-ts-enum); - --color-ts-class: var(--dark-color-ts-class); - --color-ts-private: var(--dark-color-ts-private); - --color-toolbar: var(--dark-color-toolbar); - --color-toolbar-text: var(--dark-color-toolbar-text); - --icon-filter: var(--dark-icon-filter); - --external-icon: var(--dark-external-icon); - } -} - -body { - margin: 0; -} - -body.light { - --color-background: var(--light-color-background); - --color-secondary-background: var(--light-color-secondary-background); - --color-text: var(--light-color-text); - --color-text-aside: var(--light-color-text-aside); - --color-link: var(--light-color-link); - --color-menu-divider: var(--light-color-menu-divider); - --color-menu-divider-focus: var(--light-color-menu-divider-focus); - --color-menu-label: var(--light-color-menu-label); - --color-panel: var(--light-color-panel); - --color-panel-divider: var(--light-color-panel-divider); - --color-comment-tag: var(--light-color-comment-tag); - --color-comment-tag-text: var(--light-color-comment-tag-text); - --color-ts: var(--light-color-ts); - --color-ts-interface: var(--light-color-ts-interface); - --color-ts-enum: var(--light-color-ts-enum); - --color-ts-class: var(--light-color-ts-class); - --color-ts-private: var(--light-color-ts-private); - --color-toolbar: var(--light-color-toolbar); - --color-toolbar-text: var(--light-color-toolbar-text); - --icon-filter: var(--light-icon-filter); - --external-icon: var(--light-external-icon); -} - -body.dark { - --color-background: var(--dark-color-background); - --color-secondary-background: var(--dark-color-secondary-background); - --color-text: var(--dark-color-text); - --color-text-aside: var(--dark-color-text-aside); - --color-link: var(--dark-color-link); - --color-menu-divider: var(--dark-color-menu-divider); - --color-menu-divider-focus: var(--dark-color-menu-divider-focus); - --color-menu-label: var(--dark-color-menu-label); - --color-panel: var(--dark-color-panel); - --color-panel-divider: var(--dark-color-panel-divider); - --color-comment-tag: var(--dark-color-comment-tag); - --color-comment-tag-text: var(--dark-color-comment-tag-text); - --color-ts: var(--dark-color-ts); - --color-ts-interface: var(--dark-color-ts-interface); - --color-ts-enum: var(--dark-color-ts-enum); - --color-ts-class: var(--dark-color-ts-class); - --color-ts-private: var(--dark-color-ts-private); - --color-toolbar: var(--dark-color-toolbar); - --color-toolbar-text: var(--dark-color-toolbar-text); - --icon-filter: var(--dark-icon-filter); - --external-icon: var(--dark-external-icon); -} - -h1, -h2, -h3, -h4, -h5, -h6 { - line-height: 1.2; -} - -h1 { - font-size: 2em; - margin: 0.67em 0; -} - -h2 { - font-size: 1.5em; - margin: 0.83em 0; -} - -h3 { - font-size: 1.17em; - margin: 1em 0; -} - -h4, -.tsd-index-panel h3 { - font-size: 1em; - margin: 1.33em 0; -} - -h5 { - font-size: 0.83em; - margin: 1.67em 0; -} - -h6 { - font-size: 0.67em; - margin: 2.33em 0; -} - -pre { - white-space: pre; - white-space: pre-wrap; - word-wrap: break-word; -} - -dl, -menu, -ol, -ul { - margin: 1em 0; -} - -dd { - margin: 0 0 0 40px; -} - -.container { - max-width: 1200px; - margin: 0 auto; - padding: 0 40px; -} -@media (max-width: 640px) { - .container { - padding: 0 20px; - } -} - -.container-main { - padding-bottom: 200px; -} - -.row { - display: flex; - position: relative; - margin: 0 -10px; -} -.row:after { - visibility: hidden; - display: block; - content: ""; - clear: both; - height: 0; -} - -.col-4, -.col-8 { - box-sizing: border-box; - float: left; - padding: 0 10px; -} - -.col-4 { - width: 33.3333333333%; -} -.col-8 { - width: 66.6666666667%; -} - -ul.tsd-descriptions > li > :first-child, -.tsd-panel > :first-child, -.col-8 > :first-child, -.col-4 > :first-child, -ul.tsd-descriptions > li > :first-child > :first-child, -.tsd-panel > :first-child > :first-child, -.col-8 > :first-child > :first-child, -.col-4 > :first-child > :first-child, -ul.tsd-descriptions > li > :first-child > :first-child > :first-child, -.tsd-panel > :first-child > :first-child > :first-child, -.col-8 > :first-child > :first-child > :first-child, -.col-4 > :first-child > :first-child > :first-child { - margin-top: 0; -} -ul.tsd-descriptions > li > :last-child, -.tsd-panel > :last-child, -.col-8 > :last-child, -.col-4 > :last-child, -ul.tsd-descriptions > li > :last-child > :last-child, -.tsd-panel > :last-child > :last-child, -.col-8 > :last-child > :last-child, -.col-4 > :last-child > :last-child, -ul.tsd-descriptions > li > :last-child > :last-child > :last-child, -.tsd-panel > :last-child > :last-child > :last-child, -.col-8 > :last-child > :last-child > :last-child, -.col-4 > :last-child > :last-child > :last-child { - margin-bottom: 0; -} - -@keyframes fade-in { - from { - opacity: 0; - } - to { - opacity: 1; - } -} -@keyframes fade-out { - from { - opacity: 1; - visibility: visible; - } - to { - opacity: 0; - } -} -@keyframes fade-in-delayed { - 0% { - opacity: 0; - } - 33% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -@keyframes fade-out-delayed { - 0% { - opacity: 1; - visibility: visible; - } - 66% { - opacity: 0; - } - 100% { - opacity: 0; - } -} -@keyframes shift-to-left { - from { - transform: translate(0, 0); - } - to { - transform: translate(-25%, 0); - } -} -@keyframes unshift-to-left { - from { - transform: translate(-25%, 0); - } - to { - transform: translate(0, 0); - } -} -@keyframes pop-in-from-right { - from { - transform: translate(100%, 0); - } - to { - transform: translate(0, 0); - } -} -@keyframes pop-out-to-right { - from { - transform: translate(0, 0); - visibility: visible; - } - to { - transform: translate(100%, 0); - } -} -body { - background: var(--color-background); - font-family: "Segoe UI", sans-serif; - font-size: 16px; - color: var(--color-text); -} - -a { - color: var(--color-link); - text-decoration: none; -} -a:hover { - text-decoration: underline; -} -a.external[target="_blank"] { - background-image: var(--external-icon); - background-position: top 3px right; - background-repeat: no-repeat; - padding-right: 13px; -} - -code, -pre { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - padding: 0.2em; - margin: 0; - font-size: 14px; -} - -pre { - padding: 10px; -} -pre code { - padding: 0; - font-size: 100%; -} - -blockquote { - margin: 1em 0; - padding-left: 1em; - border-left: 4px solid gray; -} - -.tsd-typography { - line-height: 1.333em; -} -.tsd-typography ul { - list-style: square; - padding: 0 0 0 20px; - margin: 0; -} -.tsd-typography h4, -.tsd-typography .tsd-index-panel h3, -.tsd-index-panel .tsd-typography h3, -.tsd-typography h5, -.tsd-typography h6 { - font-size: 1em; - margin: 0; -} -.tsd-typography h5, -.tsd-typography h6 { - font-weight: normal; -} -.tsd-typography p, -.tsd-typography ul, -.tsd-typography ol { - margin: 1em 0; -} - -@media (min-width: 901px) and (max-width: 1024px) { - html .col-content { - width: 72%; - } - html .col-menu { - width: 28%; - } - html .tsd-navigation { - padding-left: 10px; - } -} -@media (max-width: 900px) { - html .col-content { - float: none; - width: 100%; - } - html .col-menu { - position: fixed !important; - overflow: auto; - -webkit-overflow-scrolling: touch; - z-index: 1024; - top: 0 !important; - bottom: 0 !important; - left: auto !important; - right: 0 !important; - width: 100%; - padding: 20px 20px 0 0; - max-width: 450px; - visibility: hidden; - background-color: var(--color-panel); - transform: translate(100%, 0); - } - html .col-menu > *:last-child { - padding-bottom: 20px; - } - html .overlay { - content: ""; - display: block; - position: fixed; - z-index: 1023; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(0, 0, 0, 0.75); - visibility: hidden; - } - - .to-has-menu .overlay { - animation: fade-in 0.4s; - } - - .to-has-menu :is(header, footer, .col-content) { - animation: shift-to-left 0.4s; - } - - .to-has-menu .col-menu { - animation: pop-in-from-right 0.4s; - } - - .from-has-menu .overlay { - animation: fade-out 0.4s; - } - - .from-has-menu :is(header, footer, .col-content) { - animation: unshift-to-left 0.4s; - } - - .from-has-menu .col-menu { - animation: pop-out-to-right 0.4s; - } - - .has-menu body { - overflow: hidden; - } - .has-menu .overlay { - visibility: visible; - } - .has-menu :is(header, footer, .col-content) { - transform: translate(-25%, 0); - } - .has-menu .col-menu { - visibility: visible; - transform: translate(0, 0); - display: grid; - grid-template-rows: auto 1fr; - max-height: 100vh; - } - .has-menu .tsd-navigation { - max-height: 100%; - } -} - -.tsd-page-title { - padding: 70px 0 20px 0; - margin: 0 0 40px 0; - background: var(--color-panel); - box-shadow: 0 0 5px rgba(0, 0, 0, 0.35); -} -.tsd-page-title h1 { - margin: 0; -} - -.tsd-breadcrumb { - margin: 0; - padding: 0; - color: var(--color-text-aside); -} -.tsd-breadcrumb a { - color: var(--color-text-aside); - text-decoration: none; -} -.tsd-breadcrumb a:hover { - text-decoration: underline; -} -.tsd-breadcrumb li { - display: inline; -} -.tsd-breadcrumb li:after { - content: " / "; -} - -dl.tsd-comment-tags { - overflow: hidden; -} -dl.tsd-comment-tags dt { - float: left; - padding: 1px 5px; - margin: 0 10px 0 0; - border-radius: 4px; - border: 1px solid var(--color-comment-tag); - color: var(--color-comment-tag); - font-size: 0.8em; - font-weight: normal; -} -dl.tsd-comment-tags dd { - margin: 0 0 10px 0; -} -dl.tsd-comment-tags dd:before, -dl.tsd-comment-tags dd:after { - display: table; - content: " "; -} -dl.tsd-comment-tags dd pre, -dl.tsd-comment-tags dd:after { - clear: both; -} -dl.tsd-comment-tags p { - margin: 0; -} - -.tsd-panel.tsd-comment .lead { - font-size: 1.1em; - line-height: 1.333em; - margin-bottom: 2em; -} -.tsd-panel.tsd-comment .lead:last-child { - margin-bottom: 0; -} - -.toggle-protected .tsd-is-private { - display: none; -} - -.toggle-public .tsd-is-private, -.toggle-public .tsd-is-protected, -.toggle-public .tsd-is-private-protected { - display: none; -} - -.toggle-inherited .tsd-is-inherited { - display: none; -} - -.toggle-externals .tsd-is-external { - display: none; -} - -#tsd-filter { - position: relative; - display: inline-block; - height: 40px; - vertical-align: bottom; -} -.no-filter #tsd-filter { - display: none; -} -#tsd-filter .tsd-filter-group { - display: inline-block; - height: 40px; - vertical-align: bottom; - white-space: nowrap; -} -#tsd-filter input { - display: none; -} -@media (max-width: 900px) { - #tsd-filter .tsd-filter-group { - display: block; - position: absolute; - top: 40px; - right: 20px; - height: auto; - background-color: var(--color-panel); - visibility: hidden; - transform: translate(50%, 0); - box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); - } - .has-options #tsd-filter .tsd-filter-group { - visibility: visible; - } - .to-has-options #tsd-filter .tsd-filter-group { - animation: fade-in 0.2s; - } - .from-has-options #tsd-filter .tsd-filter-group { - animation: fade-out 0.2s; - } - #tsd-filter label, - #tsd-filter .tsd-select { - display: block; - padding-right: 20px; - } -} - -footer { - border-top: 1px solid var(--color-panel-divider); - background-color: var(--color-panel); -} -footer:after { - content: ""; - display: table; -} -footer.with-border-bottom { - border-bottom: 1px solid var(--color-panel-divider); -} -footer .tsd-legend-group { - font-size: 0; -} -footer .tsd-legend { - display: inline-block; - width: 25%; - padding: 0; - font-size: 16px; - list-style: none; - line-height: 1.333em; - vertical-align: top; -} -@media (max-width: 900px) { - footer .tsd-legend { - width: 50%; - } -} - -.tsd-hierarchy { - list-style: square; - padding: 0 0 0 20px; - margin: 0; -} -.tsd-hierarchy .target { - font-weight: bold; -} - -.tsd-index-panel .tsd-index-content { - margin-bottom: -30px !important; -} -.tsd-index-panel .tsd-index-section { - margin-bottom: 30px !important; -} -.tsd-index-panel h3 { - margin: 0 -20px 10px -20px; - padding: 0 20px 10px 20px; - border-bottom: 1px solid var(--color-panel-divider); -} -.tsd-index-panel ul.tsd-index-list { - -webkit-column-count: 3; - -moz-column-count: 3; - -ms-column-count: 3; - -o-column-count: 3; - column-count: 3; - -webkit-column-gap: 20px; - -moz-column-gap: 20px; - -ms-column-gap: 20px; - -o-column-gap: 20px; - column-gap: 20px; - padding: 0; - list-style: none; - line-height: 1.333em; -} -@media (max-width: 900px) { - .tsd-index-panel ul.tsd-index-list { - -webkit-column-count: 1; - -moz-column-count: 1; - -ms-column-count: 1; - -o-column-count: 1; - column-count: 1; - } -} -@media (min-width: 901px) and (max-width: 1024px) { - .tsd-index-panel ul.tsd-index-list { - -webkit-column-count: 2; - -moz-column-count: 2; - -ms-column-count: 2; - -o-column-count: 2; - column-count: 2; - } -} -.tsd-index-panel ul.tsd-index-list li { - -webkit-page-break-inside: avoid; - -moz-page-break-inside: avoid; - -ms-page-break-inside: avoid; - -o-page-break-inside: avoid; - page-break-inside: avoid; -} -.tsd-index-panel a, -.tsd-index-panel .tsd-parent-kind-module a { - color: var(--color-ts); -} -.tsd-index-panel .tsd-parent-kind-interface a { - color: var(--color-ts-interface); -} -.tsd-index-panel .tsd-parent-kind-enum a { - color: var(--color-ts-enum); -} -.tsd-index-panel .tsd-parent-kind-class a { - color: var(--color-ts-class); -} -.tsd-index-panel .tsd-kind-module a { - color: var(--color-ts); -} -.tsd-index-panel .tsd-kind-interface a { - color: var(--color-ts-interface); -} -.tsd-index-panel .tsd-kind-enum a { - color: var(--color-ts-enum); -} -.tsd-index-panel .tsd-kind-class a { - color: var(--color-ts-class); -} -.tsd-index-panel .tsd-is-private a { - color: var(--color-ts-private); -} - -.tsd-flag { - display: inline-block; - padding: 1px 5px; - border-radius: 4px; - color: var(--color-comment-tag-text); - background-color: var(--color-comment-tag); - text-indent: 0; - font-size: 14px; - font-weight: normal; -} - -.tsd-anchor { - position: absolute; - top: -100px; -} - -.tsd-member { - position: relative; -} -.tsd-member .tsd-anchor + h3 { - margin-top: 0; - margin-bottom: 0; - border-bottom: none; -} -.tsd-member [data-tsd-kind] { - color: var(--color-ts); -} -.tsd-member [data-tsd-kind="Interface"] { - color: var(--color-ts-interface); -} -.tsd-member [data-tsd-kind="Enum"] { - color: var(--color-ts-enum); -} -.tsd-member [data-tsd-kind="Class"] { - color: var(--color-ts-class); -} -.tsd-member [data-tsd-kind="Private"] { - color: var(--color-ts-private); -} - -.tsd-navigation { - margin: 0 0 0 40px; -} -.tsd-navigation a { - display: block; - padding-top: 2px; - padding-bottom: 2px; - border-left: 2px solid transparent; - color: var(--color-text); - text-decoration: none; - transition: border-left-color 0.1s; -} -.tsd-navigation a:hover { - text-decoration: underline; -} -.tsd-navigation ul { - margin: 0; - padding: 0; - list-style: none; -} -.tsd-navigation li { - padding: 0; -} - -.tsd-navigation.primary { - padding-bottom: 40px; -} -.tsd-navigation.primary a { - display: block; - padding-top: 6px; - padding-bottom: 6px; -} -.tsd-navigation.primary ul li a { - padding-left: 5px; -} -.tsd-navigation.primary ul li li a { - padding-left: 25px; -} -.tsd-navigation.primary ul li li li a { - padding-left: 45px; -} -.tsd-navigation.primary ul li li li li a { - padding-left: 65px; -} -.tsd-navigation.primary ul li li li li li a { - padding-left: 85px; -} -.tsd-navigation.primary ul li li li li li li a { - padding-left: 105px; -} -.tsd-navigation.primary > ul { - border-bottom: 1px solid var(--color-panel-divider); -} -.tsd-navigation.primary li { - border-top: 1px solid var(--color-panel-divider); -} -.tsd-navigation.primary li.current > a { - font-weight: bold; -} -.tsd-navigation.primary li.label span { - display: block; - padding: 20px 0 6px 5px; - color: var(--color-menu-label); -} -.tsd-navigation.primary li.globals + li > span, -.tsd-navigation.primary li.globals + li > a { - padding-top: 20px; -} - -.tsd-navigation.secondary { - max-height: calc(100vh - 1rem - 40px); - overflow: auto; - position: sticky; - top: calc(0.5rem + 40px); - transition: 0.3s; -} -.tsd-navigation.secondary.tsd-navigation--toolbar-hide { - max-height: calc(100vh - 1rem); - top: 0.5rem; -} -.tsd-navigation.secondary ul { - transition: opacity 0.2s; -} -.tsd-navigation.secondary ul li a { - padding-left: 25px; -} -.tsd-navigation.secondary ul li li a { - padding-left: 45px; -} -.tsd-navigation.secondary ul li li li a { - padding-left: 65px; -} -.tsd-navigation.secondary ul li li li li a { - padding-left: 85px; -} -.tsd-navigation.secondary ul li li li li li a { - padding-left: 105px; -} -.tsd-navigation.secondary ul li li li li li li a { - padding-left: 125px; -} -.tsd-navigation.secondary ul.current a { - border-left-color: var(--color-panel-divider); -} -.tsd-navigation.secondary li.focus > a, -.tsd-navigation.secondary ul.current li.focus > a { - border-left-color: var(--color-menu-divider-focus); -} -.tsd-navigation.secondary li.current { - margin-top: 20px; - margin-bottom: 20px; - border-left-color: var(--color-panel-divider); -} -.tsd-navigation.secondary li.current > a { - font-weight: bold; -} - -@media (min-width: 901px) { - .menu-sticky-wrap { - position: static; - } -} - -.tsd-panel { - margin: 20px 0; - padding: 20px; - background-color: var(--color-panel); - box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); -} -.tsd-panel:empty { - display: none; -} -.tsd-panel > h1, -.tsd-panel > h2, -.tsd-panel > h3 { - margin: 1.5em -20px 10px -20px; - padding: 0 20px 10px 20px; - border-bottom: 1px solid var(--color-panel-divider); -} -.tsd-panel > h1.tsd-before-signature, -.tsd-panel > h2.tsd-before-signature, -.tsd-panel > h3.tsd-before-signature { - margin-bottom: 0; - border-bottom: 0; -} -.tsd-panel table { - display: block; - width: 100%; - overflow: auto; - margin-top: 10px; - word-break: normal; - word-break: keep-all; - border-collapse: collapse; -} -.tsd-panel table th { - font-weight: bold; -} -.tsd-panel table th, -.tsd-panel table td { - padding: 6px 13px; - border: 1px solid var(--color-panel-divider); -} -.tsd-panel table tr { - background: var(--color-background); -} -.tsd-panel table tr:nth-child(even) { - background: var(--color-secondary-background); -} - -.tsd-panel-group { - margin: 60px 0; -} -.tsd-panel-group > h1, -.tsd-panel-group > h2, -.tsd-panel-group > h3 { - padding-left: 20px; - padding-right: 20px; -} - -#tsd-search { - transition: background-color 0.2s; -} -#tsd-search .title { - position: relative; - z-index: 2; -} -#tsd-search .field { - position: absolute; - left: 0; - top: 0; - right: 40px; - height: 40px; -} -#tsd-search .field input { - box-sizing: border-box; - position: relative; - top: -50px; - z-index: 1; - width: 100%; - padding: 0 10px; - opacity: 0; - outline: 0; - border: 0; - background: transparent; - color: var(--color-text); -} -#tsd-search .field label { - position: absolute; - overflow: hidden; - right: -40px; -} -#tsd-search .field input, -#tsd-search .title { - transition: opacity 0.2s; -} -#tsd-search .results { - position: absolute; - visibility: hidden; - top: 40px; - width: 100%; - margin: 0; - padding: 0; - list-style: none; - box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); -} -#tsd-search .results li { - padding: 0 10px; - background-color: var(--color-background); -} -#tsd-search .results li:nth-child(even) { - background-color: var(--color-panel); -} -#tsd-search .results li.state { - display: none; -} -#tsd-search .results li.current, -#tsd-search .results li:hover { - background-color: var(--color-panel-divider); -} -#tsd-search .results a { - display: block; -} -#tsd-search .results a:before { - top: 10px; -} -#tsd-search .results span.parent { - color: var(--color-text-aside); - font-weight: normal; -} -#tsd-search.has-focus { - background-color: var(--color-panel-divider); -} -#tsd-search.has-focus .field input { - top: 0; - opacity: 1; -} -#tsd-search.has-focus .title { - z-index: 0; - opacity: 0; -} -#tsd-search.has-focus .results { - visibility: visible; -} -#tsd-search.loading .results li.state.loading { - display: block; -} -#tsd-search.failure .results li.state.failure { - display: block; -} - -.tsd-signature { - margin: 0 0 1em 0; - padding: 10px; - border: 1px solid var(--color-panel-divider); - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - font-size: 14px; - overflow-x: auto; -} -.tsd-signature.tsd-kind-icon { - padding-left: 30px; -} -.tsd-signature.tsd-kind-icon:before { - top: 10px; - left: 10px; -} -.tsd-panel > .tsd-signature { - margin-left: -20px; - margin-right: -20px; - border-width: 1px 0; -} -.tsd-panel > .tsd-signature.tsd-kind-icon { - padding-left: 40px; -} -.tsd-panel > .tsd-signature.tsd-kind-icon:before { - left: 20px; -} - -.tsd-signature-symbol { - color: var(--color-text-aside); - font-weight: normal; -} - -.tsd-signature-type { - font-style: italic; - font-weight: normal; -} - -.tsd-signatures { - padding: 0; - margin: 0 0 1em 0; - border: 1px solid var(--color-panel-divider); -} -.tsd-signatures .tsd-signature { - margin: 0; - border-width: 1px 0 0 0; - transition: background-color 0.1s; -} -.tsd-signatures .tsd-signature:first-child { - border-top-width: 0; -} -.tsd-signatures .tsd-signature.current { - background-color: var(--color-panel-divider); -} -.tsd-signatures.active > .tsd-signature { - cursor: pointer; -} -.tsd-panel > .tsd-signatures { - margin-left: -20px; - margin-right: -20px; - border-width: 1px 0; -} -.tsd-panel > .tsd-signatures .tsd-signature.tsd-kind-icon { - padding-left: 40px; -} -.tsd-panel > .tsd-signatures .tsd-signature.tsd-kind-icon:before { - left: 20px; -} -.tsd-panel > a.anchor + .tsd-signatures { - border-top-width: 0; - margin-top: -20px; -} - -ul.tsd-descriptions { - position: relative; - overflow: hidden; - padding: 0; - list-style: none; -} -ul.tsd-descriptions.active > .tsd-description { - display: none; -} -ul.tsd-descriptions.active > .tsd-description.current { - display: block; -} -ul.tsd-descriptions.active > .tsd-description.fade-in { - animation: fade-in-delayed 0.3s; -} -ul.tsd-descriptions.active > .tsd-description.fade-out { - animation: fade-out-delayed 0.3s; - position: absolute; - display: block; - top: 0; - left: 0; - right: 0; - opacity: 0; - visibility: hidden; -} -ul.tsd-descriptions h4, -ul.tsd-descriptions .tsd-index-panel h3, -.tsd-index-panel ul.tsd-descriptions h3 { - font-size: 16px; - margin: 1em 0 0.5em 0; -} - -ul.tsd-parameters, -ul.tsd-type-parameters { - list-style: square; - margin: 0; - padding-left: 20px; -} -ul.tsd-parameters > li.tsd-parameter-signature, -ul.tsd-type-parameters > li.tsd-parameter-signature { - list-style: none; - margin-left: -20px; -} -ul.tsd-parameters h5, -ul.tsd-type-parameters h5 { - font-size: 16px; - margin: 1em 0 0.5em 0; -} -ul.tsd-parameters .tsd-comment, -ul.tsd-type-parameters .tsd-comment { - margin-top: -0.5em; -} - -.tsd-sources { - font-size: 14px; - color: var(--color-text-aside); - margin: 0 0 1em 0; -} -.tsd-sources a { - color: var(--color-text-aside); - text-decoration: underline; -} -.tsd-sources ul, -.tsd-sources p { - margin: 0 !important; -} -.tsd-sources ul { - list-style: none; - padding: 0; -} - -.tsd-page-toolbar { - position: fixed; - z-index: 1; - top: 0; - left: 0; - width: 100%; - height: 40px; - color: var(--color-toolbar-text); - background: var(--color-toolbar); - border-bottom: 1px solid var(--color-panel-divider); - transition: transform 0.3s linear; -} -.tsd-page-toolbar a { - color: var(--color-toolbar-text); - text-decoration: none; -} -.tsd-page-toolbar a.title { - font-weight: bold; -} -.tsd-page-toolbar a.title:hover { - text-decoration: underline; -} -.tsd-page-toolbar .table-wrap { - display: table; - width: 100%; - height: 40px; -} -.tsd-page-toolbar .table-cell { - display: table-cell; - position: relative; - white-space: nowrap; - line-height: 40px; -} -.tsd-page-toolbar .table-cell:first-child { - width: 100%; -} - -.tsd-page-toolbar--hide { - transform: translateY(-100%); -} - -.tsd-select .tsd-select-list li:before, -.tsd-select .tsd-select-label:before, -.tsd-widget:before { - content: ""; - display: inline-block; - width: 40px; - height: 40px; - margin: 0 -8px 0 0; - background-image: url(./widgets.png); - background-repeat: no-repeat; - text-indent: -1024px; - vertical-align: bottom; - filter: var(--icon-filter); -} -@media (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 144dpi) { - .tsd-select .tsd-select-list li:before, - .tsd-select .tsd-select-label:before, - .tsd-widget:before { - background-image: url(./widgets@2x.png); - background-size: 320px 40px; - } -} - -.tsd-widget { - display: inline-block; - overflow: hidden; - opacity: 0.8; - height: 40px; - transition: opacity 0.1s, background-color 0.2s; - vertical-align: bottom; - cursor: pointer; -} -.tsd-widget:hover { - opacity: 0.9; -} -.tsd-widget.active { - opacity: 1; - background-color: var(--color-panel-divider); -} -.tsd-widget.no-caption { - width: 40px; -} -.tsd-widget.no-caption:before { - margin: 0; -} -.tsd-widget.search:before { - background-position: 0 0; -} -.tsd-widget.menu:before { - background-position: -40px 0; -} -.tsd-widget.options:before { - background-position: -80px 0; -} -.tsd-widget.options, -.tsd-widget.menu { - display: none; -} -@media (max-width: 900px) { - .tsd-widget.options, - .tsd-widget.menu { - display: inline-block; - } -} -input[type="checkbox"] + .tsd-widget:before { - background-position: -120px 0; -} -input[type="checkbox"]:checked + .tsd-widget:before { - background-position: -160px 0; -} - -.tsd-select { - position: relative; - display: inline-block; - height: 40px; - transition: opacity 0.1s, background-color 0.2s; - vertical-align: bottom; - cursor: pointer; -} -.tsd-select .tsd-select-label { - opacity: 0.6; - transition: opacity 0.2s; -} -.tsd-select .tsd-select-label:before { - background-position: -240px 0; -} -.tsd-select.active .tsd-select-label { - opacity: 0.8; -} -.tsd-select.active .tsd-select-list { - visibility: visible; - opacity: 1; - transition-delay: 0s; -} -.tsd-select .tsd-select-list { - position: absolute; - visibility: hidden; - top: 40px; - left: 0; - margin: 0; - padding: 0; - opacity: 0; - list-style: none; - box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); - transition: visibility 0s 0.2s, opacity 0.2s; -} -.tsd-select .tsd-select-list li { - padding: 0 20px 0 0; - background-color: var(--color-background); -} -.tsd-select .tsd-select-list li:before { - background-position: 40px 0; -} -.tsd-select .tsd-select-list li:nth-child(even) { - background-color: var(--color-panel); -} -.tsd-select .tsd-select-list li:hover { - background-color: var(--color-panel-divider); -} -.tsd-select .tsd-select-list li.selected:before { - background-position: -200px 0; -} -@media (max-width: 900px) { - .tsd-select .tsd-select-list { - top: 0; - left: auto; - right: 100%; - margin-right: -5px; - } - .tsd-select .tsd-select-label:before { - background-position: -280px 0; - } -} - -img { - max-width: 100%; -} - -.tsd-anchor-icon { - margin-left: 10px; - vertical-align: middle; - color: var(--color-text); -} - -.tsd-anchor-icon svg { - width: 1em; - height: 1em; - visibility: hidden; -} - -.tsd-anchor-link:hover > .tsd-anchor-icon svg { - visibility: visible; -} diff --git a/docs/assets/widgets.png b/docs/assets/widgets.png deleted file mode 100644 index c7380532ac1b45400620011c37c4dcb7aec27a4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 480 zcmeAS@N?(olHy`uVBq!ia0y~yU~~YoH8@y+q^jrZML>b&o-U3d6^w6h1+IPUz|;DW zIZ;96kdsD>Qv^q=09&hp0GpEni<1IR%gvP3v%OR9*{MuRTKWHZyIbuBt)Ci`cU_&% z1T+i^Y)o{%281-<3TpPAUTzw5v;RY=>1rvxmPl96#kYc9hX!6V^nB|ad#(S+)}?8C zr_H+lT3B#So$T=?$(w3-{rbQ4R<@nsf$}$hwSO)A$8&`(j+wQf=Jwhb0`CvhR5DCf z^OgI)KQemrUFPH+UynC$Y~QHG%DbTVh-Skz{enNU)cV_hPu~{TD7TPZl>0&K>iuE| z7AYn$7)Jrb9GE&SfQW4q&G*@N|4cHI`VakFa5-C!ov&XD)J(qp$rJJ*9e z-sHv}#g*T7Cv048d1v~BEAzM5FztAse#q78WWC^BUCzQ U&wLp6h6BX&boFyt=akR{0G%$)mH+?% diff --git a/docs/assets/widgets@2x.png b/docs/assets/widgets@2x.png deleted file mode 100644 index 4bbbd57272f3b28f47527d4951ad10f950b8ad43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 855 zcmeAS@N?(olHy`uVBq!ia0y~yU}^xe12~w0Jcmn z@(X6T|9^jgLcx21{)7exgY)a>N6m2F0<`Rqr;B4q1>>88jUdw-7W`c)zLE*mq8W2H z-<&Jl_Hco5BuC5n@AbF5GD82~-e8-v=#zCyUX0F-o}8pPfAv`!GN$ff+TL<~@kgt} z62eO?_|&+>xBmM$@p|z`tIKEdpPf8%qI>4r7@jn<=eta*{3~?g(zz{Ke9zc-G^gr? z-7foa?LcS!hmbwzru}ICvbWLlW8;+l-}!^=c32!^nV`+`C*;0-*Y%l94pC;Cb3GXz zzSf%a!{gVr{Y_lVuUj+a)*Ca+!-Hu%xmP&&X-2CuANY8^i{D7Kg6qzP zXz_ps9+lN8ESH{K4`yu&b~I>N9xGlE&;2u*b?+Go!AhN?m-bxlLvtC#MzDF2kFzfHJ1W7ybqdefSqVhbOykd*Yi%EDuhs z4wF{ft^bv2+DDnKb8gj1FuvcV`M}luS>lO<^)8x>y1#R;a=-ZKwWTQQb)ioBbi;zh zD!f5V)8581to1LL7c9!l^PSC$NBPYif!_vAZhmL4)v4U)4UsrLYiH_9rmQDd?)(e5 z^pcH>qvBg*i0dus2r*mp4;zKvu=P#s-ti;2obl`NjjwoYd>e(oo#j_uyRb<7Pv^If zzZ|mGHmV)8^tbO%^>eqMw(@7(&3g{jEp-Najo7V75xI_ZHK*FA`elF{r5}E*d7+j_R diff --git a/docs/classes/framework.BaseRequest.html b/docs/classes/framework.BaseRequest.html deleted file mode 100644 index 83940b82b..000000000 --- a/docs/classes/framework.BaseRequest.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -BaseRequest | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • BaseRequest

Index

Constructors

Properties

getCookieValue: (key_: string) => undefined | string

Type declaration

    • (key_: string): undefined | string
    • Parameters

      • key_: string

      Returns undefined | string

getFormData: () => Promise<any>

Type declaration

    • (): Promise<any>
    • Returns Promise<any>

getHeaderValue: (key: string) => undefined | string

Type declaration

    • (key: string): undefined | string
    • Parameters

      • key: string

      Returns undefined | string

getJSONBody: () => Promise<any>

Type declaration

    • (): Promise<any>
    • Returns Promise<any>

getKeyValueFromQuery: (key: string) => undefined | string

Type declaration

    • (key: string): undefined | string
    • Parameters

      • key: string

      Returns undefined | string

getMethod: () => HTTPMethod

Type declaration

    • (): HTTPMethod
    • Returns HTTPMethod

getOriginalURL: () => string

Type declaration

    • (): string
    • Returns string

original: any
wrapperUsed: boolean

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Property
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -BaseRequest | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • BaseRequest

Index

Constructors

Properties

getCookieValue: (key_: string) => undefined | string

Type declaration

    • (key_: string): undefined | string
    • Parameters

      • key_: string

      Returns undefined | string

getFormData: () => Promise<any>

Type declaration

    • (): Promise<any>
    • Returns Promise<any>

getHeaderValue: (key: string) => undefined | string

Type declaration

    • (key: string): undefined | string
    • Parameters

      • key: string

      Returns undefined | string

getJSONBody: () => Promise<any>

Type declaration

    • (): Promise<any>
    • Returns Promise<any>

getKeyValueFromQuery: (key: string) => undefined | string

Type declaration

    • (key: string): undefined | string
    • Parameters

      • key: string

      Returns undefined | string

getMethod: () => HTTPMethod

Type declaration

    • (): HTTPMethod
    • Returns HTTPMethod

getOriginalURL: () => string

Type declaration

    • (): string
    • Returns string

original: any
wrapperUsed: boolean

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Property
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/framework.BaseResponse.html b/docs/classes/framework.BaseResponse.html deleted file mode 100644 index 3a86bf80b..000000000 --- a/docs/classes/framework.BaseResponse.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -BaseResponse | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • BaseResponse

Index

Constructors

Properties

original: any
removeHeader: (key: string) => void

Type declaration

    • (key: string): void
    • Parameters

      • key: string

      Returns void

sendHTMLResponse: (html: string) => void

Type declaration

    • (html: string): void
    • Parameters

      • html: string

      Returns void

sendJSONResponse: (content: any) => void

Type declaration

    • (content: any): void
    • Parameters

      • content: any

      Returns void

setCookie: (key: string, value: string, domain: undefined | string, secure: boolean, httpOnly: boolean, expires: number, path: string, sameSite: "strict" | "lax" | "none") => void

Type declaration

    • (key: string, value: string, domain: undefined | string, secure: boolean, httpOnly: boolean, expires: number, path: string, sameSite: "strict" | "lax" | "none"): void
    • Parameters

      • key: string
      • value: string
      • domain: undefined | string
      • secure: boolean
      • httpOnly: boolean
      • expires: number
      • path: string
      • sameSite: "strict" | "lax" | "none"

      Returns void

setHeader: (key: string, value: string, allowDuplicateKey: boolean) => void

Type declaration

    • (key: string, value: string, allowDuplicateKey: boolean): void
    • Parameters

      • key: string
      • value: string
      • allowDuplicateKey: boolean

      Returns void

setStatusCode: (statusCode: number) => void

Type declaration

    • (statusCode: number): void
    • Parameters

      • statusCode: number

      Returns void

wrapperUsed: boolean

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Property
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -BaseResponse | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • BaseResponse

Index

Constructors

Properties

original: any
removeHeader: (key: string) => void

Type declaration

    • (key: string): void
    • Parameters

      • key: string

      Returns void

sendHTMLResponse: (html: string) => void

Type declaration

    • (html: string): void
    • Parameters

      • html: string

      Returns void

sendJSONResponse: (content: any) => void

Type declaration

    • (content: any): void
    • Parameters

      • content: any

      Returns void

setCookie: (key: string, value: string, domain: undefined | string, secure: boolean, httpOnly: boolean, expires: number, path: string, sameSite: "strict" | "lax" | "none") => void

Type declaration

    • (key: string, value: string, domain: undefined | string, secure: boolean, httpOnly: boolean, expires: number, path: string, sameSite: "strict" | "lax" | "none"): void
    • Parameters

      • key: string
      • value: string
      • domain: undefined | string
      • secure: boolean
      • httpOnly: boolean
      • expires: number
      • path: string
      • sameSite: "strict" | "lax" | "none"

      Returns void

setHeader: (key: string, value: string, allowDuplicateKey: boolean) => void

Type declaration

    • (key: string, value: string, allowDuplicateKey: boolean): void
    • Parameters

      • key: string
      • value: string
      • allowDuplicateKey: boolean

      Returns void

setStatusCode: (statusCode: number) => void

Type declaration

    • (statusCode: number): void
    • Parameters

      • statusCode: number

      Returns void

wrapperUsed: boolean

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Property
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/index.default.html b/docs/classes/index.default.html deleted file mode 100644 index 50fb22f2a..000000000 --- a/docs/classes/index.default.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Error: typeof default = SuperTokensError
init: (config: TypeInput) => void = SuperTokens.init

Type declaration

    • (config: TypeInput): void
    • Parameters

      • config: TypeInput

      Returns void

Methods

  • createUserIdMapping(input: { externalUserId: string; externalUserIdInfo?: string; force?: false | true; superTokensUserId: string }): Promise<{ status: "OK" | "UNKNOWN_SUPERTOKENS_USER_ID_ERROR" } | { doesExternalUserIdExist: boolean; doesSuperTokensUserIdExist: boolean; status: "USER_ID_MAPPING_ALREADY_EXISTS_ERROR" }>
  • Parameters

    • input: { externalUserId: string; externalUserIdInfo?: string; force?: false | true; superTokensUserId: string }
      • externalUserId: string
      • Optional externalUserIdInfo?: string
      • Optional force?: false | true
      • superTokensUserId: string

    Returns Promise<{ status: "OK" | "UNKNOWN_SUPERTOKENS_USER_ID_ERROR" } | { doesExternalUserIdExist: boolean; doesSuperTokensUserIdExist: boolean; status: "USER_ID_MAPPING_ALREADY_EXISTS_ERROR" }>

  • deleteUser(userId: string): Promise<{ status: "OK" }>
  • deleteUserIdMapping(input: { force?: false | true; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }): Promise<{ didMappingExist: boolean; status: "OK" }>
  • Parameters

    • input: { force?: false | true; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }
      • Optional force?: false | true
      • userId: string
      • Optional userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"

    Returns Promise<{ didMappingExist: boolean; status: "OK" }>

  • getAllCORSHeaders(): string[]
  • getUserCount(includeRecipeIds?: string[]): Promise<number>
  • Parameters

    • Optional includeRecipeIds: string[]

    Returns Promise<number>

  • getUserIdMapping(input: { userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }): Promise<{ externalUserId: string; externalUserIdInfo: undefined | string; status: "OK"; superTokensUserId: string } | { status: "UNKNOWN_MAPPING_ERROR" }>
  • Parameters

    • input: { userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }
      • userId: string
      • Optional userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"

    Returns Promise<{ externalUserId: string; externalUserIdInfo: undefined | string; status: "OK"; superTokensUserId: string } | { status: "UNKNOWN_MAPPING_ERROR" }>

  • getUsersNewestFirst(input?: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }): Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>
  • Parameters

    • Optional input: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }
      • Optional includeRecipeIds?: string[]
      • Optional limit?: number
      • Optional paginationToken?: string

    Returns Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>

  • getUsersOldestFirst(input?: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }): Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>
  • Parameters

    • Optional input: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }
      • Optional includeRecipeIds?: string[]
      • Optional limit?: number
      • Optional paginationToken?: string

    Returns Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>

  • updateOrDeleteUserIdMappingInfo(input: { externalUserIdInfo?: string; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }): Promise<{ status: "OK" | "UNKNOWN_MAPPING_ERROR" }>
  • Parameters

    • input: { externalUserIdInfo?: string; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }
      • Optional externalUserIdInfo?: string
      • userId: string
      • Optional userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"

    Returns Promise<{ status: "OK" | "UNKNOWN_MAPPING_ERROR" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Error: typeof default = SuperTokensError
init: (config: TypeInput) => void = SuperTokens.init

Type declaration

    • (config: TypeInput): void
    • Parameters

      • config: TypeInput

      Returns void

Methods

  • createUserIdMapping(input: { externalUserId: string; externalUserIdInfo?: string; force?: boolean; superTokensUserId: string }): Promise<{ status: "OK" | "UNKNOWN_SUPERTOKENS_USER_ID_ERROR" } | { doesExternalUserIdExist: boolean; doesSuperTokensUserIdExist: boolean; status: "USER_ID_MAPPING_ALREADY_EXISTS_ERROR" }>
  • Parameters

    • input: { externalUserId: string; externalUserIdInfo?: string; force?: boolean; superTokensUserId: string }
      • externalUserId: string
      • Optional externalUserIdInfo?: string
      • Optional force?: boolean
      • superTokensUserId: string

    Returns Promise<{ status: "OK" | "UNKNOWN_SUPERTOKENS_USER_ID_ERROR" } | { doesExternalUserIdExist: boolean; doesSuperTokensUserIdExist: boolean; status: "USER_ID_MAPPING_ALREADY_EXISTS_ERROR" }>

  • deleteUser(userId: string): Promise<{ status: "OK" }>
  • deleteUserIdMapping(input: { force?: boolean; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }): Promise<{ didMappingExist: boolean; status: "OK" }>
  • Parameters

    • input: { force?: boolean; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }
      • Optional force?: boolean
      • userId: string
      • Optional userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"

    Returns Promise<{ didMappingExist: boolean; status: "OK" }>

  • getAllCORSHeaders(): string[]
  • getUserCount(includeRecipeIds?: string[]): Promise<number>
  • Parameters

    • Optional includeRecipeIds: string[]

    Returns Promise<number>

  • getUserIdMapping(input: { userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }): Promise<{ externalUserId: string; externalUserIdInfo: undefined | string; status: "OK"; superTokensUserId: string } | { status: "UNKNOWN_MAPPING_ERROR" }>
  • Parameters

    • input: { userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }
      • userId: string
      • Optional userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"

    Returns Promise<{ externalUserId: string; externalUserIdInfo: undefined | string; status: "OK"; superTokensUserId: string } | { status: "UNKNOWN_MAPPING_ERROR" }>

  • getUsersNewestFirst(input?: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }): Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>
  • Parameters

    • Optional input: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }
      • Optional includeRecipeIds?: string[]
      • Optional limit?: number
      • Optional paginationToken?: string

    Returns Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>

  • getUsersOldestFirst(input?: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }): Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>
  • Parameters

    • Optional input: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }
      • Optional includeRecipeIds?: string[]
      • Optional limit?: number
      • Optional paginationToken?: string

    Returns Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>

  • updateOrDeleteUserIdMappingInfo(input: { externalUserIdInfo?: string; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }): Promise<{ status: "OK" | "UNKNOWN_MAPPING_ERROR" }>
  • Parameters

    • input: { externalUserIdInfo?: string; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }
      • Optional externalUserIdInfo?: string
      • userId: string
      • Optional userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"

    Returns Promise<{ status: "OK" | "UNKNOWN_MAPPING_ERROR" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/ingredients_emaildelivery.default.html b/docs/classes/ingredients_emaildelivery.default.html deleted file mode 100644 index 048980417..000000000 --- a/docs/classes/ingredients_emaildelivery.default.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Property
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Property
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/ingredients_smsdelivery.default.html b/docs/classes/ingredients_smsdelivery.default.html deleted file mode 100644 index 143f1fffa..000000000 --- a/docs/classes/ingredients_smsdelivery.default.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Property
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Property
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/recipe_dashboard.default.html b/docs/classes/recipe_dashboard.default.html deleted file mode 100644 index 799bb4337..000000000 --- a/docs/classes/recipe_dashboard.default.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Interface
  • Static property

Settings

Theme

Generated using TypeDoc

-======= -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Interface
  • Static property

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/recipe_emailpassword.default.html b/docs/classes/recipe_emailpassword.default.html deleted file mode 100644 index 8ddc14a9a..000000000 --- a/docs/classes/recipe_emailpassword.default.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Error: typeof default = SuperTokensError
init: (config?: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config?: TypeInput): RecipeListFunction
    • Parameters

      • Optional config: TypeInput

      Returns RecipeListFunction

Methods

  • createResetPasswordToken(userId: string, userContext?: any): Promise<{ status: "OK"; token: string } | { status: "UNKNOWN_USER_ID_ERROR" }>
  • getUserByEmail(email: string, userContext?: any): Promise<undefined | User>
  • getUserById(userId: string, userContext?: any): Promise<undefined | User>
  • resetPasswordUsingToken(token: string, newPassword: string, userContext?: any): Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>
  • Parameters

    • token: string
    • newPassword: string
    • Optional userContext: any

    Returns Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>

  • sendEmail(input: TypeEmailPasswordPasswordResetEmailDeliveryInput & { userContext?: any }): Promise<void>
  • signIn(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>
  • signUp(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>
  • updateEmailOrPassword(input: { email?: string; password?: string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>
  • Parameters

    • input: { email?: string; password?: string; userContext?: any; userId: string }
      • Optional email?: string
      • Optional password?: string
      • Optional userContext?: any
      • userId: string

    Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Error: typeof default = SuperTokensError
init: (config?: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config?: TypeInput): RecipeListFunction
    • Parameters

      • Optional config: TypeInput

      Returns RecipeListFunction

Methods

  • createResetPasswordToken(userId: string, userContext?: any): Promise<{ status: "OK"; token: string } | { status: "UNKNOWN_USER_ID_ERROR" }>
  • getUserByEmail(email: string, userContext?: any): Promise<undefined | User>
  • getUserById(userId: string, userContext?: any): Promise<undefined | User>
  • resetPasswordUsingToken(token: string, newPassword: string, userContext?: any): Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>
  • Parameters

    • token: string
    • newPassword: string
    • Optional userContext: any

    Returns Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>

  • sendEmail(input: TypeEmailPasswordPasswordResetEmailDeliveryInput & { userContext?: any }): Promise<void>
  • signIn(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>
  • signUp(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>
  • updateEmailOrPassword(input: { email?: string; password?: string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>
  • Parameters

    • input: { email?: string; password?: string; userContext?: any; userId: string }
      • Optional email?: string
      • Optional password?: string
      • Optional userContext?: any
      • userId: string

    Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/recipe_emailverification.default.html b/docs/classes/recipe_emailverification.default.html deleted file mode 100644 index 556a16550..000000000 --- a/docs/classes/recipe_emailverification.default.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

EmailVerificationClaim: EmailVerificationClaimClass = EmailVerificationClaim
Error: typeof default = SuperTokensError
init: (config: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config: TypeInput): RecipeListFunction
    • Parameters

      • config: TypeInput

      Returns RecipeListFunction

Methods

  • createEmailVerificationToken(userId: string, email?: string, userContext?: any): Promise<{ status: "OK"; token: string } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>
  • Parameters

    • userId: string
    • Optional email: string
    • Optional userContext: any

    Returns Promise<{ status: "OK"; token: string } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>

  • isEmailVerified(userId: string, email?: string, userContext?: any): Promise<boolean>
  • revokeEmailVerificationTokens(userId: string, email?: string, userContext?: any): Promise<{ status: string }>
  • sendEmail(input: TypeEmailVerificationEmailDeliveryInput & { userContext?: any }): Promise<void>
  • unverifyEmail(userId: string, email?: string, userContext?: any): Promise<{ status: string }>
  • verifyEmailUsingToken(token: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

EmailVerificationClaim: EmailVerificationClaimClass = EmailVerificationClaim
Error: typeof default = SuperTokensError
init: (config: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config: TypeInput): RecipeListFunction
    • Parameters

      • config: TypeInput

      Returns RecipeListFunction

Methods

  • createEmailVerificationToken(userId: string, email?: string, userContext?: any): Promise<{ status: "OK"; token: string } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>
  • Parameters

    • userId: string
    • Optional email: string
    • Optional userContext: any

    Returns Promise<{ status: "OK"; token: string } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>

  • isEmailVerified(userId: string, email?: string, userContext?: any): Promise<boolean>
  • revokeEmailVerificationTokens(userId: string, email?: string, userContext?: any): Promise<{ status: string }>
  • sendEmail(input: TypeEmailVerificationEmailDeliveryInput & { userContext?: any }): Promise<void>
  • unverifyEmail(userId: string, email?: string, userContext?: any): Promise<{ status: string }>
  • verifyEmailUsingToken(token: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/recipe_jwt.default.html b/docs/classes/recipe_jwt.default.html deleted file mode 100644 index cc8152776..000000000 --- a/docs/classes/recipe_jwt.default.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Methods

Constructors

Properties

init: (config?: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config?: TypeInput): RecipeListFunction
    • Parameters

      • Optional config: TypeInput

      Returns RecipeListFunction

Methods

  • createJWT(payload: any, validitySeconds?: number, userContext?: any): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
  • Parameters

    • payload: any
    • Optional validitySeconds: number
    • Optional userContext: any

    Returns Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>

  • getJWKS(userContext?: any): Promise<{ keys: JsonWebKey[]; status: "OK" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Methods

Constructors

Properties

init: (config?: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config?: TypeInput): RecipeListFunction
    • Parameters

      • Optional config: TypeInput

      Returns RecipeListFunction

Methods

  • createJWT(payload: any, validitySeconds?: number, userContext?: any): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
  • Parameters

    • payload: any
    • Optional validitySeconds: number
    • Optional userContext: any

    Returns Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>

  • getJWKS(userContext?: any): Promise<{ keys: JsonWebKey[]; status: "OK" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/recipe_openid.default.html b/docs/classes/recipe_openid.default.html deleted file mode 100644 index d9b020d23..000000000 --- a/docs/classes/recipe_openid.default.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

init: (config?: TypeInput) => RecipeListFunction = OpenIdRecipe.init

Type declaration

    • (config?: TypeInput): RecipeListFunction
    • Parameters

      • Optional config: TypeInput

      Returns RecipeListFunction

Methods

  • createJWT(payload?: any, validitySeconds?: number, userContext?: any): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
  • Parameters

    • Optional payload: any
    • Optional validitySeconds: number
    • Optional userContext: any

    Returns Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>

  • getJWKS(userContext?: any): Promise<{ keys: JsonWebKey[]; status: "OK" }>
  • getOpenIdDiscoveryConfiguration(userContext?: any): Promise<{ issuer: string; jwks_uri: string; status: "OK" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

init: (config?: TypeInput) => RecipeListFunction = OpenIdRecipe.init

Type declaration

    • (config?: TypeInput): RecipeListFunction
    • Parameters

      • Optional config: TypeInput

      Returns RecipeListFunction

Methods

  • createJWT(payload?: any, validitySeconds?: number, userContext?: any): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
  • Parameters

    • Optional payload: any
    • Optional validitySeconds: number
    • Optional userContext: any

    Returns Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>

  • getJWKS(userContext?: any): Promise<{ keys: JsonWebKey[]; status: "OK" }>
  • getOpenIdDiscoveryConfiguration(userContext?: any): Promise<{ issuer: string; jwks_uri: string; status: "OK" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/recipe_passwordless.default.html b/docs/classes/recipe_passwordless.default.html deleted file mode 100644 index 6a83bf44f..000000000 --- a/docs/classes/recipe_passwordless.default.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Error: typeof default = SuperTokensError
init: (config: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config: TypeInput): RecipeListFunction
    • Parameters

      • config: TypeInput

      Returns RecipeListFunction

Methods

  • consumeCode(input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
  • Parameters

    • input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }

    Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

  • createCode(input: ({ email: string } & { userContext?: any; userInputCode?: string }) | ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>
  • Parameters

    • input: ({ email: string } & { userContext?: any; userInputCode?: string }) | ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })

    Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>

  • createMagicLink(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<string>
  • createNewCodeForDevice(input: { deviceId: string; userContext?: any; userInputCode?: string }): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>
  • Parameters

    • input: { deviceId: string; userContext?: any; userInputCode?: string }
      • deviceId: string
      • Optional userContext?: any
      • Optional userInputCode?: string

    Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>

  • getUserByEmail(input: { email: string; userContext?: any }): Promise<undefined | User>
  • getUserById(input: { userContext?: any; userId: string }): Promise<undefined | User>
  • getUserByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<undefined | User>
  • listCodesByDeviceId(input: { deviceId: string; userContext?: any }): Promise<undefined | DeviceType>
  • listCodesByEmail(input: { email: string; userContext?: any }): Promise<DeviceType[]>
  • listCodesByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<DeviceType[]>
  • listCodesByPreAuthSessionId(input: { preAuthSessionId: string; userContext?: any }): Promise<undefined | DeviceType>
  • Parameters

    • input: { preAuthSessionId: string; userContext?: any }
      • preAuthSessionId: string
      • Optional userContext?: any

    Returns Promise<undefined | DeviceType>

  • revokeAllCodes(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ status: "OK" }>
  • revokeCode(input: { codeId: string; userContext?: any }): Promise<{ status: "OK" }>
  • sendEmail(input: TypePasswordlessEmailDeliveryInput & { userContext?: any }): Promise<void>
  • sendSms(input: TypePasswordlessSmsDeliveryInput & { userContext?: any }): Promise<void>
  • signInUp(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: string; user: User }>
  • Parameters

    • input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }

    Returns Promise<{ createdNewUser: boolean; status: string; user: User }>

  • updateUser(input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>
  • Parameters

    • input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }
      • Optional email?: null | string
      • Optional phoneNumber?: null | string
      • Optional userContext?: any
      • userId: string

    Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Error: typeof default = SuperTokensError
init: (config: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config: TypeInput): RecipeListFunction
    • Parameters

      • config: TypeInput

      Returns RecipeListFunction

Methods

  • consumeCode(input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
  • Parameters

    • input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }

    Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

  • createCode(input: ({ email: string } & { userContext?: any; userInputCode?: string }) & ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>
  • Parameters

    • input: ({ email: string } & { userContext?: any; userInputCode?: string }) & ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })

    Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>

  • createMagicLink(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<string>
  • createNewCodeForDevice(input: { deviceId: string; userContext?: any; userInputCode?: string }): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>
  • Parameters

    • input: { deviceId: string; userContext?: any; userInputCode?: string }
      • deviceId: string
      • Optional userContext?: any
      • Optional userInputCode?: string

    Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>

  • getUserByEmail(input: { email: string; userContext?: any }): Promise<undefined | User>
  • getUserById(input: { userContext?: any; userId: string }): Promise<undefined | User>
  • getUserByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<undefined | User>
  • listCodesByDeviceId(input: { deviceId: string; userContext?: any }): Promise<undefined | DeviceType>
  • listCodesByEmail(input: { email: string; userContext?: any }): Promise<DeviceType[]>
  • listCodesByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<DeviceType[]>
  • listCodesByPreAuthSessionId(input: { preAuthSessionId: string; userContext?: any }): Promise<undefined | DeviceType>
  • Parameters

    • input: { preAuthSessionId: string; userContext?: any }
      • preAuthSessionId: string
      • Optional userContext?: any

    Returns Promise<undefined | DeviceType>

  • revokeAllCodes(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ status: "OK" }>
  • revokeCode(input: { codeId: string; userContext?: any }): Promise<{ status: "OK" }>
  • sendEmail(input: TypePasswordlessEmailDeliveryInput & { userContext?: any }): Promise<void>
  • sendSms(input: TypePasswordlessSmsDeliveryInput & { userContext?: any }): Promise<void>
  • signInUp(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: string; user: User }>
  • Parameters

    • input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }

    Returns Promise<{ createdNewUser: boolean; status: string; user: User }>

  • updateUser(input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>
  • Parameters

    • input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }
      • Optional email?: null | string
      • Optional phoneNumber?: null | string
      • Optional userContext?: any
      • userId: string

    Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/recipe_session.default.html b/docs/classes/recipe_session.default.html deleted file mode 100644 index afc1e3a84..000000000 --- a/docs/classes/recipe_session.default.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Error: typeof default = SuperTokensError
init: (config?: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config?: TypeInput): RecipeListFunction
    • Parameters

      • Optional config: TypeInput

      Returns RecipeListFunction

Methods

  • createJWT(payload?: any, validitySeconds?: number, userContext?: any): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
  • Parameters

    • Optional payload: any
    • Optional validitySeconds: number
    • userContext: any = {}

    Returns Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>

  • createNewSession(req: any, res: any, userId: string, accessTokenPayload?: any, sessionData?: any, userContext?: any): Promise<SessionContainer>
  • fetchAndSetClaim(sessionHandle: string, claim: SessionClaim<any>, userContext?: any): Promise<boolean>
  • getAllSessionHandlesForUser(userId: string, userContext?: any): Promise<string[]>
  • getClaimValue<T>(sessionHandle: string, claim: SessionClaim<T>, userContext?: any): Promise<{ status: "SESSION_DOES_NOT_EXIST_ERROR" } | { status: "OK"; value: undefined | T }>
  • Type parameters

    • T

    Parameters

    • sessionHandle: string
    • claim: SessionClaim<T>
    • userContext: any = {}

    Returns Promise<{ status: "SESSION_DOES_NOT_EXIST_ERROR" } | { status: "OK"; value: undefined | T }>

  • getJWKS(userContext?: any): Promise<{ keys: JsonWebKey[]; status: "OK" }>
  • getOpenIdDiscoveryConfiguration(userContext?: any): Promise<{ issuer: string; jwks_uri: string; status: "OK" }>
  • getSessionInformation(sessionHandle: string, userContext?: any): Promise<undefined | SessionInformation>
  • mergeIntoAccessTokenPayload(sessionHandle: string, accessTokenPayloadUpdate: JSONObject, userContext?: any): Promise<boolean>
  • refreshSession(req: any, res: any, userContext?: any): Promise<SessionContainer>
  • regenerateAccessToken(accessToken: string, newAccessTokenPayload?: any, userContext?: any): Promise<undefined | { accessToken?: { createdTime: number; expiry: number; token: string }; session: { handle: string; userDataInJWT: any; userId: string }; status: "OK" }>
  • Parameters

    • accessToken: string
    • Optional newAccessTokenPayload: any
    • userContext: any = {}

    Returns Promise<undefined | { accessToken?: { createdTime: number; expiry: number; token: string }; session: { handle: string; userDataInJWT: any; userId: string }; status: "OK" }>

  • removeClaim(sessionHandle: string, claim: SessionClaim<any>, userContext?: any): Promise<boolean>
  • revokeAllSessionsForUser(userId: string, userContext?: any): Promise<string[]>
  • revokeMultipleSessions(sessionHandles: string[], userContext?: any): Promise<string[]>
  • revokeSession(sessionHandle: string, userContext?: any): Promise<boolean>
  • setClaimValue<T>(sessionHandle: string, claim: SessionClaim<T>, value: T, userContext?: any): Promise<boolean>
  • updateAccessTokenPayload(sessionHandle: string, newAccessTokenPayload: any, userContext?: any): Promise<boolean>
  • updateSessionData(sessionHandle: string, newSessionData: any, userContext?: any): Promise<boolean>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Error: typeof default = SuperTokensError
init: (config?: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config?: TypeInput): RecipeListFunction
    • Parameters

      • Optional config: TypeInput

      Returns RecipeListFunction

Methods

  • createJWT(payload?: any, validitySeconds?: number, userContext?: any): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
  • Parameters

    • Optional payload: any
    • Optional validitySeconds: number
    • userContext: any = {}

    Returns Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>

  • createNewSession(req: any, res: any, userId: string, accessTokenPayload?: any, sessionData?: any, userContext?: any): Promise<SessionContainer>
  • fetchAndSetClaim(sessionHandle: string, claim: SessionClaim<any>, userContext?: any): Promise<boolean>
  • getAllSessionHandlesForUser(userId: string, userContext?: any): Promise<string[]>
  • getClaimValue<T>(sessionHandle: string, claim: SessionClaim<T>, userContext?: any): Promise<{ status: "SESSION_DOES_NOT_EXIST_ERROR" } | { status: "OK"; value: undefined | T }>
  • Type parameters

    • T

    Parameters

    • sessionHandle: string
    • claim: SessionClaim<T>
    • userContext: any = {}

    Returns Promise<{ status: "SESSION_DOES_NOT_EXIST_ERROR" } | { status: "OK"; value: undefined | T }>

  • getJWKS(userContext?: any): Promise<{ keys: JsonWebKey[]; status: "OK" }>
  • getOpenIdDiscoveryConfiguration(userContext?: any): Promise<{ issuer: string; jwks_uri: string; status: "OK" }>
  • getSessionInformation(sessionHandle: string, userContext?: any): Promise<undefined | SessionInformation>
  • mergeIntoAccessTokenPayload(sessionHandle: string, accessTokenPayloadUpdate: JSONObject, userContext?: any): Promise<boolean>
  • refreshSession(req: any, res: any, userContext?: any): Promise<SessionContainer>
  • regenerateAccessToken(accessToken: string, newAccessTokenPayload?: any, userContext?: any): Promise<undefined | { accessToken?: { createdTime: number; expiry: number; token: string }; session: { handle: string; userDataInJWT: any; userId: string }; status: "OK" }>
  • Parameters

    • accessToken: string
    • Optional newAccessTokenPayload: any
    • userContext: any = {}

    Returns Promise<undefined | { accessToken?: { createdTime: number; expiry: number; token: string }; session: { handle: string; userDataInJWT: any; userId: string }; status: "OK" }>

  • removeClaim(sessionHandle: string, claim: SessionClaim<any>, userContext?: any): Promise<boolean>
  • revokeAllSessionsForUser(userId: string, userContext?: any): Promise<string[]>
  • revokeMultipleSessions(sessionHandles: string[], userContext?: any): Promise<string[]>
  • revokeSession(sessionHandle: string, userContext?: any): Promise<boolean>
  • setClaimValue<T>(sessionHandle: string, claim: SessionClaim<T>, value: T, userContext?: any): Promise<boolean>
  • updateAccessTokenPayload(sessionHandle: string, newAccessTokenPayload: any, userContext?: any): Promise<boolean>
  • updateSessionData(sessionHandle: string, newSessionData: any, userContext?: any): Promise<boolean>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/recipe_thirdparty.default.html b/docs/classes/recipe_thirdparty.default.html deleted file mode 100644 index bfa654716..000000000 --- a/docs/classes/recipe_thirdparty.default.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Apple: (config: TypeThirdPartyProviderAppleConfig) => TypeProvider = thirdPartyProviders.Apple

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderAppleConfig

      Returns TypeProvider

Discord: (config: TypeThirdPartyProviderDiscordConfig) => TypeProvider = thirdPartyProviders.Discord

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderDiscordConfig

      Returns TypeProvider

Error: typeof default = SuperTokensError
Facebook: (config: TypeThirdPartyProviderFacebookConfig) => TypeProvider = thirdPartyProviders.Facebook

Type declaration

    • (config: TypeThirdPartyProviderFacebookConfig): TypeProvider
    • Parameters

      • config: TypeThirdPartyProviderFacebookConfig

      Returns TypeProvider

Github: (config: TypeThirdPartyProviderGithubConfig) => TypeProvider = thirdPartyProviders.Github

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderGithubConfig

      Returns TypeProvider

Google: (config: TypeThirdPartyProviderGoogleConfig) => TypeProvider = thirdPartyProviders.Google

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderGoogleConfig

      Returns TypeProvider

GoogleWorkspaces: (config: TypeThirdPartyProviderGoogleWorkspacesConfig) => TypeProvider = thirdPartyProviders.GoogleWorkspaces

Type declaration

    • (config: TypeThirdPartyProviderGoogleWorkspacesConfig): TypeProvider
    • Parameters

      • config: TypeThirdPartyProviderGoogleWorkspacesConfig

      Returns TypeProvider

init: (config: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config: TypeInput): RecipeListFunction
    • Parameters

      • config: TypeInput

      Returns RecipeListFunction

Methods

  • getUserById(userId: string, userContext?: any): Promise<undefined | User>
  • getUserByThirdPartyInfo(thirdPartyId: string, thirdPartyUserId: string, userContext?: any): Promise<undefined | User>
  • getUsersByEmail(email: string, userContext?: any): Promise<User[]>
  • signInUp(thirdPartyId: string, thirdPartyUserId: string, email: string, userContext?: any): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
  • Parameters

    • thirdPartyId: string
    • thirdPartyUserId: string
    • email: string
    • userContext: any = {}

    Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Apple: (config: TypeThirdPartyProviderAppleConfig) => TypeProvider = thirdPartyProviders.Apple

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderAppleConfig

      Returns TypeProvider

Discord: (config: TypeThirdPartyProviderDiscordConfig) => TypeProvider = thirdPartyProviders.Discord

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderDiscordConfig

      Returns TypeProvider

Error: typeof default = SuperTokensError
Facebook: (config: TypeThirdPartyProviderFacebookConfig) => TypeProvider = thirdPartyProviders.Facebook

Type declaration

    • (config: TypeThirdPartyProviderFacebookConfig): TypeProvider
    • Parameters

      • config: TypeThirdPartyProviderFacebookConfig

      Returns TypeProvider

Github: (config: TypeThirdPartyProviderGithubConfig) => TypeProvider = thirdPartyProviders.Github

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderGithubConfig

      Returns TypeProvider

Google: (config: TypeThirdPartyProviderGoogleConfig) => TypeProvider = thirdPartyProviders.Google

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderGoogleConfig

      Returns TypeProvider

GoogleWorkspaces: (config: TypeThirdPartyProviderGoogleWorkspacesConfig) => TypeProvider = thirdPartyProviders.GoogleWorkspaces

Type declaration

    • (config: TypeThirdPartyProviderGoogleWorkspacesConfig): TypeProvider
    • Parameters

      • config: TypeThirdPartyProviderGoogleWorkspacesConfig

      Returns TypeProvider

init: (config: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config: TypeInput): RecipeListFunction
    • Parameters

      • config: TypeInput

      Returns RecipeListFunction

Methods

  • getUserById(userId: string, userContext?: any): Promise<undefined | User>
  • getUserByThirdPartyInfo(thirdPartyId: string, thirdPartyUserId: string, userContext?: any): Promise<undefined | User>
  • getUsersByEmail(email: string, userContext?: any): Promise<User[]>
  • signInUp(thirdPartyId: string, thirdPartyUserId: string, email: string, userContext?: any): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
  • Parameters

    • thirdPartyId: string
    • thirdPartyUserId: string
    • email: string
    • userContext: any = {}

    Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/recipe_thirdpartyemailpassword.default.html b/docs/classes/recipe_thirdpartyemailpassword.default.html deleted file mode 100644 index 264e2c2f0..000000000 --- a/docs/classes/recipe_thirdpartyemailpassword.default.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Apple: (config: TypeThirdPartyProviderAppleConfig) => TypeProvider = thirdPartyProviders.Apple

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderAppleConfig

      Returns TypeProvider

Discord: (config: TypeThirdPartyProviderDiscordConfig) => TypeProvider = thirdPartyProviders.Discord

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderDiscordConfig

      Returns TypeProvider

Error: typeof default = SuperTokensError
Facebook: (config: TypeThirdPartyProviderFacebookConfig) => TypeProvider = thirdPartyProviders.Facebook

Type declaration

    • (config: TypeThirdPartyProviderFacebookConfig): TypeProvider
    • Parameters

      • config: TypeThirdPartyProviderFacebookConfig

      Returns TypeProvider

Github: (config: TypeThirdPartyProviderGithubConfig) => TypeProvider = thirdPartyProviders.Github

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderGithubConfig

      Returns TypeProvider

Google: (config: TypeThirdPartyProviderGoogleConfig) => TypeProvider = thirdPartyProviders.Google

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderGoogleConfig

      Returns TypeProvider

GoogleWorkspaces: (config: TypeThirdPartyProviderGoogleWorkspacesConfig) => TypeProvider = thirdPartyProviders.GoogleWorkspaces

Type declaration

    • (config: TypeThirdPartyProviderGoogleWorkspacesConfig): TypeProvider
    • Parameters

      • config: TypeThirdPartyProviderGoogleWorkspacesConfig

      Returns TypeProvider

init: (config: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config: TypeInput): RecipeListFunction
    • Parameters

      • config: TypeInput

      Returns RecipeListFunction

Methods

  • createResetPasswordToken(userId: string, userContext?: any): Promise<{ status: "OK"; token: string } | { status: "UNKNOWN_USER_ID_ERROR" }>
  • emailPasswordSignIn(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>
  • emailPasswordSignUp(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>
  • getUserById(userId: string, userContext?: any): Promise<undefined | User>
  • getUserByThirdPartyInfo(thirdPartyId: string, thirdPartyUserId: string, userContext?: any): Promise<undefined | User>
  • getUsersByEmail(email: string, userContext?: any): Promise<User[]>
  • resetPasswordUsingToken(token: string, newPassword: string, userContext?: any): Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>
  • sendEmail(input: TypeEmailPasswordPasswordResetEmailDeliveryInput & { userContext?: any }): Promise<void>
  • thirdPartySignInUp(thirdPartyId: string, thirdPartyUserId: string, email: string, userContext?: any): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
  • updateEmailOrPassword(input: { email?: string; password?: string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>
  • Parameters

    • input: { email?: string; password?: string; userContext?: any; userId: string }
      • Optional email?: string
      • Optional password?: string
      • Optional userContext?: any
      • userId: string

    Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Apple: (config: TypeThirdPartyProviderAppleConfig) => TypeProvider = thirdPartyProviders.Apple

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderAppleConfig

      Returns TypeProvider

Discord: (config: TypeThirdPartyProviderDiscordConfig) => TypeProvider = thirdPartyProviders.Discord

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderDiscordConfig

      Returns TypeProvider

Error: typeof default = SuperTokensError
Facebook: (config: TypeThirdPartyProviderFacebookConfig) => TypeProvider = thirdPartyProviders.Facebook

Type declaration

    • (config: TypeThirdPartyProviderFacebookConfig): TypeProvider
    • Parameters

      • config: TypeThirdPartyProviderFacebookConfig

      Returns TypeProvider

Github: (config: TypeThirdPartyProviderGithubConfig) => TypeProvider = thirdPartyProviders.Github

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderGithubConfig

      Returns TypeProvider

Google: (config: TypeThirdPartyProviderGoogleConfig) => TypeProvider = thirdPartyProviders.Google

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderGoogleConfig

      Returns TypeProvider

GoogleWorkspaces: (config: TypeThirdPartyProviderGoogleWorkspacesConfig) => TypeProvider = thirdPartyProviders.GoogleWorkspaces

Type declaration

    • (config: TypeThirdPartyProviderGoogleWorkspacesConfig): TypeProvider
    • Parameters

      • config: TypeThirdPartyProviderGoogleWorkspacesConfig

      Returns TypeProvider

init: (config: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config: TypeInput): RecipeListFunction
    • Parameters

      • config: TypeInput

      Returns RecipeListFunction

Methods

  • createResetPasswordToken(userId: string, userContext?: any): Promise<{ status: "OK"; token: string } | { status: "UNKNOWN_USER_ID_ERROR" }>
  • emailPasswordSignIn(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>
  • emailPasswordSignUp(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>
  • getUserById(userId: string, userContext?: any): Promise<undefined | User>
  • getUserByThirdPartyInfo(thirdPartyId: string, thirdPartyUserId: string, userContext?: any): Promise<undefined | User>
  • getUsersByEmail(email: string, userContext?: any): Promise<User[]>
  • resetPasswordUsingToken(token: string, newPassword: string, userContext?: any): Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>
  • sendEmail(input: TypeEmailPasswordPasswordResetEmailDeliveryInput & { userContext?: any }): Promise<void>
  • thirdPartySignInUp(thirdPartyId: string, thirdPartyUserId: string, email: string, userContext?: any): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
  • updateEmailOrPassword(input: { email?: string; password?: string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>
  • Parameters

    • input: { email?: string; password?: string; userContext?: any; userId: string }
      • Optional email?: string
      • Optional password?: string
      • Optional userContext?: any
      • userId: string

    Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/recipe_thirdpartypasswordless.default.html b/docs/classes/recipe_thirdpartypasswordless.default.html deleted file mode 100644 index 93fc48029..000000000 --- a/docs/classes/recipe_thirdpartypasswordless.default.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Apple: (config: TypeThirdPartyProviderAppleConfig) => TypeProvider = thirdPartyProviders.Apple

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderAppleConfig

      Returns TypeProvider

Discord: (config: TypeThirdPartyProviderDiscordConfig) => TypeProvider = thirdPartyProviders.Discord

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderDiscordConfig

      Returns TypeProvider

Error: typeof default = SuperTokensError
Facebook: (config: TypeThirdPartyProviderFacebookConfig) => TypeProvider = thirdPartyProviders.Facebook

Type declaration

    • (config: TypeThirdPartyProviderFacebookConfig): TypeProvider
    • Parameters

      • config: TypeThirdPartyProviderFacebookConfig

      Returns TypeProvider

Github: (config: TypeThirdPartyProviderGithubConfig) => TypeProvider = thirdPartyProviders.Github

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderGithubConfig

      Returns TypeProvider

Google: (config: TypeThirdPartyProviderGoogleConfig) => TypeProvider = thirdPartyProviders.Google

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderGoogleConfig

      Returns TypeProvider

GoogleWorkspaces: (config: TypeThirdPartyProviderGoogleWorkspacesConfig) => TypeProvider = thirdPartyProviders.GoogleWorkspaces

Type declaration

    • (config: TypeThirdPartyProviderGoogleWorkspacesConfig): TypeProvider
    • Parameters

      • config: TypeThirdPartyProviderGoogleWorkspacesConfig

      Returns TypeProvider

init: (config: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config: TypeInput): RecipeListFunction
    • Parameters

      • config: TypeInput

      Returns RecipeListFunction

Methods

  • consumeCode(input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
  • Parameters

    • input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }

    Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

  • createCode(input: ({ email: string } & { userContext?: any; userInputCode?: string }) | ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>
  • Parameters

    • input: ({ email: string } & { userContext?: any; userInputCode?: string }) | ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })

    Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>

  • createMagicLink(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<string>
  • createNewCodeForDevice(input: { deviceId: string; userContext?: any; userInputCode?: string }): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>
  • Parameters

    • input: { deviceId: string; userContext?: any; userInputCode?: string }
      • deviceId: string
      • Optional userContext?: any
      • Optional userInputCode?: string

    Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>

  • getUserById(userId: string, userContext?: any): Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>
  • Parameters

    • userId: string
    • userContext: any = {}

    Returns Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>

  • getUserByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>
  • Parameters

    • input: { phoneNumber: string; userContext?: any }
      • phoneNumber: string
      • Optional userContext?: any

    Returns Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>

  • getUserByThirdPartyInfo(thirdPartyId: string, thirdPartyUserId: string, userContext?: any): Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>
  • Parameters

    • thirdPartyId: string
    • thirdPartyUserId: string
    • userContext: any = {}

    Returns Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>

  • getUsersByEmail(email: string, userContext?: any): Promise<User[]>
  • listCodesByDeviceId(input: { deviceId: string; userContext?: any }): Promise<undefined | DeviceType>
  • listCodesByEmail(input: { email: string; userContext?: any }): Promise<DeviceType[]>
  • listCodesByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<DeviceType[]>
  • listCodesByPreAuthSessionId(input: { preAuthSessionId: string; userContext?: any }): Promise<undefined | DeviceType>
  • passwordlessSignInUp(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: string; user: User }>
  • revokeAllCodes(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ status: "OK" }>
  • revokeCode(input: { codeId: string; userContext?: any }): Promise<{ status: "OK" }>
  • sendEmail(input: TypePasswordlessEmailDeliveryInput & { userContext?: any }): Promise<void>
  • sendSms(input: TypePasswordlessSmsDeliveryInput & { userContext?: any }): Promise<void>
  • thirdPartySignInUp(thirdPartyId: string, thirdPartyUserId: string, email: string, userContext?: any): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
  • updatePasswordlessUser(input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>
  • Parameters

    • input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }
      • Optional email?: null | string
      • Optional phoneNumber?: null | string
      • Optional userContext?: any
      • userId: string

    Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

Apple: (config: TypeThirdPartyProviderAppleConfig) => TypeProvider = thirdPartyProviders.Apple

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderAppleConfig

      Returns TypeProvider

Discord: (config: TypeThirdPartyProviderDiscordConfig) => TypeProvider = thirdPartyProviders.Discord

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderDiscordConfig

      Returns TypeProvider

Error: typeof default = SuperTokensError
Facebook: (config: TypeThirdPartyProviderFacebookConfig) => TypeProvider = thirdPartyProviders.Facebook

Type declaration

    • (config: TypeThirdPartyProviderFacebookConfig): TypeProvider
    • Parameters

      • config: TypeThirdPartyProviderFacebookConfig

      Returns TypeProvider

Github: (config: TypeThirdPartyProviderGithubConfig) => TypeProvider = thirdPartyProviders.Github

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderGithubConfig

      Returns TypeProvider

Google: (config: TypeThirdPartyProviderGoogleConfig) => TypeProvider = thirdPartyProviders.Google

Type declaration

    • Parameters

      • config: TypeThirdPartyProviderGoogleConfig

      Returns TypeProvider

GoogleWorkspaces: (config: TypeThirdPartyProviderGoogleWorkspacesConfig) => TypeProvider = thirdPartyProviders.GoogleWorkspaces

Type declaration

    • (config: TypeThirdPartyProviderGoogleWorkspacesConfig): TypeProvider
    • Parameters

      • config: TypeThirdPartyProviderGoogleWorkspacesConfig

      Returns TypeProvider

init: (config: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config: TypeInput): RecipeListFunction
    • Parameters

      • config: TypeInput

      Returns RecipeListFunction

Methods

  • consumeCode(input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
  • Parameters

    • input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }

    Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

  • createCode(input: ({ email: string } & { userContext?: any; userInputCode?: string }) & ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>
  • Parameters

    • input: ({ email: string } & { userContext?: any; userInputCode?: string }) & ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })

    Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>

  • createMagicLink(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<string>
  • createNewCodeForDevice(input: { deviceId: string; userContext?: any; userInputCode?: string }): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>
  • Parameters

    • input: { deviceId: string; userContext?: any; userInputCode?: string }
      • deviceId: string
      • Optional userContext?: any
      • Optional userInputCode?: string

    Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>

  • getUserById(userId: string, userContext?: any): Promise<undefined | User>
  • getUserByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<undefined | User>
  • getUserByThirdPartyInfo(thirdPartyId: string, thirdPartyUserId: string, userContext?: any): Promise<undefined | User>
  • getUsersByEmail(email: string, userContext?: any): Promise<User[]>
  • listCodesByDeviceId(input: { deviceId: string; userContext?: any }): Promise<undefined | DeviceType>
  • listCodesByEmail(input: { email: string; userContext?: any }): Promise<DeviceType[]>
  • listCodesByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<DeviceType[]>
  • listCodesByPreAuthSessionId(input: { preAuthSessionId: string; userContext?: any }): Promise<undefined | DeviceType>
  • passwordlessSignInUp(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: string; user: User }>
  • revokeAllCodes(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ status: "OK" }>
  • revokeCode(input: { codeId: string; userContext?: any }): Promise<{ status: "OK" }>
  • sendEmail(input: TypePasswordlessEmailDeliveryInput & { userContext?: any }): Promise<void>
  • sendSms(input: TypePasswordlessSmsDeliveryInput & { userContext?: any }): Promise<void>
  • thirdPartySignInUp(thirdPartyId: string, thirdPartyUserId: string, email: string, userContext?: any): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
  • updatePasswordlessUser(input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>
  • Parameters

    • input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }
      • Optional email?: null | string
      • Optional phoneNumber?: null | string
      • Optional userContext?: any
      • userId: string

    Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/recipe_usermetadata.default.html b/docs/classes/recipe_usermetadata.default.html deleted file mode 100644 index a245325aa..000000000 --- a/docs/classes/recipe_usermetadata.default.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

init: (config?: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config?: TypeInput): RecipeListFunction
    • Parameters

      • Optional config: TypeInput

      Returns RecipeListFunction

Methods

  • clearUserMetadata(userId: string, userContext?: any): Promise<{ status: "OK" }>
  • getUserMetadata(userId: string, userContext?: any): Promise<{ metadata: any; status: "OK" }>
  • updateUserMetadata(userId: string, metadataUpdate: JSONObject, userContext?: any): Promise<{ metadata: JSONObject; status: "OK" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

init: (config?: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config?: TypeInput): RecipeListFunction
    • Parameters

      • Optional config: TypeInput

      Returns RecipeListFunction

Methods

  • clearUserMetadata(userId: string, userContext?: any): Promise<{ status: "OK" }>
  • getUserMetadata(userId: string, userContext?: any): Promise<{ metadata: any; status: "OK" }>
  • updateUserMetadata(userId: string, metadataUpdate: JSONObject, userContext?: any): Promise<{ metadata: JSONObject; status: "OK" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/classes/recipe_userroles.default.html b/docs/classes/recipe_userroles.default.html deleted file mode 100644 index 987cb4bf5..000000000 --- a/docs/classes/recipe_userroles.default.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

PermissionClaim: PermissionClaimClass = PermissionClaim
UserRoleClaim: UserRoleClaimClass = UserRoleClaim
init: (config?: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config?: TypeInput): RecipeListFunction
    • Parameters

      • Optional config: TypeInput

      Returns RecipeListFunction

Methods

  • addRoleToUser(userId: string, role: string, userContext?: any): Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
  • Parameters

    • userId: string
    • role: string
    • Optional userContext: any

    Returns Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

  • createNewRoleOrAddPermissions(role: string, permissions: string[], userContext?: any): Promise<{ createdNewRole: boolean; status: "OK" }>
  • deleteRole(role: string, userContext?: any): Promise<{ didRoleExist: boolean; status: "OK" }>
  • getAllRoles(userContext?: any): Promise<{ roles: string[]; status: "OK" }>
  • getPermissionsForRole(role: string, userContext?: any): Promise<{ permissions: string[]; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
  • Parameters

    • role: string
    • Optional userContext: any

    Returns Promise<{ permissions: string[]; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

  • getRolesForUser(userId: string, userContext?: any): Promise<{ roles: string[]; status: "OK" }>
  • getRolesThatHavePermission(permission: string, userContext?: any): Promise<{ roles: string[]; status: "OK" }>
  • getUsersThatHaveRole(role: string, userContext?: any): Promise<{ status: "OK"; users: string[] } | { status: "UNKNOWN_ROLE_ERROR" }>
  • Parameters

    • role: string
    • Optional userContext: any

    Returns Promise<{ status: "OK"; users: string[] } | { status: "UNKNOWN_ROLE_ERROR" }>

  • removePermissionsFromRole(role: string, permissions: string[], userContext?: any): Promise<{ status: "OK" | "UNKNOWN_ROLE_ERROR" }>
  • removeUserRole(userId: string, role: string, userContext?: any): Promise<{ didUserHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
  • Parameters

    • userId: string
    • role: string
    • Optional userContext: any

    Returns Promise<{ didUserHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

-======= -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

PermissionClaim: PermissionClaimClass = PermissionClaim
UserRoleClaim: UserRoleClaimClass = UserRoleClaim
init: (config?: TypeInput) => RecipeListFunction = Recipe.init

Type declaration

    • (config?: TypeInput): RecipeListFunction
    • Parameters

      • Optional config: TypeInput

      Returns RecipeListFunction

Methods

  • addRoleToUser(userId: string, role: string, userContext?: any): Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
  • Parameters

    • userId: string
    • role: string
    • Optional userContext: any

    Returns Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

  • createNewRoleOrAddPermissions(role: string, permissions: string[], userContext?: any): Promise<{ createdNewRole: boolean; status: "OK" }>
  • deleteRole(role: string, userContext?: any): Promise<{ didRoleExist: boolean; status: "OK" }>
  • getAllRoles(userContext?: any): Promise<{ roles: string[]; status: "OK" }>
  • getPermissionsForRole(role: string, userContext?: any): Promise<{ permissions: string[]; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
  • Parameters

    • role: string
    • Optional userContext: any

    Returns Promise<{ permissions: string[]; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

  • getRolesForUser(userId: string, userContext?: any): Promise<{ roles: string[]; status: "OK" }>
  • getRolesThatHavePermission(permission: string, userContext?: any): Promise<{ roles: string[]; status: "OK" }>
  • getUsersThatHaveRole(role: string, userContext?: any): Promise<{ status: "OK"; users: string[] } | { status: "UNKNOWN_ROLE_ERROR" }>
  • Parameters

    • role: string
    • Optional userContext: any

    Returns Promise<{ status: "OK"; users: string[] } | { status: "UNKNOWN_ROLE_ERROR" }>

  • removePermissionsFromRole(role: string, permissions: string[], userContext?: any): Promise<{ status: "OK" | "UNKNOWN_ROLE_ERROR" }>
  • removeUserRole(userId: string, role: string, userContext?: any): Promise<{ didUserHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
  • Parameters

    • userId: string
    • role: string
    • Optional userContext: any

    Returns Promise<{ didUserHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Constructor
  • Static property
  • Static method
  • Interface

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 6af2b272b..000000000 --- a/docs/index.html +++ /dev/null @@ -1,38 +0,0 @@ -supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

supertokens-node

SuperTokens banner

- - -

SuperTokens Node driver

-
- -chat on Discord - - - - -

About

-
-

This is a NodeJS library that is used to interface between a node API process and the SuperTokens http service.

-

Learn more at https://supertokens.com

- - -

Documentation

-
-

To see documentation, please click here.

- - -

Contributing

-
-

Please see the CONTRIBUTING.md file for instructions.

- - -

Contact us

-
-

For any queries, or support requests, please email us at team@supertokens.com, or join our Discord server.

- - -

Authors

-
-

Created with :heart: by the folks at supertokens.com.

-

Featured on Openbase

-

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Class
  • Class with type parameter
  • Interface

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/interfaces/framework_awsLambda.SessionEvent.html b/docs/interfaces/framework_awsLambda.SessionEvent.html deleted file mode 100644 index 6c18d8d66..000000000 --- a/docs/interfaces/framework_awsLambda.SessionEvent.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -SessionEvent | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • SupertokensLambdaEvent
    • SessionEvent

Index

Properties

body: null | string
headers: APIGatewayProxyEventHeaders
httpMethod: string
isBase64Encoded: boolean
multiValueHeaders: APIGatewayProxyEventMultiValueHeaders
multiValueQueryStringParameters: null | APIGatewayProxyEventMultiValueQueryStringParameters
path: string
pathParameters: null | APIGatewayProxyEventPathParameters
queryStringParameters: null | APIGatewayProxyEventQueryStringParameters
requestContext: APIGatewayEventRequestContextWithAuthorizer<APIGatewayEventDefaultAuthorizerContext>
resource: string
stageVariables: null | APIGatewayProxyEventStageVariables
supertokens: { response: { cookies: string[]; headers: { allowDuplicateKey: boolean; key: string; value: string | number | false | true }[] } }

Type declaration

  • response: { cookies: string[]; headers: { allowDuplicateKey: boolean; key: string; value: string | number | false | true }[] }
    • cookies: string[]
    • headers: { allowDuplicateKey: boolean; key: string; value: string | number | false | true }[]

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Interface
  • Property
  • Class
  • Class with type parameter

Settings

Theme

Generated using TypeDoc

-======= -SessionEvent | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • SupertokensLambdaEvent
    • SessionEvent

Index

Properties

body: null | string
headers: APIGatewayProxyEventHeaders
httpMethod: string
isBase64Encoded: boolean
multiValueHeaders: APIGatewayProxyEventMultiValueHeaders
multiValueQueryStringParameters: null | APIGatewayProxyEventMultiValueQueryStringParameters
path: string
pathParameters: null | APIGatewayProxyEventPathParameters
queryStringParameters: null | APIGatewayProxyEventQueryStringParameters
requestContext: APIGatewayEventRequestContextWithAuthorizer<APIGatewayEventDefaultAuthorizerContext>
resource: string
stageVariables: null | APIGatewayProxyEventStageVariables
supertokens: { response: { cookies: string[]; headers: { allowDuplicateKey: boolean; key: string; value: string | number | boolean }[] } }

Type declaration

  • response: { cookies: string[]; headers: { allowDuplicateKey: boolean; key: string; value: string | number | boolean }[] }
    • cookies: string[]
    • headers: { allowDuplicateKey: boolean; key: string; value: string | number | boolean }[]

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Interface
  • Property
  • Class
  • Class with type parameter

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/interfaces/framework_awsLambda.SessionEventV2.html b/docs/interfaces/framework_awsLambda.SessionEventV2.html deleted file mode 100644 index 2511fdb04..000000000 --- a/docs/interfaces/framework_awsLambda.SessionEventV2.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -SessionEventV2 | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • SupertokensLambdaEventV2
    • SessionEventV2

Index

Properties

body?: string
cookies?: string[]
headers: APIGatewayProxyEventHeaders
isBase64Encoded: boolean
pathParameters?: APIGatewayProxyEventPathParameters
queryStringParameters?: APIGatewayProxyEventQueryStringParameters
rawPath: string
rawQueryString: string
requestContext: { accountId: string; apiId: string; authorizer?: { jwt: { claims: {}; scopes: string[] } }; domainName: string; domainPrefix: string; http: { method: string; path: string; protocol: string; sourceIp: string; userAgent: string }; requestId: string; routeKey: string; stage: string; time: string; timeEpoch: number }

Type declaration

  • accountId: string
  • apiId: string
  • Optional authorizer?: { jwt: { claims: {}; scopes: string[] } }
    • jwt: { claims: {}; scopes: string[] }
      • claims: {}
        • [name: string]: string | number | boolean | string[]
      • scopes: string[]
  • domainName: string
  • domainPrefix: string
  • http: { method: string; path: string; protocol: string; sourceIp: string; userAgent: string }
    • method: string
    • path: string
    • protocol: string
    • sourceIp: string
    • userAgent: string
  • requestId: string
  • routeKey: string
  • stage: string
  • time: string
  • timeEpoch: number
routeKey: string
stageVariables?: APIGatewayProxyEventStageVariables
supertokens: { response: { cookies: string[]; headers: { allowDuplicateKey: boolean; key: string; value: string | number | false | true }[] } }

Type declaration

  • response: { cookies: string[]; headers: { allowDuplicateKey: boolean; key: string; value: string | number | false | true }[] }
    • cookies: string[]
    • headers: { allowDuplicateKey: boolean; key: string; value: string | number | false | true }[]
version: string

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Interface
  • Property
  • Class
  • Class with type parameter

Settings

Theme

Generated using TypeDoc

-======= -SessionEventV2 | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • SupertokensLambdaEventV2
    • SessionEventV2

Index

Properties

body?: string
cookies?: string[]
headers: APIGatewayProxyEventHeaders
isBase64Encoded: boolean
pathParameters?: APIGatewayProxyEventPathParameters
queryStringParameters?: APIGatewayProxyEventQueryStringParameters
rawPath: string
rawQueryString: string
requestContext: { accountId: string; apiId: string; authorizer?: { jwt: { claims: {}; scopes: string[] } }; domainName: string; domainPrefix: string; http: { method: string; path: string; protocol: string; sourceIp: string; userAgent: string }; requestId: string; routeKey: string; stage: string; time: string; timeEpoch: number }

Type declaration

  • accountId: string
  • apiId: string
  • Optional authorizer?: { jwt: { claims: {}; scopes: string[] } }
    • jwt: { claims: {}; scopes: string[] }
      • claims: {}
        • [name: string]: string | number | boolean | string[]
      • scopes: string[]
  • domainName: string
  • domainPrefix: string
  • http: { method: string; path: string; protocol: string; sourceIp: string; userAgent: string }
    • method: string
    • path: string
    • protocol: string
    • sourceIp: string
    • userAgent: string
  • requestId: string
  • routeKey: string
  • stage: string
  • time: string
  • timeEpoch: number
routeKey: string
stageVariables?: APIGatewayProxyEventStageVariables
supertokens: { response: { cookies: string[]; headers: { allowDuplicateKey: boolean; key: string; value: string | number | boolean }[] } }

Type declaration

  • response: { cookies: string[]; headers: { allowDuplicateKey: boolean; key: string; value: string | number | boolean }[] }
    • cookies: string[]
    • headers: { allowDuplicateKey: boolean; key: string; value: string | number | boolean }[]
version: string

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Interface
  • Property
  • Class
  • Class with type parameter

Settings

Theme

Generated using TypeDoc

->>>>>>> 13.0 diff --git a/docs/interfaces/framework_express.SessionRequest.html b/docs/interfaces/framework_express.SessionRequest.html deleted file mode 100644 index 34d7b917f..000000000 --- a/docs/interfaces/framework_express.SessionRequest.html +++ /dev/null @@ -1,487 +0,0 @@ -SessionRequest | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • Request
    • SessionRequest

Index

Properties

aborted: boolean
-

The message.aborted property will be true if the request has -been aborted.

-
since

v10.1.0

-
deprecated

Since v17.0.0 - Check message.destroyed from stream.Readable.

-<<<<<<< HEAD -
accepted: MediaType[]
-

Return an array of Accepted media types -ordered from highest quality to lowest.

-
app: Application<Record<string, any>>
baseUrl: string
body: any
complete: boolean
-======= -
accepted: MediaType[]
-

Return an array of Accepted media types -ordered from highest quality to lowest.

-
app: Application<Record<string, any>>
baseUrl: string
body: any
complete: boolean
->>>>>>> 13.0 -

The message.complete property will be true if a complete HTTP message has -been received and successfully parsed.

-

This property is particularly useful as a means of determining if a client or -server fully transmitted a message before a connection was terminated:

-
const req = http.request({
host: '127.0.0.1',
port: 8080,
method: 'POST'
}, (res) => {
res.resume();
res.on('end', () => {
if (!res.complete)
console.error(
'The connection was terminated while the message was still being sent');
});
}); -
-
since

v0.3.0

-
connection: Socket
-

Alias for message.socket.

-
since

v0.1.90

-
deprecated

Since v16.0.0 - Use socket.

-<<<<<<< HEAD -
cookies: any
destroyed: boolean
-

Is true after readable.destroy() has been called.

-
since

v8.0.0

-
fresh: boolean
-======= -
cookies: any
destroyed: boolean
-

Is true after readable.destroy() has been called.

-
since

v8.0.0

-
fresh: boolean
->>>>>>> 13.0 -

Check if the request is fresh, aka -Last-Modified and/or the ETag -still match.

-
headers: IncomingHttpHeaders
-

The request/response headers object.

-

Key-value pairs of header names and values. Header names are lower-cased.

-
// Prints something like:
//
// { 'user-agent': 'curl/7.22.0',
// host: '127.0.0.1:8000',
// accept: '*' }
console.log(request.headers); -
-

Duplicates in raw headers are handled in the following ways, depending on the -header name:

-
    -
  • Duplicates of age, authorization, content-length, content-type,etag, expires, from, host, if-modified-since, if-unmodified-since,last-modified, location, -max-forwards, proxy-authorization, referer,retry-after, server, or user-agent are discarded.
  • -
  • set-cookie is always an array. Duplicates are added to the array.
  • -
  • For duplicate cookie headers, the values are joined together with '; '.
  • -
  • For all other headers, the values are joined together with ', '.
  • -
-
since

v0.1.5

-
host: string
deprecated

Use hostname instead.

-
hostname: string
-

Parse the "Host" header field hostname.

-
httpVersion: string
-

In case of server request, the HTTP version sent by the client. In the case of -client response, the HTTP version of the connected-to server. -Probably either '1.1' or '1.0'.

-

Also message.httpVersionMajor is the first integer andmessage.httpVersionMinor is the second.

-
since

v0.1.1

-<<<<<<< HEAD -
httpVersionMajor: number
httpVersionMinor: number
ip: string
-======= -
httpVersionMajor: number
httpVersionMinor: number
ip: string
->>>>>>> 13.0 -

Return the remote address, or when -"trust proxy" is true return -the upstream addr.

-
ips: string[]
-

When "trust proxy" is true, parse -the "X-Forwarded-For" ip address list.

-

For example if the value were "client, proxy1, proxy2" -you would receive the array ["client", "proxy1", "proxy2"] -where "proxy2" is the furthest down-stream.

-
method: string
next?: NextFunction
originalUrl: string
params: ParamsDictionary
path: string
-

Short-hand for url.parse(req.url).pathname.

-
protocol: string
-

Return the protocol string "http" or "https" -when requested with TLS. When the "trust proxy" -setting is enabled the "X-Forwarded-Proto" header -field will be trusted. If you're running behind -a reverse proxy that supplies https for you this -may be enabled.

-<<<<<<< HEAD -
query: ParsedQs
rawHeaders: string[]
-======= -
query: ParsedQs
rawHeaders: string[]
->>>>>>> 13.0 -

The raw request/response headers list exactly as they were received.

-

The keys and values are in the same list. It is not a -list of tuples. So, the even-numbered offsets are key values, and the -odd-numbered offsets are the associated values.

-

Header names are not lowercased, and duplicates are not merged.

-
// Prints something like:
//
// [ 'user-agent',
// 'this is invalid because there can be only one',
// 'User-Agent',
// 'curl/7.22.0',
// 'Host',
// '127.0.0.1:8000',
// 'ACCEPT',
// '*' ]
console.log(request.rawHeaders); -
-
since

v0.11.6

-
rawTrailers: string[]
-

The raw request/response trailer keys and values exactly as they were -received. Only populated at the 'end' event.

-
since

v0.11.6

-
readable: boolean
-

Is true if it is safe to call readable.read(), which means -the stream has not been destroyed or emitted 'error' or 'end'.

-
since

v11.4.0

-
readableAborted: boolean
-

Returns whether the stream was destroyed or errored before emitting 'end'.

-
since

v16.8.0

-
experimental
readableDidRead: boolean
-

Returns whether 'data' has been emitted.

-
since

v16.7.0, v14.18.0

-<<<<<<< HEAD -
experimental
readableEncoding: null | "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "base64url" | "latin1" | "binary" | "hex"
-======= -
experimental
readableEncoding: null | BufferEncoding
->>>>>>> 13.0 -

Getter for the property encoding of a given Readable stream. The encodingproperty can be set using the readable.setEncoding() method.

-
since

v12.7.0

-
readableEnded: boolean
-

Becomes true when 'end' event is emitted.

-
since

v12.9.0

-<<<<<<< HEAD -
readableFlowing: null | false | true
-======= -
readableFlowing: null | boolean
->>>>>>> 13.0 -

This property reflects the current state of a Readable stream as described -in the Three states section.

-
since

v9.4.0

-
readableHighWaterMark: number
-

Returns the value of highWaterMark passed when creating this Readable.

-
since

v9.3.0

-
readableLength: number
-

This property contains the number of bytes (or objects) in the queue -ready to be read. The value provides introspection data regarding -the status of the highWaterMark.

-
since

v9.4.0

-
readableObjectMode: boolean
-

Getter for the property objectMode of a given Readable stream.

-
since

v12.3.0

-
res?: Response<any, Record<string, any>, number>
-

After middleware.init executed, Request will contain res and next properties -See: express/lib/middleware/init.js

-
route: any
secure: boolean
-

Short-hand for:

-

req.protocol == 'https'

-<<<<<<< HEAD -
signedCookies: any
socket: Socket
-======= -
signedCookies: any
socket: Socket
->>>>>>> 13.0 -

The net.Socket object associated with the connection.

-

With HTTPS support, use request.socket.getPeerCertificate() to obtain the -client's authentication details.

-

This property is guaranteed to be an instance of the net.Socket class, -a subclass of stream.Duplex, unless the user specified a socket -type other than net.Socket.

-
since

v0.3.0

-
stale: boolean
-

Check if the request is stale, aka -"Last-Modified" and / or the "ETag" for the -resource has changed.

-
statusCode?: number
-

Only valid for response obtained from {@link ClientRequest}.

-

The 3-digit HTTP response status code. E.G. 404.

-
since

v0.1.1

-
statusMessage?: string
-

Only valid for response obtained from {@link ClientRequest}.

-

The HTTP response status message (reason phrase). E.G. OK or Internal Server Error.

-
since

v0.11.10

-
subdomains: string[]
-

Return subdomains as an array.

-

Subdomains are the dot-separated parts of the host before the main domain of -the app. By default, the domain of the app is assumed to be the last two -parts of the host. This can be changed by setting "subdomain offset".

-

For example, if the domain is "tobi.ferrets.example.com": -If "subdomain offset" is not set, req.subdomains is ["ferrets", "tobi"]. -If "subdomain offset" is 3, req.subdomains is ["tobi"].

-
trailers: Dict<string>
-

The request/response trailers object. Only populated at the 'end' event.

-
since

v0.3.0

-
url: string
xhr: boolean
-

Check if the request was an XMLHttpRequest.

-<<<<<<< HEAD -

Methods

  • [Symbol.asyncIterator](): AsyncIterableIterator<any>
  • Returns AsyncIterableIterator<any>

  • _construct(callback: (error?: null | Error) => void): void
  • Parameters

    • callback: (error?: null | Error) => void
        • (error?: null | Error): void
        • Parameters

          • Optional error: null | Error

          Returns void

    Returns void

  • _destroy(error: null | Error, callback: (error?: null | Error) => void): void
  • Parameters

    • error: null | Error
    • callback: (error?: null | Error) => void
        • (error?: null | Error): void
        • Parameters

          • Optional error: null | Error

          Returns void

    Returns void

  • _read(size: number): void
  • Parameters

    • size: number

    Returns void

  • accepts(): string[]
  • accepts(type: string): string | false
  • accepts(type: string[]): string | false
  • accepts(...type: string[]): string | false
  • -======= -

Methods

  • [Symbol.asyncIterator](): AsyncIterableIterator<any>
  • Returns AsyncIterableIterator<any>

  • _construct(callback: (error?: null | Error) => void): void
  • Parameters

    • callback: (error?: null | Error) => void
        • (error?: null | Error): void
        • Parameters

          • Optional error: null | Error

          Returns void

    Returns void

  • _destroy(error: null | Error, callback: (error?: null | Error) => void): void
  • Parameters

    • error: null | Error
    • callback: (error?: null | Error) => void
        • (error?: null | Error): void
        • Parameters

          • Optional error: null | Error

          Returns void

    Returns void

  • _read(size: number): void
  • Parameters

    • size: number

    Returns void

  • accepts(): string[]
  • accepts(type: string): string | false
  • accepts(type: string[]): string | false
  • accepts(...type: string[]): string | false
  • ->>>>>>> 13.0 -

    Check if the given type(s) is acceptable, returning -the best match when true, otherwise undefined, in which -case you should respond with 406 "Not Acceptable".

    -

    The type value may be a single mime type string -such as "application/json", the extension name -such as "json", a comma-delimted list such as "json, html, text/plain", -or an array ["json", "html", "text/plain"]. When a list -or array is given the best match, if any is returned.

    -

    Examples:

    -
    // Accept: text/html
    req.accepts('html');
    // => "html"

    // Accept: text/*, application/json
    req.accepts('html');
    // => "html"
    req.accepts('text/html');
    // => "text/html"
    req.accepts('json, text');
    // => "json"
    req.accepts('application/json');
    // => "application/json"

    // Accept: text/*, application/json
    req.accepts('image/png');
    req.accepts('png');
    // => undefined

    // Accept: text/*;q=.5, application/json
    req.accepts(['html', 'json']);
    req.accepts('html, json');
    // => "json" -
    -<<<<<<< HEAD -

    Returns string[]

  • Parameters

    • type: string

    Returns string | false

  • Parameters

    • type: string[]

    Returns string | false

  • Parameters

    • Rest ...type: string[]

    Returns string | false

  • acceptsCharsets(): string[]
  • acceptsCharsets(charset: string): string | false
  • acceptsCharsets(charset: string[]): string | false
  • acceptsCharsets(...charset: string[]): string | false
  • -======= -

    Returns string[]

  • Parameters

    • type: string

    Returns string | false

  • Parameters

    • type: string[]

    Returns string | false

  • Parameters

    • Rest ...type: string[]

    Returns string | false

  • acceptsCharsets(): string[]
  • acceptsCharsets(charset: string): string | false
  • acceptsCharsets(charset: string[]): string | false
  • acceptsCharsets(...charset: string[]): string | false
  • ->>>>>>> 13.0 -

    Returns the first accepted charset of the specified character sets, -based on the request's Accept-Charset HTTP header field. -If none of the specified charsets is accepted, returns false.

    -

    For more information, or if you have issues or concerns, see accepts.

    -<<<<<<< HEAD -

    Returns string[]

  • Parameters

    • charset: string

    Returns string | false

  • Parameters

    • charset: string[]

    Returns string | false

  • Parameters

    • Rest ...charset: string[]

    Returns string | false

  • acceptsEncodings(): string[]
  • acceptsEncodings(encoding: string): string | false
  • acceptsEncodings(encoding: string[]): string | false
  • acceptsEncodings(...encoding: string[]): string | false
  • -======= -

    Returns string[]

  • Parameters

    • charset: string

    Returns string | false

  • Parameters

    • charset: string[]

    Returns string | false

  • Parameters

    • Rest ...charset: string[]

    Returns string | false

  • acceptsEncodings(): string[]
  • acceptsEncodings(encoding: string): string | false
  • acceptsEncodings(encoding: string[]): string | false
  • acceptsEncodings(...encoding: string[]): string | false
  • ->>>>>>> 13.0 -

    Returns the first accepted encoding of the specified encodings, -based on the request's Accept-Encoding HTTP header field. -If none of the specified encodings is accepted, returns false.

    -

    For more information, or if you have issues or concerns, see accepts.

    -<<<<<<< HEAD -

    Returns string[]

  • Parameters

    • encoding: string

    Returns string | false

  • Parameters

    • encoding: string[]

    Returns string | false

  • Parameters

    • Rest ...encoding: string[]

    Returns string | false

  • acceptsLanguages(): string[]
  • acceptsLanguages(lang: string): string | false
  • acceptsLanguages(lang: string[]): string | false
  • acceptsLanguages(...lang: string[]): string | false
  • -======= -

    Returns string[]

  • Parameters

    • encoding: string

    Returns string | false

  • Parameters

    • encoding: string[]

    Returns string | false

  • Parameters

    • Rest ...encoding: string[]

    Returns string | false

  • acceptsLanguages(): string[]
  • acceptsLanguages(lang: string): string | false
  • acceptsLanguages(lang: string[]): string | false
  • acceptsLanguages(...lang: string[]): string | false
  • ->>>>>>> 13.0 -

    Returns the first accepted language of the specified languages, -based on the request's Accept-Language HTTP header field. -If none of the specified languages is accepted, returns false.

    -

    For more information, or if you have issues or concerns, see accepts.

    -<<<<<<< HEAD -

    Returns string[]

  • Parameters

    • lang: string

    Returns string | false

  • Parameters

    • lang: string[]

    Returns string | false

  • Parameters

    • Rest ...lang: string[]

    Returns string | false

  • addListener(event: "close", listener: () => void): SessionRequest
  • addListener(event: "data", listener: (chunk: any) => void): SessionRequest
  • addListener(event: "end", listener: () => void): SessionRequest
  • addListener(event: "error", listener: (err: Error) => void): SessionRequest
  • addListener(event: "pause", listener: () => void): SessionRequest
  • addListener(event: "readable", listener: () => void): SessionRequest
  • addListener(event: "resume", listener: () => void): SessionRequest
  • addListener(event: string | symbol, listener: (...args: any[]) => void): SessionRequest
  • -======= -

    Returns string[]

  • Parameters

    • lang: string

    Returns string | false

  • Parameters

    • lang: string[]

    Returns string | false

  • Parameters

    • Rest ...lang: string[]

    Returns string | false

  • addListener(event: "close", listener: () => void): SessionRequest
  • addListener(event: "data", listener: (chunk: any) => void): SessionRequest
  • addListener(event: "end", listener: () => void): SessionRequest
  • addListener(event: "error", listener: (err: Error) => void): SessionRequest
  • addListener(event: "pause", listener: () => void): SessionRequest
  • addListener(event: "readable", listener: () => void): SessionRequest
  • addListener(event: "resume", listener: () => void): SessionRequest
  • addListener(event: string | symbol, listener: (...args: any[]) => void): SessionRequest
  • ->>>>>>> 13.0 -

    Event emitter -The defined events on documents including:

    -
      -
    1. close
    2. -
    3. data
    4. -
    5. end
    6. -
    7. error
    8. -
    9. pause
    10. -
    11. readable
    12. -
    13. resume
    14. -
    -

    Parameters

    • event: "close"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "data"
    • listener: (chunk: any) => void
        • (chunk: any): void
        • Parameters

          • chunk: any

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "end"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "error"
    • listener: (err: Error) => void
        • (err: Error): void
        • Parameters

          • err: Error

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "pause"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "readable"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "resume"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: string | symbol
    • listener: (...args: any[]) => void
        • (...args: any[]): void
        • Parameters

          • Rest ...args: any[]

          Returns void

    Returns SessionRequest

  • -

    Calls destroy() on the socket that received the IncomingMessage. If erroris provided, an 'error' event is emitted on the socket and error is passed -as an argument to any listeners on the event.

    -
    since

    v0.3.0

    -

    Parameters

    • Optional error: Error

    Returns SessionRequest

  • emit(event: "close"): boolean
  • emit(event: "data", chunk: any): boolean
  • emit(event: "end"): boolean
  • emit(event: "error", err: Error): boolean
  • emit(event: "pause"): boolean
  • emit(event: "readable"): boolean
  • emit(event: "resume"): boolean
  • emit(event: string | symbol, ...args: any[]): boolean
  • Parameters

    • event: "close"

    Returns boolean

  • Parameters

    • event: "data"
    • chunk: any

    Returns boolean

  • Parameters

    • event: "end"

    Returns boolean

  • Parameters

    • event: "error"
    • err: Error

    Returns boolean

  • Parameters

    • event: "pause"

    Returns boolean

  • Parameters

    • event: "readable"

    Returns boolean

  • Parameters

    • event: "resume"

    Returns boolean

  • Parameters

    • event: string | symbol
    • Rest ...args: any[]

    Returns boolean

  • eventNames(): (string | symbol)[]
  • -

    Returns an array listing the events for which the emitter has registered -listeners. The values in the array are strings or Symbols.

    -
    const EventEmitter = require('events');
    const myEE = new EventEmitter();
    myEE.on('foo', () => {});
    myEE.on('bar', () => {});

    const sym = Symbol('symbol');
    myEE.on(sym, () => {});

    console.log(myEE.eventNames());
    // Prints: [ 'foo', 'bar', Symbol(symbol) ] -
    -
    since

    v6.0.0

    -

    Returns (string | symbol)[]

  • get(name: "set-cookie"): undefined | string[]
  • get(name: string): undefined | string
  • -

    Return request header.

    -

    The Referrer header field is special-cased, -both Referrer and Referer are interchangeable.

    -

    Examples:

    -
    req.get('Content-Type');
    // => "text/plain"

    req.get('content-type');
    // => "text/plain"

    req.get('Something');
    // => undefined -
    -

    Aliased as req.header().

    -<<<<<<< HEAD -

    Parameters

    • name: "set-cookie"

    Returns undefined | string[]

  • Parameters

    • name: string

    Returns undefined | string

  • getMaxListeners(): number
  • -

    Returns the current max listener value for the EventEmitter which is either -set by emitter.setMaxListeners(n) or defaults to {@link defaultMaxListeners}.

    -
    since

    v1.0.0

    -

    Returns number

  • header(name: "set-cookie"): undefined | string[]
  • header(name: string): undefined | string
  • Parameters

    • name: "set-cookie"

    Returns undefined | string[]

  • Parameters

    • name: string

    Returns undefined | string

  • is(type: string | string[]): null | string | false
  • -======= -

    Parameters

    • name: "set-cookie"

    Returns undefined | string[]

  • Parameters

    • name: string

    Returns undefined | string

  • getMaxListeners(): number
  • -

    Returns the current max listener value for the EventEmitter which is either -set by emitter.setMaxListeners(n) or defaults to {@link defaultMaxListeners}.

    -
    since

    v1.0.0

    -

    Returns number

  • header(name: "set-cookie"): undefined | string[]
  • header(name: string): undefined | string
  • Parameters

    • name: "set-cookie"

    Returns undefined | string[]

  • Parameters

    • name: string

    Returns undefined | string

  • is(type: string | string[]): null | string | false
  • ->>>>>>> 13.0 -

    Check if the incoming request contains the "Content-Type" -header field, and it contains the give mime type.

    -

    Examples:

    -
     // With Content-Type: text/html; charset=utf-8
    req.is('html');
    req.is('text/html');
    req.is('text/*');
    // => true

    // When Content-Type is application/json
    req.is('json');
    req.is('application/json');
    req.is('application/*');
    // => true

    req.is('html');
    // => false -
    -<<<<<<< HEAD -

    Parameters

    • type: string | string[]

    Returns null | string | false

  • isPaused(): boolean
  • -======= -

    Parameters

    • type: string | string[]

    Returns null | string | false

  • isPaused(): boolean
  • ->>>>>>> 13.0 -

    The readable.isPaused() method returns the current operating state of theReadable. This is used primarily by the mechanism that underlies thereadable.pipe() method. In most -typical cases, there will be no reason to -use this method directly.

    -
    const readable = new stream.Readable();

    readable.isPaused(); // === false
    readable.pause();
    readable.isPaused(); // === true
    readable.resume();
    readable.isPaused(); // === false -
    -
    since

    v0.11.14

    -

    Returns boolean

  • listenerCount(eventName: string | symbol): number
  • -

    Returns the number of listeners listening to the event named eventName.

    -
    since

    v3.2.0

    -

    Parameters

    • eventName: string | symbol
      -

      The name of the event being listened for

      -

    Returns number

  • listeners(eventName: string | symbol): Function[]
  • -

    Returns a copy of the array of listeners for the event named eventName.

    -
    server.on('connection', (stream) => {
    console.log('someone connected!');
    });
    console.log(util.inspect(server.listeners('connection')));
    // Prints: [ [Function] ] -
    -
    since

    v0.1.26

    -

    Parameters

    • eventName: string | symbol

    Returns Function[]

  • off(eventName: string | symbol, listener: (...args: any[]) => void): SessionRequest
  • -

    Alias for emitter.removeListener().

    -
    since

    v10.0.0

    -<<<<<<< HEAD -

    Parameters

    • eventName: string | symbol
    • listener: (...args: any[]) => void
        • (...args: any[]): void
        • Parameters

          • Rest ...args: any[]

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "close"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "data"
    • listener: (chunk: any) => void
        • (chunk: any): void
        • Parameters

          • chunk: any

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "end"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "error"
    • listener: (err: Error) => void
        • (err: Error): void
        • Parameters

          • err: Error

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "pause"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "readable"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "resume"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: string | symbol
    • listener: (...args: any[]) => void
        • (...args: any[]): void
        • Parameters

          • Rest ...args: any[]

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "close"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "data"
    • listener: (chunk: any) => void
        • (chunk: any): void
        • Parameters

          • chunk: any

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "end"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "error"
    • listener: (err: Error) => void
        • (err: Error): void
        • Parameters

          • err: Error

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "pause"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "readable"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "resume"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: string | symbol
    • listener: (...args: any[]) => void
        • (...args: any[]): void
        • Parameters

          • Rest ...args: any[]

          Returns void

    Returns SessionRequest

  • param(name: string, defaultValue?: any): string
  • deprecated

    since 4.11 Use either req.params, req.body or req.query, as applicable.

    -======= -

    Parameters

    • eventName: string | symbol
    • listener: (...args: any[]) => void
        • (...args: any[]): void
        • Parameters

          • Rest ...args: any[]

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "close"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "data"
    • listener: (chunk: any) => void
        • (chunk: any): void
        • Parameters

          • chunk: any

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "end"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "error"
    • listener: (err: Error) => void
        • (err: Error): void
        • Parameters

          • err: Error

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "pause"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "readable"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "resume"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: string | symbol
    • listener: (...args: any[]) => void
        • (...args: any[]): void
        • Parameters

          • Rest ...args: any[]

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "close"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "data"
    • listener: (chunk: any) => void
        • (chunk: any): void
        • Parameters

          • chunk: any

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "end"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "error"
    • listener: (err: Error) => void
        • (err: Error): void
        • Parameters

          • err: Error

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "pause"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "readable"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "resume"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: string | symbol
    • listener: (...args: any[]) => void
        • (...args: any[]): void
        • Parameters

          • Rest ...args: any[]

          Returns void

    Returns SessionRequest

  • param(name: string, defaultValue?: any): string
  • deprecated

    since 4.11 Use either req.params, req.body or req.query, as applicable.

    ->>>>>>> 13.0 -

    Return the value of param name when present or defaultValue.

    -
      -
    • Checks route placeholders, ex: /user/:id
    • -
    • Checks body params, ex: id=12, {"id":12}
    • -
    • Checks query string params, ex: ?id=12
    • -
    -

    To utilize request bodies, req.body -should be an object. This can be done by using -the connect.bodyParser() middleware.

    -

    Parameters

    • name: string
    • Optional defaultValue: any

    Returns string

  • -

    The readable.pause() method will cause a stream in flowing mode to stop -emitting 'data' events, switching out of flowing mode. Any data that -becomes available will remain in the internal buffer.

    -
    const readable = getReadableStreamSomehow();
    readable.on('data', (chunk) => {
    console.log(`Received ${chunk.length} bytes of data.`);
    readable.pause();
    console.log('There will be no additional data for 1 second.');
    setTimeout(() => {
    console.log('Now data will start flowing again.');
    readable.resume();
    }, 1000);
    }); -
    -

    The readable.pause() method has no effect if there is a 'readable'event listener.

    -
    since

    v0.9.4

    -<<<<<<< HEAD -

    Returns SessionRequest

  • pipe<T>(destination: T, options?: { end?: false | true }): T
  • Type parameters

    • T: WritableStream<T>

    Parameters

    • destination: T
    • Optional options: { end?: false | true }
      • Optional end?: false | true

    Returns T

  • prependListener(event: "close", listener: () => void): SessionRequest
  • prependListener(event: "data", listener: (chunk: any) => void): SessionRequest
  • prependListener(event: "end", listener: () => void): SessionRequest
  • prependListener(event: "error", listener: (err: Error) => void): SessionRequest
  • prependListener(event: "pause", listener: () => void): SessionRequest
  • prependListener(event: "readable", listener: () => void): SessionRequest
  • prependListener(event: "resume", listener: () => void): SessionRequest
  • prependListener(event: string | symbol, listener: (...args: any[]) => void): SessionRequest
  • Parameters

    • event: "close"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "data"
    • listener: (chunk: any) => void
        • (chunk: any): void
        • Parameters

          • chunk: any

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "end"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "error"
    • listener: (err: Error) => void
        • (err: Error): void
        • Parameters

          • err: Error

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "pause"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "readable"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "resume"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: string | symbol
    • listener: (...args: any[]) => void
        • (...args: any[]): void
        • Parameters

          • Rest ...args: any[]

          Returns void

    Returns SessionRequest

  • prependOnceListener(event: "close", listener: () => void): SessionRequest
  • prependOnceListener(event: "data", listener: (chunk: any) => void): SessionRequest
  • prependOnceListener(event: "end", listener: () => void): SessionRequest
  • prependOnceListener(event: "error", listener: (err: Error) => void): SessionRequest
  • prependOnceListener(event: "pause", listener: () => void): SessionRequest
  • prependOnceListener(event: "readable", listener: () => void): SessionRequest
  • prependOnceListener(event: "resume", listener: () => void): SessionRequest
  • prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): SessionRequest
  • Parameters

    • event: "close"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "data"
    • listener: (chunk: any) => void
        • (chunk: any): void
        • Parameters

          • chunk: any

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "end"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "error"
    • listener: (err: Error) => void
        • (err: Error): void
        • Parameters

          • err: Error

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "pause"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "readable"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "resume"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: string | symbol
    • listener: (...args: any[]) => void
        • (...args: any[]): void
        • Parameters

          • Rest ...args: any[]

          Returns void

    Returns SessionRequest

  • push(chunk: any, encoding?: "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "base64url" | "latin1" | "binary" | "hex"): boolean
  • Parameters

    • chunk: any
    • Optional encoding: "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "base64url" | "latin1" | "binary" | "hex"

    Returns boolean

  • range(size: number, options?: Options): undefined | Ranges | -1 | -2
  • -======= -

    Returns SessionRequest

  • pipe<T>(destination: T, options?: { end?: boolean }): T
  • Type parameters

    • T: WritableStream<T>

    Parameters

    • destination: T
    • Optional options: { end?: boolean }
      • Optional end?: boolean

    Returns T

  • prependListener(event: "close", listener: () => void): SessionRequest
  • prependListener(event: "data", listener: (chunk: any) => void): SessionRequest
  • prependListener(event: "end", listener: () => void): SessionRequest
  • prependListener(event: "error", listener: (err: Error) => void): SessionRequest
  • prependListener(event: "pause", listener: () => void): SessionRequest
  • prependListener(event: "readable", listener: () => void): SessionRequest
  • prependListener(event: "resume", listener: () => void): SessionRequest
  • prependListener(event: string | symbol, listener: (...args: any[]) => void): SessionRequest
  • Parameters

    • event: "close"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "data"
    • listener: (chunk: any) => void
        • (chunk: any): void
        • Parameters

          • chunk: any

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "end"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "error"
    • listener: (err: Error) => void
        • (err: Error): void
        • Parameters

          • err: Error

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "pause"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "readable"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "resume"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: string | symbol
    • listener: (...args: any[]) => void
        • (...args: any[]): void
        • Parameters

          • Rest ...args: any[]

          Returns void

    Returns SessionRequest

  • prependOnceListener(event: "close", listener: () => void): SessionRequest
  • prependOnceListener(event: "data", listener: (chunk: any) => void): SessionRequest
  • prependOnceListener(event: "end", listener: () => void): SessionRequest
  • prependOnceListener(event: "error", listener: (err: Error) => void): SessionRequest
  • prependOnceListener(event: "pause", listener: () => void): SessionRequest
  • prependOnceListener(event: "readable", listener: () => void): SessionRequest
  • prependOnceListener(event: "resume", listener: () => void): SessionRequest
  • prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): SessionRequest
  • Parameters

    • event: "close"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "data"
    • listener: (chunk: any) => void
        • (chunk: any): void
        • Parameters

          • chunk: any

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "end"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "error"
    • listener: (err: Error) => void
        • (err: Error): void
        • Parameters

          • err: Error

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "pause"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "readable"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "resume"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: string | symbol
    • listener: (...args: any[]) => void
        • (...args: any[]): void
        • Parameters

          • Rest ...args: any[]

          Returns void

    Returns SessionRequest

  • push(chunk: any, encoding?: BufferEncoding): boolean
  • Parameters

    • chunk: any
    • Optional encoding: BufferEncoding

    Returns boolean

  • range(size: number, options?: Options): undefined | Ranges | Result
  • ->>>>>>> 13.0 -

    Parse Range header field, capping to the given size.

    -

    Unspecified ranges such as "0-" require knowledge of your resource length. In -the case of a byte range this is of course the total number of bytes. -If the Range header field is not given undefined is returned. -If the Range header field is given, return value is a result of range-parser. -See more ./types/range-parser/index.d.ts

    -

    NOTE: remember that ranges are inclusive, so for example "Range: users=0-3" -should respond with 4 users when available, not 3.

    -<<<<<<< HEAD -

    Parameters

    • size: number
    • Optional options: Options

    Returns undefined | Ranges | -1 | -2

  • rawListeners(eventName: string | symbol): Function[]
  • -======= -

    Parameters

    • size: number
    • Optional options: Options

    Returns undefined | Ranges | Result

  • rawListeners(eventName: string | symbol): Function[]
  • ->>>>>>> 13.0 -

    Returns a copy of the array of listeners for the event named eventName, -including any wrappers (such as those created by .once()).

    -
    const emitter = new EventEmitter();
    emitter.once('log', () => console.log('log once'));

    // Returns a new Array with a function `onceWrapper` which has a property
    // `listener` which contains the original listener bound above
    const listeners = emitter.rawListeners('log');
    const logFnWrapper = listeners[0];

    // Logs "log once" to the console and does not unbind the `once` event
    logFnWrapper.listener();

    // Logs "log once" to the console and removes the listener
    logFnWrapper();

    emitter.on('log', () => console.log('log persistently'));
    // Will return a new Array with a single function bound by `.on()` above
    const newListeners = emitter.rawListeners('log');

    // Logs "log persistently" twice
    newListeners[0]();
    emitter.emit('log'); -
    -
    since

    v9.4.0

    -

    Parameters

    • eventName: string | symbol

    Returns Function[]

  • read(size?: number): any
  • -

    The readable.read() method pulls some data out of the internal buffer and -returns it. If no data available to be read, null is returned. By default, -the data will be returned as a Buffer object unless an encoding has been -specified using the readable.setEncoding() method or the stream is operating -in object mode.

    -

    The optional size argument specifies a specific number of bytes to read. Ifsize bytes are not available to be read, null will be returned _unless_the stream has ended, in which -case all of the data remaining in the internal -buffer will be returned.

    -

    If the size argument is not specified, all of the data contained in the -internal buffer will be returned.

    -

    The size argument must be less than or equal to 1 GiB.

    -

    The readable.read() method should only be called on Readable streams -operating in paused mode. In flowing mode, readable.read() is called -automatically until the internal buffer is fully drained.

    -
    const readable = getReadableStreamSomehow();

    // 'readable' may be triggered multiple times as data is buffered in
    readable.on('readable', () => {
    let chunk;
    console.log('Stream is readable (new data received in buffer)');
    // Use a loop to make sure we read all currently available data
    while (null !== (chunk = readable.read())) {
    console.log(`Read ${chunk.length} bytes of data...`);
    }
    });

    // 'end' will be triggered once when there is no more data available
    readable.on('end', () => {
    console.log('Reached end of stream.');
    }); -
    -

    Each call to readable.read() returns a chunk of data, or null. The chunks -are not concatenated. A while loop is necessary to consume all data -currently in the buffer. When reading a large file .read() may return null, -having consumed all buffered content so far, but there is still more data to -come not yet buffered. In this case a new 'readable' event will be emitted -when there is more data in the buffer. Finally the 'end' event will be -emitted when there is no more data to come.

    -

    Therefore to read a file's whole contents from a readable, it is necessary -to collect chunks across multiple 'readable' events:

    -
    const chunks = [];

    readable.on('readable', () => {
    let chunk;
    while (null !== (chunk = readable.read())) {
    chunks.push(chunk);
    }
    });

    readable.on('end', () => {
    const content = chunks.join('');
    }); -
    -

    A Readable stream in object mode will always return a single item from -a call to readable.read(size), regardless of the value of thesize argument.

    -

    If the readable.read() method returns a chunk of data, a 'data' event will -also be emitted.

    -

    Calling read after the 'end' event has -been emitted will return null. No runtime error will be raised.

    -
    since

    v0.9.4

    -

    Parameters

    • Optional size: number
      -

      Optional argument to specify how much data to read.

      -

    Returns any

  • -

    Removes all listeners, or those of the specified eventName.

    -

    It is bad practice to remove listeners added elsewhere in the code, -particularly when the EventEmitter instance was created by some other -component or module (e.g. sockets or file streams).

    -

    Returns a reference to the EventEmitter, so that calls can be chained.

    -
    since

    v0.1.26

    -

    Parameters

    • Optional event: string | symbol

    Returns SessionRequest

  • removeListener(event: "close", listener: () => void): SessionRequest
  • removeListener(event: "data", listener: (chunk: any) => void): SessionRequest
  • removeListener(event: "end", listener: () => void): SessionRequest
  • removeListener(event: "error", listener: (err: Error) => void): SessionRequest
  • removeListener(event: "pause", listener: () => void): SessionRequest
  • removeListener(event: "readable", listener: () => void): SessionRequest
  • removeListener(event: "resume", listener: () => void): SessionRequest
  • removeListener(event: string | symbol, listener: (...args: any[]) => void): SessionRequest
  • Parameters

    • event: "close"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "data"
    • listener: (chunk: any) => void
        • (chunk: any): void
        • Parameters

          • chunk: any

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "end"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "error"
    • listener: (err: Error) => void
        • (err: Error): void
        • Parameters

          • err: Error

          Returns void

    Returns SessionRequest

  • Parameters

    • event: "pause"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "readable"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: "resume"
    • listener: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • Parameters

    • event: string | symbol
    • listener: (...args: any[]) => void
        • (...args: any[]): void
        • Parameters

          • Rest ...args: any[]

          Returns void

    Returns SessionRequest

  • -

    The readable.resume() method causes an explicitly paused Readable stream to -resume emitting 'data' events, switching the stream into flowing mode.

    -

    The readable.resume() method can be used to fully consume the data from a -stream without actually processing any of that data:

    -
    getReadableStreamSomehow()
    .resume()
    .on('end', () => {
    console.log('Reached the end, but did not read anything.');
    }); -
    -

    The readable.resume() method has no effect if there is a 'readable'event listener.

    -
    since

    v0.9.4

    -

    Returns SessionRequest

  • -

    The readable.setEncoding() method sets the character encoding for -data read from the Readable stream.

    -

    By default, no encoding is assigned and stream data will be returned asBuffer objects. Setting an encoding causes the stream data -to be returned as strings of the specified encoding rather than as Bufferobjects. For instance, calling readable.setEncoding('utf8') will cause the -output data to be interpreted as UTF-8 data, and passed as strings. Callingreadable.setEncoding('hex') will cause the data to be encoded in hexadecimal -string format.

    -

    The Readable stream will properly handle multi-byte characters delivered -through the stream that would otherwise become improperly decoded if simply -pulled from the stream as Buffer objects.

    -
    const readable = getReadableStreamSomehow();
    readable.setEncoding('utf8');
    readable.on('data', (chunk) => {
    assert.equal(typeof chunk, 'string');
    console.log('Got %d characters of string data:', chunk.length);
    }); -
    -
    since

    v0.9.4

    -

    Parameters

    • encoding: BufferEncoding
      -

      The encoding to use.

      -

    Returns SessionRequest

  • -

    By default EventEmitters will print a warning if more than 10 listeners are -added for a particular event. This is a useful default that helps finding -memory leaks. The emitter.setMaxListeners() method allows the limit to be -modified for this specific EventEmitter instance. The value can be set toInfinity (or 0) to indicate an unlimited number of listeners.

    -

    Returns a reference to the EventEmitter, so that calls can be chained.

    -
    since

    v0.3.5

    -

    Parameters

    • n: number

    Returns SessionRequest

  • -

    Calls message.socket.setTimeout(msecs, callback).

    -
    since

    v0.5.9

    -

    Parameters

    • msecs: number
    • Optional callback: () => void
        • (): void
        • Returns void

    Returns SessionRequest

  • -

    The readable.unpipe() method detaches a Writable stream previously attached -using the pipe method.

    -

    If the destination is not specified, then all pipes are detached.

    -

    If the destination is specified, but no pipe is set up for it, then -the method does nothing.

    -
    const fs = require('fs');
    const readable = getReadableStreamSomehow();
    const writable = fs.createWriteStream('file.txt');
    // All the data from readable goes into 'file.txt',
    // but only for the first second.
    readable.pipe(writable);
    setTimeout(() => {
    console.log('Stop writing to file.txt.');
    readable.unpipe(writable);
    console.log('Manually close the file stream.');
    writable.end();
    }, 1000); -
    -
    since

    v0.9.4

    -

    Parameters

    • Optional destination: WritableStream
      -

      Optional specific stream to unpipe

      -<<<<<<< HEAD -

    Returns SessionRequest

  • unshift(chunk: any, encoding?: "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "base64url" | "latin1" | "binary" | "hex"): void
  • -======= -

Returns SessionRequest

  • unshift(chunk: any, encoding?: BufferEncoding): void
  • ->>>>>>> 13.0 -

    Passing chunk as null signals the end of the stream (EOF) and behaves the -same as readable.push(null), after which no more data can be written. The EOF -signal is put at the end of the buffer and any buffered data will still be -flushed.

    -

    The readable.unshift() method pushes a chunk of data back into the internal -buffer. This is useful in certain situations where a stream is being consumed by -code that needs to "un-consume" some amount of data that it has optimistically -pulled out of the source, so that the data can be passed on to some other party.

    -

    The stream.unshift(chunk) method cannot be called after the 'end' event -has been emitted or a runtime error will be thrown.

    -

    Developers using stream.unshift() often should consider switching to -use of a Transform stream instead. See the API for stream implementers section for more information.

    -
    // Pull off a header delimited by \n\n.
    // Use unshift() if we get too much.
    // Call the callback with (error, header, stream).
    const { StringDecoder } = require('string_decoder');
    function parseHeader(stream, callback) {
    stream.on('error', callback);
    stream.on('readable', onReadable);
    const decoder = new StringDecoder('utf8');
    let header = '';
    function onReadable() {
    let chunk;
    while (null !== (chunk = stream.read())) {
    const str = decoder.write(chunk);
    if (str.match(/\n\n/)) {
    // Found the header boundary.
    const split = str.split(/\n\n/);
    header += split.shift();
    const remaining = split.join('\n\n');
    const buf = Buffer.from(remaining, 'utf8');
    stream.removeListener('error', callback);
    // Remove the 'readable' listener before unshifting.
    stream.removeListener('readable', onReadable);
    if (buf.length)
    stream.unshift(buf);
    // Now the body of the message can be read from the stream.
    callback(null, header, stream);
    } else {
    // Still reading the header.
    header += str;
    }
    }
    }
    } -
    -

    Unlike push, stream.unshift(chunk) will not -end the reading process by resetting the internal reading state of the stream. -This can cause unexpected results if readable.unshift() is called during a -read (i.e. from within a _read implementation on a -custom stream). Following the call to readable.unshift() with an immediate push will reset the reading state appropriately, -however it is best to simply avoid calling readable.unshift() while in the -process of performing a read.

    -
    since

    v0.9.11

    -

    Parameters

    • chunk: any
      -

      Chunk of data to unshift onto the read queue. For streams not operating in object mode, chunk must be a string, Buffer, Uint8Array or null. For object mode -streams, chunk may be any JavaScript value.

      -
    • Optional encoding: BufferEncoding
      -

      Encoding of string chunks. Must be a valid Buffer encoding, such as 'utf8' or 'ascii'.

      -

    Returns void

  • -

    Prior to Node.js 0.10, streams did not implement the entire stream module API -as it is currently defined. (See Compatibility for more information.)

    -

    When using an older Node.js library that emits 'data' events and has a pause method that is advisory only, thereadable.wrap() method can be used to create a Readable -stream that uses -the old stream as its data source.

    -

    It will rarely be necessary to use readable.wrap() but the method has been -provided as a convenience for interacting with older Node.js applications and -libraries.

    -
    const { OldReader } = require('./old-api-module.js');
    const { Readable } = require('stream');
    const oreader = new OldReader();
    const myReader = new Readable().wrap(oreader);

    myReader.on('readable', () => {
    myReader.read(); // etc.
    }); -
    -
    since

    v0.9.4

    -

    Parameters

    • stream: ReadableStream
      -

      An "old style" readable stream

      -

    Returns SessionRequest

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Interface
  • Property
  • Class
  • Class with type parameter

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/interfaces/framework_fastify.SessionRequest.html b/docs/interfaces/framework_fastify.SessionRequest.html deleted file mode 100644 index dbcb249c8..000000000 --- a/docs/interfaces/framework_fastify.SessionRequest.html +++ /dev/null @@ -1,8 +0,0 @@ -SessionRequest | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • FastifyRequest
    • SessionRequest

Index

Properties

body: unknown
connection: Socket
headers: IncomingHttpHeaders
hostname: string
id: any
ip: string
ips?: string[]
is404: boolean
log: FastifyLoggerInstance
method: string
params: unknown
protocol: "http" | "https"
query: unknown
raw: IncomingMessage
req: IncomingMessage
deprecated

Use raw property

-<<<<<<< HEAD -
routerMethod: string
routerPath: string
socket: Socket
url: string
validationError?: Error & { validation: any; validationContext: string }
-======= -
routerMethod: string
routerPath: string
socket: Socket
url: string
validationError?: Error & { validation: any; validationContext: string }
->>>>>>> 13.0 -

in order for this to be used the user should ensure they have set the attachValidation option.

-

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Interface
  • Property
  • Class
  • Class with type parameter

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/interfaces/framework_hapi.SessionRequest.html b/docs/interfaces/framework_hapi.SessionRequest.html deleted file mode 100644 index 19c838333..000000000 --- a/docs/interfaces/framework_hapi.SessionRequest.html +++ /dev/null @@ -1,245 +0,0 @@ -SessionRequest | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • Request
    • SessionRequest

Index

Properties

app: RequestApplicationState
-

Application-specific state. Provides a safe place to store application data without potential conflicts with the framework. Should not be used by plugins which should use plugins[name]. -See docs

-
auth: RequestAuth
-

Authentication information:

-
    -
  • artifacts - an artifact object received from the authentication strategy and used in authentication-related actions.
  • -
  • credentials - the credential object received during the authentication process. The presence of an object does not mean successful authentication.
  • -
  • error - the authentication error is failed and mode set to 'try'.
  • -
  • isAuthenticated - true if the request has been successfully authenticated, otherwise false.
  • -
  • isAuthorized - true is the request has been successfully authorized against the route authentication access configuration. If the route has not access rules defined or if the request failed -authorization, set to false.
  • -
  • mode - the route authentication mode.
  • -
  • strategy - the name of the strategy used. -See docs
  • -
-
events: RequestEvents
-

Access: read only and the public podium interface. -The request.events supports the following events:

-
    -
  • 'peek' - emitted for each chunk of payload data read from the client connection. The event method signature is function(chunk, encoding).
  • -
  • 'finish' - emitted when the request payload finished reading. The event method signature is function ().
  • -
  • 'disconnect' - emitted when a request errors or aborts unexpectedly. -See docs
  • -
-
headers: Dictionary<string>
-

The raw request headers (references request.raw.req.headers). -See docs

-
info: RequestInfo
-

Request information:

-
    -
  • acceptEncoding - the request preferred encoding.
  • -
  • cors - if CORS is enabled for the route, contains the following:
  • -
  • isOriginMatch - true if the request 'Origin' header matches the configured CORS restrictions. Set to false if no 'Origin' header is found or if it does not match. Note that this is only -available after the 'onRequest' extension point as CORS is configured per-route and no routing decisions are made at that point in the request lifecycle.
  • -
  • host - content of the HTTP 'Host' header (e.g. 'example.com:8080').
  • -
  • hostname - the hostname part of the 'Host' header (e.g. 'example.com').
  • -
  • id - a unique request identifier (using the format '{now}:{connection.info.id}:{5 digits counter}').
  • -
  • received - request reception timestamp.
  • -
  • referrer - content of the HTTP 'Referrer' (or 'Referer') header.
  • -
  • remoteAddress - remote client IP address.
  • -
  • remotePort - remote client port.
  • -
  • responded - request response timestamp (0 is not responded yet). -Note that the request.info object is not meant to be modified. -See docs
  • -
-
logs: RequestLog[]
-

An array containing the logged request events. -Note that this array will be empty if route log.collect is set to false.

-
method: HTTP_METHODS_PARTIAL_LOWERCASE
-

The request method in lower case (e.g. 'get', 'post').

-
mime: string
-

The parsed content-type header. Only available when payload parsing enabled and no payload error occurred.

-
orig: RequestOrig
-

An object containing the values of params, query, and payload before any validation modifications made. Only set when input validation is performed.

-
params: Dictionary<any>
-

An object where each key is a path parameter name with matching value as described in Path parameters.

-
paramsArray: string[]
-

An array containing all the path params values in the order they appeared in the path.

-
path: string
-

The request URI's pathname component.

-
payload: string | object | Readable | Buffer
-

The request payload based on the route payload.output and payload.parse settings. -TODO check this typing and add references / links.

-
plugins: PluginsStates
-

Plugin-specific state. Provides a place to store and pass request-level plugin data. The plugins is an object where each key is a plugin name and the value is the state.

-
pre: Dictionary<any>
-

An object where each key is the name assigned by a route pre-handler methods function. The values are the raw values provided to the continuation function as argument. For the wrapped response -object, use responses.

-
preResponses: Dictionary<any>
-

Same as pre but represented as the response object created by the pre method.

-
query: RequestQuery
-

By default the object outputted from node's URL parse() method.

-
raw: { req: IncomingMessage; res: ServerResponse }
-

An object containing the Node HTTP server objects. Direct interaction with these raw objects is not recommended.

-
    -
  • req - the node request object.
  • -
  • res - the node response object.
  • -
-

Type declaration

  • req: IncomingMessage
  • res: ServerResponse
response: ResponseObject | Boom<any>
-

Access: read / write (see limitations below). -The response object when set. The object can be modified but must not be assigned another object. To replace the response with another from within an extension point, use reply(response) to -override with a different response. -In case of an aborted request the status code will be set to disconnectStatusCode.

-
route: RequestRoute
-

The request route information object and method -See docs -See docs

-
server: Server
-

Access: read only and the public server interface. -The server object.

-<<<<<<< HEAD -
state: Dictionary<any>
-======= -
state: Dictionary<any>
->>>>>>> 13.0 -

An object containing parsed HTTP state information (cookies) where each key is the cookie name and value is the matching cookie content after processing using any registered cookie definition.

-
url: URL
-

The parsed request URI.

-

Methods

  • active(): boolean
  • -

    Returns true when the request is active and processing should continue and false when the - request terminated early or completed its lifecycle. Useful when request processing is a -resource-intensive operation and should be terminated early if the request is no longer active -(e.g. client disconnected or aborted early).

    -

    Returns boolean

  • addListener<TArgs, Tcontext>(criteria: string | CriteriaObject, listener: Listener<Tcontext, TArgs>, context?: Tcontext): SessionRequest
  • addListener<TArgs, Tcontext>(criteria: string | CriteriaObject, listener: Listener<Tcontext, TArgs>, context?: Tcontext): SessionRequest
  • -

    Subscribe a handler to an event. Same as podium.on().

    -

    Type parameters

    Parameters

    • criteria: string | CriteriaObject
      -

      The subscription criteria.

      -
    • listener: Listener<Tcontext, TArgs>
      -

      The handler method set to receive event updates. The function signature - depends on the block, spread, and tags options.

      -
    • Optional context: Tcontext
      -

      Optional object that binds to the listener handler.

      -

    Returns SessionRequest

    A reference to the current emitter.

    -
  • Type parameters

    Parameters

    • criteria: string | CriteriaObject
    • listener: Listener<Tcontext, TArgs>
    • Optional context: Tcontext

    Returns SessionRequest

  • emit(criteria: string | EmitCriteria, data?: any): Promise<void>
  • -

    Emits an event update to all the subscribed listeners.

    -

    Parameters

    • criteria: string | EmitCriteria
      -

      The event update criteria.

      -
    • Optional data: any
      -

      The value emitted to the subscribers.

      -

    Returns Promise<void>

    Promise that resolves when all events has been processed. Any errors will cause an -immediate rejection.

    -<<<<<<< HEAD -
  • generateResponse(source: null | string | object, options?: { variety?: string; close?: any; marshal?: any; prepare?: any }): ResponseObject
  • -

    Returns a response which you can pass into the reply interface where:

    -

    Parameters

    • source: null | string | object
      -======= -
  • generateResponse(source: null | string | object, options?: { variety?: string; close?: any; marshal?: any; prepare?: any }): ResponseObject
  • -

    Returns a response which you can pass into the reply interface where:

    -

    Parameters

    • source: null | string | object
      ->>>>>>> 13.0 -

      the value to set as the source of the reply interface, optional.

      -
    • Optional options: { variety?: string; close?: any; marshal?: any; prepare?: any }
      -

      options for the method, optional.

      -
      • Optional variety?: string
      • close?:function
        • close(response: ResponseObject): void
        • Parameters

          • response: ResponseObject

          Returns void

      • marshal?:function
        • marshal(response: ResponseObject): Promise<ResponseValue>
        • Parameters

          • response: ResponseObject

          Returns Promise<ResponseValue>

      • prepare?:function
        • prepare(response: ResponseObject): Promise<ResponseObject>
        • Parameters

          • response: ResponseObject

          Returns Promise<ResponseObject>

    Returns ResponseObject

    ResponseObject -See docs

    -
  • hasListeners(name: string): boolean
  • -

    Returns whether an event has any listeners subscribed.

    -

    Parameters

    • name: string
      -

      the event name string.

      -

    Returns boolean

    true if the event name has any listeners, otherwise false.

    -
  • log(tags: string | string[], data?: string | object | (() => string | object)): void
  • -

    Logs request-specific events. When called, the server emits a 'request' event which can be used by other listeners or plugins. The arguments are:

    -

    Parameters

    • tags: string | string[]
      -

      a string or an array of strings (e.g. ['error', 'database', 'read']) used to identify the event. Tags are used instead of log levels and provide a much more expressive mechanism - for describing and filtering events.

      -
    • Optional data: string | object | (() => string | object)
      -

      (optional) an message string or object with the application data being logged. If data is a function, the function signature is function() and it called once to generate (return - value) the actual data emitted to the listeners. Any logs generated by the server internally will be emitted only on the 'request-internal' channel and will include the event.internal flag - set to true.

      -

    Returns void

    void -See docs

    -
  • on<TArgs, Tcontext>(criteria: string | CriteriaObject, listener: Listener<Tcontext, TArgs>, context?: Tcontext): SessionRequest
  • on<TArgs, Tcontext>(criteria: string | CriteriaObject, listener: Listener<Tcontext, TArgs>, context?: Tcontext): SessionRequest
  • -

    Subscribe a handler to an event.

    -

    Type parameters

    Parameters

    • criteria: string | CriteriaObject
      -

      The subscription criteria.

      -
    • listener: Listener<Tcontext, TArgs>
      -

      The handler method set to receive event updates. The function signature - depends on the block, spread, and tags options.

      -
    • Optional context: Tcontext
      -

      Optional object that binds to the listener handler.

      -

    Returns SessionRequest

    A reference to the current emitter.

    -<<<<<<< HEAD -
  • Type parameters

    Parameters

    • criteria: string | CriteriaObject
    • listener: Listener<Tcontext, TArgs>
    • Optional context: Tcontext

    Returns SessionRequest

  • once<TArgs, Tcontext>(criteria: string | Pick<CriteriaObject, "name" | "channels" | "clone" | "filter" | "spread" | "tags">, listener: Listener<Tcontext, TArgs>, context?: Tcontext): SessionRequest
  • once<TArgs, Tcontext>(criteria: string | Pick<CriteriaObject, "name" | "channels" | "clone" | "filter" | "spread" | "tags">, listener: Listener<Tcontext, TArgs>, context?: Tcontext): SessionRequest
  • once<TArgs, Tcontext>(criteria: string | Pick<CriteriaObject, "name" | "channels" | "clone" | "filter" | "spread" | "tags">): Promise<TArgs>
  • once<TArgs, Tcontext>(criteria: string | Pick<CriteriaObject, "name" | "channels" | "clone" | "filter" | "spread" | "tags">): Promise<TArgs>
  • -

    Same as podium.on() with the count option set to 1.

    -

    Can also be called without an listener to wait for a single event.

    -

    Type parameters

    Parameters

    • criteria: string | Pick<CriteriaObject, "name" | "channels" | "clone" | "filter" | "spread" | "tags">
      -======= -
    • Type parameters

      Parameters

      • criteria: string | CriteriaObject
      • listener: Listener<Tcontext, TArgs>
      • Optional context: Tcontext

      Returns SessionRequest

  • once<TArgs, Tcontext>(criteria: string | Omit<CriteriaObject, "count">, listener: Listener<Tcontext, TArgs>, context?: Tcontext): SessionRequest
  • once<TArgs, Tcontext>(criteria: string | Omit<CriteriaObject, "count">, listener: Listener<Tcontext, TArgs>, context?: Tcontext): SessionRequest
  • once<TArgs, Tcontext>(criteria: string | Omit<CriteriaObject, "count">): Promise<TArgs>
  • once<TArgs, Tcontext>(criteria: string | Omit<CriteriaObject, "count">): Promise<TArgs>
  • -

    Same as podium.on() with the count option set to 1.

    -

    Can also be called without an listener to wait for a single event.

    -

    Type parameters

    Parameters

    • criteria: string | Omit<CriteriaObject, "count">
      ->>>>>>> 13.0 -

      The subscription criteria.

      -
    • listener: Listener<Tcontext, TArgs>
      -

      The handler method set to receive event updates. The function signature - depends on the block, spread, and tags options.

      -
    • Optional context: Tcontext
      -

      Optional object that binds to the listener handler.

      -

    Returns SessionRequest

    A reference to the current emitter.

    -<<<<<<< HEAD -
  • Type parameters

    Parameters

    • criteria: string | Pick<CriteriaObject, "name" | "channels" | "clone" | "filter" | "spread" | "tags">
    • listener: Listener<Tcontext, TArgs>
    • Optional context: Tcontext

    Returns SessionRequest

  • -

    Wait for a single event. The count option is fixed to 1.

    -

    Type parameters

    • TArgs: any[] = unknown[]

    • Tcontext: void = void

    Parameters

    • criteria: string | Pick<CriteriaObject, "name" | "channels" | "clone" | "filter" | "spread" | "tags">
      -

      The subscription criteria.

      -

    Returns Promise<TArgs>

    Promise with array of emitted parameters.

    -
  • Type parameters

    • TArgs: any[] = any[]

    • Tcontext: void = void

    Parameters

    • criteria: string | Pick<CriteriaObject, "name" | "channels" | "clone" | "filter" | "spread" | "tags">

    Returns Promise<TArgs>

  • registerEvent(events: string | Podium | EventOptions | Event[]): void
  • -======= -
  • Type parameters

    Parameters

    • criteria: string | Omit<CriteriaObject, "count">
    • listener: Listener<Tcontext, TArgs>
    • Optional context: Tcontext

    Returns SessionRequest

  • -

    Wait for a single event. The count option is fixed to 1.

    -

    Type parameters

    • TArgs: any[] = unknown[]

    • Tcontext: void = void

    Parameters

    • criteria: string | Omit<CriteriaObject, "count">
      -

      The subscription criteria.

      -

    Returns Promise<TArgs>

    Promise with array of emitted parameters.

    -
  • Type parameters

    • TArgs: any[] = any[]

    • Tcontext: void = void

    Parameters

    • criteria: string | Omit<CriteriaObject, "count">

    Returns Promise<TArgs>

  • registerEvent(events: Event | Event[]): void
  • ->>>>>>> 13.0 -

    Register the specified events and their optional configuration. Events must be registered -before they can be emitted or subscribed to. This is done to detect event name mispelling -and invalid event activities.

    -

    Parameters

    • events: Event | Event[]
      -

      The event(s) to register.

      -

    Returns void

  • registerPodium(podiums: Podium | Podium[]): void
  • -

    Registers another emitter as an event source for the current emitter (any event update -emitted by the source emitter is passed to any subscriber of the current emitter).

    -

    Note that any events registered with a source emitter are automatically added to the current -emitter. If the events are already registered, they are left as-is.

    -

    Parameters

    • podiums: Podium | Podium[]
      -

      A Podium object or an array of objects, each added as a source.

      -

    Returns void

  • -

    Removes all listeners subscribed to a given event name.

    -

    Parameters

    • name: string
      -

      The event name string.

      -

    Returns SessionRequest

    A reference to the current emitter.

    -
  • removeListener(name: string, listener: Listener<any, any[]>): SessionRequest
  • -

    Removes all listeners subscribed to a given event name matching the provided listener method.

    -

    Parameters

    • name: string
      -

      The event name string.

      -
    • listener: Listener<any, any[]>
      -

      The function reference provided when subscribed.

      -

    Returns SessionRequest

    A reference to the current emitter.

    -
  • setMethod(method: HTTP_METHODS_PARTIAL): void
  • -

    Changes the request method before the router begins processing the request where:

    -

    Parameters

    • method: HTTP_METHODS_PARTIAL
      -

      is the request HTTP method (e.g. 'GET').

      -

    Returns void

    void -Can only be called from an 'onRequest' extension method. -See docs

    -<<<<<<< HEAD -
  • setUrl(url: string | URL, stripTrailingSlash?: false | true): void
  • -======= -
  • setUrl(url: string | URL, stripTrailingSlash?: boolean): void
  • ->>>>>>> 13.0 -

    Changes the request URI before the router begins processing the request where: -Can only be called from an 'onRequest' extension method.

    -

    Parameters

    • url: string | URL
      -

      the new request URI. If url is a string, it is parsed with node's URL parse() method with parseQueryString set to true. url can also be set to an object compatible with node's URL - parse() method output.

      -<<<<<<< HEAD -
    • Optional stripTrailingSlash: false | true
      -======= -
    • Optional stripTrailingSlash: boolean
      ->>>>>>> 13.0 -

      if true, strip the trailing slash from the path. Defaults to false.

      -

    Returns void

    void -See docs

    -

Legend

  • Variable
  • Function
  • Function with type parameter
  • Type alias
  • Interface
  • Property
  • Class
  • Class with type parameter

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/interfaces/framework_koa.SessionContext.html b/docs/interfaces/framework_koa.SessionContext.html deleted file mode 100644 index 512f63e63..000000000 --- a/docs/interfaces/framework_koa.SessionContext.html +++ /dev/null @@ -1,250 +0,0 @@ -SessionContext | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • Context
    • SessionContext

Index

Properties

URL: URL
-

Get WHATWG parsed URL object.

-
accept: Accepts
app: __module
assert: typeof assert
-

Similar to .throw(), adds assertion.

-

this.assert(this.user, 401, 'Please login!');

-

See: https://github.com/jshttp/http-assert

-
body: unknown
-

Get/Set response body.

-
cookies: Cookies
etag: string
-

Get/Set the ETag of a response. -This will normalize the quotes if necessary.

-
this.response.etag = 'md5hashsum';
this.response.etag = '"md5hashsum"';
this.response.etag = 'W/"123456789"'; -
-
param etag
api

public

-
fresh: boolean
-

Check if the request is fresh, aka -Last-Modified and/or the ETag -still match.

-
header: IncomingHttpHeaders
-

Return request header.

-
headerSent: boolean
-

Check if a header has been written to the socket.

-
headers: IncomingHttpHeaders
-

Return request header, alias as request.header

-
host: string
-

Parse the "Host" header field host -and support X-Forwarded-Host when a -proxy is enabled.

-
hostname: string
-

Parse the "Host" header field hostname -and support X-Forwarded-Host when a -proxy is enabled.

-
href: string
-

Get full request URL.

-
idempotent: boolean
-

Check if the request is idempotent.

-
ip: string
-

Request remote address. Supports X-Forwarded-For when app.proxy is true.

-
ips: string[]
-

When app.proxy is true, parse -the "X-Forwarded-For" ip address list.

-

For example if the value were "client, proxy1, proxy2" -you would receive the array ["client", "proxy1", "proxy2"] -where "proxy2" is the furthest down-stream.

-
lastModified: Date
-

Get the Last-Modified date in Date form, if it exists. -Set the Last-Modified date using a string or a Date.

-
this.response.lastModified = new Date();
this.response.lastModified = '2013-09-13'; -
-
length: number
-

Return parsed response Content-Length when present. -Set Content-Length field to n.

-
message: string
-

Get response status message

-
method: string
-

Get/Set request method.

-
origin: string
-

Get origin of URL.

-
originalUrl: string
path: string
-

Get request pathname. -Set pathname, retaining the query-string when present.

-
protocol: string
-

Return the protocol string "http" or "https" -when requested with TLS. When the proxy setting -is enabled the "X-Forwarded-Proto" header -field will be trusted. If you're running behind -a reverse proxy that supplies https for you this -may be enabled.

-
query: ParsedUrlQuery
-

Get parsed query-string. -Set query-string as an object.

-
querystring: string
-

Get/Set query string.

-<<<<<<< HEAD -
req: IncomingMessage
request: Request
res: ServerResponse
respond?: false | true
-======= -
req: IncomingMessage
request: Request
res: ServerResponse
respond?: boolean
->>>>>>> 13.0 -

To bypass Koa's built-in response handling, you may explicitly set ctx.respond = false;

-
response: Response & { body: unknown }
search: string
-

Get the search string. Same as the querystring -except it includes the leading ?.

-

Set the search string. Same as -response.querystring= but included for ubiquity.

-
secure: boolean
-

Short-hand for:

-

this.protocol == 'https'

-<<<<<<< HEAD -
socket: Socket
-======= -
socket: Socket
->>>>>>> 13.0 -

Return the request socket.

-
stale: boolean
-

Check if the request is stale, aka -"Last-Modified" and / or the "ETag" for the -resource has changed.

-
state: DefaultState
status: number
-

Get/Set response status code.

-
subdomains: string[]
-

Return subdomains as an array.

-

Subdomains are the dot-separated parts of the host before the main domain -of the app. By default, the domain of the app is assumed to be the last two -parts of the host. This can be changed by setting app.subdomainOffset.

-

For example, if the domain is "tobi.ferrets.example.com": -If app.subdomainOffset is not set, this.subdomains is -["ferrets", "tobi"]. -If app.subdomainOffset is 3, this.subdomains is ["tobi"].

-
type: string
-

Return the response mime type void of -parameters such as "charset".

-

Set Content-Type response header with type through mime.lookup() -when it does not contain a charset.

-

Examples:

-
this.type = '.html';
this.type = 'html';
this.type = 'json';
this.type = 'application/json';
this.type = 'png'; -
-
url: string
-

Get/Set request URL.

-
writable: boolean
-

Checks if the request is writable. -Tests for the existence of the socket -as node sometimes does not set it.

-<<<<<<< HEAD -

Methods

  • accepts(): string[]
  • accepts(...types: string[]): string | false
  • accepts(types: string[]): string | false
  • -======= -

Methods

  • accepts(): string[]
  • accepts(...types: string[]): string | false
  • accepts(types: string[]): string | false
  • ->>>>>>> 13.0 -

    Check if the given type(s) is acceptable, returning -the best match when true, otherwise false, in which -case you should respond with 406 "Not Acceptable".

    -

    The type value may be a single mime type string -such as "application/json", the extension name -such as "json" or an array ["json", "html", "text/plain"]. When a list -or array is given the best match, if any is returned.

    -

    Examples:

    -
    // Accept: text/html
    this.accepts('html');
    // => "html"

    // Accept: text/*, application/json
    this.accepts('html');
    // => "html"
    this.accepts('text/html');
    // => "text/html"
    this.accepts('json', 'text');
    // => "json"
    this.accepts('application/json');
    // => "application/json"

    // Accept: text/*, application/json
    this.accepts('image/png');
    this.accepts('png');
    // => undefined

    // Accept: text/*;q=.5, application/json
    this.accepts(['html', 'json']);
    this.accepts('html', 'json');
    // => "json" -
    -<<<<<<< HEAD -

    Returns string[]

  • Parameters

    • Rest ...types: string[]

    Returns string | false

  • Parameters

    • types: string[]

    Returns string | false

  • acceptsCharsets(): string[]
  • acceptsCharsets(...charsets: string[]): string | false
  • acceptsCharsets(charsets: string[]): string | false
  • -======= -

    Returns string[]

  • Parameters

    • Rest ...types: string[]

    Returns string | false

  • Parameters

    • types: string[]

    Returns string | false

  • acceptsCharsets(): string[]
  • acceptsCharsets(...charsets: string[]): string | false
  • acceptsCharsets(charsets: string[]): string | false
  • ->>>>>>> 13.0 -

    Return accepted charsets or best fit based on charsets.

    -

    Given Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5 -an array sorted by quality is returned:

    -
    ['utf-8', 'utf-7', 'iso-8859-1']
    -
    -<<<<<<< HEAD -

    Returns string[]

  • Parameters

    • Rest ...charsets: string[]

    Returns string | false

  • Parameters

    • charsets: string[]

    Returns string | false

  • acceptsEncodings(): string[]
  • acceptsEncodings(...encodings: string[]): string | false
  • acceptsEncodings(encodings: string[]): string | false
  • -======= -

    Returns string[]

  • Parameters

    • Rest ...charsets: string[]

    Returns string | false

  • Parameters

    • charsets: string[]

    Returns string | false

  • acceptsEncodings(): string[]
  • acceptsEncodings(...encodings: string[]): string | false
  • acceptsEncodings(encodings: string[]): string | false
  • ->>>>>>> 13.0 -

    Return accepted encodings or best fit based on encodings.

    -

    Given Accept-Encoding: gzip, deflate -an array sorted by quality is returned:

    -
    ['gzip', 'deflate']
    -
    -<<<<<<< HEAD -

    Returns string[]

  • Parameters

    • Rest ...encodings: string[]

    Returns string | false

  • Parameters

    • encodings: string[]

    Returns string | false

  • acceptsLanguages(): string[]
  • acceptsLanguages(...langs: string[]): string | false
  • acceptsLanguages(langs: string[]): string | false
  • -======= -

    Returns string[]

  • Parameters

    • Rest ...encodings: string[]

    Returns string | false

  • Parameters

    • encodings: string[]

    Returns string | false

  • acceptsLanguages(): string[]
  • acceptsLanguages(...langs: string[]): string | false
  • acceptsLanguages(langs: string[]): string | false
  • ->>>>>>> 13.0 -

    Return accepted languages or best fit based on langs.

    -

    Given Accept-Language: en;q=0.8, es, pt -an array sorted by quality is returned:

    -
    ['es', 'pt', 'en']
    -
    -<<<<<<< HEAD -

    Returns string[]

  • Parameters

    • Rest ...langs: string[]

    Returns string | false

  • Parameters

    • langs: string[]

    Returns string | false

  • append(field: string, val: string | string[]): void
  • -======= -

    Returns string[]

  • Parameters

    • Rest ...langs: string[]

    Returns string | false

  • Parameters

    • langs: string[]

    Returns string | false

  • append(field: string, val: string | string[]): void
  • ->>>>>>> 13.0 -

    Append additional header field with value val.

    -

    Examples:

    -
    this.append('Link', ['<http://localhost/>', '<http://localhost:3000/>']);
    this.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly');
    this.append('Warning', '199 Miscellaneous warning'); -
    -

    Parameters

    • field: string
    • val: string | string[]

    Returns void

  • attachment(filename?: string, options?: Options): void
  • -

    Set Content-Disposition to "attachment" to signal the client to prompt for download. -Optionally specify the filename of the download and some options.

    -

    Parameters

    • Optional filename: string
    • Optional options: Options

    Returns void

  • flushHeaders(): void
  • -

    Flush any set headers, and begin the body

    -

    Returns void

  • get(field: string): string
  • -

    Return request header. If the header is not set, will return an empty -string.

    -

    The Referrer header field is special-cased, both Referrer and -Referer are interchangeable.

    -

    Examples:

    -
    this.get('Content-Type');
    // => "text/plain"

    this.get('content-type');
    // => "text/plain"

    this.get('Something');
    // => '' -
    -

    Parameters

    • field: string

    Returns string

  • inspect(): any
  • -

    util.inspect() implementation, which -just returns the JSON output.

    -<<<<<<< HEAD -

    Returns any

  • is(...types: string[]): null | string | false
  • is(types: string[]): null | string | false
  • -======= -

    Returns any

  • is(...types: string[]): null | string | false
  • is(types: string[]): null | string | false
  • ->>>>>>> 13.0 -

    Check if the incoming request contains the "Content-Type" -header field, and it contains any of the give mime types. -If there is no request body, null is returned. -If there is no content type, false is returned. -Otherwise, it returns the first type that matches.

    -

    Examples:

    -
    // With Content-Type: text/html; charset=utf-8
    this.is('html'); // => 'html'
    this.is('text/html'); // => 'text/html'
    this.is('text/*', 'application/json'); // => 'text/html'

    // When Content-Type is application/json
    this.is('json', 'urlencoded'); // => 'json'
    this.is('application/json'); // => 'application/json'
    this.is('html', 'application/*'); // => 'application/json'

    this.is('html'); // => false -
    -<<<<<<< HEAD -

    Parameters

    • Rest ...types: string[]

    Returns null | string | false

  • Parameters

    • types: string[]

    Returns null | string | false

  • onerror(err: Error): void
  • -======= -

    Parameters

    • Rest ...types: string[]

    Returns null | string | false

  • Parameters

    • types: string[]

    Returns null | string | false

  • onerror(err: Error): void
  • ->>>>>>> 13.0 -

    Default error handling.

    -

    Parameters

    • err: Error

    Returns void

  • redirect(url: string, alt?: string): void
  • -

    Perform a 302 redirect to url.

    -

    The string "back" is special-cased -to provide Referrer support, when Referrer -is not present alt or "/" is used.

    -

    Examples:

    -

    this.redirect('back'); - this.redirect('back', '/index.html'); - this.redirect('/login'); - this.redirect('http://google.com');

    -

    Parameters

    • url: string
    • Optional alt: string

    Returns void

  • remove(field: string): void
  • -

    Remove header field.

    -

    Parameters

    • field: string

    Returns void

  • set(field: {}): void
  • set(field: string, val: string | string[]): void
  • -

    Set header field to val, or pass -an object of header fields.

    -

    Examples:

    -

    this.set('Foo', ['bar', 'baz']); - this.set('Accept', 'application/json'); - this.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });

    -

    Parameters

    • field: {}
      • [key: string]: string | string[]

    Returns void

  • Parameters

    • field: string
    • val: string | string[]

    Returns void

  • throw(message: string, code?: number, properties?: {}): never
  • throw(status: number): never
  • throw(...properties: (string | number | {})[]): never
  • -

    Throw an error with msg and optional status -defaulting to 500. Note that these are user-level -errors, and the message may be exposed to the client.

    -

    this.throw(403) - this.throw('name required', 400) - this.throw(400, 'name required') - this.throw('something exploded') - this.throw(new Error('invalid'), 400); - this.throw(400, new Error('invalid'));

    -

    See: https://github.com/jshttp/http-errors

    -

    Parameters

    • message: string
    • Optional code: number
    • Optional properties: {}

      Returns never

    • Parameters

      • status: number

      Returns never

    • Parameters

      • Rest ...properties: (string | number | {})[]

      Returns never

    • toJSON(): any
    • -

      Return JSON representation.

      -

      Here we explicitly invoke .toJSON() on each -object, as iteration will otherwise fail due -to the getters and cause utilities such as -clone() to fail.

      -

      Returns any

    • vary(field: string): void
    • -

      Vary on field.

      -

      Parameters

      • field: string

      Returns void

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Interface
    • Property
    • Class
    • Class with type parameter

    Settings

    Theme

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/framework_loopback.SessionContext.html b/docs/interfaces/framework_loopback.SessionContext.html deleted file mode 100644 index 4fd3e15fd..000000000 --- a/docs/interfaces/framework_loopback.SessionContext.html +++ /dev/null @@ -1,431 +0,0 @@ -SessionContext | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Hierarchy

    • MiddlewareContext
      • SessionContext

    Index

    Properties

    _debug: Debugger
    -

    A debug function which can be overridden by subclasses.

    -
    example
    import debugFactory from 'debug';
    const debug = debugFactory('loopback:context:application');
    export class Application extends Context {
    super('application');
    this._debug = debug;
    } -
    -
    _parent?: Context
    -

    Parent context

    -
    configResolver: ConfigurationResolver
    -

    Configuration resolver

    -
    name: string
    -

    Name of the context

    -
    registry: Map<string, Binding<any>>
    -

    Key to binding map as the internal registry

    -
    request: Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>
    response: Response<any, Record<string, any>>
    responseFinished: boolean
    -

    A flag to tell if the response is finished.

    -
    scope: BindingScope
    -

    Scope for binding resolution

    -<<<<<<< HEAD -
    subscriptionManager: ContextSubscriptionManager
    -======= -
    subscriptionManager: ContextSubscriptionManager
    ->>>>>>> 13.0 -

    Manager for observer subscriptions

    -
    tagIndexer: ContextTagIndexer
    -

    Indexer for bindings by tag

    -

    Accessors

    • get parent(): undefined | Context
    • internal

      Getter for ContextSubscriptionManager

      -

      Returns undefined | Context

    Methods

    • _findByTagIndex<ValueType>(tag: RegExp | BindingTag): Readonly<Binding<ValueType>>[]
    • -

      Find bindings by tag leveraging indexes

      -<<<<<<< HEAD -

      Type parameters

      • ValueType = any

      Parameters

      • tag: string | RegExp | Record<string, any>
        -======= -

        Type parameters

        • ValueType = any

        Parameters

        • tag: RegExp | BindingTag
          ->>>>>>> 13.0 -

          Tag name pattern or name/value pairs

          -

        Returns Readonly<Binding<ValueType>>[]

    • _mergeWithParent<ValueType>(childList: Readonly<Binding<ValueType>>[], parentList?: Readonly<Binding<ValueType>>[]): Readonly<Binding<ValueType>>[]
    • Type parameters

      • ValueType

      Parameters

      • childList: Readonly<Binding<ValueType>>[]
      • Optional parentList: Readonly<Binding<ValueType>>[]

      Returns Readonly<Binding<ValueType>>[]

    • -

      Add a binding to the context. If a locked binding already exists with the -same key, an error will be thrown.

      -

      Parameters

      • binding: Binding<unknown>
        -

        The configured binding to be added

        -

      Returns SessionContext

    • addListener(eventName: string | symbol, listener: (...args: any[]) => void): SessionContext
    • -

      Alias for emitter.on(eventName, listener).

      -
      since

      v0.1.26

      -

      Parameters

      • eventName: string | symbol
      • listener: (...args: any[]) => void
          • (...args: any[]): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns SessionContext

    • bind<ValueType>(key: BindingAddress<ValueType>): Binding<ValueType>
    • -

      Create a binding with the given key in the context. If a locked binding -already exists with the same key, an error will be thrown.

      -

      Type parameters

      • ValueType = any

      Parameters

      • key: BindingAddress<ValueType>
        -

        Binding key

        -

      Returns Binding<ValueType>

    • close(): void
    • -

      Close the context: clear observers, stop notifications, and remove event -listeners from its parent context.

      -
      remarks

      This method MUST be called to avoid memory leaks once a context object is -no longer needed and should be recycled. An example is the RequestContext, -which is created per request.

      -

      Returns void

    • configure<ConfigValueType>(key?: BindingAddress<unknown>): Binding<ConfigValueType>
    • -

      Create a corresponding binding for configuration of the target bound by -the given key in the context.

      -

      For example, ctx.configure('controllers.MyController').to({x: 1}) will -create binding controllers.MyController:$config with value {x: 1}.

      -<<<<<<< HEAD -

      Type parameters

      • ConfigValueType = any

      Parameters

      • Optional key: string | BindingKey<unknown>
        -======= -

        Type parameters

        • ConfigValueType = any

        Parameters

        • Optional key: BindingAddress<unknown>
          ->>>>>>> 13.0 -

          The key for the binding to be configured

          -

        Returns Binding<ConfigValueType>

    • contains(key: BindingAddress<unknown>): boolean
    • -

      Check if a binding exists with the given key in the local context without -delegating to the parent context

      -

      Parameters

      • key: BindingAddress<unknown>
        -

        Binding key

        -

      Returns boolean

    • createView<T>(filter: BindingFilter, comparator?: BindingComparator, options?: Omit<ResolutionOptions, "session">): ContextView<T>
    • -

      Create a view of the context chain with the given binding filter

      -

      Type parameters

      • T = unknown

      Parameters

      • filter: BindingFilter
        -

        A function to match bindings

        -
      • Optional comparator: BindingComparator
        -

        A function to sort matched bindings

        -
      • Optional options: Omit<ResolutionOptions, "session">
        -

        Resolution options

        -

      Returns ContextView<T>

    • debug(...args: unknown[]): void
    • -

      Wrap the debug statement so that it always print out the context name -as the prefix

      -

      Parameters

      • Rest ...args: unknown[]
        -

        Arguments for the debug

        -

      Returns void

    • emit(eventName: string | symbol, ...args: any[]): boolean
    • -

      Synchronously calls each of the listeners registered for the event namedeventName, in the order they were registered, passing the supplied arguments -to each.

      -

      Returns true if the event had listeners, false otherwise.

      -
      const EventEmitter = require('events');
      const myEmitter = new EventEmitter();

      // First listener
      myEmitter.on('event', function firstListener() {
      console.log('Helloooo! first listener');
      });
      // Second listener
      myEmitter.on('event', function secondListener(arg1, arg2) {
      console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
      });
      // Third listener
      myEmitter.on('event', function thirdListener(...args) {
      const parameters = args.join(', ');
      console.log(`event with parameters ${parameters} in third listener`);
      });

      console.log(myEmitter.listeners('event'));

      myEmitter.emit('event', 1, 2, 3, 4, 5);

      // Prints:
      // [
      // [Function: firstListener],
      // [Function: secondListener],
      // [Function: thirdListener]
      // ]
      // Helloooo! first listener
      // event with parameters 1, 2 in second listener
      // event with parameters 1, 2, 3, 4, 5 in third listener -
      -
      since

      v0.1.26

      -

      Parameters

      • eventName: string | symbol
      • Rest ...args: any[]

      Returns boolean

    • emitError(err: unknown): void
    • -

      Emit an error event

      -

      Parameters

      • err: unknown
        -

        Error

        -

      Returns void

    • emitEvent<T>(type: string, event: T): void
    • -

      A strongly-typed method to emit context events

      -

      Type parameters

      • T: ContextEvent

      Parameters

      • type: string
        -

        Event type

        -
      • event: T
        -

        Context event

        -

      Returns void

    • eventNames(): (string | symbol)[]
    • -

      Returns an array listing the events for which the emitter has registered -listeners. The values in the array are strings or Symbols.

      -
      const EventEmitter = require('events');
      const myEE = new EventEmitter();
      myEE.on('foo', () => {});
      myEE.on('bar', () => {});

      const sym = Symbol('symbol');
      myEE.on(sym, () => {});

      console.log(myEE.eventNames());
      // Prints: [ 'foo', 'bar', Symbol(symbol) ] -
      -
      since

      v6.0.0

      -

      Returns (string | symbol)[]

    • find<ValueType>(pattern?: string | RegExp | BindingFilter): Readonly<Binding<ValueType>>[]
    • -

      Find bindings using a key pattern or filter function

      -

      Type parameters

      • ValueType = any

      Parameters

      • Optional pattern: string | RegExp | BindingFilter
        -

        A filter function, a regexp or a wildcard pattern with -optional * and ?. Find returns such bindings where the key matches -the provided pattern.

        -

        For a wildcard:

        -
          -
        • * matches zero or more characters except . and :
        • -
        • ? matches exactly one character except . and :
        • -
        -

        For a filter function:

        -
          -
        • return true to include the binding in the results
        • -
        • return false to exclude it.
        • -
        -

      Returns Readonly<Binding<ValueType>>[]

    • findByTag<ValueType>(tagFilter: RegExp | BindingTag): Readonly<Binding<ValueType>>[]
    • -

      Find bindings using the tag filter. If the filter matches one of the -binding tags, the binding is included.

      -<<<<<<< HEAD -

      Type parameters

      • ValueType = any

      Parameters

      • tagFilter: string | RegExp | Record<string, any>
        -======= -

        Type parameters

        • ValueType = any

        Parameters

        • tagFilter: RegExp | BindingTag
          ->>>>>>> 13.0 -

          A filter for tags. It can be in one of the following -forms:

          -
            -
          • A regular expression, such as /controller/
          • -
          • A wildcard pattern string with optional * and ?, such as 'con*' -For a wildcard:
              -
            • * matches zero or more characters except . and :
            • -
            • ? matches exactly one character except . and :
            • -
            -
          • -
          • An object containing tag name/value pairs, such as -{name: 'my-controller'}
          • -
          -

        Returns Readonly<Binding<ValueType>>[]

    • findOrCreateBinding<T>(key: BindingAddress<T>, policy?: BindingCreationPolicy): Binding<T>
    • -

      Find or create a binding for the given key

      -

      Type parameters

      • T

      Parameters

      • key: BindingAddress<T>
        -

        Binding address

        -
      • Optional policy: BindingCreationPolicy
        -

        Binding creation policy

        -

      Returns Binding<T>

    • get<ValueType>(keyWithPath: BindingAddress<ValueType>, session?: ResolutionSession): Promise<ValueType>
    • get<ValueType>(keyWithPath: BindingAddress<ValueType>, options: ResolutionOptions): Promise<undefined | ValueType>
    • -

      Get the value bound to the given key, throw an error when no value is -bound for the given key.

      -
      example
      // get the value bound to "application.instance"
      const app = await ctx.get<Application>('application.instance');

      // get "rest" property from the value bound to "config"
      const config = await ctx.get<RestComponentConfig>('config#rest');

      // get "a" property of "numbers" property from the value bound to "data"
      ctx.bind('data').to({numbers: {a: 1, b: 2}, port: 3000});
      const a = await ctx.get<number>('data#numbers.a'); -
      -

      Type parameters

      • ValueType

      Parameters

      • keyWithPath: BindingAddress<ValueType>
        -

        The binding key, optionally suffixed with a path to the - (deeply) nested property to retrieve.

        -
      • Optional session: ResolutionSession
        -

        Optional session for resolution (accepted for backward -compatibility)

        -

      Returns Promise<ValueType>

      A promise of the bound value.

      -
    • -

      Get the value bound to the given key, optionally return a (deep) property -of the bound value.

      -
      example
      // get "rest" property from the value bound to "config"
      // use `undefined` when no config is provided
      const config = await ctx.get<RestComponentConfig>('config#rest', {
      optional: true
      }); -
      -

      Type parameters

      • ValueType

      Parameters

      • keyWithPath: BindingAddress<ValueType>
        -

        The binding key, optionally suffixed with a path to the - (deeply) nested property to retrieve.

        -
      • options: ResolutionOptions
        -

        Options for resolution.

        -

      Returns Promise<undefined | ValueType>

      A promise of the bound value, or a promise of undefined when -the optional binding is not found.

      -<<<<<<< HEAD -
    • getBinding<ValueType>(key: BindingAddress<ValueType>): Binding<ValueType>
    • getBinding<ValueType>(key: BindingAddress<ValueType>, options?: { optional?: false | true }): undefined | Binding<ValueType>
    • -======= -
    • getBinding<ValueType>(key: BindingAddress<ValueType>): Binding<ValueType>
    • getBinding<ValueType>(key: BindingAddress<ValueType>, options?: { optional?: boolean }): undefined | Binding<ValueType>
    • ->>>>>>> 13.0 -

      Look up a binding by key in the context and its ancestors. If no matching -binding is found, an error will be thrown.

      -

      Type parameters

      • ValueType = any

      Parameters

      • key: BindingAddress<ValueType>
        -

        Binding key

        -

      Returns Binding<ValueType>

    • -

      Look up a binding by key in the context and its ancestors. If no matching -binding is found and options.optional is not set to true, an error will -be thrown.

      -

      Type parameters

      • ValueType

      Parameters

      • key: BindingAddress<ValueType>
        -

        Binding key

        -<<<<<<< HEAD -
      • Optional options: { optional?: false | true }
        -

        Options to control if the binding is optional. If -options.optional is set to true, the method will return undefined -instead of throwing an error if the binding key is not found.

        -
        • Optional optional?: false | true

      Returns undefined | Binding<ValueType>

    • getConfig<ConfigValueType>(key: BindingAddress<unknown>, propertyPath?: string, resolutionOptions?: ResolutionOptions): Promise<undefined | ConfigValueType>
    • -======= -
    • Optional options: { optional?: boolean }
      -

      Options to control if the binding is optional. If -options.optional is set to true, the method will return undefined -instead of throwing an error if the binding key is not found.

      -
      • Optional optional?: boolean

    Returns undefined | Binding<ValueType>

    • getConfig<ConfigValueType>(key: BindingAddress<unknown>, propertyPath?: string, resolutionOptions?: ResolutionOptions): Promise<undefined | ConfigValueType>
    • ->>>>>>> 13.0 -

      Resolve configuration for the binding by key

      -

      Type parameters

      • ConfigValueType

      Parameters

      • key: BindingAddress<unknown>
        -

        Binding key

        -
      • Optional propertyPath: string
        -

        Property path for the option. For example, x.y -requests for <config>.x.y. If not set, the <config> object will be -returned.

        -
      • Optional resolutionOptions: ResolutionOptions
        -

        Options for the resolution.

        -

      Returns Promise<undefined | ConfigValueType>

    • getConfigAsValueOrPromise<ConfigValueType>(key: BindingAddress<unknown>, propertyPath?: string, resolutionOptions?: ResolutionOptions): ValueOrPromise<undefined | ConfigValueType>
    • -

      Get the value or promise of configuration for a given binding by key

      -

      Type parameters

      • ConfigValueType

      Parameters

      • key: BindingAddress<unknown>
        -

        Binding key

        -
      • Optional propertyPath: string
        -

        Property path for the option. For example, x.y -requests for <config>.x.y. If not set, the <config> object will be -returned.

        -
      • Optional resolutionOptions: ResolutionOptions
        -

        Options for the resolution.

        -
          -
        • optional: if not set or set to true, undefined will be returned if -no corresponding value is found. Otherwise, an error will be thrown.
        • -
        -

      Returns ValueOrPromise<undefined | ConfigValueType>

    • getConfigSync<ConfigValueType>(key: BindingAddress<unknown>, propertyPath?: string, resolutionOptions?: ResolutionOptions): undefined | ConfigValueType
    • -

      Resolve configuration synchronously for the binding by key

      -

      Type parameters

      • ConfigValueType

      Parameters

      • key: BindingAddress<unknown>
        -

        Binding key

        -
      • Optional propertyPath: string
        -

        Property path for the option. For example, x.y -requests for config.x.y. If not set, the config object will be -returned.

        -
      • Optional resolutionOptions: ResolutionOptions
        -

        Options for the resolution.

        -

      Returns undefined | ConfigValueType

    • getDebugNamespace(): string
    • -

      Get the debug namespace for the context class. Subclasses can override -this method to supply its own namespace.

      -
      example
      export class Application extends Context {
      super('application');
      }

      protected getDebugNamespace() {
      return 'loopback:context:application';
      } -
      -

      Returns string

    • getMaxListeners(): number
    • -

      Returns the current max listener value for the EventEmitter which is either -set by emitter.setMaxListeners(n) or defaults to {@link defaultMaxListeners}.

      -
      since

      v1.0.0

      -

      Returns number

    • getOwnerContext(keyOrBinding: BindingAddress<unknown> | Readonly<Binding<unknown>>): undefined | Context
    • -

      Get the owning context for a binding or its key

      -

      Parameters

      • keyOrBinding: BindingAddress<unknown> | Readonly<Binding<unknown>>
        -

        Binding object or key

        -

      Returns undefined | Context

    • getResolutionContext(binding: Readonly<Binding<unknown>>): undefined | Context
    • -

      Locate the resolution context for the given binding. Only bindings in the -resolution context and its ancestors are visible as dependencies to resolve -the given binding

      -

      Parameters

      • binding: Readonly<Binding<unknown>>
        -

        Binding object

        -

      Returns undefined | Context

    • getScopedContext(scope: APPLICATION | SERVER | REQUEST): undefined | Context
    • -

      Get the context matching the scope

      -

      Parameters

      • scope: APPLICATION | SERVER | REQUEST
        -

        Binding scope

        -

      Returns undefined | Context

    • getSync<ValueType>(keyWithPath: BindingAddress<ValueType>, session?: ResolutionSession): ValueType
    • getSync<ValueType>(keyWithPath: BindingAddress<ValueType>, options?: ResolutionOptions): undefined | ValueType
    • -

      Get the synchronous value bound to the given key, optionally -return a (deep) property of the bound value.

      -

      This method throws an error if the bound value requires async computation -(returns a promise). You should never rely on sync bindings in production -code.

      -
      example
      // get the value bound to "application.instance"
      const app = ctx.getSync<Application>('application.instance');

      // get "rest" property from the value bound to "config"
      const config = await ctx.getSync<RestComponentConfig>('config#rest'); -
      -

      Type parameters

      • ValueType

      Parameters

      • keyWithPath: BindingAddress<ValueType>
        -

        The binding key, optionally suffixed with a path to the - (deeply) nested property to retrieve.

        -
      • Optional session: ResolutionSession
        -

        Session for resolution (accepted for backward compatibility)

        -

      Returns ValueType

      A promise of the bound value.

      -
    • -

      Get the synchronous value bound to the given key, optionally -return a (deep) property of the bound value.

      -

      This method throws an error if the bound value requires async computation -(returns a promise). You should never rely on sync bindings in production -code.

      -
      example
      // get "rest" property from the value bound to "config"
      // use "undefined" when no config is provided
      const config = await ctx.getSync<RestComponentConfig>('config#rest', {
      optional: true
      }); -
      -

      Type parameters

      • ValueType

      Parameters

      • keyWithPath: BindingAddress<ValueType>
        -

        The binding key, optionally suffixed with a path to the - (deeply) nested property to retrieve.

        -
      • Optional options: ResolutionOptions
        -

        Options for resolution.

        -

      Returns undefined | ValueType

      The bound value, or undefined when an optional binding is not found.

      -
    • getValueOrPromise<ValueType>(keyWithPath: BindingAddress<ValueType>, optionsOrSession?: ResolutionOptionsOrSession): ValueOrPromise<undefined | ValueType>
    • -

      Get the value bound to the given key.

      -

      This is an internal version that preserves the dual sync/async result -of Binding#getValue(). Users should use get() or getSync() instead.

      -
      example
      // get the value bound to "application.instance"
      ctx.getValueOrPromise<Application>('application.instance');

      // get "rest" property from the value bound to "config"
      ctx.getValueOrPromise<RestComponentConfig>('config#rest');

      // get "a" property of "numbers" property from the value bound to "data"
      ctx.bind('data').to({numbers: {a: 1, b: 2}, port: 3000});
      ctx.getValueOrPromise<number>('data#numbers.a'); -
      -
      internal

      Type parameters

      • ValueType

      Parameters

      • keyWithPath: BindingAddress<ValueType>
        -

        The binding key, optionally suffixed with a path to the - (deeply) nested property to retrieve.

        -
      • Optional optionsOrSession: ResolutionOptionsOrSession
        -

        Options for resolution or a session

        -

      Returns ValueOrPromise<undefined | ValueType>

      The bound value or a promise of the bound value, depending - on how the binding is configured.

      -
    • inspect(options?: ContextInspectOptions): JSONObject
    • -

      Inspect the context and dump out a JSON object representing the context -hierarchy

      -

      Parameters

      • Optional options: ContextInspectOptions
        -

        Options for inspect

        -

      Returns JSONObject

    • isBound(key: BindingAddress<unknown>): boolean
    • -

      Check if a key is bound in the context or its ancestors

      -

      Parameters

      • key: BindingAddress<unknown>
        -

        Binding key

        -

      Returns boolean

    • isSubscribed(observer: ContextObserver): boolean
    • -

      Check if an observer is subscribed to this context

      -

      Parameters

      • observer: ContextObserver
        -

        Context observer

        -

      Returns boolean

    • isVisibleTo(ctx: Context): boolean
    • -

      Check if this context is visible (same or ancestor) to the given one

      -

      Parameters

      • ctx: Context
        -

        Another context object

        -

      Returns boolean

    • listenerCount(eventName: string | symbol): number
    • -

      Returns the number of listeners listening to the event named eventName.

      -
      since

      v3.2.0

      -

      Parameters

      • eventName: string | symbol
        -

        The name of the event being listened for

        -

      Returns number

    • listeners(eventName: string | symbol): Function[]
    • -

      Returns a copy of the array of listeners for the event named eventName.

      -
      server.on('connection', (stream) => {
      console.log('someone connected!');
      });
      console.log(util.inspect(server.listeners('connection')));
      // Prints: [ [Function] ] -
      -
      since

      v0.1.26

      -

      Parameters

      • eventName: string | symbol

      Returns Function[]

    • off(eventName: string | symbol, listener: (...args: any[]) => void): SessionContext
    • -

      Alias for emitter.removeListener().

      -
      since

      v10.0.0

      -

      Parameters

      • eventName: string | symbol
      • listener: (...args: any[]) => void
          • (...args: any[]): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns SessionContext

    • on(eventName: "bind" | "unbind", listener: ContextEventListener): SessionContext
    • on(event: string | symbol, listener: (...args: any[]) => void): SessionContext
    • -

      The "bind" event is emitted when a new binding is added to the context. -The "unbind" event is emitted when an existing binding is removed.

      -

      Parameters

      • eventName: "bind" | "unbind"
        -

        The name of the event - always bind or unbind.

        -
      • listener: ContextEventListener
        -

        The listener function to call when the event is emitted.

        -

      Returns SessionContext

    • Parameters

      • event: string | symbol
      • listener: (...args: any[]) => void
          • (...args: any[]): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns SessionContext

    • once(eventName: "bind" | "unbind", listener: ContextEventListener): SessionContext
    • once(event: string | symbol, listener: (...args: any[]) => void): SessionContext
    • -

      The "bind" event is emitted when a new binding is added to the context. -The "unbind" event is emitted when an existing binding is removed.

      -

      Parameters

      • eventName: "bind" | "unbind"
        -

        The name of the event - always bind or unbind.

        -
      • listener: ContextEventListener
        -

        The listener function to call when the event is emitted.

        -

      Returns SessionContext

    • Parameters

      • event: string | symbol
      • listener: (...args: any[]) => void
          • (...args: any[]): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns SessionContext

    • prependListener(eventName: string | symbol, listener: (...args: any[]) => void): SessionContext
    • -

      Adds the listener function to the beginning of the listeners array for the -event named eventName. No checks are made to see if the listener has -already been added. Multiple calls passing the same combination of eventNameand listener will result in the listener being added, and called, multiple -times.

      -
      server.prependListener('connection', (stream) => {
      console.log('someone connected!');
      }); -
      -

      Returns a reference to the EventEmitter, so that calls can be chained.

      -
      since

      v6.0.0

      -

      Parameters

      • eventName: string | symbol
        -

        The name of the event.

        -
      • listener: (...args: any[]) => void
        -

        The callback function

        -
          • (...args: any[]): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns SessionContext

    • prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): SessionContext
    • -

      Adds a one-timelistener function for the event named eventName to the_beginning_ of the listeners array. The next time eventName is triggered, this -listener is removed, and then invoked.

      -
      server.prependOnceListener('connection', (stream) => {
      console.log('Ah, we have our first user!');
      }); -
      -

      Returns a reference to the EventEmitter, so that calls can be chained.

      -
      since

      v6.0.0

      -

      Parameters

      • eventName: string | symbol
        -

        The name of the event.

        -
      • listener: (...args: any[]) => void
        -

        The callback function

        -
          • (...args: any[]): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns SessionContext

    • rawListeners(eventName: string | symbol): Function[]
    • -

      Returns a copy of the array of listeners for the event named eventName, -including any wrappers (such as those created by .once()).

      -
      const emitter = new EventEmitter();
      emitter.once('log', () => console.log('log once'));

      // Returns a new Array with a function `onceWrapper` which has a property
      // `listener` which contains the original listener bound above
      const listeners = emitter.rawListeners('log');
      const logFnWrapper = listeners[0];

      // Logs "log once" to the console and does not unbind the `once` event
      logFnWrapper.listener();

      // Logs "log once" to the console and removes the listener
      logFnWrapper();

      emitter.on('log', () => console.log('log persistently'));
      // Will return a new Array with a single function bound by `.on()` above
      const newListeners = emitter.rawListeners('log');

      // Logs "log persistently" twice
      newListeners[0]();
      emitter.emit('log'); -
      -
      since

      v9.4.0

      -

      Parameters

      • eventName: string | symbol

      Returns Function[]

    • -

      Removes all listeners, or those of the specified eventName.

      -

      It is bad practice to remove listeners added elsewhere in the code, -particularly when the EventEmitter instance was created by some other -component or module (e.g. sockets or file streams).

      -

      Returns a reference to the EventEmitter, so that calls can be chained.

      -
      since

      v0.1.26

      -

      Parameters

      • Optional event: string | symbol

      Returns SessionContext

    • removeListener(eventName: string | symbol, listener: (...args: any[]) => void): SessionContext
    • -

      Removes the specified listener from the listener array for the event namedeventName.

      -
      const callback = (stream) => {
      console.log('someone connected!');
      };
      server.on('connection', callback);
      // ...
      server.removeListener('connection', callback); -
      -

      removeListener() will remove, at most, one instance of a listener from the -listener array. If any single listener has been added multiple times to the -listener array for the specified eventName, then removeListener() must be -called multiple times to remove each instance.

      -

      Once an event is emitted, all listeners attached to it at the -time of emitting are called in order. This implies that anyremoveListener() or removeAllListeners() calls after emitting and_before_ the last listener finishes execution will -not remove them fromemit() in progress. Subsequent events behave as expected.

      -
      const myEmitter = new MyEmitter();

      const callbackA = () => {
      console.log('A');
      myEmitter.removeListener('event', callbackB);
      };

      const callbackB = () => {
      console.log('B');
      };

      myEmitter.on('event', callbackA);

      myEmitter.on('event', callbackB);

      // callbackA removes listener callbackB but it will still be called.
      // Internal listener array at time of emit [callbackA, callbackB]
      myEmitter.emit('event');
      // Prints:
      // A
      // B

      // callbackB is now removed.
      // Internal listener array [callbackA]
      myEmitter.emit('event');
      // Prints:
      // A -
      -

      Because listeners are managed using an internal array, calling this will -change the position indices of any listener registered after the listener -being removed. This will not impact the order in which listeners are called, -but it means that any copies of the listener array as returned by -the emitter.listeners() method will need to be recreated.

      -

      When a single function has been added as a handler multiple times for a single -event (as in the example below), removeListener() will remove the most -recently added instance. In the example the once('ping')listener is removed:

      -
      const ee = new EventEmitter();

      function pong() {
      console.log('pong');
      }

      ee.on('ping', pong);
      ee.once('ping', pong);
      ee.removeListener('ping', pong);

      ee.emit('ping');
      ee.emit('ping'); -
      -

      Returns a reference to the EventEmitter, so that calls can be chained.

      -
      since

      v0.1.26

      -

      Parameters

      • eventName: string | symbol
      • listener: (...args: any[]) => void
          • (...args: any[]): void
          • Parameters

            • Rest ...args: any[]

            Returns void

      Returns SessionContext

    • -

      By default EventEmitters will print a warning if more than 10 listeners are -added for a particular event. This is a useful default that helps finding -memory leaks. The emitter.setMaxListeners() method allows the limit to be -modified for this specific EventEmitter instance. The value can be set toInfinity (or 0) to indicate an unlimited number of listeners.

      -

      Returns a reference to the EventEmitter, so that calls can be chained.

      -
      since

      v0.3.5

      -

      Parameters

      • n: number

      Returns SessionContext

    • setupBindings(): void
    • Returns void

    • setupConfigurationResolverIfNeeded(): ConfigurationResolver
    • -

      Set up the configuration resolver if needed

      -

      Returns ConfigurationResolver

    • subscribe(observer: ContextEventObserver): Subscription
    • -

      Add a context event observer to the context

      -

      Parameters

      • observer: ContextEventObserver
        -

        Context observer instance or function

        -

      Returns Subscription

    • toJSON(): JSONObject
    • -

      Create a plain JSON object for the context

      -

      Returns JSONObject

    • unbind(key: BindingAddress<unknown>): boolean
    • -

      Unbind a binding from the context. No parent contexts will be checked.

      -
      remarks

      If you need to unbind a binding owned by a parent context, use the code -below:

      -
      const ownerCtx = ctx.getOwnerContext(key);
      return ownerCtx != null && ownerCtx.unbind(key); -
      -

      Parameters

      • key: BindingAddress<unknown>
        -

        Binding key

        -

      Returns boolean

      true if the binding key is found and removed from this context

      -
    • unsubscribe(observer: ContextEventObserver): boolean
    • -

      Remove the context event observer from the context

      -

      Parameters

      • observer: ContextEventObserver
        -

        Context event observer

        -

      Returns boolean

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Interface
    • Property
    • Class
    • Class with type parameter

    Settings

    Theme

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/recipe_session.SessionContainer.html b/docs/interfaces/recipe_session.SessionContainer.html deleted file mode 100644 index 00162888c..000000000 --- a/docs/interfaces/recipe_session.SessionContainer.html +++ /dev/null @@ -1,7 +0,0 @@ -<<<<<<< HEAD -SessionContainer | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Hierarchy

    • SessionContainer

    Index

    Methods

    • fetchAndSetClaim<T>(claim: SessionClaim<T>, userContext?: any): Promise<void>
    • getAccessToken(userContext?: any): string
    • getAccessTokenPayload(userContext?: any): any
    • getClaimValue<T>(claim: SessionClaim<T>, userContext?: any): Promise<undefined | T>
    • getExpiry(userContext?: any): Promise<number>
    • getHandle(userContext?: any): string
    • getSessionData(userContext?: any): Promise<any>
    • getTimeCreated(userContext?: any): Promise<number>
    • getUserId(userContext?: any): string
    • mergeIntoAccessTokenPayload(accessTokenPayloadUpdate: JSONObject, userContext?: any): Promise<void>
    • removeClaim(claim: SessionClaim<any>, userContext?: any): Promise<void>
    • revokeSession(userContext?: any): Promise<void>
    • setClaimValue<T>(claim: SessionClaim<T>, value: T, userContext?: any): Promise<void>
    • updateAccessTokenPayload(newAccessTokenPayload: any, userContext?: any): Promise<void>
    • deprecated

      Use mergeIntoAccessTokenPayload instead

      -

      Parameters

      • newAccessTokenPayload: any
      • Optional userContext: any

      Returns Promise<void>

    • updateSessionData(newSessionData: any, userContext?: any): Promise<any>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Interface
    • Method
    • Class
    • Class with type parameter

    Settings

    Theme

    Generated using TypeDoc

    -======= -SessionContainer | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Hierarchy

    • SessionContainer

    Index

    Methods

    • fetchAndSetClaim<T>(claim: SessionClaim<T>, userContext?: any): Promise<void>
    • getAccessToken(userContext?: any): string
    • getAccessTokenPayload(userContext?: any): any
    • getClaimValue<T>(claim: SessionClaim<T>, userContext?: any): Promise<undefined | T>
    • getExpiry(userContext?: any): Promise<number>
    • getHandle(userContext?: any): string
    • getSessionData(userContext?: any): Promise<any>
    • getTimeCreated(userContext?: any): Promise<number>
    • getUserId(userContext?: any): string
    • mergeIntoAccessTokenPayload(accessTokenPayloadUpdate: JSONObject, userContext?: any): Promise<void>
    • removeClaim(claim: SessionClaim<any>, userContext?: any): Promise<void>
    • revokeSession(userContext?: any): Promise<void>
    • setClaimValue<T>(claim: SessionClaim<T>, value: T, userContext?: any): Promise<void>
    • updateAccessTokenPayload(newAccessTokenPayload: any, userContext?: any): Promise<void>
    • deprecated

      Use mergeIntoAccessTokenPayload instead

      -

      Parameters

      • newAccessTokenPayload: any
      • Optional userContext: any

      Returns Promise<void>

    • updateSessionData(newSessionData: any, userContext?: any): Promise<any>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Interface
    • Method
    • Class
    • Class with type parameter

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/interfaces/recipe_session.VerifySessionOptions.html b/docs/interfaces/recipe_session.VerifySessionOptions.html deleted file mode 100644 index fbb52b6f6..000000000 --- a/docs/interfaces/recipe_session.VerifySessionOptions.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -VerifySessionOptions | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Interface
    • Property
    • Method
    • Class
    • Class with type parameter

    Settings

    Theme

    Generated using TypeDoc

    -======= -VerifySessionOptions | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Interface
    • Property
    • Method
    • Class
    • Class with type parameter

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/interfaces/recipe_usermetadata.JSONObject.html b/docs/interfaces/recipe_usermetadata.JSONObject.html deleted file mode 100644 index 8e8e88cbe..000000000 --- a/docs/interfaces/recipe_usermetadata.JSONObject.html +++ /dev/null @@ -1 +0,0 @@ -JSONObject | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules.html b/docs/modules.html deleted file mode 100644 index bec108aeb..000000000 --- a/docs/modules.html +++ /dev/null @@ -1 +0,0 @@ -supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    supertokens-node

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules/framework.html b/docs/modules/framework.html deleted file mode 100644 index 24b69d308..000000000 --- a/docs/modules/framework.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -framework | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -framework | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/framework_awsLambda.html b/docs/modules/framework_awsLambda.html deleted file mode 100644 index 1565b6459..000000000 --- a/docs/modules/framework_awsLambda.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -framework/awsLambda | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module framework/awsLambda

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -framework/awsLambda | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module framework/awsLambda

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/framework_express.html b/docs/modules/framework_express.html deleted file mode 100644 index f3918ed00..000000000 --- a/docs/modules/framework_express.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -framework/express | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module framework/express

    Index

    Functions

    • errorHandler(): (err: any, req: Request, res: Response, next: NextFunction) => Promise<void>
    • Returns (err: any, req: Request, res: Response, next: NextFunction) => Promise<void>

        • (err: any, req: Request, res: Response, next: NextFunction): Promise<void>
        • Parameters

          • err: any
          • req: Request
          • res: Response
          • next: NextFunction

          Returns Promise<void>

    • middleware(): (req: Request, res: Response, next: NextFunction) => Promise<void>
    • Returns (req: Request, res: Response, next: NextFunction) => Promise<void>

        • (req: Request, res: Response, next: NextFunction): Promise<void>
        • Parameters

          • req: Request
          • res: Response
          • next: NextFunction

          Returns Promise<void>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -framework/express | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module framework/express

    Index

    Functions

    • errorHandler(): (err: any, req: Request, res: Response, next: NextFunction) => Promise<void>
    • Returns (err: any, req: Request, res: Response, next: NextFunction) => Promise<void>

        • (err: any, req: Request, res: Response, next: NextFunction): Promise<void>
        • Parameters

          • err: any
          • req: Request
          • res: Response
          • next: NextFunction

          Returns Promise<void>

    • middleware(): (req: Request, res: Response, next: NextFunction) => Promise<void>
    • Returns (req: Request, res: Response, next: NextFunction) => Promise<void>

        • (req: Request, res: Response, next: NextFunction): Promise<void>
        • Parameters

          • req: Request
          • res: Response
          • next: NextFunction

          Returns Promise<void>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/framework_fastify.html b/docs/modules/framework_fastify.html deleted file mode 100644 index 83ac244d3..000000000 --- a/docs/modules/framework_fastify.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -framework/fastify | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module framework/fastify

    Index

    Functions

    • errorHandler(): (err: any, req: FastifyRequest<RouteGenericInterface, Server, IncomingMessage>, res: FastifyReply<Server, IncomingMessage, ServerResponse, RouteGenericInterface, unknown>) => Promise<void>
    • Returns (err: any, req: FastifyRequest<RouteGenericInterface, Server, IncomingMessage>, res: FastifyReply<Server, IncomingMessage, ServerResponse, RouteGenericInterface, unknown>) => Promise<void>

        • (err: any, req: FastifyRequest<RouteGenericInterface, Server, IncomingMessage>, res: FastifyReply<Server, IncomingMessage, ServerResponse, RouteGenericInterface, unknown>): Promise<void>
        • Parameters

          • err: any
          • req: FastifyRequest<RouteGenericInterface, Server, IncomingMessage>
          • res: FastifyReply<Server, IncomingMessage, ServerResponse, RouteGenericInterface, unknown>

          Returns Promise<void>

    • plugin(instance: FastifyInstance<Server, IncomingMessage, ServerResponse, FastifyLoggerInstance>, opts: Record<never, never>, done: (err?: Error) => void): void
    • Parameters

      • instance: FastifyInstance<Server, IncomingMessage, ServerResponse, FastifyLoggerInstance>
      • opts: Record<never, never>
      • done: (err?: Error) => void
          • (err?: Error): void
          • Parameters

            • Optional err: Error

            Returns void

      Returns void

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -framework/fastify | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module framework/fastify

    Index

    Functions

    • errorHandler(): (err: any, req: FastifyRequest<RouteGenericInterface, Server, IncomingMessage>, res: FastifyReply<Server, IncomingMessage, ServerResponse, RouteGenericInterface, unknown>) => Promise<void>
    • Returns (err: any, req: FastifyRequest<RouteGenericInterface, Server, IncomingMessage>, res: FastifyReply<Server, IncomingMessage, ServerResponse, RouteGenericInterface, unknown>) => Promise<void>

        • (err: any, req: FastifyRequest<RouteGenericInterface, Server, IncomingMessage>, res: FastifyReply<Server, IncomingMessage, ServerResponse, RouteGenericInterface, unknown>): Promise<void>
        • Parameters

          • err: any
          • req: FastifyRequest<RouteGenericInterface, Server, IncomingMessage>
          • res: FastifyReply<Server, IncomingMessage, ServerResponse, RouteGenericInterface, unknown>

          Returns Promise<void>

    • plugin(instance: FastifyInstance<Server, IncomingMessage, ServerResponse, FastifyLoggerInstance>, opts: Record<never, never>, done: (err?: Error) => void): void
    • Parameters

      • instance: FastifyInstance<Server, IncomingMessage, ServerResponse, FastifyLoggerInstance>
      • opts: Record<never, never>
      • done: (err?: Error) => void
          • (err?: Error): void
          • Parameters

            • Optional err: Error

            Returns void

      Returns void

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/framework_hapi.html b/docs/modules/framework_hapi.html deleted file mode 100644 index f25391703..000000000 --- a/docs/modules/framework_hapi.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -framework/hapi | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module framework/hapi

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -framework/hapi | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module framework/hapi

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/framework_koa.html b/docs/modules/framework_koa.html deleted file mode 100644 index 0738bb3b1..000000000 --- a/docs/modules/framework_koa.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -framework/koa | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module framework/koa

    Index

    Functions

    • middleware(): (ctx: Context, next: Next) => Promise<void>
    • Returns (ctx: Context, next: Next) => Promise<void>

        • (ctx: Context, next: Next): Promise<void>
        • Parameters

          • ctx: Context
          • next: Next

          Returns Promise<void>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -framework/koa | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module framework/koa

    Index

    Functions

    • middleware(): (ctx: Context, next: Next) => Promise<void>
    • Returns (ctx: Context, next: Next) => Promise<void>

        • (ctx: Context, next: Next): Promise<void>
        • Parameters

          • ctx: Context
          • next: Next

          Returns Promise<void>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/framework_loopback.html b/docs/modules/framework_loopback.html deleted file mode 100644 index 8e0e1c1a1..000000000 --- a/docs/modules/framework_loopback.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -framework/loopback | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module framework/loopback

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -framework/loopback | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module framework/loopback

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/index.html b/docs/modules/index.html deleted file mode 100644 index c7d16ed22..000000000 --- a/docs/modules/index.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -index | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Index

    Variables

    Error: typeof default = SuperTokensWrapper.Error

    Functions

    • createUserIdMapping(input: { externalUserId: string; externalUserIdInfo?: string; force?: false | true; superTokensUserId: string }): Promise<{ status: "OK" | "UNKNOWN_SUPERTOKENS_USER_ID_ERROR" } | { doesExternalUserIdExist: boolean; doesSuperTokensUserIdExist: boolean; status: "USER_ID_MAPPING_ALREADY_EXISTS_ERROR" }>
    • Parameters

      • input: { externalUserId: string; externalUserIdInfo?: string; force?: false | true; superTokensUserId: string }
        • externalUserId: string
        • Optional externalUserIdInfo?: string
        • Optional force?: false | true
        • superTokensUserId: string

      Returns Promise<{ status: "OK" | "UNKNOWN_SUPERTOKENS_USER_ID_ERROR" } | { doesExternalUserIdExist: boolean; doesSuperTokensUserIdExist: boolean; status: "USER_ID_MAPPING_ALREADY_EXISTS_ERROR" }>

    • deleteUser(userId: string): Promise<{ status: "OK" }>
    • deleteUserIdMapping(input: { force?: false | true; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }): Promise<{ didMappingExist: boolean; status: "OK" }>
    • Parameters

      • input: { force?: false | true; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }
        • Optional force?: false | true
        • userId: string
        • Optional userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"

      Returns Promise<{ didMappingExist: boolean; status: "OK" }>

    • getAllCORSHeaders(): string[]
    • getUserCount(includeRecipeIds?: string[]): Promise<number>
    • Parameters

      • Optional includeRecipeIds: string[]

      Returns Promise<number>

    • getUserIdMapping(input: { userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }): Promise<{ externalUserId: string; externalUserIdInfo: undefined | string; status: "OK"; superTokensUserId: string } | { status: "UNKNOWN_MAPPING_ERROR" }>
    • Parameters

      • input: { userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }
        • userId: string
        • Optional userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"

      Returns Promise<{ externalUserId: string; externalUserIdInfo: undefined | string; status: "OK"; superTokensUserId: string } | { status: "UNKNOWN_MAPPING_ERROR" }>

    • getUsersNewestFirst(input?: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }): Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>
    • Parameters

      • Optional input: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }
        • Optional includeRecipeIds?: string[]
        • Optional limit?: number
        • Optional paginationToken?: string

      Returns Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>

    • getUsersOldestFirst(input?: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }): Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>
    • Parameters

      • Optional input: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }
        • Optional includeRecipeIds?: string[]
        • Optional limit?: number
        • Optional paginationToken?: string

      Returns Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>

    • init(config: TypeInput): void
    • updateOrDeleteUserIdMappingInfo(input: { externalUserIdInfo?: string; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }): Promise<{ status: "OK" | "UNKNOWN_MAPPING_ERROR" }>
    • Parameters

      • input: { externalUserIdInfo?: string; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }
        • Optional externalUserIdInfo?: string
        • userId: string
        • Optional userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"

      Returns Promise<{ status: "OK" | "UNKNOWN_MAPPING_ERROR" }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -index | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Index

    Variables

    Error: typeof default = SuperTokensWrapper.Error

    Functions

    • createUserIdMapping(input: { externalUserId: string; externalUserIdInfo?: string; force?: boolean; superTokensUserId: string }): Promise<{ status: "OK" | "UNKNOWN_SUPERTOKENS_USER_ID_ERROR" } | { doesExternalUserIdExist: boolean; doesSuperTokensUserIdExist: boolean; status: "USER_ID_MAPPING_ALREADY_EXISTS_ERROR" }>
    • Parameters

      • input: { externalUserId: string; externalUserIdInfo?: string; force?: boolean; superTokensUserId: string }
        • externalUserId: string
        • Optional externalUserIdInfo?: string
        • Optional force?: boolean
        • superTokensUserId: string

      Returns Promise<{ status: "OK" | "UNKNOWN_SUPERTOKENS_USER_ID_ERROR" } | { doesExternalUserIdExist: boolean; doesSuperTokensUserIdExist: boolean; status: "USER_ID_MAPPING_ALREADY_EXISTS_ERROR" }>

    • deleteUser(userId: string): Promise<{ status: "OK" }>
    • deleteUserIdMapping(input: { force?: boolean; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }): Promise<{ didMappingExist: boolean; status: "OK" }>
    • Parameters

      • input: { force?: boolean; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }
        • Optional force?: boolean
        • userId: string
        • Optional userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"

      Returns Promise<{ didMappingExist: boolean; status: "OK" }>

    • getAllCORSHeaders(): string[]
    • getUserCount(includeRecipeIds?: string[]): Promise<number>
    • Parameters

      • Optional includeRecipeIds: string[]

      Returns Promise<number>

    • getUserIdMapping(input: { userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }): Promise<{ externalUserId: string; externalUserIdInfo: undefined | string; status: "OK"; superTokensUserId: string } | { status: "UNKNOWN_MAPPING_ERROR" }>
    • Parameters

      • input: { userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }
        • userId: string
        • Optional userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"

      Returns Promise<{ externalUserId: string; externalUserIdInfo: undefined | string; status: "OK"; superTokensUserId: string } | { status: "UNKNOWN_MAPPING_ERROR" }>

    • getUsersNewestFirst(input?: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }): Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>
    • Parameters

      • Optional input: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }
        • Optional includeRecipeIds?: string[]
        • Optional limit?: number
        • Optional paginationToken?: string

      Returns Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>

    • getUsersOldestFirst(input?: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }): Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>
    • Parameters

      • Optional input: { includeRecipeIds?: string[]; limit?: number; paginationToken?: string }
        • Optional includeRecipeIds?: string[]
        • Optional limit?: number
        • Optional paginationToken?: string

      Returns Promise<{ nextPaginationToken?: string; users: { recipeId: string; user: any }[] }>

    • init(config: TypeInput): void
    • updateOrDeleteUserIdMappingInfo(input: { externalUserIdInfo?: string; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }): Promise<{ status: "OK" | "UNKNOWN_MAPPING_ERROR" }>
    • Parameters

      • input: { externalUserIdInfo?: string; userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY" }
        • Optional externalUserIdInfo?: string
        • userId: string
        • Optional userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"

      Returns Promise<{ status: "OK" | "UNKNOWN_MAPPING_ERROR" }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/ingredients_emaildelivery.html b/docs/modules/ingredients_emaildelivery.html deleted file mode 100644 index 13e2b0062..000000000 --- a/docs/modules/ingredients_emaildelivery.html +++ /dev/null @@ -1 +0,0 @@ -ingredients/emaildelivery | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module ingredients/emaildelivery

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules/ingredients_smsdelivery.html b/docs/modules/ingredients_smsdelivery.html deleted file mode 100644 index bd7188521..000000000 --- a/docs/modules/ingredients_smsdelivery.html +++ /dev/null @@ -1 +0,0 @@ -ingredients/smsdelivery | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module ingredients/smsdelivery

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules/recipe_dashboard.html b/docs/modules/recipe_dashboard.html deleted file mode 100644 index 00697d499..000000000 --- a/docs/modules/recipe_dashboard.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -recipe/dashboard | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/dashboard

    Index

    Type aliases

    APIInterface: { dashboardGET: undefined | ((input: { options: APIOptions; userContext: any }) => Promise<string>) }

    Type declaration

    • dashboardGET: undefined | ((input: { options: APIOptions; userContext: any }) => Promise<string>)
    APIOptions: { appInfo: NormalisedAppinfo; config: TypeNormalisedInput; isInServerlessEnv: boolean; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse }

    Type declaration

    RecipeInterface: { getDashboardBundleLocation: any; shouldAllowAccess: any }

    Type declaration

    • getDashboardBundleLocation:function
      • getDashboardBundleLocation(input: { userContext: any }): Promise<string>
    • shouldAllowAccess:function
      • shouldAllowAccess(input: { config: TypeNormalisedInput; req: BaseRequest; userContext: any }): Promise<boolean>

    Functions

    • init(config: TypeInput): RecipeListFunction

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -recipe/dashboard | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/dashboard

    Index

    Type aliases

    APIInterface: { dashboardGET: undefined | ((input: { options: APIOptions; userContext: any }) => Promise<string>) }

    Type declaration

    • dashboardGET: undefined | ((input: { options: APIOptions; userContext: any }) => Promise<string>)
    APIOptions: { appInfo: NormalisedAppinfo; config: TypeNormalisedInput; isInServerlessEnv: boolean; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse }

    Type declaration

    RecipeInterface: { getDashboardBundleLocation: any; shouldAllowAccess: any }

    Type declaration

    • getDashboardBundleLocation:function
      • getDashboardBundleLocation(input: { userContext: any }): Promise<string>
    • shouldAllowAccess:function
      • shouldAllowAccess(input: { config: TypeNormalisedInput; req: BaseRequest; userContext: any }): Promise<boolean>

    Functions

    • init(config: TypeInput): RecipeListFunction

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/recipe_emailpassword.html b/docs/modules/recipe_emailpassword.html deleted file mode 100644 index 4dc000378..000000000 --- a/docs/modules/recipe_emailpassword.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -recipe/emailpassword | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/emailpassword

    Index

    Type aliases

    APIInterface: { emailExistsGET: undefined | ((input: { email: string; options: APIOptions; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>); generatePasswordResetTokenPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; userContext: any }) => Promise<{ status: "OK" } | GeneralErrorResponse>); passwordResetPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; token: string; userContext: any }) => Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" } | GeneralErrorResponse>); signInPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" } | GeneralErrorResponse>); signUpPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" } | GeneralErrorResponse>) }

    Type declaration

    • emailExistsGET: undefined | ((input: { email: string; options: APIOptions; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>)
    • generatePasswordResetTokenPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; userContext: any }) => Promise<{ status: "OK" } | GeneralErrorResponse>)
    • passwordResetPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; token: string; userContext: any }) => Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" } | GeneralErrorResponse>)
    • signInPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" } | GeneralErrorResponse>)
    • signUpPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" } | GeneralErrorResponse>)
    APIOptions: { appInfo: NormalisedAppinfo; config: TypeNormalisedInput; emailDelivery: default<TypeEmailPasswordEmailDeliveryInput>; isInServerlessEnv: boolean; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse }

    Type declaration

    RecipeInterface: { createResetPasswordToken: any; getUserByEmail: any; getUserById: any; resetPasswordUsingToken: any; signIn: any; signUp: any; updateEmailOrPassword: any }

    Type declaration

    • createResetPasswordToken:function
      • createResetPasswordToken(input: { userContext: any; userId: string }): Promise<{ status: "OK"; token: string } | { status: "UNKNOWN_USER_ID_ERROR" }>
      • Parameters

        • input: { userContext: any; userId: string }
          • userContext: any
          • userId: string

        Returns Promise<{ status: "OK"; token: string } | { status: "UNKNOWN_USER_ID_ERROR" }>

    • getUserByEmail:function
      • getUserByEmail(input: { email: string; userContext: any }): Promise<undefined | User>
    • getUserById:function
      • getUserById(input: { userContext: any; userId: string }): Promise<undefined | User>
    • resetPasswordUsingToken:function
      • resetPasswordUsingToken(input: { newPassword: string; token: string; userContext: any }): Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>
      • Parameters

        • input: { newPassword: string; token: string; userContext: any }
          • newPassword: string
          • token: string
          • userContext: any

        Returns Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>

    • signIn:function
      • signIn(input: { email: string; password: string; userContext: any }): Promise<{ status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>
      • Parameters

        • input: { email: string; password: string; userContext: any }
          • email: string
          • password: string
          • userContext: any

        Returns Promise<{ status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>

    • signUp:function
      • signUp(input: { email: string; password: string; userContext: any }): Promise<{ status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>
      • Parameters

        • input: { email: string; password: string; userContext: any }
          • email: string
          • password: string
          • userContext: any

        Returns Promise<{ status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>

    • updateEmailOrPassword:function
      • updateEmailOrPassword(input: { email?: string; password?: string; userContext: any; userId: string }): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" }>
      • Parameters

        • input: { email?: string; password?: string; userContext: any; userId: string }
          • Optional email?: string
          • Optional password?: string
          • userContext: any
          • userId: string

        Returns Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" }>

    User: { email: string; id: string; timeJoined: number }

    Type declaration

    • email: string
    • id: string
    • timeJoined: number

    Variables

    Error: typeof default = Wrapper.Error

    Functions

    • createResetPasswordToken(userId: string, userContext?: any): Promise<{ status: "OK"; token: string } | { status: "UNKNOWN_USER_ID_ERROR" }>
    • getUserByEmail(email: string, userContext?: any): Promise<undefined | User>
    • getUserById(userId: string, userContext?: any): Promise<undefined | User>
    • init(config?: TypeInput): RecipeListFunction
    • resetPasswordUsingToken(token: string, newPassword: string, userContext?: any): Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>
    • Parameters

      • token: string
      • newPassword: string
      • Optional userContext: any

      Returns Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>

    • sendEmail(input: TypeEmailPasswordPasswordResetEmailDeliveryInput & { userContext?: any }): Promise<void>
    • signIn(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>
    • signUp(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>
    • updateEmailOrPassword(input: { email?: string; password?: string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>
    • Parameters

      • input: { email?: string; password?: string; userContext?: any; userId: string }
        • Optional email?: string
        • Optional password?: string
        • Optional userContext?: any
        • userId: string

      Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -recipe/emailpassword | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/emailpassword

    Index

    Type aliases

    APIInterface: { emailExistsGET: undefined | ((input: { email: string; options: APIOptions; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>); generatePasswordResetTokenPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; userContext: any }) => Promise<{ status: "OK" } | GeneralErrorResponse>); passwordResetPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; token: string; userContext: any }) => Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" } | GeneralErrorResponse>); signInPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" } | GeneralErrorResponse>); signUpPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" } | GeneralErrorResponse>) }

    Type declaration

    • emailExistsGET: undefined | ((input: { email: string; options: APIOptions; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>)
    • generatePasswordResetTokenPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; userContext: any }) => Promise<{ status: "OK" } | GeneralErrorResponse>)
    • passwordResetPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; token: string; userContext: any }) => Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" } | GeneralErrorResponse>)
    • signInPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" } | GeneralErrorResponse>)
    • signUpPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: APIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" } | GeneralErrorResponse>)
    APIOptions: { appInfo: NormalisedAppinfo; config: TypeNormalisedInput; emailDelivery: default<TypeEmailPasswordEmailDeliveryInput>; isInServerlessEnv: boolean; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse }

    Type declaration

    RecipeInterface: { createResetPasswordToken: any; getUserByEmail: any; getUserById: any; resetPasswordUsingToken: any; signIn: any; signUp: any; updateEmailOrPassword: any }

    Type declaration

    • createResetPasswordToken:function
      • createResetPasswordToken(input: { userContext: any; userId: string }): Promise<{ status: "OK"; token: string } | { status: "UNKNOWN_USER_ID_ERROR" }>
      • Parameters

        • input: { userContext: any; userId: string }
          • userContext: any
          • userId: string

        Returns Promise<{ status: "OK"; token: string } | { status: "UNKNOWN_USER_ID_ERROR" }>

    • getUserByEmail:function
      • getUserByEmail(input: { email: string; userContext: any }): Promise<undefined | User>
    • getUserById:function
      • getUserById(input: { userContext: any; userId: string }): Promise<undefined | User>
    • resetPasswordUsingToken:function
      • resetPasswordUsingToken(input: { newPassword: string; token: string; userContext: any }): Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>
      • Parameters

        • input: { newPassword: string; token: string; userContext: any }
          • newPassword: string
          • token: string
          • userContext: any

        Returns Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>

    • signIn:function
      • signIn(input: { email: string; password: string; userContext: any }): Promise<{ status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>
      • Parameters

        • input: { email: string; password: string; userContext: any }
          • email: string
          • password: string
          • userContext: any

        Returns Promise<{ status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>

    • signUp:function
      • signUp(input: { email: string; password: string; userContext: any }): Promise<{ status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>
      • Parameters

        • input: { email: string; password: string; userContext: any }
          • email: string
          • password: string
          • userContext: any

        Returns Promise<{ status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>

    • updateEmailOrPassword:function
      • updateEmailOrPassword(input: { email?: string; password?: string; userContext: any; userId: string }): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" }>
      • Parameters

        • input: { email?: string; password?: string; userContext: any; userId: string }
          • Optional email?: string
          • Optional password?: string
          • userContext: any
          • userId: string

        Returns Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" }>

    User: { email: string; id: string; timeJoined: number }

    Type declaration

    • email: string
    • id: string
    • timeJoined: number

    Variables

    Error: typeof default = Wrapper.Error

    Functions

    • createResetPasswordToken(userId: string, userContext?: any): Promise<{ status: "OK"; token: string } | { status: "UNKNOWN_USER_ID_ERROR" }>
    • getUserByEmail(email: string, userContext?: any): Promise<undefined | User>
    • getUserById(userId: string, userContext?: any): Promise<undefined | User>
    • init(config?: TypeInput): RecipeListFunction
    • resetPasswordUsingToken(token: string, newPassword: string, userContext?: any): Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>
    • Parameters

      • token: string
      • newPassword: string
      • Optional userContext: any

      Returns Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>

    • sendEmail(input: TypeEmailPasswordPasswordResetEmailDeliveryInput & { userContext?: any }): Promise<void>
    • signIn(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>
    • signUp(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>
    • updateEmailOrPassword(input: { email?: string; password?: string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>
    • Parameters

      • input: { email?: string; password?: string; userContext?: any; userId: string }
        • Optional email?: string
        • Optional password?: string
        • Optional userContext?: any
        • userId: string

      Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/recipe_emailverification.html b/docs/modules/recipe_emailverification.html deleted file mode 100644 index a25e034a2..000000000 --- a/docs/modules/recipe_emailverification.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -recipe/emailverification | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/emailverification

    Index

    Type aliases

    APIInterface: { generateEmailVerifyTokenPOST: undefined | ((input: { options: APIOptions; session: SessionContainer; userContext: any }) => Promise<{ status: "EMAIL_ALREADY_VERIFIED_ERROR" | "OK" } | GeneralErrorResponse>); isEmailVerifiedGET: undefined | ((input: { options: APIOptions; session: SessionContainer; userContext: any }) => Promise<{ isVerified: boolean; status: "OK" } | GeneralErrorResponse>); verifyEmailPOST: undefined | ((input: { options: APIOptions; session?: SessionContainer; token: string; userContext: any }) => Promise<{ status: "OK"; user: User } | { status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR" } | GeneralErrorResponse>) }

    Type declaration

    • generateEmailVerifyTokenPOST: undefined | ((input: { options: APIOptions; session: SessionContainer; userContext: any }) => Promise<{ status: "EMAIL_ALREADY_VERIFIED_ERROR" | "OK" } | GeneralErrorResponse>)
    • isEmailVerifiedGET: undefined | ((input: { options: APIOptions; session: SessionContainer; userContext: any }) => Promise<{ isVerified: boolean; status: "OK" } | GeneralErrorResponse>)
    • verifyEmailPOST: undefined | ((input: { options: APIOptions; session?: SessionContainer; token: string; userContext: any }) => Promise<{ status: "OK"; user: User } | { status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR" } | GeneralErrorResponse>)
    APIOptions: { appInfo: NormalisedAppinfo; config: TypeNormalisedInput; emailDelivery: default<TypeEmailVerificationEmailDeliveryInput>; isInServerlessEnv: boolean; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse }

    Type declaration

    • appInfo: NormalisedAppinfo
    • config: TypeNormalisedInput
    • emailDelivery: default<TypeEmailVerificationEmailDeliveryInput>
    • isInServerlessEnv: boolean
    • recipeId: string
    • recipeImplementation: RecipeInterface
    • req: BaseRequest
    • res: BaseResponse
    RecipeInterface: { createEmailVerificationToken: any; isEmailVerified: any; revokeEmailVerificationTokens: any; unverifyEmail: any; verifyEmailUsingToken: any }

    Type declaration

    • createEmailVerificationToken:function
      • createEmailVerificationToken(input: { email: string; userContext: any; userId: string }): Promise<{ status: "OK"; token: string } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>
      • Parameters

        • input: { email: string; userContext: any; userId: string }
          • email: string
          • userContext: any
          • userId: string

        Returns Promise<{ status: "OK"; token: string } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>

    • isEmailVerified:function
      • isEmailVerified(input: { email: string; userContext: any; userId: string }): Promise<boolean>
    • revokeEmailVerificationTokens:function
      • revokeEmailVerificationTokens(input: { email: string; userContext: any; userId: string }): Promise<{ status: "OK" }>
    • unverifyEmail:function
      • unverifyEmail(input: { email: string; userContext: any; userId: string }): Promise<{ status: "OK" }>
    • verifyEmailUsingToken:function
      • verifyEmailUsingToken(input: { token: string; userContext: any }): Promise<{ status: "OK"; user: User } | { status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR" }>
      • Parameters

        • input: { token: string; userContext: any }
          • token: string
          • userContext: any

        Returns Promise<{ status: "OK"; user: User } | { status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR" }>

    User: { email: string; id: string }

    Type declaration

    • email: string
    • id: string

    Variables

    EmailVerificationClaim: EmailVerificationClaimClass = ...
    Error: typeof default = Wrapper.Error

    Functions

    • createEmailVerificationToken(userId: string, email?: string, userContext?: any): Promise<{ status: "OK"; token: string } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>
    • init(config: TypeInput): RecipeListFunction
    • isEmailVerified(userId: string, email?: string, userContext?: any): Promise<boolean>
    • revokeEmailVerificationTokens(userId: string, email?: string, userContext?: any): Promise<{ status: string }>
    • sendEmail(input: TypeEmailVerificationEmailDeliveryInput & { userContext?: any }): Promise<void>
    • unverifyEmail(userId: string, email?: string, userContext?: any): Promise<{ status: string }>
    • verifyEmailUsingToken(token: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR" }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -recipe/emailverification | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/emailverification

    Index

    Type aliases

    APIInterface: { generateEmailVerifyTokenPOST: undefined | ((input: { options: APIOptions; session: SessionContainer; userContext: any }) => Promise<{ status: "EMAIL_ALREADY_VERIFIED_ERROR" | "OK" } | GeneralErrorResponse>); isEmailVerifiedGET: undefined | ((input: { options: APIOptions; session: SessionContainer; userContext: any }) => Promise<{ isVerified: boolean; status: "OK" } | GeneralErrorResponse>); verifyEmailPOST: undefined | ((input: { options: APIOptions; session?: SessionContainer; token: string; userContext: any }) => Promise<{ status: "OK"; user: User } | { status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR" } | GeneralErrorResponse>) }

    Type declaration

    • generateEmailVerifyTokenPOST: undefined | ((input: { options: APIOptions; session: SessionContainer; userContext: any }) => Promise<{ status: "EMAIL_ALREADY_VERIFIED_ERROR" | "OK" } | GeneralErrorResponse>)
    • isEmailVerifiedGET: undefined | ((input: { options: APIOptions; session: SessionContainer; userContext: any }) => Promise<{ isVerified: boolean; status: "OK" } | GeneralErrorResponse>)
    • verifyEmailPOST: undefined | ((input: { options: APIOptions; session?: SessionContainer; token: string; userContext: any }) => Promise<{ status: "OK"; user: User } | { status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR" } | GeneralErrorResponse>)
    APIOptions: { appInfo: NormalisedAppinfo; config: TypeNormalisedInput; emailDelivery: default<TypeEmailVerificationEmailDeliveryInput>; isInServerlessEnv: boolean; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse }

    Type declaration

    • appInfo: NormalisedAppinfo
    • config: TypeNormalisedInput
    • emailDelivery: default<TypeEmailVerificationEmailDeliveryInput>
    • isInServerlessEnv: boolean
    • recipeId: string
    • recipeImplementation: RecipeInterface
    • req: BaseRequest
    • res: BaseResponse
    RecipeInterface: { createEmailVerificationToken: any; isEmailVerified: any; revokeEmailVerificationTokens: any; unverifyEmail: any; verifyEmailUsingToken: any }

    Type declaration

    • createEmailVerificationToken:function
      • createEmailVerificationToken(input: { email: string; userContext: any; userId: string }): Promise<{ status: "OK"; token: string } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>
      • Parameters

        • input: { email: string; userContext: any; userId: string }
          • email: string
          • userContext: any
          • userId: string

        Returns Promise<{ status: "OK"; token: string } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>

    • isEmailVerified:function
      • isEmailVerified(input: { email: string; userContext: any; userId: string }): Promise<boolean>
    • revokeEmailVerificationTokens:function
      • revokeEmailVerificationTokens(input: { email: string; userContext: any; userId: string }): Promise<{ status: "OK" }>
    • unverifyEmail:function
      • unverifyEmail(input: { email: string; userContext: any; userId: string }): Promise<{ status: "OK" }>
    • verifyEmailUsingToken:function
      • verifyEmailUsingToken(input: { token: string; userContext: any }): Promise<{ status: "OK"; user: User } | { status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR" }>
      • Parameters

        • input: { token: string; userContext: any }
          • token: string
          • userContext: any

        Returns Promise<{ status: "OK"; user: User } | { status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR" }>

    User: { email: string; id: string }

    Type declaration

    • email: string
    • id: string

    Variables

    EmailVerificationClaim: EmailVerificationClaimClass = ...
    Error: typeof default = Wrapper.Error

    Functions

    • createEmailVerificationToken(userId: string, email?: string, userContext?: any): Promise<{ status: "OK"; token: string } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>
    • init(config: TypeInput): RecipeListFunction
    • isEmailVerified(userId: string, email?: string, userContext?: any): Promise<boolean>
    • revokeEmailVerificationTokens(userId: string, email?: string, userContext?: any): Promise<{ status: string }>
    • sendEmail(input: TypeEmailVerificationEmailDeliveryInput & { userContext?: any }): Promise<void>
    • unverifyEmail(userId: string, email?: string, userContext?: any): Promise<{ status: string }>
    • verifyEmailUsingToken(token: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR" }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/recipe_jwt.html b/docs/modules/recipe_jwt.html deleted file mode 100644 index 7a4a7cfd1..000000000 --- a/docs/modules/recipe_jwt.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -recipe/jwt | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Index

    Type aliases

    APIInterface: { getJWKSGET: undefined | ((input: { options: APIOptions; userContext: any }) => Promise<{ keys: JsonWebKey[]; status: "OK" } | GeneralErrorResponse>) }

    Type declaration

    • getJWKSGET: undefined | ((input: { options: APIOptions; userContext: any }) => Promise<{ keys: JsonWebKey[]; status: "OK" } | GeneralErrorResponse>)
    APIOptions: { config: TypeNormalisedInput; isInServerlessEnv: boolean; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse }

    Type declaration

    JsonWebKey: { alg: string; e: string; kid: string; kty: string; n: string; use: string }

    Type declaration

    • alg: string
    • e: string
    • kid: string
    • kty: string
    • n: string
    • use: string
    RecipeInterface: { createJWT: any; getJWKS: any }

    Type declaration

    • createJWT:function
      • createJWT(input: { payload?: any; userContext: any; validitySeconds?: number }): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
      • Parameters

        • input: { payload?: any; userContext: any; validitySeconds?: number }
          • Optional payload?: any
          • userContext: any
          • Optional validitySeconds?: number

        Returns Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>

    • getJWKS:function
      • getJWKS(input: { userContext: any }): Promise<{ keys: JsonWebKey[]; status: "OK" }>

    Functions

    • createJWT(payload: any, validitySeconds?: number, userContext?: any): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
    • Parameters

      • payload: any
      • Optional validitySeconds: number
      • Optional userContext: any

      Returns Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>

    • getJWKS(userContext?: any): Promise<{ keys: JsonWebKey[]; status: "OK" }>
    • init(config?: TypeInput): RecipeListFunction

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -recipe/jwt | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Index

    Type aliases

    APIInterface: { getJWKSGET: undefined | ((input: { options: APIOptions; userContext: any }) => Promise<{ keys: JsonWebKey[]; status: "OK" } | GeneralErrorResponse>) }

    Type declaration

    • getJWKSGET: undefined | ((input: { options: APIOptions; userContext: any }) => Promise<{ keys: JsonWebKey[]; status: "OK" } | GeneralErrorResponse>)
    APIOptions: { config: TypeNormalisedInput; isInServerlessEnv: boolean; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse }

    Type declaration

    JsonWebKey: { alg: string; e: string; kid: string; kty: string; n: string; use: string }

    Type declaration

    • alg: string
    • e: string
    • kid: string
    • kty: string
    • n: string
    • use: string
    RecipeInterface: { createJWT: any; getJWKS: any }

    Type declaration

    • createJWT:function
      • createJWT(input: { payload?: any; userContext: any; validitySeconds?: number }): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
      • Parameters

        • input: { payload?: any; userContext: any; validitySeconds?: number }
          • Optional payload?: any
          • userContext: any
          • Optional validitySeconds?: number

        Returns Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>

    • getJWKS:function
      • getJWKS(input: { userContext: any }): Promise<{ keys: JsonWebKey[]; status: "OK" }>

    Functions

    • createJWT(payload: any, validitySeconds?: number, userContext?: any): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
    • Parameters

      • payload: any
      • Optional validitySeconds: number
      • Optional userContext: any

      Returns Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>

    • getJWKS(userContext?: any): Promise<{ keys: JsonWebKey[]; status: "OK" }>
    • init(config?: TypeInput): RecipeListFunction

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/recipe_openid.html b/docs/modules/recipe_openid.html deleted file mode 100644 index cd40b59ed..000000000 --- a/docs/modules/recipe_openid.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -recipe/openid | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/openid

    Index

    Functions

    • createJWT(payload?: any, validitySeconds?: number, userContext?: any): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
    • Parameters

      • Optional payload: any
      • Optional validitySeconds: number
      • Optional userContext: any

      Returns Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>

    • getJWKS(userContext?: any): Promise<{ keys: JsonWebKey[]; status: "OK" }>
    • getOpenIdDiscoveryConfiguration(userContext?: any): Promise<{ issuer: string; jwks_uri: string; status: "OK" }>
    • init(config?: TypeInput): RecipeListFunction

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -recipe/openid | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/openid

    Index

    Functions

    • createJWT(payload?: any, validitySeconds?: number, userContext?: any): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
    • Parameters

      • Optional payload: any
      • Optional validitySeconds: number
      • Optional userContext: any

      Returns Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>

    • getJWKS(userContext?: any): Promise<{ keys: JsonWebKey[]; status: "OK" }>
    • getOpenIdDiscoveryConfiguration(userContext?: any): Promise<{ issuer: string; jwks_uri: string; status: "OK" }>
    • init(config?: TypeInput): RecipeListFunction

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/recipe_passwordless.html b/docs/modules/recipe_passwordless.html deleted file mode 100644 index 2e01ba141..000000000 --- a/docs/modules/recipe_passwordless.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -recipe/passwordless | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/passwordless

    Index

    Type aliases

    APIInterface: { consumeCodePOST?: any; createCodePOST?: any; emailExistsGET?: any; phoneNumberExistsGET?: any; resendCodePOST?: any }

    Type declaration

    • consumeCodePOST?:function
      • consumeCodePOST(input: ({ deviceId: string; preAuthSessionId: string; userInputCode: string } & { options: APIOptions; userContext: any }) | ({ linkCode: string; preAuthSessionId: string } & { options: APIOptions; userContext: any })): Promise<GeneralErrorResponse | { createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
      • Parameters

        • input: ({ deviceId: string; preAuthSessionId: string; userInputCode: string } & { options: APIOptions; userContext: any }) | ({ linkCode: string; preAuthSessionId: string } & { options: APIOptions; userContext: any })

        Returns Promise<GeneralErrorResponse | { createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

    • createCodePOST?:function
      • createCodePOST(input: ({ email: string } & { options: APIOptions; userContext: any }) | ({ phoneNumber: string } & { options: APIOptions; userContext: any })): Promise<GeneralErrorResponse | { deviceId: string; flowType: "USER_INPUT_CODE" | "MAGIC_LINK" | "USER_INPUT_CODE_AND_MAGIC_LINK"; preAuthSessionId: string; status: "OK" }>
      • Parameters

        • input: ({ email: string } & { options: APIOptions; userContext: any }) | ({ phoneNumber: string } & { options: APIOptions; userContext: any })

        Returns Promise<GeneralErrorResponse | { deviceId: string; flowType: "USER_INPUT_CODE" | "MAGIC_LINK" | "USER_INPUT_CODE_AND_MAGIC_LINK"; preAuthSessionId: string; status: "OK" }>

    • emailExistsGET?:function
      • emailExistsGET(input: { email: string; options: APIOptions; userContext: any }): Promise<GeneralErrorResponse | { exists: boolean; status: "OK" }>
    • phoneNumberExistsGET?:function
      • phoneNumberExistsGET(input: { options: APIOptions; phoneNumber: string; userContext: any }): Promise<GeneralErrorResponse | { exists: boolean; status: "OK" }>
    • resendCodePOST?:function
      • resendCodePOST(input: { deviceId: string; preAuthSessionId: string } & { options: APIOptions; userContext: any }): Promise<GeneralErrorResponse | { status: "RESTART_FLOW_ERROR" | "OK" }>
    APIOptions: { appInfo: NormalisedAppinfo; config: TypeNormalisedInput; emailDelivery: default<TypePasswordlessEmailDeliveryInput>; isInServerlessEnv: boolean; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse; smsDelivery: default<TypePasswordlessSmsDeliveryInput> }

    Type declaration

    • appInfo: NormalisedAppinfo
    • config: TypeNormalisedInput
    • emailDelivery: default<TypePasswordlessEmailDeliveryInput>
    • isInServerlessEnv: boolean
    • recipeId: string
    • recipeImplementation: RecipeInterface
    • req: BaseRequest
    • res: BaseResponse
    • smsDelivery: default<TypePasswordlessSmsDeliveryInput>
    RecipeInterface: { consumeCode: any; createCode: any; createNewCodeForDevice: any; getUserByEmail: any; getUserById: any; getUserByPhoneNumber: any; listCodesByDeviceId: any; listCodesByEmail: any; listCodesByPhoneNumber: any; listCodesByPreAuthSessionId: any; revokeAllCodes: any; revokeCode: any; updateUser: any }

    Type declaration

    • consumeCode:function
      • consumeCode(input: { deviceId: string; preAuthSessionId: string; userContext: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
      • Parameters

        • input: { deviceId: string; preAuthSessionId: string; userContext: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext: any }

        Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

    • createCode:function
      • createCode(input: ({ email: string } & { userContext: any; userInputCode?: string }) | ({ phoneNumber: string } & { userContext: any; userInputCode?: string })): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>
      • Parameters

        • input: ({ email: string } & { userContext: any; userInputCode?: string }) | ({ phoneNumber: string } & { userContext: any; userInputCode?: string })

        Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>

    • createNewCodeForDevice:function
      • createNewCodeForDevice(input: { deviceId: string; userContext: any; userInputCode?: string }): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>
      • Parameters

        • input: { deviceId: string; userContext: any; userInputCode?: string }
          • deviceId: string
          • userContext: any
          • Optional userInputCode?: string

        Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>

    • getUserByEmail:function
      • getUserByEmail(input: { email: string; userContext: any }): Promise<undefined | User>
    • getUserById:function
      • getUserById(input: { userContext: any; userId: string }): Promise<undefined | User>
    • getUserByPhoneNumber:function
      • getUserByPhoneNumber(input: { phoneNumber: string; userContext: any }): Promise<undefined | User>
    • listCodesByDeviceId:function
      • listCodesByDeviceId(input: { deviceId: string; userContext: any }): Promise<undefined | DeviceType>
    • listCodesByEmail:function
      • listCodesByEmail(input: { email: string; userContext: any }): Promise<DeviceType[]>
    • listCodesByPhoneNumber:function
      • listCodesByPhoneNumber(input: { phoneNumber: string; userContext: any }): Promise<DeviceType[]>
    • listCodesByPreAuthSessionId:function
      • listCodesByPreAuthSessionId(input: { preAuthSessionId: string; userContext: any }): Promise<undefined | DeviceType>
    • revokeAllCodes:function
      • revokeAllCodes(input: { email: string; userContext: any } | { phoneNumber: string; userContext: any }): Promise<{ status: "OK" }>
    • revokeCode:function
      • revokeCode(input: { codeId: string; userContext: any }): Promise<{ status: "OK" }>
    • updateUser:function
      • updateUser(input: { email?: string | null; phoneNumber?: string | null; userContext: any; userId: string }): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>
      • Parameters

        • input: { email?: string | null; phoneNumber?: string | null; userContext: any; userId: string }
          • Optional email?: string | null
          • Optional phoneNumber?: string | null
          • userContext: any
          • userId: string

        Returns Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>

    User: { email?: string; id: string; phoneNumber?: string; timeJoined: number }

    Type declaration

    • Optional email?: string
    • id: string
    • Optional phoneNumber?: string
    • timeJoined: number

    Variables

    Error: typeof default = Wrapper.Error

    Functions

    • consumeCode(input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
    • Parameters

      • input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }

      Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

    • createCode(input: ({ email: string } & { userContext?: any; userInputCode?: string }) | ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>
    • Parameters

      • input: ({ email: string } & { userContext?: any; userInputCode?: string }) | ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })

      Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>

    • createMagicLink(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<string>
    • createNewCodeForDevice(input: { deviceId: string; userContext?: any; userInputCode?: string }): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>
    • Parameters

      • input: { deviceId: string; userContext?: any; userInputCode?: string }
        • deviceId: string
        • Optional userContext?: any
        • Optional userInputCode?: string

      Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>

    • getUserByEmail(input: { email: string; userContext?: any }): Promise<undefined | User>
    • getUserById(input: { userContext?: any; userId: string }): Promise<undefined | User>
    • getUserByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<undefined | User>
    • init(config: TypeInput): RecipeListFunction
    • listCodesByDeviceId(input: { deviceId: string; userContext?: any }): Promise<undefined | DeviceType>
    • listCodesByEmail(input: { email: string; userContext?: any }): Promise<DeviceType[]>
    • listCodesByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<DeviceType[]>
    • listCodesByPreAuthSessionId(input: { preAuthSessionId: string; userContext?: any }): Promise<undefined | DeviceType>
    • Parameters

      • input: { preAuthSessionId: string; userContext?: any }
        • preAuthSessionId: string
        • Optional userContext?: any

      Returns Promise<undefined | DeviceType>

    • revokeAllCodes(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ status: "OK" }>
    • revokeCode(input: { codeId: string; userContext?: any }): Promise<{ status: "OK" }>
    • sendEmail(input: TypePasswordlessEmailDeliveryInput & { userContext?: any }): Promise<void>
    • sendSms(input: TypePasswordlessSmsDeliveryInput & { userContext?: any }): Promise<void>
    • signInUp(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: string; user: User }>
    • Parameters

      • input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }

      Returns Promise<{ createdNewUser: boolean; status: string; user: User }>

    • updateUser(input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>
    • Parameters

      • input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }
        • Optional email?: null | string
        • Optional phoneNumber?: null | string
        • Optional userContext?: any
        • userId: string

      Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -recipe/passwordless | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/passwordless

    Index

    Type aliases

    APIInterface: { consumeCodePOST?: any; createCodePOST?: any; emailExistsGET?: any; phoneNumberExistsGET?: any; resendCodePOST?: any }

    Type declaration

    • consumeCodePOST?:function
      • consumeCodePOST(input: ({ deviceId: string; preAuthSessionId: string; userInputCode: string } & { options: APIOptions; userContext: any }) & ({ linkCode: string; preAuthSessionId: string } & { options: APIOptions; userContext: any })): Promise<GeneralErrorResponse | { createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
      • Parameters

        • input: ({ deviceId: string; preAuthSessionId: string; userInputCode: string } & { options: APIOptions; userContext: any }) & ({ linkCode: string; preAuthSessionId: string } & { options: APIOptions; userContext: any })

        Returns Promise<GeneralErrorResponse | { createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

    • createCodePOST?:function
      • createCodePOST(input: ({ email: string } & { options: APIOptions; userContext: any }) & ({ phoneNumber: string } & { options: APIOptions; userContext: any })): Promise<GeneralErrorResponse | { deviceId: string; flowType: "USER_INPUT_CODE" | "MAGIC_LINK" | "USER_INPUT_CODE_AND_MAGIC_LINK"; preAuthSessionId: string; status: "OK" }>
      • Parameters

        • input: ({ email: string } & { options: APIOptions; userContext: any }) & ({ phoneNumber: string } & { options: APIOptions; userContext: any })

        Returns Promise<GeneralErrorResponse | { deviceId: string; flowType: "USER_INPUT_CODE" | "MAGIC_LINK" | "USER_INPUT_CODE_AND_MAGIC_LINK"; preAuthSessionId: string; status: "OK" }>

    • emailExistsGET?:function
      • emailExistsGET(input: { email: string; options: APIOptions; userContext: any }): Promise<GeneralErrorResponse | { exists: boolean; status: "OK" }>
    • phoneNumberExistsGET?:function
      • phoneNumberExistsGET(input: { options: APIOptions; phoneNumber: string; userContext: any }): Promise<GeneralErrorResponse | { exists: boolean; status: "OK" }>
    • resendCodePOST?:function
      • resendCodePOST(input: { deviceId: string; preAuthSessionId: string } & { options: APIOptions; userContext: any }): Promise<GeneralErrorResponse | { status: "RESTART_FLOW_ERROR" | "OK" }>
    APIOptions: { appInfo: NormalisedAppinfo; config: TypeNormalisedInput; emailDelivery: default<TypePasswordlessEmailDeliveryInput>; isInServerlessEnv: boolean; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse; smsDelivery: default<TypePasswordlessSmsDeliveryInput> }

    Type declaration

    • appInfo: NormalisedAppinfo
    • config: TypeNormalisedInput
    • emailDelivery: default<TypePasswordlessEmailDeliveryInput>
    • isInServerlessEnv: boolean
    • recipeId: string
    • recipeImplementation: RecipeInterface
    • req: BaseRequest
    • res: BaseResponse
    • smsDelivery: default<TypePasswordlessSmsDeliveryInput>
    RecipeInterface: { consumeCode: any; createCode: any; createNewCodeForDevice: any; getUserByEmail: any; getUserById: any; getUserByPhoneNumber: any; listCodesByDeviceId: any; listCodesByEmail: any; listCodesByPhoneNumber: any; listCodesByPreAuthSessionId: any; revokeAllCodes: any; revokeCode: any; updateUser: any }

    Type declaration

    • consumeCode:function
      • consumeCode(input: { deviceId: string; preAuthSessionId: string; userContext: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
      • Parameters

        • input: { deviceId: string; preAuthSessionId: string; userContext: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext: any }

        Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

    • createCode:function
      • createCode(input: ({ email: string } & { userContext: any; userInputCode?: string }) & ({ phoneNumber: string } & { userContext: any; userInputCode?: string })): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>
      • Parameters

        • input: ({ email: string } & { userContext: any; userInputCode?: string }) & ({ phoneNumber: string } & { userContext: any; userInputCode?: string })

        Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>

    • createNewCodeForDevice:function
      • createNewCodeForDevice(input: { deviceId: string; userContext: any; userInputCode?: string }): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>
      • Parameters

        • input: { deviceId: string; userContext: any; userInputCode?: string }
          • deviceId: string
          • userContext: any
          • Optional userInputCode?: string

        Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>

    • getUserByEmail:function
      • getUserByEmail(input: { email: string; userContext: any }): Promise<undefined | User>
    • getUserById:function
      • getUserById(input: { userContext: any; userId: string }): Promise<undefined | User>
    • getUserByPhoneNumber:function
      • getUserByPhoneNumber(input: { phoneNumber: string; userContext: any }): Promise<undefined | User>
    • listCodesByDeviceId:function
      • listCodesByDeviceId(input: { deviceId: string; userContext: any }): Promise<undefined | DeviceType>
    • listCodesByEmail:function
      • listCodesByEmail(input: { email: string; userContext: any }): Promise<DeviceType[]>
    • listCodesByPhoneNumber:function
      • listCodesByPhoneNumber(input: { phoneNumber: string; userContext: any }): Promise<DeviceType[]>
    • listCodesByPreAuthSessionId:function
      • listCodesByPreAuthSessionId(input: { preAuthSessionId: string; userContext: any }): Promise<undefined | DeviceType>
    • revokeAllCodes:function
      • revokeAllCodes(input: { email: string; userContext: any } | { phoneNumber: string; userContext: any }): Promise<{ status: "OK" }>
    • revokeCode:function
      • revokeCode(input: { codeId: string; userContext: any }): Promise<{ status: "OK" }>
    • updateUser:function
      • updateUser(input: { email?: string | null; phoneNumber?: string | null; userContext: any; userId: string }): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>
      • Parameters

        • input: { email?: string | null; phoneNumber?: string | null; userContext: any; userId: string }
          • Optional email?: string | null
          • Optional phoneNumber?: string | null
          • userContext: any
          • userId: string

        Returns Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>

    User: { email?: string; id: string; phoneNumber?: string; timeJoined: number }

    Type declaration

    • Optional email?: string
    • id: string
    • Optional phoneNumber?: string
    • timeJoined: number

    Variables

    Error: typeof default = Wrapper.Error

    Functions

    • consumeCode(input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
    • Parameters

      • input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }

      Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

    • createCode(input: ({ email: string } & { userContext?: any; userInputCode?: string }) & ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>
    • Parameters

      • input: ({ email: string } & { userContext?: any; userInputCode?: string }) & ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })

      Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>

    • createMagicLink(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<string>
    • createNewCodeForDevice(input: { deviceId: string; userContext?: any; userInputCode?: string }): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>
    • Parameters

      • input: { deviceId: string; userContext?: any; userInputCode?: string }
        • deviceId: string
        • Optional userContext?: any
        • Optional userInputCode?: string

      Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>

    • getUserByEmail(input: { email: string; userContext?: any }): Promise<undefined | User>
    • getUserById(input: { userContext?: any; userId: string }): Promise<undefined | User>
    • getUserByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<undefined | User>
    • init(config: TypeInput): RecipeListFunction
    • listCodesByDeviceId(input: { deviceId: string; userContext?: any }): Promise<undefined | DeviceType>
    • listCodesByEmail(input: { email: string; userContext?: any }): Promise<DeviceType[]>
    • listCodesByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<DeviceType[]>
    • listCodesByPreAuthSessionId(input: { preAuthSessionId: string; userContext?: any }): Promise<undefined | DeviceType>
    • Parameters

      • input: { preAuthSessionId: string; userContext?: any }
        • preAuthSessionId: string
        • Optional userContext?: any

      Returns Promise<undefined | DeviceType>

    • revokeAllCodes(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ status: "OK" }>
    • revokeCode(input: { codeId: string; userContext?: any }): Promise<{ status: "OK" }>
    • sendEmail(input: TypePasswordlessEmailDeliveryInput & { userContext?: any }): Promise<void>
    • sendSms(input: TypePasswordlessSmsDeliveryInput & { userContext?: any }): Promise<void>
    • signInUp(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: string; user: User }>
    • Parameters

      • input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }

      Returns Promise<{ createdNewUser: boolean; status: string; user: User }>

    • updateUser(input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>
    • Parameters

      • input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }
        • Optional email?: null | string
        • Optional phoneNumber?: null | string
        • Optional userContext?: any
        • userId: string

      Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/recipe_session.html b/docs/modules/recipe_session.html deleted file mode 100644 index 1a764282d..000000000 --- a/docs/modules/recipe_session.html +++ /dev/null @@ -1,30 +0,0 @@ -<<<<<<< HEAD -recipe/session | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/session

    Index

    Type aliases

    APIInterface: { refreshPOST: undefined | ((input: { options: APIOptions; userContext: any }) => Promise<SessionContainer>); signOutPOST: undefined | ((input: { options: APIOptions; session: SessionContainer | undefined; userContext: any }) => Promise<{ status: "OK" } | GeneralErrorResponse>); verifySession: any }

    Type declaration

    APIOptions: { config: TypeNormalisedInput; isInServerlessEnv: boolean; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse }

    Type declaration

    RecipeInterface: { createNewSession: any; fetchAndSetClaim: any; getAccessTokenLifeTimeMS: any; getAllSessionHandlesForUser: any; getClaimValue: any; getGlobalClaimValidators: any; getRefreshTokenLifeTimeMS: any; getSession: any; getSessionInformation: any; mergeIntoAccessTokenPayload: any; refreshSession: any; regenerateAccessToken: any; removeClaim: any; revokeAllSessionsForUser: any; revokeMultipleSessions: any; revokeSession: any; setClaimValue: any; updateAccessTokenPayload: any; updateSessionData: any; validateClaims: any; validateClaimsInJWTPayload: any }

    Type declaration

    SessionClaimValidator: ({ claim: SessionClaim<any>; shouldRefetch: any } | {}) & { id: string; validate: any }
    SessionInformation: { accessTokenPayload: any; expiry: number; sessionData: any; sessionHandle: string; timeCreated: number; userId: string }

    Type declaration

    • accessTokenPayload: any
    • expiry: number
    • sessionData: any
    • sessionHandle: string
    • timeCreated: number
    • userId: string

    Variables

    Error: typeof default = SessionWrapper.Error

    Functions

    • createJWT(payload?: any, validitySeconds?: number, userContext?: any): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
    • Parameters

      • Optional payload: any
      • Optional validitySeconds: number
      • userContext: any = {}

      Returns Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>

    • createNewSession(req: any, res: any, userId: string, accessTokenPayload?: any, sessionData?: any, userContext?: any): Promise<SessionContainer>
    • fetchAndSetClaim(sessionHandle: string, claim: SessionClaim<any>, userContext?: any): Promise<boolean>
    • getAllSessionHandlesForUser(userId: string, userContext?: any): Promise<string[]>
    • getClaimValue<T>(sessionHandle: string, claim: SessionClaim<T>, userContext?: any): Promise<{ status: "SESSION_DOES_NOT_EXIST_ERROR" } | { status: "OK"; value: undefined | T }>
    • Type parameters

      • T

      Parameters

      • sessionHandle: string
      • claim: SessionClaim<T>
      • userContext: any = {}

      Returns Promise<{ status: "SESSION_DOES_NOT_EXIST_ERROR" } | { status: "OK"; value: undefined | T }>

    • getJWKS(userContext?: any): Promise<{ keys: JsonWebKey[]; status: "OK" }>
    • getOpenIdDiscoveryConfiguration(userContext?: any): Promise<{ issuer: string; jwks_uri: string; status: "OK" }>
    • getSessionInformation(sessionHandle: string, userContext?: any): Promise<undefined | SessionInformation>
    • init(config?: TypeInput): RecipeListFunction
    • mergeIntoAccessTokenPayload(sessionHandle: string, accessTokenPayloadUpdate: JSONObject, userContext?: any): Promise<boolean>
    • refreshSession(req: any, res: any, userContext?: any): Promise<SessionContainer>
    • removeClaim(sessionHandle: string, claim: SessionClaim<any>, userContext?: any): Promise<boolean>
    • revokeAllSessionsForUser(userId: string, userContext?: any): Promise<string[]>
    • revokeMultipleSessions(sessionHandles: string[], userContext?: any): Promise<string[]>
    • revokeSession(sessionHandle: string, userContext?: any): Promise<boolean>
    • setClaimValue<T>(sessionHandle: string, claim: SessionClaim<T>, value: T, userContext?: any): Promise<boolean>
    • updateAccessTokenPayload(sessionHandle: string, newAccessTokenPayload: any, userContext?: any): Promise<boolean>
    • updateSessionData(sessionHandle: string, newSessionData: any, userContext?: any): Promise<boolean>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/recipe_thirdparty.html b/docs/modules/recipe_thirdparty.html deleted file mode 100644 index 5d45f143d..000000000 --- a/docs/modules/recipe_thirdparty.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -recipe/thirdparty | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/thirdparty

    Index

    Type aliases

    APIInterface: { appleRedirectHandlerPOST: undefined | ((input: { code: string; options: APIOptions; state: string; userContext: any }) => Promise<void>); authorisationUrlGET: undefined | ((input: { options: APIOptions; provider: TypeProvider; userContext: any }) => Promise<{ status: "OK"; url: string } | GeneralErrorResponse>); signInUpPOST: undefined | ((input: { authCodeResponse?: any; clientId?: string; code: string; options: APIOptions; provider: TypeProvider; redirectURI: string; userContext: any }) => Promise<{ authCodeResponse: any; createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" } | GeneralErrorResponse>) }

    Type declaration

    • appleRedirectHandlerPOST: undefined | ((input: { code: string; options: APIOptions; state: string; userContext: any }) => Promise<void>)
    • authorisationUrlGET: undefined | ((input: { options: APIOptions; provider: TypeProvider; userContext: any }) => Promise<{ status: "OK"; url: string } | GeneralErrorResponse>)
    • signInUpPOST: undefined | ((input: { authCodeResponse?: any; clientId?: string; code: string; options: APIOptions; provider: TypeProvider; redirectURI: string; userContext: any }) => Promise<{ authCodeResponse: any; createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" } | GeneralErrorResponse>)
    APIOptions: { appInfo: NormalisedAppinfo; config: TypeNormalisedInput; isInServerlessEnv: boolean; providers: TypeProvider[]; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse }

    Type declaration

    RecipeInterface: { getUserById: any; getUserByThirdPartyInfo: any; getUsersByEmail: any; signInUp: any }

    Type declaration

    • getUserById:function
      • getUserById(input: { userContext: any; userId: string }): Promise<undefined | User>
    • getUserByThirdPartyInfo:function
      • getUserByThirdPartyInfo(input: { thirdPartyId: string; thirdPartyUserId: string; userContext: any }): Promise<undefined | User>
      • Parameters

        • input: { thirdPartyId: string; thirdPartyUserId: string; userContext: any }
          • thirdPartyId: string
          • thirdPartyUserId: string
          • userContext: any

        Returns Promise<undefined | User>

    • getUsersByEmail:function
      • getUsersByEmail(input: { email: string; userContext: any }): Promise<User[]>
    • signInUp:function
      • signInUp(input: { email: string; thirdPartyId: string; thirdPartyUserId: string; userContext: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
      • Parameters

        • input: { email: string; thirdPartyId: string; thirdPartyUserId: string; userContext: any }
          • email: string
          • thirdPartyId: string
          • thirdPartyUserId: string
          • userContext: any

        Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User }>

    TypeProvider: { id: string; isDefault?: boolean; get: any }

    Type declaration

    • id: string
    • Optional isDefault?: boolean
    • get:function
      • get(redirectURI: undefined | string, authCodeFromRequest: undefined | string, userContext: any): TypeProviderGetResponse
    User: { email: string; id: string; thirdParty: { id: string; userId: string }; timeJoined: number }

    Type declaration

    • email: string
    • id: string
    • thirdParty: { id: string; userId: string }
      • id: string
      • userId: string
    • timeJoined: number

    Variables

    Error: typeof default = Wrapper.Error

    Functions

    • Apple(config: TypeThirdPartyProviderAppleConfig): TypeProvider
    • Discord(config: TypeThirdPartyProviderDiscordConfig): TypeProvider
    • Facebook(config: TypeThirdPartyProviderFacebookConfig): TypeProvider
    • Github(config: TypeThirdPartyProviderGithubConfig): TypeProvider
    • Google(config: TypeThirdPartyProviderGoogleConfig): TypeProvider
    • GoogleWorkspaces(config: TypeThirdPartyProviderGoogleWorkspacesConfig): TypeProvider
    • getUserById(userId: string, userContext?: any): Promise<undefined | User>
    • getUserByThirdPartyInfo(thirdPartyId: string, thirdPartyUserId: string, userContext?: any): Promise<undefined | User>
    • getUsersByEmail(email: string, userContext?: any): Promise<User[]>
    • init(config: TypeInput): RecipeListFunction
    • signInUp(thirdPartyId: string, thirdPartyUserId: string, email: string, userContext?: any): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
    • Parameters

      • thirdPartyId: string
      • thirdPartyUserId: string
      • email: string
      • userContext: any = {}

      Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -recipe/thirdparty | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/thirdparty

    Index

    Type aliases

    APIInterface: { appleRedirectHandlerPOST: undefined | ((input: { code: string; options: APIOptions; state: string; userContext: any }) => Promise<void>); authorisationUrlGET: undefined | ((input: { options: APIOptions; provider: TypeProvider; userContext: any }) => Promise<{ status: "OK"; url: string } | GeneralErrorResponse>); signInUpPOST: undefined | ((input: { authCodeResponse?: any; clientId?: string; code: string; options: APIOptions; provider: TypeProvider; redirectURI: string; userContext: any }) => Promise<{ authCodeResponse: any; createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" } | GeneralErrorResponse>) }

    Type declaration

    • appleRedirectHandlerPOST: undefined | ((input: { code: string; options: APIOptions; state: string; userContext: any }) => Promise<void>)
    • authorisationUrlGET: undefined | ((input: { options: APIOptions; provider: TypeProvider; userContext: any }) => Promise<{ status: "OK"; url: string } | GeneralErrorResponse>)
    • signInUpPOST: undefined | ((input: { authCodeResponse?: any; clientId?: string; code: string; options: APIOptions; provider: TypeProvider; redirectURI: string; userContext: any }) => Promise<{ authCodeResponse: any; createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" } | GeneralErrorResponse>)
    APIOptions: { appInfo: NormalisedAppinfo; config: TypeNormalisedInput; isInServerlessEnv: boolean; providers: TypeProvider[]; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse }

    Type declaration

    RecipeInterface: { getUserById: any; getUserByThirdPartyInfo: any; getUsersByEmail: any; signInUp: any }

    Type declaration

    • getUserById:function
      • getUserById(input: { userContext: any; userId: string }): Promise<undefined | User>
    • getUserByThirdPartyInfo:function
      • getUserByThirdPartyInfo(input: { thirdPartyId: string; thirdPartyUserId: string; userContext: any }): Promise<undefined | User>
      • Parameters

        • input: { thirdPartyId: string; thirdPartyUserId: string; userContext: any }
          • thirdPartyId: string
          • thirdPartyUserId: string
          • userContext: any

        Returns Promise<undefined | User>

    • getUsersByEmail:function
      • getUsersByEmail(input: { email: string; userContext: any }): Promise<User[]>
    • signInUp:function
      • signInUp(input: { email: string; thirdPartyId: string; thirdPartyUserId: string; userContext: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
      • Parameters

        • input: { email: string; thirdPartyId: string; thirdPartyUserId: string; userContext: any }
          • email: string
          • thirdPartyId: string
          • thirdPartyUserId: string
          • userContext: any

        Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User }>

    TypeProvider: { id: string; isDefault?: boolean; get: any }

    Type declaration

    • id: string
    • Optional isDefault?: boolean
    • get:function
      • get(redirectURI: undefined | string, authCodeFromRequest: undefined | string, userContext: any): TypeProviderGetResponse
    User: { email: string; id: string; thirdParty: { id: string; userId: string }; timeJoined: number }

    Type declaration

    • email: string
    • id: string
    • thirdParty: { id: string; userId: string }
      • id: string
      • userId: string
    • timeJoined: number

    Variables

    Error: typeof default = Wrapper.Error

    Functions

    • Apple(config: TypeThirdPartyProviderAppleConfig): TypeProvider
    • Discord(config: TypeThirdPartyProviderDiscordConfig): TypeProvider
    • Facebook(config: TypeThirdPartyProviderFacebookConfig): TypeProvider
    • Github(config: TypeThirdPartyProviderGithubConfig): TypeProvider
    • Google(config: TypeThirdPartyProviderGoogleConfig): TypeProvider
    • GoogleWorkspaces(config: TypeThirdPartyProviderGoogleWorkspacesConfig): TypeProvider
    • getUserById(userId: string, userContext?: any): Promise<undefined | User>
    • getUserByThirdPartyInfo(thirdPartyId: string, thirdPartyUserId: string, userContext?: any): Promise<undefined | User>
    • getUsersByEmail(email: string, userContext?: any): Promise<User[]>
    • init(config: TypeInput): RecipeListFunction
    • signInUp(thirdPartyId: string, thirdPartyUserId: string, email: string, userContext?: any): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
    • Parameters

      • thirdPartyId: string
      • thirdPartyUserId: string
      • email: string
      • userContext: any = {}

      Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/recipe_thirdpartyemailpassword.html b/docs/modules/recipe_thirdpartyemailpassword.html deleted file mode 100644 index 3d4672c2f..000000000 --- a/docs/modules/recipe_thirdpartyemailpassword.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -recipe/thirdpartyemailpassword | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/thirdpartyemailpassword

    Index

    References

    Re-exports TypeProvider

    Type aliases

    APIInterface: { appleRedirectHandlerPOST: undefined | ((input: { code: string; options: ThirdPartyAPIOptions; state: string; userContext: any }) => Promise<void>); authorisationUrlGET: undefined | ((input: { options: ThirdPartyAPIOptions; provider: TypeProvider; userContext: any }) => Promise<{ status: "OK"; url: string } | GeneralErrorResponse>); emailPasswordEmailExistsGET: undefined | ((input: { email: string; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>); emailPasswordSignInPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" } | GeneralErrorResponse>); emailPasswordSignUpPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" } | GeneralErrorResponse>); generatePasswordResetTokenPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ status: "OK" } | GeneralErrorResponse>); passwordResetPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; token: string; userContext: any }) => Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" } | GeneralErrorResponse>); thirdPartySignInUpPOST: undefined | ((input: { authCodeResponse?: any; clientId?: string; code: string; options: ThirdPartyAPIOptions; provider: TypeProvider; redirectURI: string; userContext: any }) => Promise<{ authCodeResponse: any; createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | GeneralErrorResponse | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" }>) }

    Type declaration

    • appleRedirectHandlerPOST: undefined | ((input: { code: string; options: ThirdPartyAPIOptions; state: string; userContext: any }) => Promise<void>)
    • authorisationUrlGET: undefined | ((input: { options: ThirdPartyAPIOptions; provider: TypeProvider; userContext: any }) => Promise<{ status: "OK"; url: string } | GeneralErrorResponse>)
    • emailPasswordEmailExistsGET: undefined | ((input: { email: string; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>)
    • emailPasswordSignInPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" } | GeneralErrorResponse>)
    • emailPasswordSignUpPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" } | GeneralErrorResponse>)
    • generatePasswordResetTokenPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ status: "OK" } | GeneralErrorResponse>)
    • passwordResetPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; token: string; userContext: any }) => Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" } | GeneralErrorResponse>)
    • thirdPartySignInUpPOST: undefined | ((input: { authCodeResponse?: any; clientId?: string; code: string; options: ThirdPartyAPIOptions; provider: TypeProvider; redirectURI: string; userContext: any }) => Promise<{ authCodeResponse: any; createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | GeneralErrorResponse | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" }>)
    EmailPasswordAPIOptions: APIOptions
    RecipeInterface: { createResetPasswordToken: any; emailPasswordSignIn: any; emailPasswordSignUp: any; getUserById: any; getUserByThirdPartyInfo: any; getUsersByEmail: any; resetPasswordUsingToken: any; thirdPartySignInUp: any; updateEmailOrPassword: any }

    Type declaration

    • createResetPasswordToken:function
      • createResetPasswordToken(input: { userContext: any; userId: string }): Promise<{ status: "OK"; token: string } | { status: "UNKNOWN_USER_ID_ERROR" }>
    • emailPasswordSignIn:function
      • emailPasswordSignIn(input: { email: string; password: string; userContext: any }): Promise<{ status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>
    • emailPasswordSignUp:function
      • emailPasswordSignUp(input: { email: string; password: string; userContext: any }): Promise<{ status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>
    • getUserById:function
      • getUserById(input: { userContext: any; userId: string }): Promise<undefined | User>
    • getUserByThirdPartyInfo:function
      • getUserByThirdPartyInfo(input: { thirdPartyId: string; thirdPartyUserId: string; userContext: any }): Promise<undefined | User>
    • getUsersByEmail:function
      • getUsersByEmail(input: { email: string; userContext: any }): Promise<User[]>
    • resetPasswordUsingToken:function
      • resetPasswordUsingToken(input: { newPassword: string; token: string; userContext: any }): Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>
      • Parameters

        • input: { newPassword: string; token: string; userContext: any }
          • newPassword: string
          • token: string
          • userContext: any

        Returns Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>

    • thirdPartySignInUp:function
      • thirdPartySignInUp(input: { email: string; thirdPartyId: string; thirdPartyUserId: string; userContext: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
      • Parameters

        • input: { email: string; thirdPartyId: string; thirdPartyUserId: string; userContext: any }
          • email: string
          • thirdPartyId: string
          • thirdPartyUserId: string
          • userContext: any

        Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User }>

    • updateEmailOrPassword:function
      • updateEmailOrPassword(input: { email?: string; password?: string; userContext: any; userId: string }): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" }>
      • Parameters

        • input: { email?: string; password?: string; userContext: any; userId: string }
          • Optional email?: string
          • Optional password?: string
          • userContext: any
          • userId: string

        Returns Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" }>

    ThirdPartyAPIOptions: APIOptions
    User: { email: string; id: string; thirdParty?: { id: string; userId: string }; timeJoined: number }

    Type declaration

    • email: string
    • id: string
    • Optional thirdParty?: { id: string; userId: string }
      • id: string
      • userId: string
    • timeJoined: number

    Variables

    Error: typeof default = Wrapper.Error

    Functions

    • Apple(config: TypeThirdPartyProviderAppleConfig): TypeProvider
    • Discord(config: TypeThirdPartyProviderDiscordConfig): TypeProvider
    • Facebook(config: TypeThirdPartyProviderFacebookConfig): TypeProvider
    • Github(config: TypeThirdPartyProviderGithubConfig): TypeProvider
    • Google(config: TypeThirdPartyProviderGoogleConfig): TypeProvider
    • GoogleWorkspaces(config: TypeThirdPartyProviderGoogleWorkspacesConfig): TypeProvider
    • createResetPasswordToken(userId: string, userContext?: any): Promise<{ status: "OK"; token: string } | { status: "UNKNOWN_USER_ID_ERROR" }>
    • emailPasswordSignIn(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>
    • emailPasswordSignUp(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>
    • getUserById(userId: string, userContext?: any): Promise<undefined | User>
    • getUserByThirdPartyInfo(thirdPartyId: string, thirdPartyUserId: string, userContext?: any): Promise<undefined | User>
    • getUsersByEmail(email: string, userContext?: any): Promise<User[]>
    • init(config: TypeInput): RecipeListFunction
    • resetPasswordUsingToken(token: string, newPassword: string, userContext?: any): Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>
    • sendEmail(input: TypeEmailPasswordPasswordResetEmailDeliveryInput & { userContext?: any }): Promise<void>
    • thirdPartySignInUp(thirdPartyId: string, thirdPartyUserId: string, email: string, userContext?: any): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
    • updateEmailOrPassword(input: { email?: string; password?: string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>
    • Parameters

      • input: { email?: string; password?: string; userContext?: any; userId: string }
        • Optional email?: string
        • Optional password?: string
        • Optional userContext?: any
        • userId: string

      Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -recipe/thirdpartyemailpassword | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/thirdpartyemailpassword

    Index

    References

    Re-exports TypeProvider

    Type aliases

    APIInterface: { appleRedirectHandlerPOST: undefined | ((input: { code: string; options: ThirdPartyAPIOptions; state: string; userContext: any }) => Promise<void>); authorisationUrlGET: undefined | ((input: { options: ThirdPartyAPIOptions; provider: TypeProvider; userContext: any }) => Promise<{ status: "OK"; url: string } | GeneralErrorResponse>); emailPasswordEmailExistsGET: undefined | ((input: { email: string; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>); emailPasswordSignInPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" } | GeneralErrorResponse>); emailPasswordSignUpPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" } | GeneralErrorResponse>); generatePasswordResetTokenPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ status: "OK" } | GeneralErrorResponse>); passwordResetPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; token: string; userContext: any }) => Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" } | GeneralErrorResponse>); thirdPartySignInUpPOST: undefined | ((input: { authCodeResponse?: any; clientId?: string; code: string; options: ThirdPartyAPIOptions; provider: TypeProvider; redirectURI: string; userContext: any }) => Promise<{ authCodeResponse: any; createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | GeneralErrorResponse | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" }>) }

    Type declaration

    • appleRedirectHandlerPOST: undefined | ((input: { code: string; options: ThirdPartyAPIOptions; state: string; userContext: any }) => Promise<void>)
    • authorisationUrlGET: undefined | ((input: { options: ThirdPartyAPIOptions; provider: TypeProvider; userContext: any }) => Promise<{ status: "OK"; url: string } | GeneralErrorResponse>)
    • emailPasswordEmailExistsGET: undefined | ((input: { email: string; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>)
    • emailPasswordSignInPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" } | GeneralErrorResponse>)
    • emailPasswordSignUpPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ session: SessionContainer; status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" } | GeneralErrorResponse>)
    • generatePasswordResetTokenPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; userContext: any }) => Promise<{ status: "OK" } | GeneralErrorResponse>)
    • passwordResetPOST: undefined | ((input: { formFields: { id: string; value: string }[]; options: EmailPasswordAPIOptions; token: string; userContext: any }) => Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" } | GeneralErrorResponse>)
    • thirdPartySignInUpPOST: undefined | ((input: { authCodeResponse?: any; clientId?: string; code: string; options: ThirdPartyAPIOptions; provider: TypeProvider; redirectURI: string; userContext: any }) => Promise<{ authCodeResponse: any; createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | GeneralErrorResponse | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" }>)
    EmailPasswordAPIOptions: APIOptions
    RecipeInterface: { createResetPasswordToken: any; emailPasswordSignIn: any; emailPasswordSignUp: any; getUserById: any; getUserByThirdPartyInfo: any; getUsersByEmail: any; resetPasswordUsingToken: any; thirdPartySignInUp: any; updateEmailOrPassword: any }

    Type declaration

    • createResetPasswordToken:function
      • createResetPasswordToken(input: { userContext: any; userId: string }): Promise<{ status: "OK"; token: string } | { status: "UNKNOWN_USER_ID_ERROR" }>
    • emailPasswordSignIn:function
      • emailPasswordSignIn(input: { email: string; password: string; userContext: any }): Promise<{ status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>
    • emailPasswordSignUp:function
      • emailPasswordSignUp(input: { email: string; password: string; userContext: any }): Promise<{ status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>
    • getUserById:function
      • getUserById(input: { userContext: any; userId: string }): Promise<undefined | User>
    • getUserByThirdPartyInfo:function
      • getUserByThirdPartyInfo(input: { thirdPartyId: string; thirdPartyUserId: string; userContext: any }): Promise<undefined | User>
    • getUsersByEmail:function
      • getUsersByEmail(input: { email: string; userContext: any }): Promise<User[]>
    • resetPasswordUsingToken:function
      • resetPasswordUsingToken(input: { newPassword: string; token: string; userContext: any }): Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>
      • Parameters

        • input: { newPassword: string; token: string; userContext: any }
          • newPassword: string
          • token: string
          • userContext: any

        Returns Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>

    • thirdPartySignInUp:function
      • thirdPartySignInUp(input: { email: string; thirdPartyId: string; thirdPartyUserId: string; userContext: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
      • Parameters

        • input: { email: string; thirdPartyId: string; thirdPartyUserId: string; userContext: any }
          • email: string
          • thirdPartyId: string
          • thirdPartyUserId: string
          • userContext: any

        Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User }>

    • updateEmailOrPassword:function
      • updateEmailOrPassword(input: { email?: string; password?: string; userContext: any; userId: string }): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" }>
      • Parameters

        • input: { email?: string; password?: string; userContext: any; userId: string }
          • Optional email?: string
          • Optional password?: string
          • userContext: any
          • userId: string

        Returns Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" }>

    ThirdPartyAPIOptions: APIOptions
    User: { email: string; id: string; thirdParty?: { id: string; userId: string }; timeJoined: number }

    Type declaration

    • email: string
    • id: string
    • Optional thirdParty?: { id: string; userId: string }
      • id: string
      • userId: string
    • timeJoined: number

    Variables

    Error: typeof default = Wrapper.Error

    Functions

    • Apple(config: TypeThirdPartyProviderAppleConfig): TypeProvider
    • Discord(config: TypeThirdPartyProviderDiscordConfig): TypeProvider
    • Facebook(config: TypeThirdPartyProviderFacebookConfig): TypeProvider
    • Github(config: TypeThirdPartyProviderGithubConfig): TypeProvider
    • Google(config: TypeThirdPartyProviderGoogleConfig): TypeProvider
    • GoogleWorkspaces(config: TypeThirdPartyProviderGoogleWorkspacesConfig): TypeProvider
    • createResetPasswordToken(userId: string, userContext?: any): Promise<{ status: "OK"; token: string } | { status: "UNKNOWN_USER_ID_ERROR" }>
    • emailPasswordSignIn(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>
    • emailPasswordSignUp(email: string, password: string, userContext?: any): Promise<{ status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>
    • getUserById(userId: string, userContext?: any): Promise<undefined | User>
    • getUserByThirdPartyInfo(thirdPartyId: string, thirdPartyUserId: string, userContext?: any): Promise<undefined | User>
    • getUsersByEmail(email: string, userContext?: any): Promise<User[]>
    • init(config: TypeInput): RecipeListFunction
    • resetPasswordUsingToken(token: string, newPassword: string, userContext?: any): Promise<{ status: "OK"; userId?: string } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" }>
    • sendEmail(input: TypeEmailPasswordPasswordResetEmailDeliveryInput & { userContext?: any }): Promise<void>
    • thirdPartySignInUp(thirdPartyId: string, thirdPartyUserId: string, email: string, userContext?: any): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
    • updateEmailOrPassword(input: { email?: string; password?: string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>
    • Parameters

      • input: { email?: string; password?: string; userContext?: any; userId: string }
        • Optional email?: string
        • Optional password?: string
        • Optional userContext?: any
        • userId: string

      Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/recipe_thirdpartypasswordless.html b/docs/modules/recipe_thirdpartypasswordless.html deleted file mode 100644 index d9062b7e3..000000000 --- a/docs/modules/recipe_thirdpartypasswordless.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -recipe/thirdpartypasswordless | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/thirdpartypasswordless

    Index

    References

    Re-exports TypeProvider

    Type aliases

    APIInterface: { appleRedirectHandlerPOST: undefined | ((input: { code: string; options: ThirdPartyAPIOptions; state: string; userContext: any }) => Promise<void>); authorisationUrlGET: undefined | ((input: { options: ThirdPartyAPIOptions; provider: TypeProvider; userContext: any }) => Promise<{ status: "OK"; url: string } | GeneralErrorResponse>); consumeCodePOST: undefined | ((input: ({ deviceId: string; preAuthSessionId: string; userInputCode: string } | { linkCode: string; preAuthSessionId: string }) & { options: PasswordlessAPIOptions; userContext: any }) => Promise<{ createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | GeneralErrorResponse | { status: "RESTART_FLOW_ERROR" }>); createCodePOST: undefined | ((input: ({ email: string } | { phoneNumber: string }) & { options: PasswordlessAPIOptions; userContext: any }) => Promise<{ deviceId: string; flowType: "USER_INPUT_CODE" | "MAGIC_LINK" | "USER_INPUT_CODE_AND_MAGIC_LINK"; preAuthSessionId: string; status: "OK" } | GeneralErrorResponse>); passwordlessUserEmailExistsGET: undefined | ((input: { email: string; options: PasswordlessAPIOptions; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>); passwordlessUserPhoneNumberExistsGET: undefined | ((input: { options: PasswordlessAPIOptions; phoneNumber: string; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>); resendCodePOST: undefined | ((input: { deviceId: string; preAuthSessionId: string } & { options: PasswordlessAPIOptions; userContext: any }) => Promise<GeneralErrorResponse | { status: "RESTART_FLOW_ERROR" | "OK" }>); thirdPartySignInUpPOST: undefined | ((input: { authCodeResponse?: any; clientId?: string; code: string; options: ThirdPartyAPIOptions; provider: TypeProvider; redirectURI: string; userContext: any }) => Promise<{ authCodeResponse: any; createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | GeneralErrorResponse | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" }>) }

    Type declaration

    • appleRedirectHandlerPOST: undefined | ((input: { code: string; options: ThirdPartyAPIOptions; state: string; userContext: any }) => Promise<void>)
    • authorisationUrlGET: undefined | ((input: { options: ThirdPartyAPIOptions; provider: TypeProvider; userContext: any }) => Promise<{ status: "OK"; url: string } | GeneralErrorResponse>)
    • consumeCodePOST: undefined | ((input: ({ deviceId: string; preAuthSessionId: string; userInputCode: string } | { linkCode: string; preAuthSessionId: string }) & { options: PasswordlessAPIOptions; userContext: any }) => Promise<{ createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | GeneralErrorResponse | { status: "RESTART_FLOW_ERROR" }>)
    • createCodePOST: undefined | ((input: ({ email: string } | { phoneNumber: string }) & { options: PasswordlessAPIOptions; userContext: any }) => Promise<{ deviceId: string; flowType: "USER_INPUT_CODE" | "MAGIC_LINK" | "USER_INPUT_CODE_AND_MAGIC_LINK"; preAuthSessionId: string; status: "OK" } | GeneralErrorResponse>)
    • passwordlessUserEmailExistsGET: undefined | ((input: { email: string; options: PasswordlessAPIOptions; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>)
    • passwordlessUserPhoneNumberExistsGET: undefined | ((input: { options: PasswordlessAPIOptions; phoneNumber: string; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>)
    • resendCodePOST: undefined | ((input: { deviceId: string; preAuthSessionId: string } & { options: PasswordlessAPIOptions; userContext: any }) => Promise<GeneralErrorResponse | { status: "RESTART_FLOW_ERROR" | "OK" }>)
    • thirdPartySignInUpPOST: undefined | ((input: { authCodeResponse?: any; clientId?: string; code: string; options: ThirdPartyAPIOptions; provider: TypeProvider; redirectURI: string; userContext: any }) => Promise<{ authCodeResponse: any; createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | GeneralErrorResponse | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" }>)
    PasswordlessAPIOptions: APIOptions
    RecipeInterface: { consumeCode: any; createCode: any; createNewCodeForDevice: any; getUserById: any; getUserByPhoneNumber: any; getUserByThirdPartyInfo: any; getUsersByEmail: any; listCodesByDeviceId: any; listCodesByEmail: any; listCodesByPhoneNumber: any; listCodesByPreAuthSessionId: any; revokeAllCodes: any; revokeCode: any; thirdPartySignInUp: any; updatePasswordlessUser: any }

    Type declaration

    • consumeCode:function
      • consumeCode(input: { deviceId: string; preAuthSessionId: string; userContext: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
      • Parameters

        • input: { deviceId: string; preAuthSessionId: string; userContext: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext: any }

        Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

    • createCode:function
      • createCode(input: ({ email: string } & { userContext: any; userInputCode?: string }) | ({ phoneNumber: string } & { userContext: any; userInputCode?: string })): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>
      • Parameters

        • input: ({ email: string } & { userContext: any; userInputCode?: string }) | ({ phoneNumber: string } & { userContext: any; userInputCode?: string })

        Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>

    • createNewCodeForDevice:function
      • createNewCodeForDevice(input: { deviceId: string; userContext: any; userInputCode?: string }): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>
      • Parameters

        • input: { deviceId: string; userContext: any; userInputCode?: string }
          • deviceId: string
          • userContext: any
          • Optional userInputCode?: string

        Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>

    • getUserById:function
      • getUserById(input: { userContext: any; userId: string }): Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>
      • Parameters

        • input: { userContext: any; userId: string }
          • userContext: any
          • userId: string

        Returns Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>

    • getUserByPhoneNumber:function
      • getUserByPhoneNumber(input: { phoneNumber: string; userContext: any }): Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>
      • Parameters

        • input: { phoneNumber: string; userContext: any }
          • phoneNumber: string
          • userContext: any

        Returns Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>

    • getUserByThirdPartyInfo:function
      • getUserByThirdPartyInfo(input: { thirdPartyId: string; thirdPartyUserId: string; userContext: any }): Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>
      • Parameters

        • input: { thirdPartyId: string; thirdPartyUserId: string; userContext: any }
          • thirdPartyId: string
          • thirdPartyUserId: string
          • userContext: any

        Returns Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>

    • getUsersByEmail:function
      • getUsersByEmail(input: { email: string; userContext: any }): Promise<User[]>
    • listCodesByDeviceId:function
      • listCodesByDeviceId(input: { deviceId: string; userContext: any }): Promise<undefined | DeviceType>
    • listCodesByEmail:function
      • listCodesByEmail(input: { email: string; userContext: any }): Promise<DeviceType[]>
    • listCodesByPhoneNumber:function
      • listCodesByPhoneNumber(input: { phoneNumber: string; userContext: any }): Promise<DeviceType[]>
    • listCodesByPreAuthSessionId:function
      • listCodesByPreAuthSessionId(input: { preAuthSessionId: string; userContext: any }): Promise<undefined | DeviceType>
    • revokeAllCodes:function
      • revokeAllCodes(input: { email: string; userContext: any } | { phoneNumber: string; userContext: any }): Promise<{ status: "OK" }>
    • revokeCode:function
      • revokeCode(input: { codeId: string; userContext: any }): Promise<{ status: "OK" }>
    • thirdPartySignInUp:function
      • thirdPartySignInUp(input: { email: string; thirdPartyId: string; thirdPartyUserId: string; userContext: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
      • Parameters

        • input: { email: string; thirdPartyId: string; thirdPartyUserId: string; userContext: any }
          • email: string
          • thirdPartyId: string
          • thirdPartyUserId: string
          • userContext: any

        Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User }>

    • updatePasswordlessUser:function
      • updatePasswordlessUser(input: { email?: string | null; phoneNumber?: string | null; userContext: any; userId: string }): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>
      • Parameters

        • input: { email?: string | null; phoneNumber?: string | null; userContext: any; userId: string }
          • Optional email?: string | null
          • Optional phoneNumber?: string | null
          • userContext: any
          • userId: string

        Returns Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>

    ThirdPartyAPIOptions: APIOptions
    User: ({ email?: string; phoneNumber?: string } | { email: string; thirdParty: { id: string; userId: string } }) & { id: string; timeJoined: number }

    Variables

    Error: typeof default = Wrapper.Error

    Functions

    • Apple(config: TypeThirdPartyProviderAppleConfig): TypeProvider
    • Discord(config: TypeThirdPartyProviderDiscordConfig): TypeProvider
    • Facebook(config: TypeThirdPartyProviderFacebookConfig): TypeProvider
    • Github(config: TypeThirdPartyProviderGithubConfig): TypeProvider
    • Google(config: TypeThirdPartyProviderGoogleConfig): TypeProvider
    • GoogleWorkspaces(config: TypeThirdPartyProviderGoogleWorkspacesConfig): TypeProvider
    • consumeCode(input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
    • Parameters

      • input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }

      Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

    • createCode(input: ({ email: string } & { userContext?: any; userInputCode?: string }) | ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>
    • Parameters

      • input: ({ email: string } & { userContext?: any; userInputCode?: string }) | ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })

      Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>

    • createMagicLink(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<string>
    • createNewCodeForDevice(input: { deviceId: string; userContext?: any; userInputCode?: string }): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>
    • Parameters

      • input: { deviceId: string; userContext?: any; userInputCode?: string }
        • deviceId: string
        • Optional userContext?: any
        • Optional userInputCode?: string

      Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>

    • getUserById(userId: string, userContext?: any): Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>
    • Parameters

      • userId: string
      • userContext: any = {}

      Returns Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>

    • getUserByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>
    • Parameters

      • input: { phoneNumber: string; userContext?: any }
        • phoneNumber: string
        • Optional userContext?: any

      Returns Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>

    • getUserByThirdPartyInfo(thirdPartyId: string, thirdPartyUserId: string, userContext?: any): Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>
    • Parameters

      • thirdPartyId: string
      • thirdPartyUserId: string
      • userContext: any = {}

      Returns Promise<undefined | ({ email?: string; phoneNumber?: string } & { id: string; timeJoined: number }) | ({ email: string; thirdParty: { id: string; userId: string } } & { id: string; timeJoined: number })>

    • getUsersByEmail(email: string, userContext?: any): Promise<User[]>
    • init(config: TypeInput): RecipeListFunction
    • listCodesByDeviceId(input: { deviceId: string; userContext?: any }): Promise<undefined | DeviceType>
    • listCodesByEmail(input: { email: string; userContext?: any }): Promise<DeviceType[]>
    • listCodesByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<DeviceType[]>
    • listCodesByPreAuthSessionId(input: { preAuthSessionId: string; userContext?: any }): Promise<undefined | DeviceType>
    • passwordlessSignInUp(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: string; user: User }>
    • revokeAllCodes(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ status: "OK" }>
    • revokeCode(input: { codeId: string; userContext?: any }): Promise<{ status: "OK" }>
    • sendEmail(input: TypePasswordlessEmailDeliveryInput & { userContext?: any }): Promise<void>
    • sendSms(input: TypePasswordlessSmsDeliveryInput & { userContext?: any }): Promise<void>
    • thirdPartySignInUp(thirdPartyId: string, thirdPartyUserId: string, email: string, userContext?: any): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
    • updatePasswordlessUser(input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>
    • Parameters

      • input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }
        • Optional email?: null | string
        • Optional phoneNumber?: null | string
        • Optional userContext?: any
        • userId: string

      Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -recipe/thirdpartypasswordless | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/thirdpartypasswordless

    Index

    References

    Re-exports TypeProvider

    Type aliases

    APIInterface: { appleRedirectHandlerPOST: undefined | ((input: { code: string; options: ThirdPartyAPIOptions; state: string; userContext: any }) => Promise<void>); authorisationUrlGET: undefined | ((input: { options: ThirdPartyAPIOptions; provider: TypeProvider; userContext: any }) => Promise<{ status: "OK"; url: string } | GeneralErrorResponse>); consumeCodePOST: undefined | ((input: ({ deviceId: string; preAuthSessionId: string; userInputCode: string } | { linkCode: string; preAuthSessionId: string }) & { options: PasswordlessAPIOptions; userContext: any }) => Promise<{ createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | GeneralErrorResponse | { status: "RESTART_FLOW_ERROR" }>); createCodePOST: undefined | ((input: ({ email: string } | { phoneNumber: string }) & { options: PasswordlessAPIOptions; userContext: any }) => Promise<{ deviceId: string; flowType: "USER_INPUT_CODE" | "MAGIC_LINK" | "USER_INPUT_CODE_AND_MAGIC_LINK"; preAuthSessionId: string; status: "OK" } | GeneralErrorResponse>); passwordlessUserEmailExistsGET: undefined | ((input: { email: string; options: PasswordlessAPIOptions; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>); passwordlessUserPhoneNumberExistsGET: undefined | ((input: { options: PasswordlessAPIOptions; phoneNumber: string; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>); resendCodePOST: undefined | ((input: { deviceId: string; preAuthSessionId: string } & { options: PasswordlessAPIOptions; userContext: any }) => Promise<GeneralErrorResponse | { status: "RESTART_FLOW_ERROR" | "OK" }>); thirdPartySignInUpPOST: undefined | ((input: { authCodeResponse?: any; clientId?: string; code: string; options: ThirdPartyAPIOptions; provider: TypeProvider; redirectURI: string; userContext: any }) => Promise<{ authCodeResponse: any; createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | GeneralErrorResponse | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" }>) }

    Type declaration

    • appleRedirectHandlerPOST: undefined | ((input: { code: string; options: ThirdPartyAPIOptions; state: string; userContext: any }) => Promise<void>)
    • authorisationUrlGET: undefined | ((input: { options: ThirdPartyAPIOptions; provider: TypeProvider; userContext: any }) => Promise<{ status: "OK"; url: string } | GeneralErrorResponse>)
    • consumeCodePOST: undefined | ((input: ({ deviceId: string; preAuthSessionId: string; userInputCode: string } | { linkCode: string; preAuthSessionId: string }) & { options: PasswordlessAPIOptions; userContext: any }) => Promise<{ createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | GeneralErrorResponse | { status: "RESTART_FLOW_ERROR" }>)
    • createCodePOST: undefined | ((input: ({ email: string } | { phoneNumber: string }) & { options: PasswordlessAPIOptions; userContext: any }) => Promise<{ deviceId: string; flowType: "USER_INPUT_CODE" | "MAGIC_LINK" | "USER_INPUT_CODE_AND_MAGIC_LINK"; preAuthSessionId: string; status: "OK" } | GeneralErrorResponse>)
    • passwordlessUserEmailExistsGET: undefined | ((input: { email: string; options: PasswordlessAPIOptions; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>)
    • passwordlessUserPhoneNumberExistsGET: undefined | ((input: { options: PasswordlessAPIOptions; phoneNumber: string; userContext: any }) => Promise<{ exists: boolean; status: "OK" } | GeneralErrorResponse>)
    • resendCodePOST: undefined | ((input: { deviceId: string; preAuthSessionId: string } & { options: PasswordlessAPIOptions; userContext: any }) => Promise<GeneralErrorResponse | { status: "RESTART_FLOW_ERROR" | "OK" }>)
    • thirdPartySignInUpPOST: undefined | ((input: { authCodeResponse?: any; clientId?: string; code: string; options: ThirdPartyAPIOptions; provider: TypeProvider; redirectURI: string; userContext: any }) => Promise<{ authCodeResponse: any; createdNewUser: boolean; session: SessionContainer; status: "OK"; user: User } | GeneralErrorResponse | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" }>)
    PasswordlessAPIOptions: APIOptions
    RecipeInterface: { consumeCode: any; createCode: any; createNewCodeForDevice: any; getUserById: any; getUserByPhoneNumber: any; getUserByThirdPartyInfo: any; getUsersByEmail: any; listCodesByDeviceId: any; listCodesByEmail: any; listCodesByPhoneNumber: any; listCodesByPreAuthSessionId: any; revokeAllCodes: any; revokeCode: any; thirdPartySignInUp: any; updatePasswordlessUser: any }

    Type declaration

    • consumeCode:function
      • consumeCode(input: { deviceId: string; preAuthSessionId: string; userContext: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
      • Parameters

        • input: { deviceId: string; preAuthSessionId: string; userContext: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext: any }

        Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

    • createCode:function
      • createCode(input: ({ email: string } & { userContext: any; userInputCode?: string }) & ({ phoneNumber: string } & { userContext: any; userInputCode?: string })): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>
      • Parameters

        • input: ({ email: string } & { userContext: any; userInputCode?: string }) & ({ phoneNumber: string } & { userContext: any; userInputCode?: string })

        Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>

    • createNewCodeForDevice:function
      • createNewCodeForDevice(input: { deviceId: string; userContext: any; userInputCode?: string }): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>
      • Parameters

        • input: { deviceId: string; userContext: any; userInputCode?: string }
          • deviceId: string
          • userContext: any
          • Optional userInputCode?: string

        Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>

    • getUserById:function
      • getUserById(input: { userContext: any; userId: string }): Promise<undefined | User>
    • getUserByPhoneNumber:function
      • getUserByPhoneNumber(input: { phoneNumber: string; userContext: any }): Promise<undefined | User>
    • getUserByThirdPartyInfo:function
      • getUserByThirdPartyInfo(input: { thirdPartyId: string; thirdPartyUserId: string; userContext: any }): Promise<undefined | User>
    • getUsersByEmail:function
      • getUsersByEmail(input: { email: string; userContext: any }): Promise<User[]>
    • listCodesByDeviceId:function
      • listCodesByDeviceId(input: { deviceId: string; userContext: any }): Promise<undefined | DeviceType>
    • listCodesByEmail:function
      • listCodesByEmail(input: { email: string; userContext: any }): Promise<DeviceType[]>
    • listCodesByPhoneNumber:function
      • listCodesByPhoneNumber(input: { phoneNumber: string; userContext: any }): Promise<DeviceType[]>
    • listCodesByPreAuthSessionId:function
      • listCodesByPreAuthSessionId(input: { preAuthSessionId: string; userContext: any }): Promise<undefined | DeviceType>
    • revokeAllCodes:function
      • revokeAllCodes(input: { email: string; userContext: any } | { phoneNumber: string; userContext: any }): Promise<{ status: "OK" }>
    • revokeCode:function
      • revokeCode(input: { codeId: string; userContext: any }): Promise<{ status: "OK" }>
    • thirdPartySignInUp:function
      • thirdPartySignInUp(input: { email: string; thirdPartyId: string; thirdPartyUserId: string; userContext: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
      • Parameters

        • input: { email: string; thirdPartyId: string; thirdPartyUserId: string; userContext: any }
          • email: string
          • thirdPartyId: string
          • thirdPartyUserId: string
          • userContext: any

        Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User }>

    • updatePasswordlessUser:function
      • updatePasswordlessUser(input: { email?: string | null; phoneNumber?: string | null; userContext: any; userId: string }): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>
      • Parameters

        • input: { email?: string | null; phoneNumber?: string | null; userContext: any; userId: string }
          • Optional email?: string | null
          • Optional phoneNumber?: string | null
          • userContext: any
          • userId: string

        Returns Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>

    ThirdPartyAPIOptions: APIOptions
    User: ({ email?: string; phoneNumber?: string } | { email: string; thirdParty: { id: string; userId: string } }) & { id: string; timeJoined: number }

    Variables

    Error: typeof default = Wrapper.Error

    Functions

    • Apple(config: TypeThirdPartyProviderAppleConfig): TypeProvider
    • Discord(config: TypeThirdPartyProviderDiscordConfig): TypeProvider
    • Facebook(config: TypeThirdPartyProviderFacebookConfig): TypeProvider
    • Github(config: TypeThirdPartyProviderGithubConfig): TypeProvider
    • Google(config: TypeThirdPartyProviderGoogleConfig): TypeProvider
    • GoogleWorkspaces(config: TypeThirdPartyProviderGoogleWorkspacesConfig): TypeProvider
    • consumeCode(input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
    • Parameters

      • input: { deviceId: string; preAuthSessionId: string; userContext?: any; userInputCode: string } | { linkCode: string; preAuthSessionId: string; userContext?: any }

      Returns Promise<{ createdNewUser: boolean; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

    • createCode(input: ({ email: string } & { userContext?: any; userInputCode?: string }) & ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>
    • Parameters

      • input: ({ email: string } & { userContext?: any; userInputCode?: string }) & ({ phoneNumber: string } & { userContext?: any; userInputCode?: string })

      Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string }>

    • createMagicLink(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<string>
    • createNewCodeForDevice(input: { deviceId: string; userContext?: any; userInputCode?: string }): Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>
    • Parameters

      • input: { deviceId: string; userContext?: any; userInputCode?: string }
        • deviceId: string
        • Optional userContext?: any
        • Optional userInputCode?: string

      Returns Promise<{ codeId: string; codeLifetime: number; deviceId: string; linkCode: string; preAuthSessionId: string; status: "OK"; timeCreated: number; userInputCode: string } | { status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR" }>

    • getUserById(userId: string, userContext?: any): Promise<undefined | User>
    • getUserByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<undefined | User>
    • getUserByThirdPartyInfo(thirdPartyId: string, thirdPartyUserId: string, userContext?: any): Promise<undefined | User>
    • getUsersByEmail(email: string, userContext?: any): Promise<User[]>
    • init(config: TypeInput): RecipeListFunction
    • listCodesByDeviceId(input: { deviceId: string; userContext?: any }): Promise<undefined | DeviceType>
    • listCodesByEmail(input: { email: string; userContext?: any }): Promise<DeviceType[]>
    • listCodesByPhoneNumber(input: { phoneNumber: string; userContext?: any }): Promise<DeviceType[]>
    • listCodesByPreAuthSessionId(input: { preAuthSessionId: string; userContext?: any }): Promise<undefined | DeviceType>
    • passwordlessSignInUp(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ createdNewUser: boolean; status: string; user: User }>
    • revokeAllCodes(input: { email: string; userContext?: any } | { phoneNumber: string; userContext?: any }): Promise<{ status: "OK" }>
    • revokeCode(input: { codeId: string; userContext?: any }): Promise<{ status: "OK" }>
    • sendEmail(input: TypePasswordlessEmailDeliveryInput & { userContext?: any }): Promise<void>
    • sendSms(input: TypePasswordlessSmsDeliveryInput & { userContext?: any }): Promise<void>
    • thirdPartySignInUp(thirdPartyId: string, thirdPartyUserId: string, email: string, userContext?: any): Promise<{ createdNewUser: boolean; status: "OK"; user: User }>
    • updatePasswordlessUser(input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>
    • Parameters

      • input: { email?: null | string; phoneNumber?: null | string; userContext?: any; userId: string }
        • Optional email?: null | string
        • Optional phoneNumber?: null | string
        • Optional userContext?: any
        • userId: string

      Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/recipe_usermetadata.html b/docs/modules/recipe_usermetadata.html deleted file mode 100644 index b98210fbe..000000000 --- a/docs/modules/recipe_usermetadata.html +++ /dev/null @@ -1,18 +0,0 @@ -<<<<<<< HEAD -recipe/usermetadata | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/usermetadata

    Index

    Type aliases

    RecipeInterface: { clearUserMetadata: any; getUserMetadata: any; updateUserMetadata: any }

    Type declaration

    Functions

    • clearUserMetadata(userId: string, userContext?: any): Promise<{ status: "OK" }>
    • getUserMetadata(userId: string, userContext?: any): Promise<{ metadata: any; status: "OK" }>
    • init(config?: TypeInput): RecipeListFunction
    • updateUserMetadata(userId: string, metadataUpdate: JSONObject, userContext?: any): Promise<{ metadata: JSONObject; status: "OK" }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/docs/modules/recipe_userroles.html b/docs/modules/recipe_userroles.html deleted file mode 100644 index 15bc8a5f1..000000000 --- a/docs/modules/recipe_userroles.html +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -recipe/userroles | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/userroles

    Index

    Type aliases

    RecipeInterface: { addRoleToUser: any; createNewRoleOrAddPermissions: any; deleteRole: any; getAllRoles: any; getPermissionsForRole: any; getRolesForUser: any; getRolesThatHavePermission: any; getUsersThatHaveRole: any; removePermissionsFromRole: any; removeUserRole: any }

    Type declaration

    • addRoleToUser:function
      • addRoleToUser(input: { role: string; userContext: any; userId: string }): Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; userContext: any; userId: string }
          • role: string
          • userContext: any
          • userId: string

        Returns Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

    • createNewRoleOrAddPermissions:function
      • createNewRoleOrAddPermissions(input: { permissions: string[]; role: string; userContext: any }): Promise<{ createdNewRole: boolean; status: "OK" }>
      • Parameters

        • input: { permissions: string[]; role: string; userContext: any }
          • permissions: string[]
          • role: string
          • userContext: any

        Returns Promise<{ createdNewRole: boolean; status: "OK" }>

    • deleteRole:function
      • deleteRole(input: { role: string; userContext: any }): Promise<{ didRoleExist: boolean; status: "OK" }>
      • Parameters

        • input: { role: string; userContext: any }
          • role: string
          • userContext: any

        Returns Promise<{ didRoleExist: boolean; status: "OK" }>

    • getAllRoles:function
      • getAllRoles(input: { userContext: any }): Promise<{ roles: string[]; status: "OK" }>
    • getPermissionsForRole:function
      • getPermissionsForRole(input: { role: string; userContext: any }): Promise<{ permissions: string[]; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; userContext: any }
          • role: string
          • userContext: any

        Returns Promise<{ permissions: string[]; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

    • getRolesForUser:function
      • getRolesForUser(input: { userContext: any; userId: string }): Promise<{ roles: string[]; status: "OK" }>
      • Parameters

        • input: { userContext: any; userId: string }
          • userContext: any
          • userId: string

        Returns Promise<{ roles: string[]; status: "OK" }>

    • getRolesThatHavePermission:function
      • getRolesThatHavePermission(input: { permission: string; userContext: any }): Promise<{ roles: string[]; status: "OK" }>
      • Parameters

        • input: { permission: string; userContext: any }
          • permission: string
          • userContext: any

        Returns Promise<{ roles: string[]; status: "OK" }>

    • getUsersThatHaveRole:function
      • getUsersThatHaveRole(input: { role: string; userContext: any }): Promise<{ status: "OK"; users: string[] } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; userContext: any }
          • role: string
          • userContext: any

        Returns Promise<{ status: "OK"; users: string[] } | { status: "UNKNOWN_ROLE_ERROR" }>

    • removePermissionsFromRole:function
      • removePermissionsFromRole(input: { permissions: string[]; role: string; userContext: any }): Promise<{ status: "OK" | "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { permissions: string[]; role: string; userContext: any }
          • permissions: string[]
          • role: string
          • userContext: any

        Returns Promise<{ status: "OK" | "UNKNOWN_ROLE_ERROR" }>

    • removeUserRole:function
      • removeUserRole(input: { role: string; userContext: any; userId: string }): Promise<{ didUserHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; userContext: any; userId: string }
          • role: string
          • userContext: any
          • userId: string

        Returns Promise<{ didUserHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

    Variables

    PermissionClaim: PermissionClaimClass = ...
    UserRoleClaim: UserRoleClaimClass = ...

    Functions

    • addRoleToUser(userId: string, role: string, userContext?: any): Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
    • Parameters

      • userId: string
      • role: string
      • Optional userContext: any

      Returns Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

    • createNewRoleOrAddPermissions(role: string, permissions: string[], userContext?: any): Promise<{ createdNewRole: boolean; status: "OK" }>
    • deleteRole(role: string, userContext?: any): Promise<{ didRoleExist: boolean; status: "OK" }>
    • getAllRoles(userContext?: any): Promise<{ roles: string[]; status: "OK" }>
    • getPermissionsForRole(role: string, userContext?: any): Promise<{ permissions: string[]; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
    • Parameters

      • role: string
      • Optional userContext: any

      Returns Promise<{ permissions: string[]; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

    • getRolesForUser(userId: string, userContext?: any): Promise<{ roles: string[]; status: "OK" }>
    • getRolesThatHavePermission(permission: string, userContext?: any): Promise<{ roles: string[]; status: "OK" }>
    • getUsersThatHaveRole(role: string, userContext?: any): Promise<{ status: "OK"; users: string[] } | { status: "UNKNOWN_ROLE_ERROR" }>
    • init(config?: TypeInput): RecipeListFunction
    • removePermissionsFromRole(role: string, permissions: string[], userContext?: any): Promise<{ status: "OK" | "UNKNOWN_ROLE_ERROR" }>
    • removeUserRole(userId: string, role: string, userContext?: any): Promise<{ didUserHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
    • Parameters

      • userId: string
      • role: string
      • Optional userContext: any

      Returns Promise<{ didUserHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    -======= -recipe/userroles | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/userroles

    Index

    Type aliases

    RecipeInterface: { addRoleToUser: any; createNewRoleOrAddPermissions: any; deleteRole: any; getAllRoles: any; getPermissionsForRole: any; getRolesForUser: any; getRolesThatHavePermission: any; getUsersThatHaveRole: any; removePermissionsFromRole: any; removeUserRole: any }

    Type declaration

    • addRoleToUser:function
      • addRoleToUser(input: { role: string; userContext: any; userId: string }): Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; userContext: any; userId: string }
          • role: string
          • userContext: any
          • userId: string

        Returns Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

    • createNewRoleOrAddPermissions:function
      • createNewRoleOrAddPermissions(input: { permissions: string[]; role: string; userContext: any }): Promise<{ createdNewRole: boolean; status: "OK" }>
      • Parameters

        • input: { permissions: string[]; role: string; userContext: any }
          • permissions: string[]
          • role: string
          • userContext: any

        Returns Promise<{ createdNewRole: boolean; status: "OK" }>

    • deleteRole:function
      • deleteRole(input: { role: string; userContext: any }): Promise<{ didRoleExist: boolean; status: "OK" }>
      • Parameters

        • input: { role: string; userContext: any }
          • role: string
          • userContext: any

        Returns Promise<{ didRoleExist: boolean; status: "OK" }>

    • getAllRoles:function
      • getAllRoles(input: { userContext: any }): Promise<{ roles: string[]; status: "OK" }>
    • getPermissionsForRole:function
      • getPermissionsForRole(input: { role: string; userContext: any }): Promise<{ permissions: string[]; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; userContext: any }
          • role: string
          • userContext: any

        Returns Promise<{ permissions: string[]; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

    • getRolesForUser:function
      • getRolesForUser(input: { userContext: any; userId: string }): Promise<{ roles: string[]; status: "OK" }>
      • Parameters

        • input: { userContext: any; userId: string }
          • userContext: any
          • userId: string

        Returns Promise<{ roles: string[]; status: "OK" }>

    • getRolesThatHavePermission:function
      • getRolesThatHavePermission(input: { permission: string; userContext: any }): Promise<{ roles: string[]; status: "OK" }>
      • Parameters

        • input: { permission: string; userContext: any }
          • permission: string
          • userContext: any

        Returns Promise<{ roles: string[]; status: "OK" }>

    • getUsersThatHaveRole:function
      • getUsersThatHaveRole(input: { role: string; userContext: any }): Promise<{ status: "OK"; users: string[] } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; userContext: any }
          • role: string
          • userContext: any

        Returns Promise<{ status: "OK"; users: string[] } | { status: "UNKNOWN_ROLE_ERROR" }>

    • removePermissionsFromRole:function
      • removePermissionsFromRole(input: { permissions: string[]; role: string; userContext: any }): Promise<{ status: "OK" | "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { permissions: string[]; role: string; userContext: any }
          • permissions: string[]
          • role: string
          • userContext: any

        Returns Promise<{ status: "OK" | "UNKNOWN_ROLE_ERROR" }>

    • removeUserRole:function
      • removeUserRole(input: { role: string; userContext: any; userId: string }): Promise<{ didUserHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; userContext: any; userId: string }
          • role: string
          • userContext: any
          • userId: string

        Returns Promise<{ didUserHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

    Variables

    PermissionClaim: PermissionClaimClass = ...
    UserRoleClaim: UserRoleClaimClass = ...

    Functions

    • addRoleToUser(userId: string, role: string, userContext?: any): Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
    • Parameters

      • userId: string
      • role: string
      • Optional userContext: any

      Returns Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

    • createNewRoleOrAddPermissions(role: string, permissions: string[], userContext?: any): Promise<{ createdNewRole: boolean; status: "OK" }>
    • deleteRole(role: string, userContext?: any): Promise<{ didRoleExist: boolean; status: "OK" }>
    • getAllRoles(userContext?: any): Promise<{ roles: string[]; status: "OK" }>
    • getPermissionsForRole(role: string, userContext?: any): Promise<{ permissions: string[]; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
    • Parameters

      • role: string
      • Optional userContext: any

      Returns Promise<{ permissions: string[]; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

    • getRolesForUser(userId: string, userContext?: any): Promise<{ roles: string[]; status: "OK" }>
    • getRolesThatHavePermission(permission: string, userContext?: any): Promise<{ roles: string[]; status: "OK" }>
    • getUsersThatHaveRole(role: string, userContext?: any): Promise<{ status: "OK"; users: string[] } | { status: "UNKNOWN_ROLE_ERROR" }>
    • init(config?: TypeInput): RecipeListFunction
    • removePermissionsFromRole(role: string, permissions: string[], userContext?: any): Promise<{ status: "OK" | "UNKNOWN_ROLE_ERROR" }>
    • removeUserRole(userId: string, role: string, userContext?: any): Promise<{ didUserHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
    • Parameters

      • userId: string
      • role: string
      • Optional userContext: any

      Returns Promise<{ didUserHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>

    Legend

    • Variable
    • Function
    • Function with type parameter
    • Type alias
    • Class
    • Class with type parameter
    • Interface

    Settings

    Theme

    Generated using TypeDoc

    ->>>>>>> 13.0 diff --git a/examples/express/with-thirdpartyemailpassword/index.js b/examples/express/with-thirdpartyemailpassword/index.js index e161f04d6..5c7340c4b 100644 --- a/examples/express/with-thirdpartyemailpassword/index.js +++ b/examples/express/with-thirdpartyemailpassword/index.js @@ -7,6 +7,7 @@ let Session = require("../../../recipe/session"); let { verifySession } = require("../../../recipe/session/framework/express"); let { middleware, errorHandler } = require("../../../framework/express"); let ThirdPartyEmailPassword = require("../../../recipe/thirdpartyemailpassword"); +let Dashboard = require("../../../recipe/dashboard"); let axios = require("axios"); // Change these values if you want to run the server on another adress @@ -112,6 +113,7 @@ supertokens.init({ ], }), Session.init(), + Dashboard.init(), ], }); diff --git a/lib/build/framework/awsLambda/framework.js b/lib/build/framework/awsLambda/framework.js index c8d01c26b..36c3dc70e 100644 --- a/lib/build/framework/awsLambda/framework.js +++ b/lib/build/framework/awsLambda/framework.js @@ -44,6 +44,7 @@ const utils_2 = require("../utils"); const constants_1 = require("../constants"); const supertokens_1 = __importDefault(require("../../supertokens")); const querystring_1 = require("querystring"); +const url_1 = require("url"); class AWSRequest extends request_1.BaseRequest { constructor(event) { super(); @@ -115,16 +116,23 @@ class AWSRequest extends request_1.BaseRequest { if (this.event.headers === undefined || this.event.headers === null) { return undefined; } - return utils_2.normalizeHeaderValue(this.event.headers[key]); + return utils_2.normalizeHeaderValue(utils_1.getFromObjectCaseInsensitive(key, this.event.headers)); }; this.getOriginalURL = () => { let path = this.event.path; + let queryParams = this.event.queryStringParameters; if (path === undefined) { path = this.event.requestContext.http.path; let stage = this.event.requestContext.stage; if (stage !== undefined && path.startsWith(`/${stage}`)) { path = path.slice(stage.length + 1); } + if (queryParams !== undefined && queryParams !== null) { + let urlString = "https://exmaple.com" + path; + let url = new url_1.URL(urlString); + Object.keys(queryParams).forEach((el) => url.searchParams.append(el, queryParams[el])); + path = url.pathname + url.search; + } } return path; }; diff --git a/lib/build/framework/fastify/framework.js b/lib/build/framework/fastify/framework.js index 54d4c879f..8c375f9ea 100644 --- a/lib/build/framework/fastify/framework.js +++ b/lib/build/framework/fastify/framework.js @@ -85,7 +85,7 @@ class FastifyRequest extends request_1.BaseRequest { return utils_2.getCookieValueFromHeaders(this.request.headers, key); }; this.getHeaderValue = (key) => { - return utils_2.normalizeHeaderValue(this.request.headers[key]); + return utils_2.normalizeHeaderValue(utils_1.getFromObjectCaseInsensitive(key, this.request.headers)); }; this.getOriginalURL = () => { return this.request.url; diff --git a/lib/build/framework/utils.js b/lib/build/framework/utils.js index 58c51cd08..ee94f30de 100644 --- a/lib/build/framework/utils.js +++ b/lib/build/framework/utils.js @@ -56,6 +56,7 @@ const body_parser_1 = require("body-parser"); const http_1 = require("http"); const error_1 = __importDefault(require("../error")); const constants_1 = require("./constants"); +const utils_1 = require("../utils"); function getCookieValueFromHeaders(headers, key) { if (headers === undefined || headers === null) { return undefined; @@ -78,7 +79,7 @@ function getCookieValueFromIncomingMessage(request, key) { } exports.getCookieValueFromIncomingMessage = getCookieValueFromIncomingMessage; function getHeaderValueFromIncomingMessage(request, key) { - return normalizeHeaderValue(request.headers[key]); + return normalizeHeaderValue(utils_1.getFromObjectCaseInsensitive(key, request.headers)); } exports.getHeaderValueFromIncomingMessage = getHeaderValueFromIncomingMessage; function normalizeHeaderValue(value) { @@ -154,29 +155,16 @@ function assertThatBodyParserHasBeenUsedForExpressLikeRequest(method, request) { let jsonParser = body_parser_1.json(); let err = yield new Promise((resolve) => { let resolvedCalled = false; - /** - * Nextjs allow users to disable the default parser. - * To handle that scenario, we are still parsing the request body - */ - if (request.__supertokensFromNextJS === true) { - /** - * the setImmediate here is to counter the next.js issue - * where the json parser would not resolve and thus the request - * just hangs forever. Next.JS does json parsing on its own. - */ - setImmediate(() => { + if (request.readable) { + jsonParser(request, new http_1.ServerResponse(request), (e) => { if (!resolvedCalled) { resolvedCalled = true; - resolve(undefined); + resolve(e); } }); + } else { + resolve(undefined); } - jsonParser(request, new http_1.ServerResponse(request), (e) => { - if (!resolvedCalled) { - resolvedCalled = true; - resolve(e); - } - }); }); if (err !== undefined) { throw new error_1.default({ @@ -192,7 +180,7 @@ function assertThatBodyParserHasBeenUsedForExpressLikeRequest(method, request) { if (err !== undefined) { throw new error_1.default({ type: error_1.default.BAD_INPUT_ERROR, - message: "API input error: Please make sure to pass valid URL query params", + message: "API input error: Please make sure to pass valid url encoded form in the request body", }); } } @@ -204,35 +192,18 @@ function assertFormDataBodyParserHasBeenUsedForExpressLikeRequest(request) { return __awaiter(this, void 0, void 0, function* () { let parser = body_parser_1.urlencoded({ extended: true }); let err = yield new Promise((resolve) => { - let resolvedCalled = false; - /** - * Nextjs allow users to disable the default parser. - * To handle that scenario, we are still parsing the request body - */ - if (request.__supertokensFromNextJS === true) { - /** - * the setImmediate here is to counter the next.js issue - * where the json parser would not resolve and thus the request - * just hangs forever. Next.JS does json parsing on its own. - */ - setImmediate(() => { - if (!resolvedCalled) { - resolvedCalled = true; - resolve(undefined); - } + if (request.readable) { + parser(request, new http_1.ServerResponse(request), (e) => { + resolve(e); }); + } else { + resolve(undefined); } - parser(request, new http_1.ServerResponse(request), (e) => { - if (!resolvedCalled) { - resolvedCalled = true; - resolve(e); - } - }); }); if (err !== undefined) { throw new error_1.default({ type: error_1.default.BAD_INPUT_ERROR, - message: "API input error: Please make sure to pass valid URL query params", + message: "API input error: Please make sure to pass valid url encoded form in the request body", }); } }); diff --git a/lib/build/index.d.ts b/lib/build/index.d.ts index a20f04e90..7b3731d9e 100644 --- a/lib/build/index.d.ts +++ b/lib/build/index.d.ts @@ -12,6 +12,7 @@ export default class SuperTokensWrapper { limit?: number; paginationToken?: string; includeRecipeIds?: string[]; + query?: object; }): Promise<{ users: User[]; nextPaginationToken?: string; @@ -20,6 +21,7 @@ export default class SuperTokensWrapper { limit?: number; paginationToken?: string; includeRecipeIds?: string[]; + query?: object; }): Promise<{ users: User[]; nextPaginationToken?: string; diff --git a/lib/build/processState.d.ts b/lib/build/processState.d.ts index aa2d9a2a8..9decf8458 100644 --- a/lib/build/processState.d.ts +++ b/lib/build/processState.d.ts @@ -1,9 +1,9 @@ // @ts-nocheck export declare enum PROCESS_STATE { CALLING_SERVICE_IN_VERIFY = 0, - CALLING_SERVICE_IN_GET_HANDSHAKE_INFO = 1, - CALLING_SERVICE_IN_GET_API_VERSION = 2, - CALLING_SERVICE_IN_REQUEST_HELPER = 3, + CALLING_SERVICE_IN_GET_API_VERSION = 1, + CALLING_SERVICE_IN_REQUEST_HELPER = 2, + MULTI_JWKS_VALIDATION = 3, } export declare class ProcessState { history: PROCESS_STATE[]; diff --git a/lib/build/processState.js b/lib/build/processState.js index cc8358844..847a97b15 100644 --- a/lib/build/processState.js +++ b/lib/build/processState.js @@ -49,10 +49,9 @@ exports.ProcessState = exports.PROCESS_STATE = void 0; var PROCESS_STATE; (function (PROCESS_STATE) { PROCESS_STATE[(PROCESS_STATE["CALLING_SERVICE_IN_VERIFY"] = 0)] = "CALLING_SERVICE_IN_VERIFY"; - PROCESS_STATE[(PROCESS_STATE["CALLING_SERVICE_IN_GET_HANDSHAKE_INFO"] = 1)] = - "CALLING_SERVICE_IN_GET_HANDSHAKE_INFO"; - PROCESS_STATE[(PROCESS_STATE["CALLING_SERVICE_IN_GET_API_VERSION"] = 2)] = "CALLING_SERVICE_IN_GET_API_VERSION"; - PROCESS_STATE[(PROCESS_STATE["CALLING_SERVICE_IN_REQUEST_HELPER"] = 3)] = "CALLING_SERVICE_IN_REQUEST_HELPER"; + PROCESS_STATE[(PROCESS_STATE["CALLING_SERVICE_IN_GET_API_VERSION"] = 1)] = "CALLING_SERVICE_IN_GET_API_VERSION"; + PROCESS_STATE[(PROCESS_STATE["CALLING_SERVICE_IN_REQUEST_HELPER"] = 2)] = "CALLING_SERVICE_IN_REQUEST_HELPER"; + PROCESS_STATE[(PROCESS_STATE["MULTI_JWKS_VALIDATION"] = 3)] = "MULTI_JWKS_VALIDATION"; })((PROCESS_STATE = exports.PROCESS_STATE || (exports.PROCESS_STATE = {}))); class ProcessState { constructor() { diff --git a/lib/build/querier.d.ts b/lib/build/querier.d.ts index 791b32e0a..d6140e86e 100644 --- a/lib/build/querier.d.ts +++ b/lib/build/querier.d.ts @@ -22,9 +22,10 @@ export declare class Querier { }[], apiKey?: string ): void; - sendPostRequest: (path: NormalisedURLPath, body: any) => Promise; - sendDeleteRequest: (path: NormalisedURLPath, body: any) => Promise; + sendPostRequest: (path: NormalisedURLPath, body: any) => Promise; + sendDeleteRequest: (path: NormalisedURLPath, body: any, params?: any) => Promise; sendGetRequest: (path: NormalisedURLPath, params: any) => Promise; sendPutRequest: (path: NormalisedURLPath, body: any) => Promise; + getAllCoreUrlsForPath(path: string): string[]; private sendRequestHelper; } diff --git a/lib/build/querier.js b/lib/build/querier.js index 4f184e7a0..267e3f830 100644 --- a/lib/build/querier.js +++ b/lib/build/querier.js @@ -135,7 +135,7 @@ class Querier { ); }); // path should start with "/" - this.sendDeleteRequest = (path, body) => + this.sendDeleteRequest = (path, body, params) => __awaiter(this, void 0, void 0, function* () { var _c; return this.sendRequestHelper( @@ -159,6 +159,7 @@ class Querier { url, data: body, headers, + params, }); }), ((_c = this.__hosts) === null || _c === void 0 ? void 0 : _c.length) || 0 @@ -232,13 +233,14 @@ class Querier { } let currentDomain = this.__hosts[Querier.lastTriedIndex].domain.getAsStringDangerous(); let currentBasePath = this.__hosts[Querier.lastTriedIndex].basePath.getAsStringDangerous(); + const url = currentDomain + currentBasePath + path.getAsStringDangerous(); Querier.lastTriedIndex++; Querier.lastTriedIndex = Querier.lastTriedIndex % this.__hosts.length; try { processState_1.ProcessState.getInstance().addState( processState_1.PROCESS_STATE.CALLING_SERVICE_IN_REQUEST_HELPER ); - let response = yield axiosFunction(currentDomain + currentBasePath + path.getAsStringDangerous()); + let response = yield axiosFunction(url); if (process.env.TEST_MODE === "testing") { Querier.hostsAliveForTesting.add(currentDomain + currentBasePath); } @@ -295,6 +297,17 @@ class Querier { Querier.hostsAliveForTesting = new Set(); } } + getAllCoreUrlsForPath(path) { + if (this.__hosts === undefined) { + return []; + } + const normalisedPath = new normalisedURLPath_1.default(path); + return this.__hosts.map((h) => { + const currentDomain = h.domain.getAsStringDangerous(); + const currentBasePath = h.basePath.getAsStringDangerous(); + return currentDomain + currentBasePath + normalisedPath.getAsStringDangerous(); + }); + } } exports.Querier = Querier; Querier.initCalled = false; diff --git a/lib/build/recipe/dashboard/api/analytics.d.ts b/lib/build/recipe/dashboard/api/analytics.d.ts new file mode 100644 index 000000000..32bbb6d19 --- /dev/null +++ b/lib/build/recipe/dashboard/api/analytics.d.ts @@ -0,0 +1,6 @@ +// @ts-nocheck +import { APIInterface, APIOptions } from "../types"; +export declare type Response = { + status: "OK"; +}; +export default function analyticsPost(_: APIInterface, options: APIOptions): Promise; diff --git a/lib/build/recipe/dashboard/api/analytics.js b/lib/build/recipe/dashboard/api/analytics.js new file mode 100644 index 000000000..0da73942f --- /dev/null +++ b/lib/build/recipe/dashboard/api/analytics.js @@ -0,0 +1,124 @@ +"use strict"; +/* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * 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. + */ +var __awaiter = + (this && this.__awaiter) || + function (thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P + ? value + : new P(function (resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; +Object.defineProperty(exports, "__esModule", { value: true }); +const supertokens_1 = __importDefault(require("../../../supertokens")); +const querier_1 = require("../../../querier"); +const normalisedURLPath_1 = __importDefault(require("../../../normalisedURLPath")); +const version_1 = require("../../../version"); +const error_1 = __importDefault(require("../../../error")); +const axios_1 = __importDefault(require("axios")); +function analyticsPost(_, options) { + return __awaiter(this, void 0, void 0, function* () { + // If telemetry is disabled, dont send any event + if (!supertokens_1.default.getInstanceOrThrowError().telemetryEnabled) { + return { + status: "OK", + }; + } + const { email, dashboardVersion } = yield options.req.getJSONBody(); + if (email === undefined) { + throw new error_1.default({ + message: "Missing required property 'email'", + type: error_1.default.BAD_INPUT_ERROR, + }); + } + if (dashboardVersion === undefined) { + throw new error_1.default({ + message: "Missing required property 'dashboardVersion'", + type: error_1.default.BAD_INPUT_ERROR, + }); + } + let telemetryId; + let numberOfUsers; + try { + let querier = querier_1.Querier.getNewInstanceOrThrowError(options.recipeId); + let response = yield querier.sendGetRequest(new normalisedURLPath_1.default("/telemetry"), {}); + if (response.exists) { + telemetryId = response.telemetryId; + } + numberOfUsers = yield supertokens_1.default.getInstanceOrThrowError().getUserCount(); + } catch (_) { + // If either telemetry id API or user count fetch fails, no event should be sent + return { + status: "OK", + }; + } + const { apiDomain, websiteDomain, appName } = options.appInfo; + const data = { + websiteDomain: websiteDomain.getAsStringDangerous(), + apiDomain: apiDomain.getAsStringDangerous(), + appName, + sdk: "node", + sdkVersion: version_1.version, + telemetryId, + numberOfUsers, + email, + dashboardVersion, + }; + try { + yield axios_1.default({ + url: "https://api.supertokens.com/0/st/telemetry", + method: "POST", + data, + headers: { + "api-version": 3, + }, + }); + } catch (e) { + // Ignored + } + return { + status: "OK", + }; + }); +} +exports.default = analyticsPost; diff --git a/lib/build/recipe/dashboard/api/implementation.js b/lib/build/recipe/dashboard/api/implementation.js index c87c7848b..730bcc1b0 100644 --- a/lib/build/recipe/dashboard/api/implementation.js +++ b/lib/build/recipe/dashboard/api/implementation.js @@ -52,7 +52,9 @@ var __importDefault = Object.defineProperty(exports, "__esModule", { value: true }); const normalisedURLDomain_1 = __importDefault(require("../../../normalisedURLDomain")); const normalisedURLPath_1 = __importDefault(require("../../../normalisedURLPath")); +const querier_1 = require("../../../querier"); const supertokens_1 = __importDefault(require("../../../supertokens")); +const utils_1 = require("../../../utils"); const constants_1 = require("../constants"); function getAPIImplementation() { return { @@ -66,9 +68,18 @@ function getAPIImplementation() { new normalisedURLPath_1.default(bundleBasePathString).getAsStringDangerous(); let connectionURI = ""; const superTokensInstance = supertokens_1.default.getInstanceOrThrowError(); + const authMode = input.options.config.authMode; if (superTokensInstance.supertokens !== undefined) { connectionURI = superTokensInstance.supertokens.connectionURI; } + let isSearchEnabled = false; + const cdiVersion = yield querier_1.Querier.getNewInstanceOrThrowError( + input.options.recipeId + ).getAPIVersion(); + if (utils_1.maxVersion("2.20", cdiVersion) === cdiVersion) { + // Only enable search if CDI version is 2.20 or above + isSearchEnabled = true; + } return ` @@ -79,6 +90,8 @@ function getAPIImplementation() { .appendPath(new normalisedURLPath_1.default(constants_1.DASHBOARD_API)) .getAsStringDangerous()}" window.connectionURI = "${connectionURI}" + window.authMode = "${authMode}" + window.isSearchEnabled = "${isSearchEnabled}" diff --git a/lib/build/recipe/dashboard/api/search/tagsGet.d.ts b/lib/build/recipe/dashboard/api/search/tagsGet.d.ts new file mode 100644 index 000000000..a8a374452 --- /dev/null +++ b/lib/build/recipe/dashboard/api/search/tagsGet.d.ts @@ -0,0 +1,8 @@ +// @ts-nocheck +import { APIInterface, APIOptions } from "../../types"; +declare type TagsResponse = { + status: "OK"; + tags: string[]; +}; +export declare const getSearchTags: (_: APIInterface, options: APIOptions) => Promise; +export {}; diff --git a/lib/build/recipe/dashboard/api/search/tagsGet.js b/lib/build/recipe/dashboard/api/search/tagsGet.js new file mode 100644 index 000000000..60d752f92 --- /dev/null +++ b/lib/build/recipe/dashboard/api/search/tagsGet.js @@ -0,0 +1,62 @@ +"use strict"; +/* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * 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. + */ +var __awaiter = + (this && this.__awaiter) || + function (thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P + ? value + : new P(function (resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getSearchTags = void 0; +const querier_1 = require("../../../../querier"); +const normalisedURLPath_1 = __importDefault(require("../../../../normalisedURLPath")); +const getSearchTags = (_, options) => + __awaiter(void 0, void 0, void 0, function* () { + let querier = querier_1.Querier.getNewInstanceOrThrowError(options.recipeId); + let tagsResponse = yield querier.sendGetRequest(new normalisedURLPath_1.default("/user/search/tags"), {}); + return tagsResponse; + }); +exports.getSearchTags = getSearchTags; diff --git a/lib/build/recipe/dashboard/api/signIn.d.ts b/lib/build/recipe/dashboard/api/signIn.d.ts new file mode 100644 index 000000000..899d506d9 --- /dev/null +++ b/lib/build/recipe/dashboard/api/signIn.d.ts @@ -0,0 +1,3 @@ +// @ts-nocheck +import { APIInterface, APIOptions } from "../types"; +export default function signIn(_: APIInterface, options: APIOptions): Promise; diff --git a/lib/build/recipe/dashboard/api/signIn.js b/lib/build/recipe/dashboard/api/signIn.js new file mode 100644 index 000000000..e78ba8aa4 --- /dev/null +++ b/lib/build/recipe/dashboard/api/signIn.js @@ -0,0 +1,84 @@ +"use strict"; +/* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * 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. + */ +var __awaiter = + (this && this.__awaiter) || + function (thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P + ? value + : new P(function (resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; +Object.defineProperty(exports, "__esModule", { value: true }); +const utils_1 = require("../../../utils"); +const error_1 = __importDefault(require("../../../error")); +const querier_1 = require("../../../querier"); +const normalisedURLPath_1 = __importDefault(require("../../../normalisedURLPath")); +function signIn(_, options) { + return __awaiter(this, void 0, void 0, function* () { + const { email, password } = yield options.req.getJSONBody(); + if (email === undefined) { + throw new error_1.default({ + message: "Missing required parameter 'email'", + type: error_1.default.BAD_INPUT_ERROR, + }); + } + if (password === undefined) { + throw new error_1.default({ + message: "Missing required parameter 'password'", + type: error_1.default.BAD_INPUT_ERROR, + }); + } + let querier = querier_1.Querier.getNewInstanceOrThrowError(undefined); + const signInResponse = yield querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/dashboard/signin"), + { + email, + password, + } + ); + utils_1.send200Response(options.res, signInResponse); + return true; + }); +} +exports.default = signIn; diff --git a/lib/build/recipe/dashboard/api/signOut.d.ts b/lib/build/recipe/dashboard/api/signOut.d.ts new file mode 100644 index 000000000..c9c5018d2 --- /dev/null +++ b/lib/build/recipe/dashboard/api/signOut.d.ts @@ -0,0 +1,3 @@ +// @ts-nocheck +import { APIInterface, APIOptions } from "../types"; +export default function signOut(_: APIInterface, options: APIOptions): Promise; diff --git a/lib/build/recipe/dashboard/api/signOut.js b/lib/build/recipe/dashboard/api/signOut.js new file mode 100644 index 000000000..929caddbe --- /dev/null +++ b/lib/build/recipe/dashboard/api/signOut.js @@ -0,0 +1,77 @@ +"use strict"; +/* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * 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. + */ +var __awaiter = + (this && this.__awaiter) || + function (thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P + ? value + : new P(function (resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; +Object.defineProperty(exports, "__esModule", { value: true }); +const utils_1 = require("../../../utils"); +const querier_1 = require("../../../querier"); +const normalisedURLPath_1 = __importDefault(require("../../../normalisedURLPath")); +function signOut(_, options) { + var _a; + return __awaiter(this, void 0, void 0, function* () { + if (options.config.authMode === "api-key") { + utils_1.send200Response(options.res, { status: "OK" }); + } else { + const sessionIdFormAuthHeader = + (_a = options.req.getHeaderValue("authorization")) === null || _a === void 0 + ? void 0 + : _a.split(" ")[1]; + let querier = querier_1.Querier.getNewInstanceOrThrowError(undefined); + const sessionDeleteResponse = yield querier.sendDeleteRequest( + new normalisedURLPath_1.default("/recipe/dashboard/session"), + {}, + { sessionId: sessionIdFormAuthHeader } + ); + utils_1.send200Response(options.res, sessionDeleteResponse); + } + return true; + }); +} +exports.default = signOut; diff --git a/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.js b/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.js index 4159bd21c..9d0867661 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.js +++ b/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.js @@ -86,15 +86,12 @@ const userPasswordPut = (_, options) => ) { // Techincally it can but its an edge case so we assume that it wont throw new Error("Should never come here"); + } else if (updateResponse.status === "PASSWORD_POLICY_VIOLATED_ERROR") { + return { + status: "INVALID_PASSWORD_ERROR", + error: updateResponse.failureReason, + }; } - // TODO: check for password policy error has well. - /** - * - * return { - status: "INVALID_PASSWORD_ERROR", - error: passwordValidationError, - }; - */ return { status: "OK", }; @@ -110,15 +107,12 @@ const userPasswordPut = (_, options) => ) { // Techincally it can but its an edge case so we assume that it wont throw new Error("Should never come here"); + } else if (updateResponse.status === "PASSWORD_POLICY_VIOLATED_ERROR") { + return { + status: "INVALID_PASSWORD_ERROR", + error: updateResponse.failureReason, + }; } - // TODO: check for password policy error has well. - /** - * - * return { - status: "INVALID_PASSWORD_ERROR", - error: passwordValidationError, - }; - */ return { status: "OK", }; diff --git a/lib/build/recipe/dashboard/api/userdetails/userPut.d.ts b/lib/build/recipe/dashboard/api/userdetails/userPut.d.ts index ba250bb3d..d976fdd9a 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userPut.d.ts +++ b/lib/build/recipe/dashboard/api/userdetails/userPut.d.ts @@ -17,6 +17,10 @@ declare type Response = | { status: "INVALID_PHONE_ERROR"; error: string; + } + | { + status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; + reason: string; }; export declare const userPut: (_: APIInterface, options: APIOptions) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/userdetails/userPut.js b/lib/build/recipe/dashboard/api/userdetails/userPut.js index 85907607a..41e039e8b 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userPut.js +++ b/lib/build/recipe/dashboard/api/userdetails/userPut.js @@ -72,6 +72,13 @@ const updateEmailForRecipeId = (recipeId, userId, email) => return { status: "EMAIL_ALREADY_EXISTS_ERROR", }; + } else if (emailUpdateResponse.status === "EMAIL_CHANGE_NOT_ALLOWED_ERROR") { + return { + status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR", + reason: emailUpdateResponse.reason, + }; + } else if (emailUpdateResponse.status === "UNKNOWN_USER_ID_ERROR") { + throw new Error("Should never come here"); } return { status: "OK", @@ -96,8 +103,12 @@ const updateEmailForRecipeId = (recipeId, userId, email) => return { status: "EMAIL_ALREADY_EXISTS_ERROR", }; - } - if (emailUpdateResponse.status === "UNKNOWN_USER_ID_ERROR") { + } else if (emailUpdateResponse.status === "EMAIL_CHANGE_NOT_ALLOWED_ERROR") { + return { + status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR", + reason: emailUpdateResponse.reason, + }; + } else if (emailUpdateResponse.status === "UNKNOWN_USER_ID_ERROR") { throw new Error("Should never come here"); } return { diff --git a/lib/build/recipe/dashboard/api/userdetails/userSessionsGet.js b/lib/build/recipe/dashboard/api/userdetails/userSessionsGet.js index 6cae91b07..cd343c187 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userSessionsGet.js +++ b/lib/build/recipe/dashboard/api/userdetails/userSessionsGet.js @@ -58,7 +58,9 @@ const userSessionsGet = (_, options) => try { const sessionResponse = yield session_1.default.getSessionInformation(response[i]); if (sessionResponse !== undefined) { - sessions[i] = sessionResponse; + const accessTokenPayload = sessionResponse.customClaimsInAccessTokenPayload; + delete sessionResponse.customClaimsInAccessTokenPayload; + sessions[i] = Object.assign(Object.assign({}, sessionResponse), { accessTokenPayload }); } res(); } catch (e) { diff --git a/lib/build/recipe/dashboard/api/usersGet.d.ts b/lib/build/recipe/dashboard/api/usersGet.d.ts index 788cec3eb..9ba0d5a05 100644 --- a/lib/build/recipe/dashboard/api/usersGet.d.ts +++ b/lib/build/recipe/dashboard/api/usersGet.d.ts @@ -23,4 +23,9 @@ export declare type Response = { users: User[]; }; export default function usersGet(_: APIInterface, options: APIOptions): Promise; +export declare function getSearchParamsFromURL( + path: string +): { + [key: string]: string; +}; export {}; diff --git a/lib/build/recipe/dashboard/api/usersGet.js b/lib/build/recipe/dashboard/api/usersGet.js index 0a194009d..7b5b34bfa 100644 --- a/lib/build/recipe/dashboard/api/usersGet.js +++ b/lib/build/recipe/dashboard/api/usersGet.js @@ -36,6 +36,7 @@ var __importDefault = return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); +exports.getSearchParamsFromURL = void 0; const error_1 = __importDefault(require("../../../error")); const __1 = require("../../.."); const recipe_1 = __importDefault(require("../../usermetadata/recipe")); @@ -61,13 +62,16 @@ function usersGet(_, options) { }); } let paginationToken = options.req.getKeyValueFromQuery("paginationToken"); + const query = getSearchParamsFromURL(options.req.getOriginalURL()); let usersResponse = timeJoinedOrder === "DESC" ? yield __1.getUsersNewestFirst({ + query, limit: parseInt(limit), paginationToken, }) : yield __1.getUsersOldestFirst({ + query, limit: parseInt(limit), paginationToken, }); @@ -142,3 +146,15 @@ function usersGet(_, options) { }); } exports.default = usersGet; +function getSearchParamsFromURL(path) { + const URLObject = new URL("https://exmaple.com" + path); + const params = new URLSearchParams(URLObject.search); + const searchQuery = {}; + for (const [key, value] of params) { + if (!["limit", "timeJoinedOrder", "paginationToken"].includes(key)) { + searchQuery[key] = value; + } + } + return searchQuery; +} +exports.getSearchParamsFromURL = getSearchParamsFromURL; diff --git a/lib/build/recipe/dashboard/api/validateKey.js b/lib/build/recipe/dashboard/api/validateKey.js index f805ab857..482e51bac 100644 --- a/lib/build/recipe/dashboard/api/validateKey.js +++ b/lib/build/recipe/dashboard/api/validateKey.js @@ -49,17 +49,17 @@ const utils_1 = require("../../../utils"); const utils_2 = require("../utils"); function validateKey(_, options) { return __awaiter(this, void 0, void 0, function* () { - const shouldAllowAccess = yield options.recipeImplementation.shouldAllowAccess({ + const input = { req: options.req, config: options.config, userContext: utils_1.makeDefaultUserContextFromAPI(options.req), - }); - if (!shouldAllowAccess) { - utils_2.sendUnauthorisedAccess(options.res); - } else { + }; + if (yield utils_2.validateApiKey(input)) { options.res.sendJSONResponse({ status: "OK", }); + } else { + utils_2.sendUnauthorisedAccess(options.res); } return true; }); diff --git a/lib/build/recipe/dashboard/constants.d.ts b/lib/build/recipe/dashboard/constants.d.ts index 5862ffc64..7b0c33787 100644 --- a/lib/build/recipe/dashboard/constants.d.ts +++ b/lib/build/recipe/dashboard/constants.d.ts @@ -1,5 +1,7 @@ // @ts-nocheck export declare const DASHBOARD_API = "/dashboard"; +export declare const SIGN_IN_API = "/api/signin"; +export declare const SIGN_OUT_API = "/api/signout"; export declare const VALIDATE_KEY_API = "/api/key/validate"; export declare const USERS_LIST_GET_API = "/api/users"; export declare const USERS_COUNT_API = "/api/users/count"; @@ -9,3 +11,5 @@ export declare const USER_METADATA_API = "/api/user/metadata"; export declare const USER_SESSIONS_API = "/api/user/sessions"; export declare const USER_PASSWORD_API = "/api/user/password"; export declare const USER_EMAIL_VERIFY_TOKEN_API = "/api/user/email/verify/token"; +export declare const SEARCH_TAGS_API = "/api/search/tags"; +export declare const DASHBOARD_ANALYTICS_API = "/api/analytics"; diff --git a/lib/build/recipe/dashboard/constants.js b/lib/build/recipe/dashboard/constants.js index c340ac76f..9cf1620dc 100644 --- a/lib/build/recipe/dashboard/constants.js +++ b/lib/build/recipe/dashboard/constants.js @@ -14,8 +14,10 @@ * under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); -exports.USER_EMAIL_VERIFY_TOKEN_API = exports.USER_PASSWORD_API = exports.USER_SESSIONS_API = exports.USER_METADATA_API = exports.USER_EMAIL_VERIFY_API = exports.USER_API = exports.USERS_COUNT_API = exports.USERS_LIST_GET_API = exports.VALIDATE_KEY_API = exports.DASHBOARD_API = void 0; +exports.DASHBOARD_ANALYTICS_API = exports.SEARCH_TAGS_API = exports.USER_EMAIL_VERIFY_TOKEN_API = exports.USER_PASSWORD_API = exports.USER_SESSIONS_API = exports.USER_METADATA_API = exports.USER_EMAIL_VERIFY_API = exports.USER_API = exports.USERS_COUNT_API = exports.USERS_LIST_GET_API = exports.VALIDATE_KEY_API = exports.SIGN_OUT_API = exports.SIGN_IN_API = exports.DASHBOARD_API = void 0; exports.DASHBOARD_API = "/dashboard"; +exports.SIGN_IN_API = "/api/signin"; +exports.SIGN_OUT_API = "/api/signout"; exports.VALIDATE_KEY_API = "/api/key/validate"; exports.USERS_LIST_GET_API = "/api/users"; exports.USERS_COUNT_API = "/api/users/count"; @@ -25,3 +27,5 @@ exports.USER_METADATA_API = "/api/user/metadata"; exports.USER_SESSIONS_API = "/api/user/sessions"; exports.USER_PASSWORD_API = "/api/user/password"; exports.USER_EMAIL_VERIFY_TOKEN_API = "/api/user/email/verify/token"; +exports.SEARCH_TAGS_API = "/api/search/tags"; +exports.DASHBOARD_ANALYTICS_API = "/api/analytics"; diff --git a/lib/build/recipe/dashboard/recipe.d.ts b/lib/build/recipe/dashboard/recipe.d.ts index 6e29b8d50..d393f7047 100644 --- a/lib/build/recipe/dashboard/recipe.d.ts +++ b/lib/build/recipe/dashboard/recipe.d.ts @@ -12,9 +12,9 @@ export default class Recipe extends RecipeModule { recipeInterfaceImpl: RecipeInterface; apiImpl: APIInterface; isInServerlessEnv: boolean; - constructor(recipeId: string, appInfo: NormalisedAppinfo, isInServerlessEnv: boolean, config: TypeInput); + constructor(recipeId: string, appInfo: NormalisedAppinfo, isInServerlessEnv: boolean, config?: TypeInput); static getInstanceOrThrowError(): Recipe; - static init(config: TypeInput): RecipeListFunction; + static init(config?: TypeInput): RecipeListFunction; static reset(): void; getAPIsHandled: () => APIHandled[]; handleAPIRequest: ( diff --git a/lib/build/recipe/dashboard/recipe.js b/lib/build/recipe/dashboard/recipe.js index a73359714..3b24127e7 100644 --- a/lib/build/recipe/dashboard/recipe.js +++ b/lib/build/recipe/dashboard/recipe.js @@ -74,6 +74,10 @@ const userPasswordPut_1 = require("./api/userdetails/userPasswordPut"); const userPut_1 = require("./api/userdetails/userPut"); const userEmailVerifyTokenPost_1 = require("./api/userdetails/userEmailVerifyTokenPost"); const userSessionsPost_1 = require("./api/userdetails/userSessionsPost"); +const signIn_1 = __importDefault(require("./api/signIn")); +const signOut_1 = __importDefault(require("./api/signOut")); +const tagsGet_1 = require("./api/search/tagsGet"); +const analytics_1 = __importDefault(require("./api/analytics")); class Recipe extends recipeModule_1.default { constructor(recipeId, appInfo, isInServerlessEnv, config) { super(recipeId, appInfo); @@ -84,10 +88,166 @@ class Recipe extends recipeModule_1.default { * handles a specific API path and method and then returns the ID. * * For the dashboard recipe this logic is fully custom and handled inside the - * `returnAPIIdIfCanHandleRequest` method of this class. Since this array is never - * used for this recipe, we simply return an empty array. + * `returnAPIIdIfCanHandleRequest` method of this class. + * + * For most frameworks this array is redundant because the `returnAPIIdIfCanHandleRequest` is used. + * But for frameworks such as Hapi that require all APIs to be declared up front, this array is used + * to make sure that the framework does not return a 404 */ - return []; + return [ + { + id: constants_1.DASHBOARD_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.DASHBOARD_API) + ), + disabled: false, + method: "get", + }, + { + id: constants_1.SIGN_IN_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.SIGN_IN_API) + ), + disabled: false, + method: "post", + }, + { + id: constants_1.VALIDATE_KEY_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.VALIDATE_KEY_API) + ), + disabled: false, + method: "post", + }, + { + id: constants_1.SIGN_OUT_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.SIGN_OUT_API) + ), + disabled: false, + method: "post", + }, + { + id: constants_1.USERS_LIST_GET_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.USERS_LIST_GET_API) + ), + disabled: false, + method: "get", + }, + { + id: constants_1.USERS_COUNT_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.USERS_COUNT_API) + ), + disabled: false, + method: "get", + }, + { + id: constants_1.USER_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.USER_API) + ), + disabled: false, + method: "get", + }, + { + id: constants_1.USER_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.USER_API) + ), + disabled: false, + method: "post", + }, + { + id: constants_1.USER_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.USER_API) + ), + disabled: false, + method: "delete", + }, + { + id: constants_1.USER_EMAIL_VERIFY_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.USER_EMAIL_VERIFY_API) + ), + disabled: false, + method: "get", + }, + { + id: constants_1.USER_EMAIL_VERIFY_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.USER_EMAIL_VERIFY_API) + ), + disabled: false, + method: "put", + }, + { + id: constants_1.USER_METADATA_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.USER_METADATA_API) + ), + disabled: false, + method: "get", + }, + { + id: constants_1.USER_METADATA_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.USER_METADATA_API) + ), + disabled: false, + method: "put", + }, + { + id: constants_1.USER_SESSIONS_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.USER_SESSIONS_API) + ), + disabled: false, + method: "get", + }, + { + id: constants_1.USER_SESSIONS_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.USER_SESSIONS_API) + ), + disabled: false, + method: "post", + }, + { + id: constants_1.USER_PASSWORD_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.USER_PASSWORD_API) + ), + disabled: false, + method: "put", + }, + { + id: constants_1.USER_EMAIL_VERIFY_TOKEN_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.USER_EMAIL_VERIFY_TOKEN_API) + ), + disabled: false, + method: "post", + }, + { + id: constants_1.SEARCH_TAGS_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.SEARCH_TAGS_API) + ), + disabled: false, + method: "get", + }, + { + id: constants_1.DASHBOARD_ANALYTICS_API, + pathWithoutApiBasePath: new normalisedURLPath_1.default( + utils_1.getApiPathWithDashboardBase(constants_1.DASHBOARD_ANALYTICS_API) + ), + disabled: false, + method: "post", + }, + ]; }; this.handleAPIRequest = (id, req, res, __, ___) => __awaiter(this, void 0, void 0, function* () { @@ -104,6 +264,9 @@ class Recipe extends recipeModule_1.default { if (id === constants_1.DASHBOARD_API) { return yield dashboard_1.default(this.apiImpl, options); } + if (id === constants_1.SIGN_IN_API) { + return yield signIn_1.default(this.apiImpl, options); + } if (id === constants_1.VALIDATE_KEY_API) { return yield validateKey_1.default(this.apiImpl, options); } @@ -148,6 +311,12 @@ class Recipe extends recipeModule_1.default { apiFunction = userPasswordPut_1.userPasswordPut; } else if (id === constants_1.USER_EMAIL_VERIFY_TOKEN_API) { apiFunction = userEmailVerifyTokenPost_1.userEmailVerifyTokenPost; + } else if (id === constants_1.SEARCH_TAGS_API) { + apiFunction = tagsGet_1.getSearchTags; + } else if (id === constants_1.SIGN_OUT_API) { + apiFunction = signOut_1.default; + } else if (id === constants_1.DASHBOARD_ANALYTICS_API && req.getMethod() === "post") { + apiFunction = analytics_1.default; } // If the id doesnt match any APIs return false if (apiFunction === undefined) { @@ -200,9 +369,7 @@ class Recipe extends recipeModule_1.default { Recipe.instance = new Recipe(Recipe.RECIPE_ID, appInfo, isInServerlessEnv, config); return Recipe.instance; } else { - throw new Error( - "Emailverification recipe has already been initialised. Please check your code for bugs." - ); + throw new Error("Dashboard recipe has already been initialised. Please check your code for bugs."); } }; } diff --git a/lib/build/recipe/dashboard/recipeImplementation.js b/lib/build/recipe/dashboard/recipeImplementation.js index 6f231cd85..a3e948462 100644 --- a/lib/build/recipe/dashboard/recipeImplementation.js +++ b/lib/build/recipe/dashboard/recipeImplementation.js @@ -44,8 +44,16 @@ var __awaiter = step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); +const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); +const querier_1 = require("../../querier"); const version_1 = require("../../version"); +const utils_1 = require("./utils"); function getRecipeImplementation() { return { getDashboardBundleLocation: function () { @@ -54,17 +62,25 @@ function getRecipeImplementation() { }); }, shouldAllowAccess: function (input) { + var _a; return __awaiter(this, void 0, void 0, function* () { - let apiKeyHeaderValue = input.req.getHeaderValue("authorization"); - // We receieve the api key as `Bearer API_KEY`, this retrieves just the key - apiKeyHeaderValue = - apiKeyHeaderValue === null || apiKeyHeaderValue === void 0 - ? void 0 - : apiKeyHeaderValue.split(" ")[1]; - if (apiKeyHeaderValue === undefined) { - return false; + // For cases where we're not using the API key, the JWT is being used; we allow their access by default + if (!input.config.apiKey) { + // make the check for the API endpoint here with querier + let querier = querier_1.Querier.getNewInstanceOrThrowError(undefined); + const authHeaderValue = + (_a = input.req.getHeaderValue("authorization")) === null || _a === void 0 + ? void 0 + : _a.split(" ")[1]; + const sessionVerificationResponse = yield querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/dashboard/session/verify"), + { + sessionId: authHeaderValue, + } + ); + return sessionVerificationResponse.status === "OK"; } - return apiKeyHeaderValue === input.config.apiKey; + return yield utils_1.validateApiKey(input); }); }, }; diff --git a/lib/build/recipe/dashboard/types.d.ts b/lib/build/recipe/dashboard/types.d.ts index be7b06b28..495b44903 100644 --- a/lib/build/recipe/dashboard/types.d.ts +++ b/lib/build/recipe/dashboard/types.d.ts @@ -3,7 +3,7 @@ import OverrideableBuilder from "supertokens-js-override"; import { BaseRequest, BaseResponse } from "../../framework"; import { NormalisedAppinfo } from "../../types"; export declare type TypeInput = { - apiKey: string; + apiKey?: string; override?: { functions?: ( originalImplementation: RecipeInterface, @@ -13,7 +13,8 @@ export declare type TypeInput = { }; }; export declare type TypeNormalisedInput = { - apiKey: string; + apiKey?: string; + authMode: AuthMode; override: { functions: ( originalImplementation: RecipeInterface, @@ -40,6 +41,7 @@ export declare type APIInterface = { }; export declare type APIFunction = (apiImplementation: APIInterface, options: APIOptions) => Promise; export declare type RecipeIdForUser = "emailpassword" | "thirdparty" | "passwordless"; +export declare type AuthMode = "api-key" | "email-password"; export declare type RecipeLevelUser = { recipeId: "emailpassword" | "thirdparty" | "passwordless"; timeJoined: number; diff --git a/lib/build/recipe/dashboard/utils.d.ts b/lib/build/recipe/dashboard/utils.d.ts index 61864bada..a7873ecbf 100644 --- a/lib/build/recipe/dashboard/utils.d.ts +++ b/lib/build/recipe/dashboard/utils.d.ts @@ -1,9 +1,9 @@ // @ts-nocheck -import { BaseResponse } from "../../framework"; +import { BaseRequest, BaseResponse } from "../../framework"; import NormalisedURLPath from "../../normalisedURLPath"; import { HTTPMethod, NormalisedAppinfo } from "../../types"; import { RecipeIdForUser, TypeInput, TypeNormalisedInput, RecipeLevelUserWithFirstAndLastName } from "./types"; -export declare function validateAndNormaliseUserInput(config: TypeInput): TypeNormalisedInput; +export declare function validateAndNormaliseUserInput(config?: TypeInput): TypeNormalisedInput; export declare function isApiPath(path: NormalisedURLPath, appInfo: NormalisedAppinfo): boolean; export declare function getApiIdIfMatched(path: NormalisedURLPath, method: HTTPMethod): string | undefined; export declare function sendUnauthorisedAccess(res: BaseResponse): void; @@ -22,3 +22,9 @@ export declare function getUserForRecipeId( | undefined; }>; export declare function isRecipeInitialised(recipeId: RecipeIdForUser): boolean; +export declare function validateApiKey(input: { + req: BaseRequest; + config: TypeNormalisedInput; + userContext: any; +}): Promise; +export declare function getApiPathWithDashboardBase(path: string): string; diff --git a/lib/build/recipe/dashboard/utils.js b/lib/build/recipe/dashboard/utils.js index 60dff2aee..2e4b5cc23 100644 --- a/lib/build/recipe/dashboard/utils.js +++ b/lib/build/recipe/dashboard/utils.js @@ -50,7 +50,7 @@ var __importDefault = return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.isRecipeInitialised = exports.getUserForRecipeId = exports.isValidRecipeId = exports.sendUnauthorisedAccess = exports.getApiIdIfMatched = exports.isApiPath = exports.validateAndNormaliseUserInput = void 0; +exports.getApiPathWithDashboardBase = exports.validateApiKey = exports.isRecipeInitialised = exports.getUserForRecipeId = exports.isValidRecipeId = exports.sendUnauthorisedAccess = exports.getApiIdIfMatched = exports.isApiPath = exports.validateAndNormaliseUserInput = void 0; const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); const utils_1 = require("../../utils"); const constants_1 = require("./constants"); @@ -64,19 +64,16 @@ const thirdparty_1 = __importDefault(require("../thirdparty")); const passwordless_1 = __importDefault(require("../passwordless")); const thirdpartypasswordless_1 = __importDefault(require("../thirdpartypasswordless")); function validateAndNormaliseUserInput(config) { - if (config.apiKey.trim().length === 0) { - throw new Error("apiKey provided to Dashboard recipe cannot be empty"); - } let override = Object.assign( { functions: (originalImplementation) => originalImplementation, apis: (originalImplementation) => originalImplementation, }, - config.override + config === undefined ? {} : config.override ); return { - apiKey: config.apiKey, override, + authMode: config !== undefined && config.apiKey ? "api-key" : "email-password", }; } exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; @@ -101,6 +98,12 @@ function getApiIdIfMatched(path, method) { if (path.getAsStringDangerous().endsWith(constants_1.VALIDATE_KEY_API) && method === "post") { return constants_1.VALIDATE_KEY_API; } + if (path.getAsStringDangerous().endsWith(constants_1.SIGN_IN_API) && method === "post") { + return constants_1.SIGN_IN_API; + } + if (path.getAsStringDangerous().endsWith(constants_1.SIGN_OUT_API) && method === "post") { + return constants_1.SIGN_OUT_API; + } if (path.getAsStringDangerous().endsWith(constants_1.USERS_LIST_GET_API) && method === "get") { return constants_1.USERS_LIST_GET_API; } @@ -136,6 +139,12 @@ function getApiIdIfMatched(path, method) { if (path.getAsStringDangerous().endsWith(constants_1.USER_PASSWORD_API) && method === "put") { return constants_1.USER_PASSWORD_API; } + if (path.getAsStringDangerous().endsWith(constants_1.SEARCH_TAGS_API) && method === "get") { + return constants_1.SEARCH_TAGS_API; + } + if (path.getAsStringDangerous().endsWith(constants_1.DASHBOARD_ANALYTICS_API) && method === "post") { + return constants_1.DASHBOARD_ANALYTICS_API; + } return undefined; } exports.getApiIdIfMatched = getApiIdIfMatched; @@ -315,3 +324,20 @@ function isRecipeInitialised(recipeId) { return isRecipeInitialised; } exports.isRecipeInitialised = isRecipeInitialised; +function validateApiKey(input) { + return __awaiter(this, void 0, void 0, function* () { + let apiKeyHeaderValue = input.req.getHeaderValue("authorization"); + // We receieve the api key as `Bearer API_KEY`, this retrieves just the key + apiKeyHeaderValue = + apiKeyHeaderValue === null || apiKeyHeaderValue === void 0 ? void 0 : apiKeyHeaderValue.split(" ")[1]; + if (apiKeyHeaderValue === undefined) { + return false; + } + return apiKeyHeaderValue === input.config.apiKey; + }); +} +exports.validateApiKey = validateApiKey; +function getApiPathWithDashboardBase(path) { + return constants_1.DASHBOARD_API + path; +} +exports.getApiPathWithDashboardBase = getApiPathWithDashboardBase; diff --git a/lib/build/recipe/emailpassword/api/implementation.js b/lib/build/recipe/emailpassword/api/implementation.js index ec58b94e9..fde1bf662 100644 --- a/lib/build/recipe/emailpassword/api/implementation.js +++ b/lib/build/recipe/emailpassword/api/implementation.js @@ -366,6 +366,11 @@ function getAPIImplementation() { return { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR", }; + } else if (updateResponse.status === "PASSWORD_POLICY_VIOLATED_ERROR") { + return { + status: "PASSWORD_POLICY_VIOLATED_ERROR", + failureReason: updateResponse.failureReason, + }; } else { // status: "OK" return { @@ -374,9 +379,6 @@ function getAPIImplementation() { email: emailForWhomTokenWasGenerated, }; } - // TODO: we need to also handle password policy error. Note that this needs - // to happen in the api file (before this function is called) as well - // cause we don't want to consume the token unnecessarily. }); } let newPassword = formFields.filter((f) => f.id === "password")[0].value; diff --git a/lib/build/recipe/emailpassword/api/passwordReset.js b/lib/build/recipe/emailpassword/api/passwordReset.js index 305462d75..f0c91ce62 100644 --- a/lib/build/recipe/emailpassword/api/passwordReset.js +++ b/lib/build/recipe/emailpassword/api/passwordReset.js @@ -87,6 +87,20 @@ function passwordReset(apiImplementation, options) { options, userContext: utils_3.makeDefaultUserContextFromAPI(options.req), }); + if (result.status === "PASSWORD_POLICY_VIOLATED_ERROR") { + // this error will be caught by the recipe error handler, just + // like it's done in the validateFormFieldsOrThrowError function above. + throw new error_1.default({ + type: error_1.default.FIELD_ERROR, + payload: [ + { + id: "password", + error: result.failureReason, + }, + ], + message: "Error in input formFields", + }); + } utils_1.send200Response( options.res, result.status === "OK" diff --git a/lib/build/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.js b/lib/build/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.js index 65fb03c6c..9a6b9d98b 100644 --- a/lib/build/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.js +++ b/lib/build/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.js @@ -923,7 +923,6 @@ function getPasswordResetEmailHTML(appName, email, resetLink) { - diff --git a/lib/build/recipe/emailpassword/index.d.ts b/lib/build/recipe/emailpassword/index.d.ts index 1e8837b73..191b4a0b2 100644 --- a/lib/build/recipe/emailpassword/index.d.ts +++ b/lib/build/recipe/emailpassword/index.d.ts @@ -74,6 +74,7 @@ export default class Wrapper { email?: string; password?: string; userContext?: any; + applyPasswordPolicy?: boolean; }): Promise< | { status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR"; @@ -82,6 +83,10 @@ export default class Wrapper { status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; reason: string; } + | { + status: "PASSWORD_POLICY_VIOLATED_ERROR"; + failureReason: string; + } >; static sendEmail( input: TypeEmailPasswordEmailDeliveryInput & { diff --git a/lib/build/recipe/emailpassword/recipe.js b/lib/build/recipe/emailpassword/recipe.js index fb106bbce..a14da3d86 100644 --- a/lib/build/recipe/emailpassword/recipe.js +++ b/lib/build/recipe/emailpassword/recipe.js @@ -189,8 +189,12 @@ class Recipe extends recipeModule_1.default { this.isInServerlessEnv = isInServerlessEnv; this.config = utils_1.validateAndNormaliseUserInput(this, appInfo, config); { + const getEmailPasswordConfig = () => this.config; let builder = new supertokens_js_override_1.default( - recipeImplementation_1.default(querier_1.Querier.getNewInstanceOrThrowError(recipeId)) + recipeImplementation_1.default( + querier_1.Querier.getNewInstanceOrThrowError(recipeId), + getEmailPasswordConfig + ) ); this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); } diff --git a/lib/build/recipe/emailpassword/recipeImplementation.d.ts b/lib/build/recipe/emailpassword/recipeImplementation.d.ts index 86bf78a27..cfb8e6ad0 100644 --- a/lib/build/recipe/emailpassword/recipeImplementation.d.ts +++ b/lib/build/recipe/emailpassword/recipeImplementation.d.ts @@ -1,4 +1,7 @@ // @ts-nocheck -import { RecipeInterface } from "./types"; +import { RecipeInterface, TypeNormalisedInput } from "./types"; import { Querier } from "../../querier"; -export default function getRecipeInterface(querier: Querier): RecipeInterface; +export default function getRecipeInterface( + querier: Querier, + getEmailPasswordConfig: () => TypeNormalisedInput +): RecipeInterface; diff --git a/lib/build/recipe/emailpassword/recipeImplementation.js b/lib/build/recipe/emailpassword/recipeImplementation.js index bb55e005e..554bc01ea 100644 --- a/lib/build/recipe/emailpassword/recipeImplementation.js +++ b/lib/build/recipe/emailpassword/recipeImplementation.js @@ -39,7 +39,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); const recipe_1 = __importDefault(require("../accountlinking/recipe")); const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); const __1 = require("../.."); -function getRecipeInterface(querier) { +const constants_1 = require("./constants"); +function getRecipeInterface(querier, getEmailPasswordConfig) { return { signUp: function ({ email, password, userContext }) { return __awaiter(this, void 0, void 0, function* () { @@ -109,7 +110,21 @@ function getRecipeInterface(querier) { }, updateEmailOrPassword: function (input) { return __awaiter(this, void 0, void 0, function* () { - // the input can be primary or recipe level user id. + if (input.applyPasswordPolicy || input.applyPasswordPolicy === undefined) { + let formFields = getEmailPasswordConfig().signUpFeature.formFields; + if (input.password !== undefined) { + const passwordField = formFields.filter( + (el) => el.id === constants_1.FORM_FIELD_PASSWORD_ID + )[0]; + const error = yield passwordField.validate(input.password); + if (error !== undefined) { + return { + status: "PASSWORD_POLICY_VIOLATED_ERROR", + failureReason: error, + }; + } + } + } return yield querier.sendPutRequest(new normalisedURLPath_1.default("/recipe/user"), { userId: input.userId, email: input.email, diff --git a/lib/build/recipe/emailpassword/types.d.ts b/lib/build/recipe/emailpassword/types.d.ts index 97451c8a0..4132d1cd9 100644 --- a/lib/build/recipe/emailpassword/types.d.ts +++ b/lib/build/recipe/emailpassword/types.d.ts @@ -138,6 +138,7 @@ export declare type RecipeInterface = { email?: string; password?: string; userContext: any; + applyPasswordPolicy?: boolean; }): Promise< | { status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR"; @@ -146,6 +147,10 @@ export declare type RecipeInterface = { status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; reason: string; } + | { + status: "PASSWORD_POLICY_VIOLATED_ERROR"; + failureReason: string; + } >; }; export declare type APIOptions = { @@ -210,6 +215,10 @@ export declare type APIInterface = { | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR"; } + | { + status: "PASSWORD_POLICY_VIOLATED_ERROR"; + failureReason: string; + } | GeneralErrorResponse >); signInPOST: diff --git a/lib/build/recipe/emailverification/emaildelivery/services/smtp/emailVerify.js b/lib/build/recipe/emailverification/emaildelivery/services/smtp/emailVerify.js index 7523109e9..521c0735f 100644 --- a/lib/build/recipe/emailverification/emaildelivery/services/smtp/emailVerify.js +++ b/lib/build/recipe/emailverification/emaildelivery/services/smtp/emailVerify.js @@ -853,7 +853,7 @@ function getEmailVerifyEmailHTML(appName, email, verificationLink) {

    + style="max-width: 600px !important; margin: auto; font-family: 'Hevetica', sans-serif; font-size: 14px; line-height: 23px; font-weight:400; text-align: center; color: #808080;"> Alternatively, you can directly paste this link in your browser
    - diff --git a/lib/build/recipe/jwt/api/getJWKS.js b/lib/build/recipe/jwt/api/getJWKS.js index b2e33b23b..20c56ccb9 100644 --- a/lib/build/recipe/jwt/api/getJWKS.js +++ b/lib/build/recipe/jwt/api/getJWKS.js @@ -56,10 +56,10 @@ function getJWKS(apiImplementation, options) { options, userContext: utils_2.makeDefaultUserContextFromAPI(options.req), }); - if (result.status === "OK") { - options.res.setHeader("Access-Control-Allow-Origin", "*", false); - utils_1.send200Response(options.res, { keys: result.keys }); + if ("status" in result && result.status === "GENERAL_ERROR") { + utils_1.send200Response(options.res, result); } else { + options.res.setHeader("Access-Control-Allow-Origin", "*", false); utils_1.send200Response(options.res, result); } return true; diff --git a/lib/build/recipe/jwt/index.d.ts b/lib/build/recipe/jwt/index.d.ts index 274bd280b..c907fff5c 100644 --- a/lib/build/recipe/jwt/index.d.ts +++ b/lib/build/recipe/jwt/index.d.ts @@ -6,6 +6,7 @@ export default class Wrapper { static createJWT( payload: any, validitySeconds?: number, + useStaticSigningKey?: boolean, userContext?: any ): Promise< | { @@ -19,7 +20,6 @@ export default class Wrapper { static getJWKS( userContext?: any ): Promise<{ - status: "OK"; keys: JsonWebKey[]; }>; } diff --git a/lib/build/recipe/jwt/index.js b/lib/build/recipe/jwt/index.js index 7b1184695..01f4ee357 100644 --- a/lib/build/recipe/jwt/index.js +++ b/lib/build/recipe/jwt/index.js @@ -53,11 +53,12 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.getJWKS = exports.createJWT = exports.init = void 0; const recipe_1 = __importDefault(require("./recipe")); class Wrapper { - static createJWT(payload, validitySeconds, userContext) { + static createJWT(payload, validitySeconds, useStaticSigningKey, userContext) { return __awaiter(this, void 0, void 0, function* () { return yield recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.createJWT({ payload, validitySeconds, + useStaticSigningKey, userContext: userContext === undefined ? {} : userContext, }); }); diff --git a/lib/build/recipe/jwt/recipeImplementation.js b/lib/build/recipe/jwt/recipeImplementation.js index 3b4f0aff8..aab389ff6 100644 --- a/lib/build/recipe/jwt/recipeImplementation.js +++ b/lib/build/recipe/jwt/recipeImplementation.js @@ -53,7 +53,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); function getRecipeInterface(querier, config, appInfo) { return { - createJWT: function ({ payload, validitySeconds }) { + createJWT: function ({ payload, validitySeconds, useStaticSigningKey }) { return __awaiter(this, void 0, void 0, function* () { if (validitySeconds === undefined) { // If the user does not provide a validity to this function and the config validity is also undefined, use 100 years (in seconds) @@ -62,6 +62,7 @@ function getRecipeInterface(querier, config, appInfo) { let response = yield querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/jwt"), { payload: payload !== null && payload !== void 0 ? payload : {}, validity: validitySeconds, + useStaticSigningKey: useStaticSigningKey !== false, algorithm: "RS256", jwksDomain: appInfo.apiDomain.getAsStringDangerous(), }); @@ -79,7 +80,7 @@ function getRecipeInterface(querier, config, appInfo) { }, getJWKS: function () { return __awaiter(this, void 0, void 0, function* () { - return yield querier.sendGetRequest(new normalisedURLPath_1.default("/recipe/jwt/jwks"), {}); + return yield querier.sendGetRequest(new normalisedURLPath_1.default("/.well-known/jwks.json"), {}); }); }, }; diff --git a/lib/build/recipe/jwt/types.d.ts b/lib/build/recipe/jwt/types.d.ts index fc400eff6..3e6fa1965 100644 --- a/lib/build/recipe/jwt/types.d.ts +++ b/lib/build/recipe/jwt/types.d.ts @@ -42,6 +42,7 @@ export declare type RecipeInterface = { createJWT(input: { payload?: any; validitySeconds?: number; + useStaticSigningKey?: boolean; userContext: any; }): Promise< | { @@ -55,7 +56,6 @@ export declare type RecipeInterface = { getJWKS(input: { userContext: any; }): Promise<{ - status: "OK"; keys: JsonWebKey[]; }>; }; @@ -67,7 +67,6 @@ export declare type APIInterface = { userContext: any; }) => Promise< | { - status: "OK"; keys: JsonWebKey[]; } | GeneralErrorResponse diff --git a/lib/build/recipe/openid/index.d.ts b/lib/build/recipe/openid/index.d.ts index c84226a59..fccc1d4c6 100644 --- a/lib/build/recipe/openid/index.d.ts +++ b/lib/build/recipe/openid/index.d.ts @@ -12,6 +12,7 @@ export default class OpenIdRecipeWrapper { static createJWT( payload?: any, validitySeconds?: number, + useStaticSigningKey?: boolean, userContext?: any ): Promise< | { @@ -25,7 +26,6 @@ export default class OpenIdRecipeWrapper { static getJWKS( userContext?: any ): Promise<{ - status: "OK"; keys: import("../jwt").JsonWebKey[]; }>; } diff --git a/lib/build/recipe/openid/index.js b/lib/build/recipe/openid/index.js index 83903ab76..8eb1cf8a8 100644 --- a/lib/build/recipe/openid/index.js +++ b/lib/build/recipe/openid/index.js @@ -13,10 +13,11 @@ class OpenIdRecipeWrapper { userContext: userContext === undefined ? {} : userContext, }); } - static createJWT(payload, validitySeconds, userContext) { + static createJWT(payload, validitySeconds, useStaticSigningKey, userContext) { return recipe_1.default.getInstanceOrThrowError().jwtRecipe.recipeInterfaceImpl.createJWT({ payload, validitySeconds, + useStaticSigningKey, userContext: userContext === undefined ? {} : userContext, }); } diff --git a/lib/build/recipe/openid/recipeImplementation.js b/lib/build/recipe/openid/recipeImplementation.js index efa935aaa..53c193eda 100644 --- a/lib/build/recipe/openid/recipeImplementation.js +++ b/lib/build/recipe/openid/recipeImplementation.js @@ -55,12 +55,13 @@ function getRecipeInterface(config, jwtRecipeImplementation) { }; }); }, - createJWT: function ({ payload, validitySeconds, userContext }) { + createJWT: function ({ payload, validitySeconds, useStaticSigningKey, userContext }) { return __awaiter(this, void 0, void 0, function* () { payload = payload === undefined || payload === null ? {} : payload; let issuer = config.issuerDomain.getAsStringDangerous() + config.issuerPath.getAsStringDangerous(); return yield jwtRecipeImplementation.createJWT({ payload: Object.assign({ iss: issuer }, payload), + useStaticSigningKey, validitySeconds, userContext, }); diff --git a/lib/build/recipe/openid/types.d.ts b/lib/build/recipe/openid/types.d.ts index a480f4b98..30af4d0b1 100644 --- a/lib/build/recipe/openid/types.d.ts +++ b/lib/build/recipe/openid/types.d.ts @@ -81,6 +81,7 @@ export declare type RecipeInterface = { createJWT(input: { payload?: any; validitySeconds?: number; + useStaticSigningKey?: boolean; userContext: any; }): Promise< | { @@ -94,7 +95,6 @@ export declare type RecipeInterface = { getJWKS(input: { userContext: any; }): Promise<{ - status: "OK"; keys: JsonWebKey[]; }>; }; diff --git a/lib/build/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.js b/lib/build/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.js index 2bb81add4..1bc7a41ba 100644 --- a/lib/build/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.js +++ b/lib/build/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.js @@ -928,7 +928,6 @@ function getPasswordlessLoginOTPBody(appName, email, codeLifetime, userInputCode - @@ -1851,7 +1850,6 @@ function getPasswordlessLoginURLLinkBody(appName, email, codeLifetime, urlWithLi - @@ -2835,7 +2833,6 @@ function getPasswordlessLoginOTPAndURLLinkBody(appName, email, codeLifetime, url - diff --git a/lib/build/recipe/session/accessToken.d.ts b/lib/build/recipe/session/accessToken.d.ts index c7a0b9757..725823f46 100644 --- a/lib/build/recipe/session/accessToken.d.ts +++ b/lib/build/recipe/session/accessToken.d.ts @@ -1,8 +1,9 @@ // @ts-nocheck import { ParsedJWTInfo } from "./jwt"; +import * as jose from "jose"; export declare function getInfoFromAccessToken( jwtInfo: ParsedJWTInfo, - jwtSigningPublicKey: string, + jwks: jose.JWTVerifyGetKey, doAntiCsrfCheck: boolean ): Promise<{ sessionHandle: string; @@ -15,5 +16,5 @@ export declare function getInfoFromAccessToken( expiryTime: number; timeCreated: number; }>; -export declare function validateAccessTokenStructure(payload: any): void; +export declare function validateAccessTokenStructure(payload: any, version: number): void; export declare function sanitizeNumberInput(field: any): number | undefined; diff --git a/lib/build/recipe/session/accessToken.js b/lib/build/recipe/session/accessToken.js index ac9a6938b..69ca2ce3d 100644 --- a/lib/build/recipe/session/accessToken.js +++ b/lib/build/recipe/session/accessToken.js @@ -13,6 +13,42 @@ * License for the specific language governing permissions and limitations * under the License. */ +var __createBinding = + (this && this.__createBinding) || + (Object.create + ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { + enumerable: true, + get: function () { + return m[k]; + }, + }); + } + : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); +var __setModuleDefault = + (this && this.__setModuleDefault) || + (Object.create + ? function (o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } + : function (o, v) { + o["default"] = v; + }); +var __importStar = + (this && this.__importStar) || + function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) + for (var k in mod) + if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; + }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { @@ -44,6 +80,38 @@ var __awaiter = step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; +var __asyncValues = + (this && this.__asyncValues) || + function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], + i; + return m + ? m.call(o) + : ((o = typeof __values === "function" ? __values(o) : o[Symbol.iterator]()), + (i = {}), + verb("next"), + verb("throw"), + verb("return"), + (i[Symbol.asyncIterator] = function () { + return this; + }), + i); + function verb(n) { + i[n] = + o[n] && + function (v) { + return new Promise(function (resolve, reject) { + (v = o[n](v)), settle(resolve, reject, v.done, v.value); + }); + }; + } + function settle(resolve, reject, d, v) { + Promise.resolve(v).then(function (v) { + resolve({ value: v, done: d }); + }, reject); + } + }; var __importDefault = (this && this.__importDefault) || function (mod) { @@ -52,24 +120,81 @@ var __importDefault = Object.defineProperty(exports, "__esModule", { value: true }); exports.sanitizeNumberInput = exports.validateAccessTokenStructure = exports.getInfoFromAccessToken = void 0; const error_1 = __importDefault(require("./error")); -const jwt_1 = require("./jwt"); -function getInfoFromAccessToken(jwtInfo, jwtSigningPublicKey, doAntiCsrfCheck) { +const jose = __importStar(require("jose")); +const processState_1 = require("../../processState"); +function getInfoFromAccessToken(jwtInfo, jwks, doAntiCsrfCheck) { + var e_1, _a; return __awaiter(this, void 0, void 0, function* () { try { - jwt_1.verifyJWT(jwtInfo, jwtSigningPublicKey); - const payload = jwtInfo.payload; + // From the library examples + let payload = undefined; + try { + payload = (yield jose.jwtVerify(jwtInfo.rawTokenString, jwks)).payload; + } catch (error) { + // We only want to opt-into this for V2 access tokens + if ( + jwtInfo.version === 2 && + (error === null || error === void 0 ? void 0 : error.code) === "ERR_JWKS_MULTIPLE_MATCHING_KEYS" + ) { + processState_1.ProcessState.getInstance().addState( + processState_1.PROCESS_STATE.MULTI_JWKS_VALIDATION + ); + try { + // We are trying to validate the token with each key. + // Since the kid is missing from v2 tokens, this basically means we try all keys present in the cache. + for ( + var error_2 = __asyncValues(error), error_2_1; + (error_2_1 = yield error_2.next()), !error_2_1.done; + + ) { + const publicKey = error_2_1.value; + try { + payload = (yield jose.jwtVerify(jwtInfo.rawTokenString, publicKey)).payload; + break; + } catch (innerError) { + if ( + (innerError === null || innerError === void 0 ? void 0 : innerError.code) === + "ERR_JWS_SIGNATURE_VERIFICATION_FAILED" + ) { + continue; + } + throw innerError; + } + } + } catch (e_1_1) { + e_1 = { error: e_1_1 }; + } finally { + try { + if (error_2_1 && !error_2_1.done && (_a = error_2.return)) yield _a.call(error_2); + } finally { + if (e_1) throw e_1.error; + } + } + if (payload === undefined) { + throw new jose.errors.JWSSignatureVerificationFailed(); + } + } else { + throw error; + } + } // This should be called before this function, but the check is very quick, so we can also do them here - validateAccessTokenStructure(payload); + validateAccessTokenStructure(payload, jwtInfo.version); // We can mark these as defined (the ! after the calls), since validateAccessTokenPayload checks this + let userId = jwtInfo.version === 2 ? sanitizeStringInput(payload.userId) : sanitizeStringInput(payload.sub); + let expiryTime = + jwtInfo.version === 2 + ? sanitizeNumberInput(payload.expiryTime) + : sanitizeNumberInput(payload.exp) * 1000; + let timeCreated = + jwtInfo.version === 2 + ? sanitizeNumberInput(payload.timeCreated) + : sanitizeNumberInput(payload.iat) * 1000; + let userData = jwtInfo.version === 2 ? payload.userData : payload; let sessionHandle = sanitizeStringInput(payload.sessionHandle); - let userId = sanitizeStringInput(payload.userId); let recipeUserId = sanitizeStringInput(payload.recipeUserId); let refreshTokenHash1 = sanitizeStringInput(payload.refreshTokenHash1); let parentRefreshTokenHash1 = sanitizeStringInput(payload.parentRefreshTokenHash1); - let userData = payload.userData; let antiCsrfToken = sanitizeStringInput(payload.antiCsrfToken); - let expiryTime = sanitizeNumberInput(payload.expiryTime); - let timeCreated = sanitizeNumberInput(payload.timeCreated); if (antiCsrfToken === undefined && doAntiCsrfCheck) { throw Error("Access token does not contain the anti-csrf token."); } @@ -96,8 +221,19 @@ function getInfoFromAccessToken(jwtInfo, jwtSigningPublicKey, doAntiCsrfCheck) { }); } exports.getInfoFromAccessToken = getInfoFromAccessToken; -function validateAccessTokenStructure(payload) { - if ( +function validateAccessTokenStructure(payload, version) { + if (version >= 3) { + if ( + typeof payload.sub !== "string" || + typeof payload.exp !== "number" || + typeof payload.iat !== "number" || + typeof payload.sessionHandle !== "string" || + typeof payload.refreshTokenHash1 !== "string" + ) { + // it would come here if we change the structure of the JWT. + throw Error("Access token does not contain all the information. Maybe the structure has changed?"); + } + } else if ( typeof payload.sessionHandle !== "string" || typeof payload.userId !== "string" || typeof payload.recipeUserId !== "string" || diff --git a/lib/build/recipe/session/api/implementation.js b/lib/build/recipe/session/api/implementation.js index 517833f85..7c8a8b26c 100644 --- a/lib/build/recipe/session/api/implementation.js +++ b/lib/build/recipe/session/api/implementation.js @@ -38,15 +38,17 @@ var __importDefault = Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("../../../utils"); const normalisedURLPath_1 = __importDefault(require("../../../normalisedURLPath")); -const utils_2 = require("../utils"); +const sessionRequestFunctions_1 = require("../sessionRequestFunctions"); function getAPIInterface() { return { refreshPOST: function ({ options, userContext }) { return __awaiter(this, void 0, void 0, function* () { - return yield options.recipeImplementation.refreshSession({ + return sessionRequestFunctions_1.refreshSessionInRequest({ req: options.req, res: options.res, userContext, + config: options.config, + recipeInterfaceImpl: options.recipeImplementation, }); }); }, @@ -59,29 +61,22 @@ function getAPIInterface() { let incomingPath = new normalisedURLPath_1.default(options.req.getOriginalURL()); let refreshTokenPath = options.config.refreshTokenPath; if (incomingPath.equals(refreshTokenPath) && method === "post") { - return options.recipeImplementation.refreshSession({ + return sessionRequestFunctions_1.refreshSessionInRequest({ req: options.req, res: options.res, userContext, + config: options.config, + recipeInterfaceImpl: options.recipeImplementation, }); } else { - const session = yield options.recipeImplementation.getSession({ + return sessionRequestFunctions_1.getSessionFromRequest({ req: options.req, res: options.res, options: verifySessionOptions, + config: options.config, + recipeInterfaceImpl: options.recipeImplementation, userContext, }); - if (session !== undefined) { - const claimValidators = yield utils_2.getRequiredClaimValidators( - session, - verifySessionOptions === null || verifySessionOptions === void 0 - ? void 0 - : verifySessionOptions.overrideGlobalClaimValidators, - userContext - ); - yield session.assertClaims(claimValidators, userContext); - } - return session; } }); }, diff --git a/lib/build/recipe/session/api/signout.js b/lib/build/recipe/session/api/signout.js index d0ca3e50c..4fe19526d 100644 --- a/lib/build/recipe/session/api/signout.js +++ b/lib/build/recipe/session/api/signout.js @@ -47,6 +47,7 @@ var __awaiter = Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("../../../utils"); const utils_2 = require("../../../utils"); +const sessionRequestFunctions_1 = require("../sessionRequestFunctions"); function signOutAPI(apiImplementation, options) { return __awaiter(this, void 0, void 0, function* () { // Logic as per https://github.com/supertokens/supertokens-node/issues/34#issuecomment-717958537 @@ -54,9 +55,11 @@ function signOutAPI(apiImplementation, options) { return false; } let defaultUserContext = utils_2.makeDefaultUserContextFromAPI(options.req); - const session = yield options.recipeImplementation.getSession({ + const session = yield sessionRequestFunctions_1.getSessionFromRequest({ req: options.req, res: options.res, + config: options.config, + recipeInterfaceImpl: options.recipeImplementation, options: { sessionRequired: false, overrideGlobalClaimValidators: () => [], diff --git a/lib/build/recipe/session/constants.d.ts b/lib/build/recipe/session/constants.d.ts index 4f1b5bd68..77315f542 100644 --- a/lib/build/recipe/session/constants.d.ts +++ b/lib/build/recipe/session/constants.d.ts @@ -3,3 +3,4 @@ import { TokenTransferMethod } from "./types"; export declare const REFRESH_API_PATH = "/session/refresh"; export declare const SIGNOUT_API_PATH = "/signout"; export declare const availableTokenTransferMethods: TokenTransferMethod[]; +export declare const hundredYearsInMs = 3153600000000; diff --git a/lib/build/recipe/session/constants.js b/lib/build/recipe/session/constants.js index 742008e66..06ebc6c0a 100644 --- a/lib/build/recipe/session/constants.js +++ b/lib/build/recipe/session/constants.js @@ -14,7 +14,8 @@ * under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); -exports.availableTokenTransferMethods = exports.SIGNOUT_API_PATH = exports.REFRESH_API_PATH = void 0; +exports.hundredYearsInMs = exports.availableTokenTransferMethods = exports.SIGNOUT_API_PATH = exports.REFRESH_API_PATH = void 0; exports.REFRESH_API_PATH = "/session/refresh"; exports.SIGNOUT_API_PATH = "/signout"; exports.availableTokenTransferMethods = ["cookie", "header"]; +exports.hundredYearsInMs = 3153600000000; diff --git a/lib/build/recipe/session/cookieAndHeaders.d.ts b/lib/build/recipe/session/cookieAndHeaders.d.ts index 40cd2f2bf..4d8feb729 100644 --- a/lib/build/recipe/session/cookieAndHeaders.d.ts +++ b/lib/build/recipe/session/cookieAndHeaders.d.ts @@ -9,12 +9,8 @@ export declare function clearSession( ): void; export declare function getAntiCsrfTokenFromHeaders(req: BaseRequest): string | undefined; export declare function setAntiCsrfTokenInHeaders(res: BaseResponse, antiCsrfToken: string): void; -export declare function setFrontTokenInHeaders( - res: BaseResponse, - userId: string, - atExpiry: number, - accessTokenPayload: any -): void; +export declare function buildFrontToken(userId: string, atExpiry: number, accessTokenPayload: any): string; +export declare function setFrontTokenInHeaders(res: BaseResponse, frontToken: string): void; export declare function getCORSAllowedHeaders(): string[]; export declare function getToken( req: BaseRequest, diff --git a/lib/build/recipe/session/cookieAndHeaders.js b/lib/build/recipe/session/cookieAndHeaders.js index 4a26d6437..89f7957ce 100644 --- a/lib/build/recipe/session/cookieAndHeaders.js +++ b/lib/build/recipe/session/cookieAndHeaders.js @@ -1,6 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.getAuthModeFromHeader = exports.setCookie = exports.setHeader = exports.setToken = exports.getToken = exports.getCORSAllowedHeaders = exports.setFrontTokenInHeaders = exports.setAntiCsrfTokenInHeaders = exports.getAntiCsrfTokenFromHeaders = exports.clearSession = exports.clearSessionFromAllTokenTransferMethods = void 0; +exports.getAuthModeFromHeader = exports.setCookie = exports.setHeader = exports.setToken = exports.getToken = exports.getCORSAllowedHeaders = exports.setFrontTokenInHeaders = exports.buildFrontToken = exports.setAntiCsrfTokenInHeaders = exports.getAntiCsrfTokenFromHeaders = exports.clearSession = exports.clearSessionFromAllTokenTransferMethods = void 0; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. * * This software is licensed under the Apache License, Version 2.0 (the @@ -16,6 +16,7 @@ exports.getAuthModeFromHeader = exports.setCookie = exports.setHeader = exports. * under the License. */ const constants_1 = require("../../constants"); +const logger_1 = require("../../logger"); const constants_2 = require("./constants"); const authorizationHeaderKey = "authorization"; const accessTokenCookieKey = "sAccessToken"; @@ -58,13 +59,17 @@ function setAntiCsrfTokenInHeaders(res, antiCsrfToken) { res.setHeader("Access-Control-Expose-Headers", antiCsrfHeaderKey, true); } exports.setAntiCsrfTokenInHeaders = setAntiCsrfTokenInHeaders; -function setFrontTokenInHeaders(res, userId, atExpiry, accessTokenPayload) { +function buildFrontToken(userId, atExpiry, accessTokenPayload) { const tokenInfo = { uid: userId, ate: atExpiry, up: accessTokenPayload, }; - res.setHeader(frontTokenHeaderKey, Buffer.from(JSON.stringify(tokenInfo)).toString("base64"), false); + return Buffer.from(JSON.stringify(tokenInfo)).toString("base64"); +} +exports.buildFrontToken = buildFrontToken; +function setFrontTokenInHeaders(res, frontToken) { + res.setHeader(frontTokenHeaderKey, frontToken, false); res.setHeader("Access-Control-Expose-Headers", frontTokenHeaderKey, true); } exports.setFrontTokenInHeaders = setFrontTokenInHeaders; @@ -107,6 +112,7 @@ function getToken(req, tokenType, transferMethod) { } exports.getToken = getToken; function setToken(config, res, tokenType, value, expires, transferMethod) { + logger_1.logDebugMessage(`setToken: Setting ${tokenType} token as ${transferMethod}`); if (transferMethod === "cookie") { setCookie( config, @@ -145,7 +151,8 @@ function setCookie(config, res, name, value, expires, pathType) { if (pathType === "refreshTokenPath") { path = config.refreshTokenPath.getAsStringDangerous(); } else if (pathType === "accessTokenPath") { - path = "/"; + path = + config.accessTokenPath.getAsStringDangerous() === "" ? "/" : config.accessTokenPath.getAsStringDangerous(); } let httpOnly = true; return res.setCookie(name, value, domain, secure, httpOnly, expires, path, sameSite); diff --git a/lib/build/recipe/session/index.d.ts b/lib/build/recipe/session/index.d.ts index 11885a9a2..67c6fbc92 100644 --- a/lib/build/recipe/session/index.d.ts +++ b/lib/build/recipe/session/index.d.ts @@ -2,7 +2,6 @@ import SuperTokensError from "./error"; import { VerifySessionOptions, - RecipeInterface, SessionContainerInterface as SessionContainer, SessionInformation, APIInterface, @@ -10,6 +9,7 @@ import { SessionClaimValidator, SessionClaim, ClaimValidationError, + RecipeInterface, } from "./types"; import Recipe from "./recipe"; import { JSONObject } from "../../types"; @@ -22,7 +22,15 @@ export default class SessionWrapper { userId: string, recipeUserId?: string, accessTokenPayload?: any, - sessionData?: any, + sessionDataInDatabase?: any, + userContext?: any + ): Promise; + static createNewSessionWithoutRequestResponse( + userId: string, + recipeUserId?: string, + accessTokenPayload?: any, + sessionDataInDatabase?: any, + disableAntiCsrf?: boolean, userContext?: any ): Promise; static validateClaimsForSessionHandle( @@ -59,41 +67,68 @@ export default class SessionWrapper { }, userContext?: any ): Promise; + static getSession( + req: any, + res: any, + options?: VerifySessionOptions, + userContext?: any + ): Promise; + /** + * Tries to validate an access token and build a Session object from it. + * + * Notes about anti-csrf checking: + * - if the `antiCsrf` is set to VIA_HEADER in the Session recipe config you have to handle anti-csrf checking before calling this function and set antiCsrfCheck to false in the options. + * - you can disable anti-csrf checks by setting antiCsrf to NONE in the Session recipe config. We only recommend this if you are always getting the access-token from the Authorization header. + * - if the antiCsrf check fails the returned satatus will be TRY_REFRESH_TOKEN_ERROR + * + * Results: + * OK: The session was successfully validated, including claim validation + * CLAIM_VALIDATION_ERROR: While the access token is valid, one or more claim validators have failed. Our frontend SDKs expect a 403 response the contents matching the value returned from this function. + * TRY_REFRESH_TOKEN_ERROR: This means, that the access token structure was valid, but it didn't pass validation for some reason and the user should call the refresh API. + * You can send a 401 response to trigger this behaviour if you are using our frontend SDKs + * UNAUTHORISED: This means that the access token likely doesn't belong to a SuperTokens session. If this is unexpected, it's best handled by sending a 401 response. + * + * @param accessToken The access token extracted from the authorization header or cookies + * @param antiCsrfToken The anti-csrf token extracted from the authorization header or cookies. Can be undefined if antiCsrfCheck is false + * @param options Same options objects as getSession or verifySession takes, except the `sessionRequired` prop, which is always set to true in this function + * @param userContext User context + */ + static getSessionWithoutRequestResponse(accessToken: string, antiCsrfToken?: string): Promise; + static getSessionWithoutRequestResponse( + accessToken: string, + antiCsrfToken?: string, + options?: VerifySessionOptions & { + sessionRequired?: true; + }, + userContext?: any + ): Promise; + static getSessionWithoutRequestResponse( + accessToken: string, + antiCsrfToken?: string, + options?: VerifySessionOptions & { + sessionRequired: false; + }, + userContext?: any + ): Promise; + static getSessionWithoutRequestResponse( + accessToken: string, + antiCsrfToken?: string, + options?: VerifySessionOptions, + userContext?: any + ): Promise; static getSessionInformation(sessionHandle: string, userContext?: any): Promise; static refreshSession(req: any, res: any, userContext?: any): Promise; + static refreshSessionWithoutRequestResponse( + refreshToken: string, + disableAntiCsrf?: boolean, + antiCsrfToken?: string, + userContext?: any + ): Promise; static revokeAllSessionsForUser(userId: string, userContext?: any): Promise; static getAllSessionHandlesForUser(userId: string, userContext?: any): Promise; static revokeSession(sessionHandle: string, userContext?: any): Promise; static revokeMultipleSessions(sessionHandles: string[], userContext?: any): Promise; - static updateSessionData(sessionHandle: string, newSessionData: any, userContext?: any): Promise; - static regenerateAccessToken( - accessToken: string, - newAccessTokenPayload?: any, - userContext?: any - ): Promise< - | { - status: "OK"; - session: { - handle: string; - userId: string; - recipeUserId: string; - userDataInJWT: any; - }; - accessToken?: - | { - token: string; - expiry: number; - createdTime: number; - } - | undefined; - } - | undefined - >; - static updateAccessTokenPayload( - sessionHandle: string, - newAccessTokenPayload: any, - userContext?: any - ): Promise; + static updateSessionDataInDatabase(sessionHandle: string, newSessionData: any, userContext?: any): Promise; static mergeIntoAccessTokenPayload( sessionHandle: string, accessTokenPayloadUpdate: JSONObject, @@ -102,6 +137,7 @@ export default class SessionWrapper { static createJWT( payload?: any, validitySeconds?: number, + useStaticSigningKey?: boolean, userContext?: any ): Promise< | { @@ -115,7 +151,6 @@ export default class SessionWrapper { static getJWKS( userContext?: any ): Promise<{ - status: "OK"; keys: import("../jwt").JsonWebKey[]; }>; static getOpenIdDiscoveryConfiguration( @@ -149,15 +184,17 @@ export default class SessionWrapper { } export declare let init: typeof Recipe.init; export declare let createNewSession: typeof SessionWrapper.createNewSession; +export declare let createNewSessionWithoutRequestResponse: typeof SessionWrapper.createNewSessionWithoutRequestResponse; export declare let getSession: typeof SessionWrapper.getSession; +export declare let getSessionWithoutRequestResponse: typeof SessionWrapper.getSessionWithoutRequestResponse; export declare let getSessionInformation: typeof SessionWrapper.getSessionInformation; export declare let refreshSession: typeof SessionWrapper.refreshSession; +export declare let refreshSessionWithoutRequestResponse: typeof SessionWrapper.refreshSessionWithoutRequestResponse; export declare let revokeAllSessionsForUser: typeof SessionWrapper.revokeAllSessionsForUser; export declare let getAllSessionHandlesForUser: typeof SessionWrapper.getAllSessionHandlesForUser; export declare let revokeSession: typeof SessionWrapper.revokeSession; export declare let revokeMultipleSessions: typeof SessionWrapper.revokeMultipleSessions; -export declare let updateSessionData: typeof SessionWrapper.updateSessionData; -export declare let updateAccessTokenPayload: typeof SessionWrapper.updateAccessTokenPayload; +export declare let updateSessionDataInDatabase: typeof SessionWrapper.updateSessionDataInDatabase; export declare let mergeIntoAccessTokenPayload: typeof SessionWrapper.mergeIntoAccessTokenPayload; export declare let fetchAndSetClaim: typeof SessionWrapper.fetchAndSetClaim; export declare let setClaimValue: typeof SessionWrapper.setClaimValue; diff --git a/lib/build/recipe/session/index.js b/lib/build/recipe/session/index.js index 84bddc02d..4818c5be2 100644 --- a/lib/build/recipe/session/index.js +++ b/lib/build/recipe/session/index.js @@ -50,12 +50,11 @@ var __importDefault = return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.getOpenIdDiscoveryConfiguration = exports.getJWKS = exports.createJWT = exports.Error = exports.validateClaimsForSessionHandle = exports.removeClaim = exports.getClaimValue = exports.setClaimValue = exports.fetchAndSetClaim = exports.mergeIntoAccessTokenPayload = exports.updateAccessTokenPayload = exports.updateSessionData = exports.revokeMultipleSessions = exports.revokeSession = exports.getAllSessionHandlesForUser = exports.revokeAllSessionsForUser = exports.refreshSession = exports.getSessionInformation = exports.getSession = exports.createNewSession = exports.init = void 0; +exports.getOpenIdDiscoveryConfiguration = exports.getJWKS = exports.createJWT = exports.Error = exports.validateClaimsForSessionHandle = exports.removeClaim = exports.getClaimValue = exports.setClaimValue = exports.fetchAndSetClaim = exports.mergeIntoAccessTokenPayload = exports.updateSessionDataInDatabase = exports.revokeMultipleSessions = exports.revokeSession = exports.getAllSessionHandlesForUser = exports.revokeAllSessionsForUser = exports.refreshSessionWithoutRequestResponse = exports.refreshSession = exports.getSessionInformation = exports.getSessionWithoutRequestResponse = exports.getSession = exports.createNewSessionWithoutRequestResponse = exports.createNewSession = exports.init = void 0; const error_1 = __importDefault(require("./error")); const recipe_1 = __importDefault(require("./recipe")); -const framework_1 = __importDefault(require("../../framework")); -const supertokens_1 = __importDefault(require("../../supertokens")); const utils_1 = require("./utils"); +const sessionRequestFunctions_1 = require("./sessionRequestFunctions"); // For Express class SessionWrapper { static createNewSession( @@ -64,29 +63,51 @@ class SessionWrapper { userId, recipeUserId, accessTokenPayload = {}, - sessionData = {}, + sessionDataInDatabase = {}, userContext = {} ) { return __awaiter(this, void 0, void 0, function* () { - const claimsAddedByOtherRecipes = recipe_1.default.getInstanceOrThrowError().getClaimsAddedByOtherRecipes(); - let finalAccessTokenPayload = accessTokenPayload; + const recipeInstance = recipe_1.default.getInstanceOrThrowError(); + const config = recipeInstance.config; + const appInfo = recipeInstance.getAppInfo(); + return yield sessionRequestFunctions_1.createNewSessionInRequest({ + req, + res, + userContext, + recipeInstance, + accessTokenPayload, + userId, + recipeUserId, + config, + appInfo, + sessionDataInDatabase, + }); + }); + } + static createNewSessionWithoutRequestResponse( + userId, + recipeUserId, + accessTokenPayload = {}, + sessionDataInDatabase = {}, + disableAntiCsrf = false, + userContext = {} + ) { + return __awaiter(this, void 0, void 0, function* () { + const recipeInstance = recipe_1.default.getInstanceOrThrowError(); + const claimsAddedByOtherRecipes = recipeInstance.getClaimsAddedByOtherRecipes(); + const appInfo = recipeInstance.getAppInfo(); + const issuer = appInfo.apiDomain.getAsStringDangerous() + appInfo.apiBasePath.getAsStringDangerous(); + let finalAccessTokenPayload = Object.assign(Object.assign({}, accessTokenPayload), { iss: issuer }); for (const claim of claimsAddedByOtherRecipes) { const update = yield claim.build(userId, recipeUserId, userContext); finalAccessTokenPayload = Object.assign(Object.assign({}, finalAccessTokenPayload), update); } - if (!req.wrapperUsed) { - req = framework_1.default[supertokens_1.default.getInstanceOrThrowError().framework].wrapRequest(req); - } - if (!res.wrapperUsed) { - res = framework_1.default[supertokens_1.default.getInstanceOrThrowError().framework].wrapResponse(res); - } return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.createNewSession({ - req, - res, userId, recipeUserId, accessTokenPayload: finalAccessTokenPayload, - sessionData, + sessionDataInDatabase, + disableAntiCsrf, userContext, }); }); @@ -119,7 +140,7 @@ class SessionWrapper { let claimValidationResponse = yield recipeImpl.validateClaims({ userId: sessionInfo.userId, recipeUserId: sessionInfo.recipeUserId, - accessTokenPayload: sessionInfo.accessTokenPayload, + accessTokenPayload: sessionInfo.customClaimsInAccessTokenPayload, claimValidators, userContext, }); @@ -142,16 +163,30 @@ class SessionWrapper { }; }); } - static getSession(req, res, options, userContext = {}) { + static getSession(req, res, options, userContext) { + return __awaiter(this, void 0, void 0, function* () { + const recipeInstance = recipe_1.default.getInstanceOrThrowError(); + const config = recipeInstance.config; + const recipeInterfaceImpl = recipeInstance.recipeInterfaceImpl; + return sessionRequestFunctions_1.getSessionFromRequest({ + req, + res, + recipeInterfaceImpl, + config, + options, + userContext, + }); + }); + } + static getSessionWithoutRequestResponse(accessToken, antiCsrfToken, options, userContext = {}) { return __awaiter(this, void 0, void 0, function* () { - if (!res.wrapperUsed) { - res = framework_1.default[supertokens_1.default.getInstanceOrThrowError().framework].wrapResponse(res); - } - if (!req.wrapperUsed) { - req = framework_1.default[supertokens_1.default.getInstanceOrThrowError().framework].wrapRequest(req); - } const recipeInterfaceImpl = recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl; - const session = yield recipeInterfaceImpl.getSession({ req, res, options, userContext }); + const session = yield recipeInterfaceImpl.getSession({ + accessToken, + antiCsrfToken, + options, + userContext, + }); if (session !== undefined) { const claimValidators = yield utils_1.getRequiredClaimValidators( session, @@ -170,13 +205,29 @@ class SessionWrapper { }); } static refreshSession(req, res, userContext = {}) { - if (!res.wrapperUsed) { - res = framework_1.default[supertokens_1.default.getInstanceOrThrowError().framework].wrapResponse(res); - } - if (!req.wrapperUsed) { - req = framework_1.default[supertokens_1.default.getInstanceOrThrowError().framework].wrapRequest(req); - } - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.refreshSession({ req, res, userContext }); + const recipeInstance = recipe_1.default.getInstanceOrThrowError(); + const config = recipeInstance.config; + const recipeInterfaceImpl = recipeInstance.recipeInterfaceImpl; + return sessionRequestFunctions_1.refreshSessionInRequest({ + res, + req, + userContext, + config, + recipeInterfaceImpl, + }); + } + static refreshSessionWithoutRequestResponse( + refreshToken, + disableAntiCsrf = false, + antiCsrfToken, + userContext = {} + ) { + return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.refreshSession({ + refreshToken, + disableAntiCsrf, + antiCsrfToken, + userContext, + }); } static revokeAllSessionsForUser(userId, userContext = {}) { return recipe_1.default @@ -200,27 +251,13 @@ class SessionWrapper { userContext, }); } - static updateSessionData(sessionHandle, newSessionData, userContext = {}) { - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.updateSessionData({ + static updateSessionDataInDatabase(sessionHandle, newSessionData, userContext = {}) { + return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.updateSessionDataInDatabase({ sessionHandle, newSessionData, userContext, }); } - static regenerateAccessToken(accessToken, newAccessTokenPayload, userContext = {}) { - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.regenerateAccessToken({ - accessToken, - newAccessTokenPayload, - userContext, - }); - } - static updateAccessTokenPayload(sessionHandle, newAccessTokenPayload, userContext = {}) { - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.updateAccessTokenPayload({ - sessionHandle, - newAccessTokenPayload, - userContext, - }); - } static mergeIntoAccessTokenPayload(sessionHandle, accessTokenPayloadUpdate, userContext = {}) { return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.mergeIntoAccessTokenPayload({ sessionHandle, @@ -228,32 +265,23 @@ class SessionWrapper { userContext, }); } - static createJWT(payload, validitySeconds, userContext = {}) { - let openIdRecipe = recipe_1.default.getInstanceOrThrowError().openIdRecipe; - if (openIdRecipe !== undefined) { - return openIdRecipe.recipeImplementation.createJWT({ payload, validitySeconds, userContext }); - } - throw new global.Error( - "createJWT cannot be used without enabling the JWT feature. Please set 'enableJWT: true' when initialising the Session recipe" - ); + static createJWT(payload, validitySeconds, useStaticSigningKey, userContext = {}) { + return recipe_1.default.getInstanceOrThrowError().openIdRecipe.recipeImplementation.createJWT({ + payload, + validitySeconds, + useStaticSigningKey, + userContext, + }); } static getJWKS(userContext = {}) { - let openIdRecipe = recipe_1.default.getInstanceOrThrowError().openIdRecipe; - if (openIdRecipe !== undefined) { - return openIdRecipe.recipeImplementation.getJWKS({ userContext }); - } - throw new global.Error( - "getJWKS cannot be used without enabling the JWT feature. Please set 'enableJWT: true' when initialising the Session recipe" - ); + return recipe_1.default.getInstanceOrThrowError().openIdRecipe.recipeImplementation.getJWKS({ userContext }); } static getOpenIdDiscoveryConfiguration(userContext = {}) { - let openIdRecipe = recipe_1.default.getInstanceOrThrowError().openIdRecipe; - if (openIdRecipe !== undefined) { - return openIdRecipe.recipeImplementation.getOpenIdDiscoveryConfiguration({ userContext }); - } - throw new global.Error( - "getOpenIdDiscoveryConfiguration cannot be used without enabling the JWT feature. Please set 'enableJWT: true' when initialising the Session recipe" - ); + return recipe_1.default + .getInstanceOrThrowError() + .openIdRecipe.recipeImplementation.getOpenIdDiscoveryConfiguration({ + userContext, + }); } static fetchAndSetClaim(sessionHandle, claim, userContext = {}) { return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.fetchAndSetClaim({ @@ -290,15 +318,17 @@ SessionWrapper.init = recipe_1.default.init; SessionWrapper.Error = error_1.default; exports.init = SessionWrapper.init; exports.createNewSession = SessionWrapper.createNewSession; +exports.createNewSessionWithoutRequestResponse = SessionWrapper.createNewSessionWithoutRequestResponse; exports.getSession = SessionWrapper.getSession; +exports.getSessionWithoutRequestResponse = SessionWrapper.getSessionWithoutRequestResponse; exports.getSessionInformation = SessionWrapper.getSessionInformation; exports.refreshSession = SessionWrapper.refreshSession; +exports.refreshSessionWithoutRequestResponse = SessionWrapper.refreshSessionWithoutRequestResponse; exports.revokeAllSessionsForUser = SessionWrapper.revokeAllSessionsForUser; exports.getAllSessionHandlesForUser = SessionWrapper.getAllSessionHandlesForUser; exports.revokeSession = SessionWrapper.revokeSession; exports.revokeMultipleSessions = SessionWrapper.revokeMultipleSessions; -exports.updateSessionData = SessionWrapper.updateSessionData; -exports.updateAccessTokenPayload = SessionWrapper.updateAccessTokenPayload; +exports.updateSessionDataInDatabase = SessionWrapper.updateSessionDataInDatabase; exports.mergeIntoAccessTokenPayload = SessionWrapper.mergeIntoAccessTokenPayload; exports.fetchAndSetClaim = SessionWrapper.fetchAndSetClaim; exports.setClaimValue = SessionWrapper.setClaimValue; diff --git a/lib/build/recipe/session/jwt.d.ts b/lib/build/recipe/session/jwt.d.ts index 4dda635b3..a0e848660 100644 --- a/lib/build/recipe/session/jwt.d.ts +++ b/lib/build/recipe/session/jwt.d.ts @@ -1,10 +1,11 @@ // @ts-nocheck export declare type ParsedJWTInfo = { + version: number; rawTokenString: string; rawPayload: string; header: string; payload: any; signature: string; + kid: string | undefined; }; export declare function parseJWTWithoutSignatureVerification(jwt: string): ParsedJWTInfo; -export declare function verifyJWT({ header, rawPayload, signature }: ParsedJWTInfo, jwtSigningPublicKey: string): void; diff --git a/lib/build/recipe/session/jwt.js b/lib/build/recipe/session/jwt.js index d13a9c7ad..e6aa04e1b 100644 --- a/lib/build/recipe/session/jwt.js +++ b/lib/build/recipe/session/jwt.js @@ -1,42 +1,4 @@ "use strict"; -var __createBinding = - (this && this.__createBinding) || - (Object.create - ? function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { - enumerable: true, - get: function () { - return m[k]; - }, - }); - } - : function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; - }); -var __setModuleDefault = - (this && this.__setModuleDefault) || - (Object.create - ? function (o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); - } - : function (o, v) { - o["default"] = v; - }); -var __importStar = - (this && this.__importStar) || - function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) - for (var k in mod) - if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; - }; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.verifyJWT = exports.parseJWTWithoutSignatureVerification = void 0; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. * * This software is licensed under the Apache License, Version 2.0 (the @@ -51,7 +13,8 @@ exports.verifyJWT = exports.parseJWTWithoutSignatureVerification = void 0; * License for the specific language governing permissions and limitations * under the License. */ -const crypto = __importStar(require("crypto")); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.parseJWTWithoutSignatureVerification = void 0; const HEADERS = new Set([ Buffer.from( JSON.stringify({ @@ -73,11 +36,27 @@ function parseJWTWithoutSignatureVerification(jwt) { if (splittedInput.length !== 3) { throw new Error("Invalid JWT"); } + // V1&V2 is functionally identical, plus all legacy tokens should be V2 now. + let version = 2; + let kid = undefined; + // V2 or older tokens did not save the key id; // checking header if (!HEADERS.has(splittedInput[0])) { - throw new Error("JWT header mismatch"); + const parsedHeader = JSON.parse(Buffer.from(splittedInput[0], "base64").toString()); + // We have to ensure version is a string, otherwise Number.parseInt can have unexpected results + if (typeof parsedHeader.version !== "string") { + throw new Error("JWT header mismatch"); + } + version = Number.parseInt(parsedHeader.version); + kid = parsedHeader.kid; + // Number.isInteger returns false for Number.NaN (if it fails to parse the version) + if (parsedHeader.typ !== "JWT" || !Number.isInteger(version) || version < 3 || kid === undefined) { + throw new Error("JWT header mismatch"); + } } return { + version, + kid, rawTokenString: jwt, rawPayload: splittedInput[1], header: splittedInput[0], @@ -88,18 +67,3 @@ function parseJWTWithoutSignatureVerification(jwt) { }; } exports.parseJWTWithoutSignatureVerification = parseJWTWithoutSignatureVerification; -function verifyJWT({ header, rawPayload, signature }, jwtSigningPublicKey) { - let verifier = crypto.createVerify("sha256"); - // convert the jwtSigningPublicKey into .pem format - verifier.update(header + "." + rawPayload); - if ( - !verifier.verify( - "-----BEGIN PUBLIC KEY-----\n" + jwtSigningPublicKey + "\n-----END PUBLIC KEY-----", - signature, - "base64" - ) - ) { - throw new Error("JWT verification failed"); - } -} -exports.verifyJWT = verifyJWT; diff --git a/lib/build/recipe/session/recipe.d.ts b/lib/build/recipe/session/recipe.d.ts index a7d920c95..ad5649db0 100644 --- a/lib/build/recipe/session/recipe.d.ts +++ b/lib/build/recipe/session/recipe.d.ts @@ -21,7 +21,7 @@ export default class SessionRecipe extends RecipeModule { private claimValidatorsAddedByOtherRecipes; config: TypeNormalisedInput; recipeInterfaceImpl: RecipeInterface; - openIdRecipe?: OpenIdRecipe; + openIdRecipe: OpenIdRecipe; apiImpl: APIInterface; isInServerlessEnv: boolean; constructor(recipeId: string, appInfo: NormalisedAppinfo, isInServerlessEnv: boolean, config?: TypeInput); diff --git a/lib/build/recipe/session/recipe.js b/lib/build/recipe/session/recipe.js index 7798b4814..7f260eb05 100644 --- a/lib/build/recipe/session/recipe.js +++ b/lib/build/recipe/session/recipe.js @@ -59,7 +59,6 @@ const constants_1 = require("./constants"); const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); const cookieAndHeaders_1 = require("./cookieAndHeaders"); const recipeImplementation_1 = __importDefault(require("./recipeImplementation")); -const with_jwt_1 = __importDefault(require("./with-jwt")); const querier_1 = require("../../querier"); const implementation_1 = __importDefault(require("./api/implementation")); const supertokens_js_override_1 = __importDefault(require("supertokens-js-override")); @@ -106,9 +105,7 @@ class SessionRecipe extends recipeModule_1.default { disabled: this.apiImpl.signOutPOST === undefined, }, ]; - if (this.openIdRecipe !== undefined) { - apisHandled.push(...this.openIdRecipe.getAPIsHandled()); - } + apisHandled.push(...this.openIdRecipe.getAPIsHandled()); return apisHandled; }; this.handleAPIRequest = (id, req, res, path, method) => @@ -125,10 +122,8 @@ class SessionRecipe extends recipeModule_1.default { return yield refresh_1.default(this.apiImpl, options); } else if (id === constants_1.SIGNOUT_API_PATH) { return yield signout_1.default(this.apiImpl, options); - } else if (this.openIdRecipe !== undefined) { - return yield this.openIdRecipe.handleAPIRequest(id, req, res, path, method); } else { - return false; + return yield this.openIdRecipe.handleAPIRequest(id, req, res, path, method); } }); this.handleError = (err, request, response) => @@ -166,24 +161,19 @@ class SessionRecipe extends recipeModule_1.default { } else { throw err; } - } else if (this.openIdRecipe !== undefined) { - return yield this.openIdRecipe.handleError(err, request, response); } else { - throw err; + return yield this.openIdRecipe.handleError(err, request, response); } }); this.getAllCORSHeaders = () => { let corsHeaders = [...cookieAndHeaders_1.getCORSAllowedHeaders()]; - if (this.openIdRecipe !== undefined) { - corsHeaders.push(...this.openIdRecipe.getAllCORSHeaders()); - } + corsHeaders.push(...this.openIdRecipe.getAllCORSHeaders()); return corsHeaders; }; this.isErrorFromThisRecipe = (err) => { return ( error_1.default.isErrorFromSuperTokens(err) && - (err.fromRecipe === SessionRecipe.RECIPE_ID || - (this.openIdRecipe !== undefined && this.openIdRecipe.isErrorFromThisRecipe(err))) + (err.fromRecipe === SessionRecipe.RECIPE_ID || this.openIdRecipe.isErrorFromThisRecipe(err)) ); }; this.verifySession = (options, request, response) => @@ -211,43 +201,18 @@ class SessionRecipe extends recipeModule_1.default { ); logger_1.logDebugMessage("session init: sessionExpiredStatusCode: " + this.config.sessionExpiredStatusCode); this.isInServerlessEnv = isInServerlessEnv; - if (this.config.jwt.enable === true) { - this.openIdRecipe = new recipe_1.default(recipeId, appInfo, isInServerlessEnv, { - issuer: this.config.jwt.issuer, - override: this.config.override.openIdFeature, - }); - let builder = new supertokens_js_override_1.default( - recipeImplementation_1.default( - querier_1.Querier.getNewInstanceOrThrowError(recipeId), - this.config, - this.getAppInfo(), - () => this.recipeInterfaceImpl - ) - ); - this.recipeInterfaceImpl = builder - .override((oI) => { - return with_jwt_1.default( - oI, - // this.jwtRecipe is never undefined here - this.openIdRecipe.recipeImplementation, - this.config - ); - }) - .override(this.config.override.functions) - .build(); - } else { - { - let builder = new supertokens_js_override_1.default( - recipeImplementation_1.default( - querier_1.Querier.getNewInstanceOrThrowError(recipeId), - this.config, - this.getAppInfo(), - () => this.recipeInterfaceImpl - ) - ); - this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); - } - } + this.openIdRecipe = new recipe_1.default(recipeId, appInfo, isInServerlessEnv, { + override: this.config.override.openIdFeature, + }); + let builder = new supertokens_js_override_1.default( + recipeImplementation_1.default( + querier_1.Querier.getNewInstanceOrThrowError(recipeId), + this.config, + this.getAppInfo(), + () => this.recipeInterfaceImpl + ) + ); + this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); { let builder = new supertokens_js_override_1.default(implementation_1.default()); this.apiImpl = builder.override(this.config.override.apis).build(); diff --git a/lib/build/recipe/session/recipeImplementation.d.ts b/lib/build/recipe/session/recipeImplementation.d.ts index bbca23737..5af8072a1 100644 --- a/lib/build/recipe/session/recipeImplementation.d.ts +++ b/lib/build/recipe/session/recipeImplementation.d.ts @@ -1,32 +1,17 @@ // @ts-nocheck -import { RecipeInterface, TypeNormalisedInput, KeyInfo, AntiCsrfType } from "./types"; +import { JWTVerifyGetKey } from "jose"; +import { RecipeInterface, TypeNormalisedInput } from "./types"; import { Querier } from "../../querier"; import { NormalisedAppinfo } from "../../types"; -export declare class HandshakeInfo { - antiCsrf: AntiCsrfType; - accessTokenBlacklistingEnabled: boolean; - accessTokenValidity: number; - refreshTokenValidity: number; - private rawJwtSigningPublicKeyList; - constructor( - antiCsrf: AntiCsrfType, - accessTokenBlacklistingEnabled: boolean, - accessTokenValidity: number, - refreshTokenValidity: number, - rawJwtSigningPublicKeyList: KeyInfo[] - ); - setJwtSigningPublicKeyList(updatedList: KeyInfo[]): void; - getJwtSigningPublicKeyList(): KeyInfo[]; - clone(): HandshakeInfo; -} export declare type Helpers = { querier: Querier; - getHandshakeInfo: (forceRefetch?: boolean) => Promise; - updateJwtSigningPublicKeyInfo: (keyList: KeyInfo[] | undefined, publicKey: string, expiryTime: number) => void; + JWKS: JWTVerifyGetKey; config: TypeNormalisedInput; appInfo: NormalisedAppinfo; getRecipeImpl: () => RecipeInterface; }; +export declare const JWKCacheMaxAgeInMs = 60000; +export declare const protectedProps: string[]; export default function getRecipeInterface( querier: Querier, config: TypeNormalisedInput, diff --git a/lib/build/recipe/session/recipeImplementation.js b/lib/build/recipe/session/recipeImplementation.js index 32d708e40..f2ca8410a 100644 --- a/lib/build/recipe/session/recipeImplementation.js +++ b/lib/build/recipe/session/recipeImplementation.js @@ -72,157 +72,91 @@ var __importDefault = return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.HandshakeInfo = void 0; +exports.protectedProps = exports.JWKCacheMaxAgeInMs = void 0; +const jose_1 = require("jose"); const SessionFunctions = __importStar(require("./sessionFunctions")); const cookieAndHeaders_1 = require("./cookieAndHeaders"); const utils_1 = require("./utils"); const sessionClass_1 = __importDefault(require("./sessionClass")); -const error_1 = __importDefault(require("./error")); -const utils_2 = require("../../utils"); -const processState_1 = require("../../processState"); const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); const logger_1 = require("../../logger"); -const constants_1 = require("./constants"); const jwt_1 = require("./jwt"); const accessToken_1 = require("./accessToken"); -class HandshakeInfo { - constructor( - antiCsrf, - accessTokenBlacklistingEnabled, - accessTokenValidity, - refreshTokenValidity, - rawJwtSigningPublicKeyList - ) { - this.antiCsrf = antiCsrf; - this.accessTokenBlacklistingEnabled = accessTokenBlacklistingEnabled; - this.accessTokenValidity = accessTokenValidity; - this.refreshTokenValidity = refreshTokenValidity; - this.rawJwtSigningPublicKeyList = rawJwtSigningPublicKeyList; - } - setJwtSigningPublicKeyList(updatedList) { - this.rawJwtSigningPublicKeyList = updatedList; - } - getJwtSigningPublicKeyList() { - return this.rawJwtSigningPublicKeyList.filter((key) => key.expiryTime > Date.now()); - } - clone() { - return new HandshakeInfo( - this.antiCsrf, - this.accessTokenBlacklistingEnabled, - this.accessTokenValidity, - this.refreshTokenValidity, - this.rawJwtSigningPublicKeyList - ); - } -} -exports.HandshakeInfo = HandshakeInfo; -// We are defining this here to reduce the scope of legacy code -const LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME = "sIdRefreshToken"; +const error_1 = __importDefault(require("./error")); +exports.JWKCacheMaxAgeInMs = 60000; +exports.protectedProps = [ + "sub", + "iat", + "exp", + "sessionHandle", + "parentRefreshTokenHash1", + "refreshTokenHash1", + "antiCsrfToken", +]; function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverrides) { - let handshakeInfo; - function getHandshakeInfo(forceRefetch = false) { - return __awaiter(this, void 0, void 0, function* () { - if ( - handshakeInfo === undefined || - handshakeInfo.getJwtSigningPublicKeyList().length === 0 || - forceRefetch - ) { - let antiCsrf = config.antiCsrf; - processState_1.ProcessState.getInstance().addState( - processState_1.PROCESS_STATE.CALLING_SERVICE_IN_GET_HANDSHAKE_INFO - ); - let response = yield querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/handshake"), {}); - handshakeInfo = new HandshakeInfo( - antiCsrf, - response.accessTokenBlacklistingEnabled, - response.accessTokenValidity, - response.refreshTokenValidity, - response.jwtSigningPublicKeyList - ); - updateJwtSigningPublicKeyInfo( - response.jwtSigningPublicKeyList, - response.jwtSigningPublicKey, - response.jwtSigningPublicKeyExpiryTime + const JWKS = querier.getAllCoreUrlsForPath("/.well-known/jwks.json").map((url) => + jose_1.createRemoteJWKSet(new URL(url), { + cooldownDuration: 500, + cacheMaxAge: exports.JWKCacheMaxAgeInMs, + }) + ); + /** + This function fetches all JWKs from the first available core instance. This combines the other JWKS functions to become + error resistant. + + Every core instance a backend is connected to is expected to connect to the same database and use the same key set for + token verification. Otherwise, the result of session verification would depend on which core is currently available. + */ + const combinedJWKS = (...args) => + __awaiter(this, void 0, void 0, function* () { + let lastError = undefined; + if (JWKS.length === 0) { + throw Error( + "No SuperTokens core available to query. Please pass supertokens > connectionURI to the init function, or override all the functions of the recipe you are using." ); } - return handshakeInfo; + for (const jwks of JWKS) { + try { + // We await before returning to make sure we catch the error + return yield jwks(...args); + } catch (ex) { + lastError = ex; + } + } + throw lastError; }); - } - function updateJwtSigningPublicKeyInfo(keyList, publicKey, expiryTime) { - if (keyList === undefined) { - // Setting createdAt to Date.now() emulates the old lastUpdatedAt logic - keyList = [{ publicKey, expiryTime, createdAt: Date.now() }]; - } - if (handshakeInfo !== undefined) { - handshakeInfo.setJwtSigningPublicKeyList(keyList); - } - } let obj = { createNewSession: function ({ - req, - res, userId, recipeUserId, accessTokenPayload = {}, - sessionData = {}, - userContext, + sessionDataInDatabase = {}, + disableAntiCsrf, }) { return __awaiter(this, void 0, void 0, function* () { logger_1.logDebugMessage("createNewSession: Started"); - let outputTransferMethod = config.getTokenTransferMethod({ - req, - forCreateNewSession: true, - userContext, - }); - if (outputTransferMethod === "any") { - outputTransferMethod = "header"; - } - logger_1.logDebugMessage("createNewSession: using transfer method " + outputTransferMethod); - if ( - outputTransferMethod === "cookie" && - helpers.config.cookieSameSite === "none" && - !helpers.config.cookieSecure && - !( - (helpers.appInfo.topLevelAPIDomain === "localhost" || - utils_2.isAnIpAddress(helpers.appInfo.topLevelAPIDomain)) && - (helpers.appInfo.topLevelWebsiteDomain === "localhost" || - utils_2.isAnIpAddress(helpers.appInfo.topLevelWebsiteDomain)) - ) - ) { - // We can allow insecure cookie when both website & API domain are localhost or an IP - // When either of them is a different domain, API domain needs to have https and a secure cookie to work - throw new Error( - "Since your API and website domain are different, for sessions to work, please use https on your apiDomain and dont set cookieSecure to false." - ); - } - const disableAntiCSRF = outputTransferMethod === "header"; let response = yield SessionFunctions.createNewSession( helpers, userId, - disableAntiCSRF, recipeUserId, + disableAntiCsrf === true, accessTokenPayload, - sessionData + sessionDataInDatabase ); - for (const transferMethod of constants_1.availableTokenTransferMethods) { - if ( - transferMethod !== outputTransferMethod && - cookieAndHeaders_1.getToken(req, "access", transferMethod) !== undefined - ) { - cookieAndHeaders_1.clearSession(config, res, transferMethod); - } - } - utils_1.attachTokensToResponse(config, res, response, outputTransferMethod); + logger_1.logDebugMessage("createNewSession: Finished"); + const payload = jwt_1.parseJWTWithoutSignatureVerification(response.accessToken.token).payload; return new sessionClass_1.default( helpers, response.accessToken.token, + cookieAndHeaders_1.buildFrontToken(response.session.userId, response.accessToken.expiry, payload), + response.refreshToken, + response.antiCsrfToken, response.session.handle, response.session.userId, response.session.recipeUserId, - response.session.userDataInJWT, - res, - req, - outputTransferMethod + payload, + undefined, + true ); }); }, @@ -231,131 +165,64 @@ function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverride return input.claimValidatorsAddedByOtherRecipes; }); }, - /* In all cases if sIdRefreshToken token exists (so it's a legacy session) we return TRY_REFRESH_TOKEN. The refresh endpoint will clear this cookie and try to upgrade the session. - Check https://supertokens.com/docs/contribute/decisions/session/0007 for further details and a table of expected behaviours - */ - getSession: function ({ req, res, options, userContext }) { + getSession: function ({ accessToken: accessTokenString, antiCsrfToken, options }) { return __awaiter(this, void 0, void 0, function* () { - logger_1.logDebugMessage("getSession: Started"); - // This token isn't handled by getToken to limit the scope of this legacy/migration code - if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { - // This could create a spike on refresh calls during the update of the backend SDK - throw new error_1.default({ - message: "using legacy session, please call the refresh API", - type: error_1.default.TRY_REFRESH_TOKEN, - }); - } - const sessionOptional = - (options === null || options === void 0 ? void 0 : options.sessionRequired) === false; - logger_1.logDebugMessage("getSession: optional validation: " + sessionOptional); - const accessTokens = {}; - // We check all token transfer methods for available access tokens - for (const transferMethod of constants_1.availableTokenTransferMethods) { - const tokenString = cookieAndHeaders_1.getToken(req, "access", transferMethod); - if (tokenString !== undefined) { - try { - const info = jwt_1.parseJWTWithoutSignatureVerification(tokenString); - accessToken_1.validateAccessTokenStructure(info.payload); - logger_1.logDebugMessage("getSession: got access token from " + transferMethod); - accessTokens[transferMethod] = info; - } catch (_a) { - logger_1.logDebugMessage( - `getSession: ignoring token in ${transferMethod}, because it doesn't match our access token structure` - ); - } - } - } - const allowedTransferMethod = config.getTokenTransferMethod({ - req, - forCreateNewSession: false, - userContext, - }); - let requestTransferMethod; - let accessToken; if ( - (allowedTransferMethod === "any" || allowedTransferMethod === "header") && - accessTokens["header"] !== undefined - ) { - logger_1.logDebugMessage("getSession: using header transfer method"); - requestTransferMethod = "header"; - accessToken = accessTokens["header"]; - } else if ( - (allowedTransferMethod === "any" || allowedTransferMethod === "cookie") && - accessTokens["cookie"] !== undefined + (options === null || options === void 0 ? void 0 : options.antiCsrfCheck) !== false && + config.antiCsrf === "VIA_CUSTOM_HEADER" ) { - logger_1.logDebugMessage("getSession: using cookie transfer method"); - requestTransferMethod = "cookie"; - accessToken = accessTokens["cookie"]; - } else { - if (sessionOptional) { + throw new Error( + "Since the anti-csrf mode is VIA_CUSTOM_HEADER getSession can't check the CSRF token. Please either use VIA_TOKEN or set antiCsrfCheck to false" + ); + } + logger_1.logDebugMessage("getSession: Started"); + let accessToken; + try { + accessToken = jwt_1.parseJWTWithoutSignatureVerification(accessTokenString); + accessToken_1.validateAccessTokenStructure(accessToken.payload, accessToken.version); + } catch (error) { + if ((options === null || options === void 0 ? void 0 : options.sessionRequired) === false) { logger_1.logDebugMessage( - "getSession: returning undefined because accessToken is undefined and sessionRequired is false" + "getSession: Returning undefined because parsing failed and sessionRequired is false" ); - // there is no session that exists here, and the user wants session verification - // to be optional. So we return undefined. return undefined; } - logger_1.logDebugMessage("getSession: UNAUTHORISED because accessToken in request is undefined"); throw new error_1.default({ - message: - "Session does not exist. Are you sending the session tokens in the request with the appropriate token transfer method?", - type: error_1.default.UNAUTHORISED, - payload: { - // we do not clear the session here because of a - // race condition mentioned here: https://github.com/supertokens/supertokens-node/issues/17 - clearTokens: false, - }, + message: "Token parsing failed", + type: "UNAUTHORISED", + payload: { clearTokens: false }, }); } - let antiCsrfToken = cookieAndHeaders_1.getAntiCsrfTokenFromHeaders(req); - let doAntiCsrfCheck = options !== undefined ? options.antiCsrfCheck : undefined; - if (doAntiCsrfCheck === undefined) { - doAntiCsrfCheck = utils_2.normaliseHttpMethod(req.getMethod()) !== "get"; - } - if (requestTransferMethod === "header") { - doAntiCsrfCheck = false; - } - logger_1.logDebugMessage("getSession: Value of doAntiCsrfCheck is: " + doAntiCsrfCheck); - let response = yield SessionFunctions.getSession( + const response = yield SessionFunctions.getSession( helpers, accessToken, antiCsrfToken, - doAntiCsrfCheck, - utils_2.getRidFromHeader(req) !== undefined + (options === null || options === void 0 ? void 0 : options.antiCsrfCheck) !== false, + (options === null || options === void 0 ? void 0 : options.checkDatabase) === true ); - let accessTokenString = accessToken.rawTokenString; - if (response.accessToken !== undefined) { - cookieAndHeaders_1.setFrontTokenInHeaders( - res, - response.session.userId, - response.accessToken.expiry, - response.session.userDataInJWT - ); - cookieAndHeaders_1.setToken( - config, - res, - "access", - response.accessToken.token, - // We set the expiration to 100 years, because we can't really access the expiration of the refresh token everywhere we are setting it. - // This should be safe to do, since this is only the validity of the cookie (set here or on the frontend) but we check the expiration of the JWT anyway. - // Even if the token is expired the presence of the token indicates that the user could have a valid refresh - // Setting them to infinity would require special case handling on the frontend and just adding 10 years seems enough. - Date.now() + 3153600000000, - requestTransferMethod - ); - accessTokenString = response.accessToken.token; - } logger_1.logDebugMessage("getSession: Success!"); + const payload = + accessToken.version >= 3 + ? response.accessToken !== undefined + ? jwt_1.parseJWTWithoutSignatureVerification(response.accessToken.token).payload + : accessToken.payload + : response.session.userDataInJWT; const session = new sessionClass_1.default( helpers, - accessTokenString, + response.accessToken !== undefined ? response.accessToken.token : accessTokenString, + cookieAndHeaders_1.buildFrontToken( + response.session.userId, + response.accessToken !== undefined ? response.accessToken.expiry : response.session.expiryTime, + payload + ), + undefined, // refresh + antiCsrfToken, response.session.handle, response.session.userId, response.session.recipeUserId, - response.session.userDataInJWT, - res, - req, - requestTransferMethod + payload, + undefined, + response.accessToken !== undefined ); return session; }); @@ -410,134 +277,35 @@ function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverride return SessionFunctions.getSessionInformation(helpers, sessionHandle); }); }, - /* - In all cases: if sIdRefreshToken token exists (so it's a legacy session) we clear it. - Check http://localhost:3002/docs/contribute/decisions/session/0008 for further details and a table of expected behaviours - */ - refreshSession: function ({ req, res, userContext }) { + refreshSession: function ({ refreshToken, antiCsrfToken, disableAntiCsrf }) { return __awaiter(this, void 0, void 0, function* () { - logger_1.logDebugMessage("refreshSession: Started"); - const refreshTokens = {}; - // We check all token transfer methods for available refresh tokens - // We do this so that we can later clear all we are not overwriting - for (const transferMethod of constants_1.availableTokenTransferMethods) { - refreshTokens[transferMethod] = cookieAndHeaders_1.getToken(req, "refresh", transferMethod); - if (refreshTokens[transferMethod] !== undefined) { - logger_1.logDebugMessage("refreshSession: got refresh token from " + transferMethod); - } - } - const allowedTransferMethod = config.getTokenTransferMethod({ - req, - forCreateNewSession: false, - userContext, - }); - logger_1.logDebugMessage("refreshSession: getTokenTransferMethod returned " + allowedTransferMethod); - let requestTransferMethod; - let refreshToken; - if ( - (allowedTransferMethod === "any" || allowedTransferMethod === "header") && - refreshTokens["header"] !== undefined - ) { - logger_1.logDebugMessage("refreshSession: using header transfer method"); - requestTransferMethod = "header"; - refreshToken = refreshTokens["header"]; - } else if ( - (allowedTransferMethod === "any" || allowedTransferMethod === "cookie") && - refreshTokens["cookie"] - ) { - logger_1.logDebugMessage("refreshSession: using cookie transfer method"); - requestTransferMethod = "cookie"; - refreshToken = refreshTokens["cookie"]; - } else { - // This token isn't handled by getToken/setToken to limit the scope of this legacy/migration code - if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { - logger_1.logDebugMessage( - "refreshSession: cleared legacy id refresh token because refresh token was not found" - ); - cookieAndHeaders_1.setCookie( - config, - res, - LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, - "", - 0, - "accessTokenPath" - ); - } - logger_1.logDebugMessage( - "refreshSession: UNAUTHORISED because refresh token in request is undefined" - ); - throw new error_1.default({ - message: "Refresh token not found. Are you sending the refresh token in the request?", - payload: { - clearTokens: false, - }, - type: error_1.default.UNAUTHORISED, - }); - } - try { - let antiCsrfToken = cookieAndHeaders_1.getAntiCsrfTokenFromHeaders(req); - let response = yield SessionFunctions.refreshSession( - helpers, - refreshToken, - antiCsrfToken, - utils_2.getRidFromHeader(req) !== undefined, - requestTransferMethod - ); - logger_1.logDebugMessage( - "refreshSession: Attaching refreshed session info as " + requestTransferMethod - ); - // We clear the tokens in all token transfer methods we are not going to overwrite - for (const transferMethod of constants_1.availableTokenTransferMethods) { - if (transferMethod !== requestTransferMethod && refreshTokens[transferMethod] !== undefined) { - cookieAndHeaders_1.clearSession(config, res, transferMethod); - } - } - utils_1.attachTokensToResponse(config, res, response, requestTransferMethod); - logger_1.logDebugMessage("refreshSession: Success!"); - // This token isn't handled by getToken/setToken to limit the scope of this legacy/migration code - if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { - logger_1.logDebugMessage( - "refreshSession: cleared legacy id refresh token after successful refresh" - ); - cookieAndHeaders_1.setCookie( - config, - res, - LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, - "", - 0, - "accessTokenPath" - ); - } - return new sessionClass_1.default( - helpers, - response.accessToken.token, - response.session.handle, - response.session.userId, - response.session.recipeUserId, - response.session.userDataInJWT, - res, - req, - requestTransferMethod + if (disableAntiCsrf !== true && config.antiCsrf === "VIA_CUSTOM_HEADER") { + throw new Error( + "Since the anti-csrf mode is VIA_CUSTOM_HEADER getSession can't check the CSRF token. Please either use VIA_TOKEN or set antiCsrfCheck to false" ); - } catch (err) { - if (err.type === error_1.default.TOKEN_THEFT_DETECTED || err.payload.clearTokens) { - // This token isn't handled by getToken/setToken to limit the scope of this legacy/migration code - if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { - logger_1.logDebugMessage( - "refreshSession: cleared legacy id refresh token because refresh is clearing other tokens" - ); - cookieAndHeaders_1.setCookie( - config, - res, - LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, - "", - 0, - "accessTokenPath" - ); - } - } - throw err; } + logger_1.logDebugMessage("refreshSession: Started"); + const response = yield SessionFunctions.refreshSession( + helpers, + refreshToken, + antiCsrfToken, + disableAntiCsrf + ); + logger_1.logDebugMessage("refreshSession: Success!"); + const payload = jwt_1.parseJWTWithoutSignatureVerification(response.accessToken.token).payload; + return new sessionClass_1.default( + helpers, + response.accessToken.token, + cookieAndHeaders_1.buildFrontToken(response.session.userId, response.accessToken.expiry, payload), + response.refreshToken, + response.antiCsrfToken, + response.session.handle, + response.session.userId, + response.session.recipeUserId, + payload, + undefined, + true + ); }); }, regenerateAccessToken: function (input) { @@ -571,11 +339,8 @@ function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverride revokeMultipleSessions: function ({ sessionHandles }) { return SessionFunctions.revokeMultipleSessions(helpers, sessionHandles); }, - updateSessionData: function ({ sessionHandle, newSessionData }) { - return SessionFunctions.updateSessionData(helpers, sessionHandle, newSessionData); - }, - updateAccessTokenPayload: function ({ sessionHandle, newAccessTokenPayload }) { - return SessionFunctions.updateAccessTokenPayload(helpers, sessionHandle, newAccessTokenPayload); + updateSessionDataInDatabase: function ({ sessionHandle, newSessionData }) { + return SessionFunctions.updateSessionDataInDatabase(helpers, sessionHandle, newSessionData); }, mergeIntoAccessTokenPayload: function ({ sessionHandle, accessTokenPayloadUpdate, userContext }) { return __awaiter(this, void 0, void 0, function* () { @@ -583,8 +348,12 @@ function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverride if (sessionInfo === undefined) { return false; } - const newAccessTokenPayload = Object.assign( - Object.assign({}, sessionInfo.accessTokenPayload), + let newAccessTokenPayload = Object.assign({}, sessionInfo.customClaimsInAccessTokenPayload); + for (const key of exports.protectedProps) { + delete newAccessTokenPayload[key]; + } + newAccessTokenPayload = Object.assign( + Object.assign({}, newAccessTokenPayload), accessTokenPayloadUpdate ); for (const key of Object.keys(accessTokenPayloadUpdate)) { @@ -592,17 +361,7 @@ function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverride delete newAccessTokenPayload[key]; } } - return this.updateAccessTokenPayload({ sessionHandle, newAccessTokenPayload, userContext }); - }); - }, - getAccessTokenLifeTimeMS: function () { - return __awaiter(this, void 0, void 0, function* () { - return (yield getHandshakeInfo()).accessTokenValidity; - }); - }, - getRefreshTokenLifeTimeMS: function () { - return __awaiter(this, void 0, void 0, function* () { - return (yield getHandshakeInfo()).refreshTokenValidity; + return SessionFunctions.updateAccessTokenPayload(helpers, sessionHandle, newAccessTokenPayload); }); }, fetchAndSetClaim: function (input) { @@ -647,7 +406,10 @@ function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverride } return { status: "OK", - value: input.claim.getValueFromPayload(sessionInfo.accessTokenPayload, input.userContext), + value: input.claim.getValueFromPayload( + sessionInfo.customClaimsInAccessTokenPayload, + input.userContext + ), }; }); }, @@ -662,20 +424,14 @@ function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverride }; let helpers = { querier, - updateJwtSigningPublicKeyInfo, - getHandshakeInfo, + JWKS: combinedJWKS, config, appInfo, getRecipeImpl: getRecipeImplAfterOverrides, }; if (process.env.TEST_MODE === "testing") { // testing mode, we add some of the help functions to the obj - obj.getHandshakeInfo = getHandshakeInfo; - obj.updateJwtSigningPublicKeyInfo = updateJwtSigningPublicKeyInfo; obj.helpers = helpers; - obj.setHandshakeInfo = function (info) { - handshakeInfo = info; - }; } return obj; } diff --git a/lib/build/recipe/session/sessionClass.d.ts b/lib/build/recipe/session/sessionClass.d.ts index 65b95bab5..72379b3a1 100644 --- a/lib/build/recipe/session/sessionClass.d.ts +++ b/lib/build/recipe/session/sessionClass.d.ts @@ -1,36 +1,46 @@ // @ts-nocheck -import { BaseRequest, BaseResponse } from "../../framework"; -import { SessionClaim, SessionClaimValidator, SessionContainerInterface, TokenTransferMethod } from "./types"; +import { SessionClaim, SessionClaimValidator, SessionContainerInterface, ReqResInfo, TokenInfo } from "./types"; import { Helpers } from "./recipeImplementation"; export default class Session implements SessionContainerInterface { protected helpers: Helpers; protected accessToken: string; + protected frontToken: string; + protected refreshToken: TokenInfo | undefined; + protected antiCsrfToken: string | undefined; protected sessionHandle: string; protected userId: string; protected recipeUserId: string; protected userDataInAccessToken: any; - protected res: BaseResponse; - protected readonly req: BaseRequest; - protected readonly transferMethod: TokenTransferMethod; + protected reqResInfo: ReqResInfo | undefined; + protected accessTokenUpdated: boolean; constructor( helpers: Helpers, accessToken: string, + frontToken: string, + refreshToken: TokenInfo | undefined, + antiCsrfToken: string | undefined, sessionHandle: string, userId: string, recipeUserId: string, userDataInAccessToken: any, - res: BaseResponse, - req: BaseRequest, - transferMethod: TokenTransferMethod + reqResInfo: ReqResInfo | undefined, + accessTokenUpdated: boolean ); getRecipeUserId(_userContext?: any): string; revokeSession(userContext?: any): Promise; - getSessionData(userContext?: any): Promise; - updateSessionData(newSessionData: any, userContext?: any): Promise; + getSessionDataFromDatabase(userContext?: any): Promise; + updateSessionDataInDatabase(newSessionData: any, userContext?: any): Promise; getUserId(_userContext?: any): string; getAccessTokenPayload(_userContext?: any): any; getHandle(): string; getAccessToken(): string; + getAllSessionTokensDangerously(): { + accessToken: string; + accessAndFrontTokenUpdated: boolean; + refreshToken: string | undefined; + frontToken: string; + antiCsrfToken: string | undefined; + }; mergeIntoAccessTokenPayload(accessTokenPayloadUpdate: any, userContext?: any): Promise; getTimeCreated(userContext?: any): Promise; getExpiry(userContext?: any): Promise; @@ -39,8 +49,5 @@ export default class Session implements SessionContainerInterface { setClaimValue(claim: SessionClaim, value: T, userContext?: any): Promise; getClaimValue(claim: SessionClaim, userContext?: any): Promise; removeClaim(claim: SessionClaim, userContext?: any): Promise; - /** - * @deprecated Use mergeIntoAccessTokenPayload - */ - updateAccessTokenPayload(newAccessTokenPayload: any, userContext: any): Promise; + attachToRequestResponse(info: ReqResInfo): void; } diff --git a/lib/build/recipe/session/sessionClass.js b/lib/build/recipe/session/sessionClass.js index 0b5182995..1745d04a1 100644 --- a/lib/build/recipe/session/sessionClass.js +++ b/lib/build/recipe/session/sessionClass.js @@ -36,29 +36,50 @@ var __importDefault = return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); +/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * 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. + */ const cookieAndHeaders_1 = require("./cookieAndHeaders"); const error_1 = __importDefault(require("./error")); +const recipeImplementation_1 = require("./recipeImplementation"); +const utils_1 = require("./utils"); +const jwt_1 = require("./jwt"); class Session { constructor( helpers, accessToken, + frontToken, + refreshToken, + antiCsrfToken, sessionHandle, userId, recipeUserId, userDataInAccessToken, - res, - req, - transferMethod + reqResInfo, + accessTokenUpdated ) { this.helpers = helpers; this.accessToken = accessToken; + this.frontToken = frontToken; + this.refreshToken = refreshToken; + this.antiCsrfToken = antiCsrfToken; this.sessionHandle = sessionHandle; this.userId = userId; this.recipeUserId = recipeUserId; this.userDataInAccessToken = userDataInAccessToken; - this.res = res; - this.req = req; - this.transferMethod = transferMethod; + this.reqResInfo = reqResInfo; + this.accessTokenUpdated = accessTokenUpdated; } getRecipeUserId(_userContext) { return this.recipeUserId; @@ -69,16 +90,22 @@ class Session { sessionHandle: this.sessionHandle, userContext: userContext === undefined ? {} : userContext, }); - // we do not check the output of calling revokeSession - // before clearing the cookies because we are revoking the - // current API request's session. - // If we instead clear the cookies only when revokeSession - // returns true, it can cause this kind of a bug: - // https://github.com/supertokens/supertokens-node/issues/343 - cookieAndHeaders_1.clearSession(this.helpers.config, this.res, this.transferMethod); + if (this.reqResInfo !== undefined) { + // we do not check the output of calling revokeSession + // before clearing the cookies because we are revoking the + // current API request's session. + // If we instead clear the cookies only when revokeSession + // returns true, it can cause this kind of a bug: + // https://github.com/supertokens/supertokens-node/issues/343 + cookieAndHeaders_1.clearSession( + this.helpers.config, + this.reqResInfo.res, + this.reqResInfo.transferMethod + ); + } }); } - getSessionData(userContext) { + getSessionDataFromDatabase(userContext) { return __awaiter(this, void 0, void 0, function* () { let sessionInfo = yield this.helpers.getRecipeImpl().getSessionInformation({ sessionHandle: this.sessionHandle, @@ -90,13 +117,13 @@ class Session { type: error_1.default.UNAUTHORISED, }); } - return sessionInfo.sessionData; + return sessionInfo.sessionDataInDatabase; }); } - updateSessionData(newSessionData, userContext) { + updateSessionDataInDatabase(newSessionData, userContext) { return __awaiter(this, void 0, void 0, function* () { if ( - !(yield this.helpers.getRecipeImpl().updateSessionData({ + !(yield this.helpers.getRecipeImpl().updateSessionDataInDatabase({ sessionHandle: this.sessionHandle, newSessionData, userContext: userContext === undefined ? {} : userContext, @@ -121,19 +148,66 @@ class Session { getAccessToken() { return this.accessToken; } + getAllSessionTokensDangerously() { + var _a; + return { + accessToken: this.accessToken, + accessAndFrontTokenUpdated: this.accessTokenUpdated, + refreshToken: (_a = this.refreshToken) === null || _a === void 0 ? void 0 : _a.token, + frontToken: this.frontToken, + antiCsrfToken: this.antiCsrfToken, + }; + } // Any update to this function should also be reflected in the respective JWT version mergeIntoAccessTokenPayload(accessTokenPayloadUpdate, userContext) { return __awaiter(this, void 0, void 0, function* () { - const updatedPayload = Object.assign( - Object.assign({}, this.getAccessTokenPayload(userContext)), - accessTokenPayloadUpdate - ); + let newAccessTokenPayload = Object.assign({}, this.getAccessTokenPayload(userContext)); + for (const key of recipeImplementation_1.protectedProps) { + delete newAccessTokenPayload[key]; + } + newAccessTokenPayload = Object.assign(Object.assign({}, newAccessTokenPayload), accessTokenPayloadUpdate); for (const key of Object.keys(accessTokenPayloadUpdate)) { if (accessTokenPayloadUpdate[key] === null) { - delete updatedPayload[key]; + delete newAccessTokenPayload[key]; + } + } + let response = yield this.helpers.getRecipeImpl().regenerateAccessToken({ + accessToken: this.getAccessToken(), + newAccessTokenPayload, + userContext: userContext === undefined ? {} : userContext, + }); + if (response === undefined) { + throw new error_1.default({ + message: "Session does not exist anymore", + type: error_1.default.UNAUTHORISED, + }); + } + if (response.accessToken !== undefined) { + const respToken = jwt_1.parseJWTWithoutSignatureVerification(response.accessToken.token); + const payload = respToken.version < 3 ? response.session.userDataInJWT : respToken.payload; + this.userDataInAccessToken = payload; + this.accessToken = response.accessToken.token; + this.frontToken = cookieAndHeaders_1.buildFrontToken(this.userId, response.accessToken.expiry, payload); + this.accessTokenUpdated = true; + if (this.reqResInfo !== undefined) { + // We need to cast to let TS know that the accessToken in the response is defined (and we don't overwrite it with undefined) + utils_1.setAccessTokenInResponse( + this.reqResInfo.res, + this.accessToken, + this.frontToken, + this.helpers.config, + this.reqResInfo.transferMethod + ); } + } else { + // This case means that the access token has expired between the validation and this update + // We can't update the access token on the FE, as it will need to call refresh anyway but we handle this as a successful update during this request. + // the changes will be reflected on the FE after refresh is called + this.userDataInAccessToken = Object.assign( + Object.assign({}, this.getAccessTokenPayload()), + response.session.userDataInJWT + ); } - yield this.updateAccessTokenPayload(updatedPayload, userContext); }); } getTimeCreated(userContext) { @@ -177,6 +251,9 @@ class Session { userContext, }); if (validateClaimResponse.accessTokenPayloadUpdate !== undefined) { + for (const key of recipeImplementation_1.protectedProps) { + delete validateClaimResponse.accessTokenPayloadUpdate[key]; + } yield this.mergeIntoAccessTokenPayload(validateClaimResponse.accessTokenPayloadUpdate, userContext); } if (validateClaimResponse.invalidClaims.length !== 0) { @@ -215,45 +292,31 @@ class Session { const update = claim.removeFromPayloadByMerge_internal({}, userContext); return this.mergeIntoAccessTokenPayload(update, userContext); } - /** - * @deprecated Use mergeIntoAccessTokenPayload - */ - updateAccessTokenPayload(newAccessTokenPayload, userContext) { - return __awaiter(this, void 0, void 0, function* () { - let response = yield this.helpers.getRecipeImpl().regenerateAccessToken({ - accessToken: this.getAccessToken(), - newAccessTokenPayload, - userContext: userContext === undefined ? {} : userContext, - }); - if (response === undefined) { - throw new error_1.default({ - message: "Session does not exist anymore", - type: error_1.default.UNAUTHORISED, - }); - } - this.userDataInAccessToken = response.session.userDataInJWT; - if (response.accessToken !== undefined) { - this.accessToken = response.accessToken.token; - cookieAndHeaders_1.setFrontTokenInHeaders( - this.res, - response.session.userId, - response.accessToken.expiry, - response.session.userDataInJWT - ); + attachToRequestResponse(info) { + this.reqResInfo = info; + if (this.accessTokenUpdated) { + const { res, transferMethod } = info; + utils_1.setAccessTokenInResponse( + res, + this.accessToken, + this.frontToken, + this.helpers.config, + transferMethod + ); + if (this.refreshToken !== undefined) { cookieAndHeaders_1.setToken( this.helpers.config, - this.res, - "access", - response.accessToken.token, - // We set the expiration to 100 years, because we can't really access the expiration of the refresh token everywhere we are setting it. - // This should be safe to do, since this is only the validity of the cookie (set here or on the frontend) but we check the expiration of the JWT anyway. - // Even if the token is expired the presence of the token indicates that the user could have a valid refresh - // Setting them to infinity would require special case handling on the frontend and just adding 10 years seems enough. - Date.now() + 3153600000000, - this.transferMethod + res, + "refresh", + this.refreshToken.token, + this.refreshToken.expiry, + transferMethod ); } - }); + if (this.antiCsrfToken !== undefined) { + cookieAndHeaders_1.setAntiCsrfTokenInHeaders(res, this.antiCsrfToken); + } + } } } exports.default = Session; diff --git a/lib/build/recipe/session/sessionFunctions.d.ts b/lib/build/recipe/session/sessionFunctions.d.ts index 70264f63e..307e3237f 100644 --- a/lib/build/recipe/session/sessionFunctions.d.ts +++ b/lib/build/recipe/session/sessionFunctions.d.ts @@ -1,6 +1,6 @@ // @ts-nocheck import { ParsedJWTInfo } from "./jwt"; -import { CreateOrRefreshAPIResponse, SessionInformation, TokenTransferMethod } from "./types"; +import { CreateOrRefreshAPIResponse, SessionInformation } from "./types"; import { Helpers } from "./recipeImplementation"; /** * @description call this to "login" a user. @@ -8,10 +8,10 @@ import { Helpers } from "./recipeImplementation"; export declare function createNewSession( helpers: Helpers, userId: string, + recipeUserId: string | undefined, disableAntiCsrf: boolean, - recipeUserId?: string, accessTokenPayload?: any, - sessionData?: any + sessionDataInDatabase?: any ): Promise; /** * @description authenticates a session. To be used in APIs that require authentication @@ -21,13 +21,14 @@ export declare function getSession( parsedAccessToken: ParsedJWTInfo, antiCsrfToken: string | undefined, doAntiCsrfCheck: boolean, - containsCustomHeader: boolean + alwaysCheckCore: boolean ): Promise<{ session: { handle: string; userId: string; recipeUserId: string; userDataInJWT: any; + expiryTime: number; }; accessToken?: { token: string; @@ -51,8 +52,7 @@ export declare function refreshSession( helpers: Helpers, refreshToken: string, antiCsrfToken: string | undefined, - containsCustomHeader: boolean, - transferMethod: TokenTransferMethod + disableAntiCsrf: boolean ): Promise; /** * @description deletes session info of a user from db. This only invalidates the refresh token. Not the access token. @@ -76,7 +76,7 @@ export declare function revokeMultipleSessions(helpers: Helpers, sessionHandles: /** * @description: It provides no locking mechanism in case other processes are updating session data for this session as well. */ -export declare function updateSessionData( +export declare function updateSessionDataInDatabase( helpers: Helpers, sessionHandle: string, newSessionData: any diff --git a/lib/build/recipe/session/sessionFunctions.js b/lib/build/recipe/session/sessionFunctions.js index 7f272ba58..2ef9f835b 100644 --- a/lib/build/recipe/session/sessionFunctions.js +++ b/lib/build/recipe/session/sessionFunctions.js @@ -36,7 +36,7 @@ var __importDefault = return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.updateAccessTokenPayload = exports.updateSessionData = exports.revokeMultipleSessions = exports.revokeSession = exports.getAllSessionHandlesForUser = exports.revokeAllSessionsForUser = exports.refreshSession = exports.getSessionInformation = exports.getSession = exports.createNewSession = void 0; +exports.updateAccessTokenPayload = exports.updateSessionDataInDatabase = exports.revokeMultipleSessions = exports.revokeSession = exports.getAllSessionHandlesForUser = exports.revokeAllSessionsForUser = exports.refreshSession = exports.getSessionInformation = exports.getSession = exports.createNewSession = void 0; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. * * This software is licensed under the Apache License, Version 2.0 (the @@ -55,36 +55,37 @@ const accessToken_1 = require("./accessToken"); const error_1 = __importDefault(require("./error")); const processState_1 = require("../../processState"); const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); +const recipeImplementation_1 = require("./recipeImplementation"); const utils_1 = require("../../utils"); const logger_1 = require("../../logger"); /** * @description call this to "login" a user. */ -function createNewSession(helpers, userId, disableAntiCsrf, recipeUserId, accessTokenPayload = {}, sessionData = {}) { +function createNewSession( + helpers, + userId, + recipeUserId, + disableAntiCsrf, + accessTokenPayload = {}, + sessionDataInDatabase = {} +) { return __awaiter(this, void 0, void 0, function* () { accessTokenPayload = accessTokenPayload === null || accessTokenPayload === undefined ? {} : accessTokenPayload; - sessionData = sessionData === null || sessionData === undefined ? {} : sessionData; - let requestBody = { + sessionDataInDatabase = + sessionDataInDatabase === null || sessionDataInDatabase === undefined ? {} : sessionDataInDatabase; + const requestBody = { userId, recipeUserId, userDataInJWT: accessTokenPayload, - userDataInDatabase: sessionData, + userDataInDatabase: sessionDataInDatabase, + useDynamicSigningKey: helpers.config.useDynamicAccessTokenSigningKey, + enableAntiCsrf: !disableAntiCsrf && helpers.config.antiCsrf === "VIA_TOKEN", }; - let handShakeInfo = yield helpers.getHandshakeInfo(); - requestBody.enableAntiCsrf = !disableAntiCsrf && handShakeInfo.antiCsrf === "VIA_TOKEN"; - let response = yield helpers.querier.sendPostRequest( + const response = yield helpers.querier.sendPostRequest( new normalisedURLPath_1.default("/recipe/session"), requestBody ); - helpers.updateJwtSigningPublicKeyInfo( - response.jwtSigningPublicKeyList, - response.jwtSigningPublicKey, - response.jwtSigningPublicKeyExpiryTime - ); delete response.status; - delete response.jwtSigningPublicKey; - delete response.jwtSigningPublicKeyExpiryTime; - delete response.jwtSigningPublicKeyList; return response; }); } @@ -92,82 +93,85 @@ exports.createNewSession = createNewSession; /** * @description authenticates a session. To be used in APIs that require authentication */ -function getSession(helpers, parsedAccessToken, antiCsrfToken, doAntiCsrfCheck, containsCustomHeader) { +function getSession(helpers, parsedAccessToken, antiCsrfToken, doAntiCsrfCheck, alwaysCheckCore) { + var _a; return __awaiter(this, void 0, void 0, function* () { - let handShakeInfo = yield helpers.getHandshakeInfo(); let accessTokenInfo; - // If we have no key old enough to verify this access token we should reject it without calling the core - let foundASigningKeyThatIsOlderThanTheAccessToken = false; - for (const key of handShakeInfo.getJwtSigningPublicKeyList()) { - try { - /** - * get access token info using existing signingKey - */ - accessTokenInfo = yield accessToken_1.getInfoFromAccessToken( - parsedAccessToken, - key.publicKey, - handShakeInfo.antiCsrf === "VIA_TOKEN" && doAntiCsrfCheck - ); - foundASigningKeyThatIsOlderThanTheAccessToken = true; - } catch (err) { - /** - * if error type is not TRY_REFRESH_TOKEN, we return the - * error to the user - */ - if (err.type !== error_1.default.TRY_REFRESH_TOKEN) { - throw err; - } - /** - * if it comes here, it means token verification has failed. - * It may be due to: - * - signing key was updated and this token was signed with new key - * - access token is actually expired - * - access token was signed with the older signing key - * - * if access token is actually expired, we don't need to call core and - * just return TRY_REFRESH_TOKEN to the client - * - * if access token creation time is after this signing key was created - * we need to call core as there are chances that the token - * was signed with the updated signing key - * - * if access token creation time is before oldest signing key was created, - * so if foundASigningKeyThatIsOlderThanTheAccessToken is still false after - * the loop we just return TRY_REFRESH_TOKEN - */ + try { + /** + * get access token info using jwks + */ + accessTokenInfo = yield accessToken_1.getInfoFromAccessToken( + parsedAccessToken, + helpers.JWKS, + helpers.config.antiCsrf === "VIA_TOKEN" && doAntiCsrfCheck + ); + } catch (err) { + /** + * if error type is not TRY_REFRESH_TOKEN, we return the + * error to the user + */ + if (err.type !== error_1.default.TRY_REFRESH_TOKEN) { + throw err; + } + /** + * if it comes here, it means token verification has failed. + * It may be due to: + * - signing key was updated and this token was signed with new key + * - access token is actually expired + * - access token was signed with the older signing key + * + * if access token is actually expired, we don't need to call core and + * just return TRY_REFRESH_TOKEN to the client + * + * if access token creation time is after this signing key was created + * we need to call core as there are chances that the token + * was signed with the updated signing key + * + * if access token creation time is before oldest signing key was created, + * so if foundASigningKeyThatIsOlderThanTheAccessToken is still false after + * the loop we just return TRY_REFRESH_TOKEN + */ + if (parsedAccessToken.version < 3) { let payload = parsedAccessToken.payload; const timeCreated = accessToken_1.sanitizeNumberInput(payload.timeCreated); const expiryTime = accessToken_1.sanitizeNumberInput(payload.expiryTime); - if (expiryTime === undefined || expiryTime < Date.now()) { + if (expiryTime === undefined || timeCreated == undefined) { throw err; } - if (timeCreated === undefined) { + if (expiryTime < Date.now()) { throw err; } - // If we reached a key older than the token and failed to validate the token, - // that means it was signed by a key newer than the cached list. - // In this case we go to the server. - if (timeCreated >= key.createdAt) { - foundASigningKeyThatIsOlderThanTheAccessToken = true; - break; + // We check if the token was created since the last time we refreshed the keys from the core + // Since we do not know the exact timing of the last refresh, we check against the max age + if (timeCreated <= Date.now() - recipeImplementation_1.JWKCacheMaxAgeInMs) { + throw err; } + } else { + // Since v3 (and above) tokens contain a kid we can trust the cache-refresh mechanism of the jose library. + // This means we do not need to call the core since the signature wouldn't pass verification anyway. + throw err; } } - // If the token was created before the oldest key in the cache but hasn't expired, then a config value must've changed. - // E.g., the access_token_signing_key_update_interval was reduced, or access_token_signing_key_dynamic was turned on. - // Either way, the user needs to refresh the access token as validating by the server is likely to do nothing. - if (!foundASigningKeyThatIsOlderThanTheAccessToken) { - throw new error_1.default({ - message: "Access token has expired. Please call the refresh API", - type: error_1.default.TRY_REFRESH_TOKEN, - }); + if (parsedAccessToken.version >= 3) { + const tokenUsesDynamicKey = parsedAccessToken.kid.startsWith("d-"); + if (tokenUsesDynamicKey !== helpers.config.useDynamicAccessTokenSigningKey) { + logger_1.logDebugMessage( + "getSession: Returning TRY_REFRESH_TOKEN because the access token doesn't match the useDynamicAccessTokenSigningKey in the config" + ); + throw new error_1.default({ + message: "The access token doesn't match the useDynamicAccessTokenSigningKey setting", + type: error_1.default.TRY_REFRESH_TOKEN, + }); + } } + // If we get here we either have a V2 token that doesn't pass verification or a valid V3> token /** * anti-csrf check if accesstokenInfo is not undefined, * which means token verification was successful */ if (doAntiCsrfCheck) { - if (handShakeInfo.antiCsrf === "VIA_TOKEN") { + if (helpers.config.antiCsrf === "VIA_TOKEN") { if (accessTokenInfo !== undefined) { if (antiCsrfToken === undefined || antiCsrfToken !== accessTokenInfo.antiCsrfToken) { if (antiCsrfToken === undefined) { @@ -190,22 +194,15 @@ function getSession(helpers, parsedAccessToken, antiCsrfToken, doAntiCsrfCheck, } } } - } else if (handShakeInfo.antiCsrf === "VIA_CUSTOM_HEADER") { - if (!containsCustomHeader) { - logger_1.logDebugMessage( - "getSession: Returning TRY_REFRESH_TOKEN because custom header (rid) was not passed" - ); - throw new error_1.default({ - message: - "anti-csrf check failed. Please pass 'rid: \"session\"' header in the request, or set doAntiCsrfCheck to false for this API", - type: error_1.default.TRY_REFRESH_TOKEN, - }); - } + } else if (helpers.config.antiCsrf === "VIA_CUSTOM_HEADER") { + // The function should never be called by this (we check this outside the function as well) + // There we can add a bit more information to the error, so that's the primary check, this is just making sure. + throw new Error("Please either use VIA_TOKEN, NONE or call with doAntiCsrfCheck false"); } } if ( accessTokenInfo !== undefined && - !handShakeInfo.accessTokenBlacklistingEnabled && + !alwaysCheckCore && accessTokenInfo.parentRefreshTokenHash1 === undefined ) { return { @@ -214,6 +211,7 @@ function getSession(helpers, parsedAccessToken, antiCsrfToken, doAntiCsrfCheck, userId: accessTokenInfo.userId, recipeUserId: accessTokenInfo.recipeUserId, userDataInJWT: accessTokenInfo.userData, + expiryTime: accessTokenInfo.expiryTime, }, }; } @@ -222,22 +220,19 @@ function getSession(helpers, parsedAccessToken, antiCsrfToken, doAntiCsrfCheck, accessToken: parsedAccessToken.rawTokenString, antiCsrfToken, doAntiCsrfCheck, - enableAntiCsrf: handShakeInfo.antiCsrf === "VIA_TOKEN", + enableAntiCsrf: helpers.config.antiCsrf === "VIA_TOKEN", + checkDatabase: alwaysCheckCore, }; let response = yield helpers.querier.sendPostRequest( new normalisedURLPath_1.default("/recipe/session/verify"), requestBody ); if (response.status === "OK") { - helpers.updateJwtSigningPublicKeyInfo( - response.jwtSigningPublicKeyList, - response.jwtSigningPublicKey, - response.jwtSigningPublicKeyExpiryTime - ); delete response.status; - delete response.jwtSigningPublicKey; - delete response.jwtSigningPublicKeyExpiryTime; - delete response.jwtSigningPublicKeyList; + response.session.expiryTime = + ((_a = response.accessToken) === null || _a === void 0 ? void 0 : _a.expiry) || // if we got a new accesstoken we take the expiry time from there + (accessTokenInfo === null || accessTokenInfo === void 0 ? void 0 : accessTokenInfo.expiryTime) || // if we didn't get a new access token but could validate the token take that info (alwaysCheckCore === true, or parentRefreshTokenHash1 !== null) + parsedAccessToken.payload["expiryTime"]; // if the token didn't pass validation, but we got here, it means it was a v2 token that we didn't have the key cached for. return response; } else if (response.status === "UNAUTHORISED") { logger_1.logDebugMessage("getSession: Returning UNAUTHORISED because of core response"); @@ -246,20 +241,6 @@ function getSession(helpers, parsedAccessToken, antiCsrfToken, doAntiCsrfCheck, type: error_1.default.UNAUTHORISED, }); } else { - if ( - response.jwtSigningPublicKeyList !== undefined || - (response.jwtSigningPublicKey !== undefined && response.jwtSigningPublicKeyExpiryTime !== undefined) - ) { - // after CDI 2.7.1, the API returns the new keys - helpers.updateJwtSigningPublicKeyInfo( - response.jwtSigningPublicKeyList, - response.jwtSigningPublicKey, - response.jwtSigningPublicKeyExpiryTime - ); - } else { - // we force update the signing keys... - yield helpers.getHandshakeInfo(true); - } logger_1.logDebugMessage("getSession: Returning TRY_REFRESH_TOKEN because of core response."); throw new error_1.default({ message: response.message, @@ -284,9 +265,9 @@ function getSessionInformation(helpers, sessionHandle) { }); if (response.status === "OK") { // Change keys to make them more readable - response["sessionData"] = response.userDataInDatabase; - response["accessTokenPayload"] = response.userDataInJWT; - delete response.userDataInJWT; + response["sessionDataInDatabase"] = response.userDataInDatabase; + response["customClaimsInAccessTokenPayload"] = response.userDataInJWT; + delete response.userDataInDatabase; delete response.userDataInJWT; return response; } else { @@ -299,27 +280,17 @@ exports.getSessionInformation = getSessionInformation; * @description generates new access and refresh tokens for a given refresh token. Called when client's access token has expired. * @sideEffects calls onTokenTheftDetection if token theft is detected. */ -function refreshSession(helpers, refreshToken, antiCsrfToken, containsCustomHeader, transferMethod) { +function refreshSession(helpers, refreshToken, antiCsrfToken, disableAntiCsrf) { return __awaiter(this, void 0, void 0, function* () { - let handShakeInfo = yield helpers.getHandshakeInfo(); let requestBody = { refreshToken, antiCsrfToken, - enableAntiCsrf: transferMethod === "cookie" && handShakeInfo.antiCsrf === "VIA_TOKEN", + enableAntiCsrf: !disableAntiCsrf && helpers.config.antiCsrf === "VIA_TOKEN", }; - if (handShakeInfo.antiCsrf === "VIA_CUSTOM_HEADER" && transferMethod === "cookie") { - if (!containsCustomHeader) { - logger_1.logDebugMessage( - "refreshSession: Returning UNAUTHORISED because custom header (rid) was not passed" - ); - throw new error_1.default({ - message: "anti-csrf check failed. Please pass 'rid: \"session\"' header in the request.", - type: error_1.default.UNAUTHORISED, - payload: { - clearTokens: false, // see https://github.com/supertokens/supertokens-node/issues/141 - }, - }); - } + if (helpers.config.antiCsrf === "VIA_CUSTOM_HEADER" && !disableAntiCsrf) { + // The function should never be called by this (we check this outside the function as well) + // There we can add a bit more information to the error, so that's the primary check, this is just making sure. + throw new Error("Please either use VIA_TOKEN, NONE or call with doAntiCsrfCheck false"); } let response = yield helpers.querier.sendPostRequest( new normalisedURLPath_1.default("/recipe/session/refresh"), @@ -412,7 +383,7 @@ exports.revokeMultipleSessions = revokeMultipleSessions; /** * @description: It provides no locking mechanism in case other processes are updating session data for this session as well. */ -function updateSessionData(helpers, sessionHandle, newSessionData) { +function updateSessionDataInDatabase(helpers, sessionHandle, newSessionData) { return __awaiter(this, void 0, void 0, function* () { newSessionData = newSessionData === null || newSessionData === undefined ? {} : newSessionData; let response = yield helpers.querier.sendPutRequest(new normalisedURLPath_1.default("/recipe/session/data"), { @@ -425,7 +396,7 @@ function updateSessionData(helpers, sessionHandle, newSessionData) { return true; }); } -exports.updateSessionData = updateSessionData; +exports.updateSessionDataInDatabase = updateSessionDataInDatabase; function updateAccessTokenPayload(helpers, sessionHandle, newAccessTokenPayload) { return __awaiter(this, void 0, void 0, function* () { newAccessTokenPayload = diff --git a/lib/build/recipe/session/sessionRequestFunctions.d.ts b/lib/build/recipe/session/sessionRequestFunctions.d.ts new file mode 100644 index 000000000..d8808bf44 --- /dev/null +++ b/lib/build/recipe/session/sessionRequestFunctions.d.ts @@ -0,0 +1,55 @@ +// @ts-nocheck +import Recipe from "./recipe"; +import { VerifySessionOptions, RecipeInterface, TypeNormalisedInput, SessionContainerInterface } from "./types"; +import { NormalisedAppinfo } from "../../types"; +export declare function getSessionFromRequest({ + req, + res, + config, + recipeInterfaceImpl, + options, + userContext, +}: { + req: any; + res: any; + config: TypeNormalisedInput; + recipeInterfaceImpl: RecipeInterface; + options?: VerifySessionOptions; + userContext?: any; +}): Promise; +export declare function refreshSessionInRequest({ + res, + req, + userContext, + config, + recipeInterfaceImpl, +}: { + res: any; + req: any; + userContext: any; + config: TypeNormalisedInput; + recipeInterfaceImpl: RecipeInterface; +}): Promise; +export declare function createNewSessionInRequest({ + req, + res, + userContext, + recipeInstance, + accessTokenPayload, + userId, + recipeUserId, + config, + appInfo, + sessionDataInDatabase, +}: { + req: any; + res: any; + userContext: any; + recipeInstance: Recipe; + accessTokenPayload: any; + userId: string; + recipeUserId: string | undefined; + config: TypeNormalisedInput; + appInfo: NormalisedAppinfo; + sessionDataInDatabase: any; +}): Promise; diff --git a/lib/build/recipe/session/sessionRequestFunctions.js b/lib/build/recipe/session/sessionRequestFunctions.js new file mode 100644 index 000000000..f01d9248c --- /dev/null +++ b/lib/build/recipe/session/sessionRequestFunctions.js @@ -0,0 +1,395 @@ +"use strict"; +var __awaiter = + (this && this.__awaiter) || + function (thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P + ? value + : new P(function (resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createNewSessionInRequest = exports.refreshSessionInRequest = exports.getSessionFromRequest = void 0; +const framework_1 = __importDefault(require("../../framework")); +const supertokens_1 = __importDefault(require("../../supertokens")); +const utils_1 = require("./utils"); +const utils_2 = require("../../utils"); +const logger_1 = require("../../logger"); +const constants_1 = require("./constants"); +const cookieAndHeaders_1 = require("./cookieAndHeaders"); +const jwt_1 = require("./jwt"); +const accessToken_1 = require("./accessToken"); +const error_1 = __importDefault(require("./error")); +// We are defining this here (and not exporting it) to reduce the scope of legacy code +const LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME = "sIdRefreshToken"; +function getSessionFromRequest({ req, res, config, recipeInterfaceImpl, options, userContext }) { + return __awaiter(this, void 0, void 0, function* () { + logger_1.logDebugMessage("getSession: Started"); + if (!res.wrapperUsed) { + res = framework_1.default[supertokens_1.default.getInstanceOrThrowError().framework].wrapResponse(res); + } + if (!req.wrapperUsed) { + req = framework_1.default[supertokens_1.default.getInstanceOrThrowError().framework].wrapRequest(req); + } + userContext = utils_2.setRequestInUserContextIfNotDefined(userContext, req); + logger_1.logDebugMessage("getSession: Wrapping done"); + // This token isn't handled by getToken to limit the scope of this legacy/migration code + if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { + // This could create a spike on refresh calls during the update of the backend SDK + throw new error_1.default({ + message: "using legacy session, please call the refresh API", + type: error_1.default.TRY_REFRESH_TOKEN, + }); + } + const sessionOptional = (options === null || options === void 0 ? void 0 : options.sessionRequired) === false; + logger_1.logDebugMessage("getSession: optional validation: " + sessionOptional); + const accessTokens = {}; + // We check all token transfer methods for available access tokens + for (const transferMethod of constants_1.availableTokenTransferMethods) { + const tokenString = cookieAndHeaders_1.getToken(req, "access", transferMethod); + if (tokenString !== undefined) { + try { + const info = jwt_1.parseJWTWithoutSignatureVerification(tokenString); + accessToken_1.validateAccessTokenStructure(info.payload, info.version); + logger_1.logDebugMessage("getSession: got access token from " + transferMethod); + accessTokens[transferMethod] = info; + } catch (_a) { + logger_1.logDebugMessage( + `getSession: ignoring token in ${transferMethod}, because it doesn't match our access token structure` + ); + } + } + } + const allowedTransferMethod = config.getTokenTransferMethod({ + req, + forCreateNewSession: false, + userContext, + }); + let requestTransferMethod; + let accessToken; + if ( + (allowedTransferMethod === "any" || allowedTransferMethod === "header") && + accessTokens["header"] !== undefined + ) { + logger_1.logDebugMessage("getSession: using header transfer method"); + requestTransferMethod = "header"; + accessToken = accessTokens["header"]; + } else if ( + (allowedTransferMethod === "any" || allowedTransferMethod === "cookie") && + accessTokens["cookie"] !== undefined + ) { + logger_1.logDebugMessage("getSession: using cookie transfer method"); + requestTransferMethod = "cookie"; + accessToken = accessTokens["cookie"]; + } else { + if (sessionOptional) { + logger_1.logDebugMessage( + "getSession: returning undefined because accessToken is undefined and sessionRequired is false" + ); + // there is no session that exists here, and the user wants session verification + // to be optional. So we return undefined. + return undefined; + } + logger_1.logDebugMessage("getSession: UNAUTHORISED because accessToken in request is undefined"); + throw new error_1.default({ + message: + "Session does not exist. Are you sending the session tokens in the request with the appropriate token transfer method?", + type: error_1.default.UNAUTHORISED, + payload: { + // we do not clear the session here because of a + // race condition mentioned here: https://github.com/supertokens/supertokens-node/issues/17 + clearTokens: false, + }, + }); + } + let antiCsrfToken = cookieAndHeaders_1.getAntiCsrfTokenFromHeaders(req); + let doAntiCsrfCheck = options !== undefined ? options.antiCsrfCheck : undefined; + if (doAntiCsrfCheck === undefined) { + doAntiCsrfCheck = utils_2.normaliseHttpMethod(req.getMethod()) !== "get"; + } + if (requestTransferMethod === "header") { + doAntiCsrfCheck = false; + } + if (doAntiCsrfCheck && config.antiCsrf === "VIA_CUSTOM_HEADER") { + if (config.antiCsrf === "VIA_CUSTOM_HEADER") { + if (utils_2.getRidFromHeader(req) === undefined) { + logger_1.logDebugMessage( + "getSession: Returning TRY_REFRESH_TOKEN because custom header (rid) was not passed" + ); + throw new error_1.default({ + message: + "anti-csrf check failed. Please pass 'rid: \"session\"' header in the request, or set doAntiCsrfCheck to false for this API", + type: error_1.default.TRY_REFRESH_TOKEN, + }); + } + logger_1.logDebugMessage("getSession: VIA_CUSTOM_HEADER anti-csrf check passed"); + doAntiCsrfCheck = false; + } + } + logger_1.logDebugMessage("getSession: Value of doAntiCsrfCheck is: " + doAntiCsrfCheck); + const session = yield recipeInterfaceImpl.getSession({ + accessToken: accessToken.rawTokenString, + antiCsrfToken, + options: Object.assign(Object.assign({}, options), { antiCsrfCheck: doAntiCsrfCheck }), + userContext, + }); + if (session !== undefined) { + const claimValidators = yield utils_1.getRequiredClaimValidators( + session, + options === null || options === void 0 ? void 0 : options.overrideGlobalClaimValidators, + userContext + ); + yield session.assertClaims(claimValidators, userContext); + yield session.attachToRequestResponse({ + req, + res, + transferMethod: requestTransferMethod, + }); + } + return session; + }); +} +exports.getSessionFromRequest = getSessionFromRequest; +/* + In all cases: if sIdRefreshToken token exists (so it's a legacy session) we clear it. + Check http://localhost:3002/docs/contribute/decisions/session/0008 for further details and a table of expected behaviours +*/ +function refreshSessionInRequest({ res, req, userContext, config, recipeInterfaceImpl }) { + return __awaiter(this, void 0, void 0, function* () { + logger_1.logDebugMessage("refreshSession: Started"); + if (!res.wrapperUsed) { + res = framework_1.default[supertokens_1.default.getInstanceOrThrowError().framework].wrapResponse(res); + } + if (!req.wrapperUsed) { + req = framework_1.default[supertokens_1.default.getInstanceOrThrowError().framework].wrapRequest(req); + } + userContext = utils_2.setRequestInUserContextIfNotDefined(userContext, req); + logger_1.logDebugMessage("refreshSession: Wrapping done"); + const refreshTokens = {}; + // We check all token transfer methods for available refresh tokens + // We do this so that we can later clear all we are not overwriting + for (const transferMethod of constants_1.availableTokenTransferMethods) { + refreshTokens[transferMethod] = cookieAndHeaders_1.getToken(req, "refresh", transferMethod); + if (refreshTokens[transferMethod] !== undefined) { + logger_1.logDebugMessage("refreshSession: got refresh token from " + transferMethod); + } + } + const allowedTransferMethod = config.getTokenTransferMethod({ + req, + forCreateNewSession: false, + userContext, + }); + logger_1.logDebugMessage("refreshSession: getTokenTransferMethod returned " + allowedTransferMethod); + let requestTransferMethod; + let refreshToken; + if ( + (allowedTransferMethod === "any" || allowedTransferMethod === "header") && + refreshTokens["header"] !== undefined + ) { + logger_1.logDebugMessage("refreshSession: using header transfer method"); + requestTransferMethod = "header"; + refreshToken = refreshTokens["header"]; + } else if ((allowedTransferMethod === "any" || allowedTransferMethod === "cookie") && refreshTokens["cookie"]) { + logger_1.logDebugMessage("refreshSession: using cookie transfer method"); + requestTransferMethod = "cookie"; + refreshToken = refreshTokens["cookie"]; + } else { + // This token isn't handled by getToken/setToken to limit the scope of this legacy/migration code + if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { + logger_1.logDebugMessage( + "refreshSession: cleared legacy id refresh token because refresh token was not found" + ); + cookieAndHeaders_1.setCookie( + config, + res, + LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, + "", + 0, + "accessTokenPath" + ); + } + logger_1.logDebugMessage("refreshSession: UNAUTHORISED because refresh token in request is undefined"); + throw new error_1.default({ + message: "Refresh token not found. Are you sending the refresh token in the request?", + payload: { + clearTokens: false, + }, + type: error_1.default.UNAUTHORISED, + }); + } + let disableAntiCsrf = requestTransferMethod === "header"; + const antiCsrfToken = cookieAndHeaders_1.getAntiCsrfTokenFromHeaders(req); + if (config.antiCsrf === "VIA_CUSTOM_HEADER" && !disableAntiCsrf) { + if (utils_2.getRidFromHeader(req) === undefined) { + logger_1.logDebugMessage( + "refreshSession: Returning UNAUTHORISED because custom header (rid) was not passed" + ); + throw new error_1.default({ + message: "anti-csrf check failed. Please pass 'rid: \"session\"' header in the request.", + type: error_1.default.UNAUTHORISED, + payload: { + clearTokens: false, // see https://github.com/supertokens/supertokens-node/issues/141 + }, + }); + } + disableAntiCsrf = true; + } + let session; + try { + session = yield recipeInterfaceImpl.refreshSession({ + refreshToken: refreshToken, + antiCsrfToken, + disableAntiCsrf, + userContext, + }); + } catch (ex) { + if ( + error_1.default.isErrorFromSuperTokens(ex) && + (ex.type === error_1.default.TOKEN_THEFT_DETECTED || ex.payload.clearTokens === true) + ) { + // We clear the LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME here because we want to limit the scope of this legacy/migration code + // so the token clearing functions in the error handlers do not + if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { + logger_1.logDebugMessage( + "refreshSession: cleared legacy id refresh token because refresh is clearing other tokens" + ); + cookieAndHeaders_1.setCookie( + config, + res, + LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, + "", + 0, + "accessTokenPath" + ); + } + } + throw ex; + } + logger_1.logDebugMessage("refreshSession: Attaching refreshed session info as " + requestTransferMethod); + // We clear the tokens in all token transfer methods we are not going to overwrite + for (const transferMethod of constants_1.availableTokenTransferMethods) { + if (transferMethod !== requestTransferMethod && refreshTokens[transferMethod] !== undefined) { + cookieAndHeaders_1.clearSession(config, res, transferMethod); + } + } + yield session.attachToRequestResponse({ + req, + res, + transferMethod: requestTransferMethod, + }); + logger_1.logDebugMessage("refreshSession: Success!"); + // This token isn't handled by getToken/setToken to limit the scope of this legacy/migration code + if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { + logger_1.logDebugMessage("refreshSession: cleared legacy id refresh token after successful refresh"); + cookieAndHeaders_1.setCookie(config, res, LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, "", 0, "accessTokenPath"); + } + return session; + }); +} +exports.refreshSessionInRequest = refreshSessionInRequest; +function createNewSessionInRequest({ + req, + res, + userContext, + recipeInstance, + accessTokenPayload, + userId, + recipeUserId, + config, + appInfo, + sessionDataInDatabase, +}) { + return __awaiter(this, void 0, void 0, function* () { + logger_1.logDebugMessage("createNewSession: Started"); + if (!req.wrapperUsed) { + req = framework_1.default[supertokens_1.default.getInstanceOrThrowError().framework].wrapRequest(req); + } + if (!res.wrapperUsed) { + res = framework_1.default[supertokens_1.default.getInstanceOrThrowError().framework].wrapResponse(res); + } + logger_1.logDebugMessage("createNewSession: Wrapping done"); + userContext = utils_2.setRequestInUserContextIfNotDefined(userContext, req); + const claimsAddedByOtherRecipes = recipeInstance.getClaimsAddedByOtherRecipes(); + const issuer = appInfo.apiDomain.getAsStringDangerous() + appInfo.apiBasePath.getAsStringDangerous(); + let finalAccessTokenPayload = Object.assign(Object.assign({}, accessTokenPayload), { iss: issuer }); + for (const claim of claimsAddedByOtherRecipes) { + const update = yield claim.build(userId, userContext); + finalAccessTokenPayload = Object.assign(Object.assign({}, finalAccessTokenPayload), update); + } + logger_1.logDebugMessage("createNewSession: Access token payload built"); + let outputTransferMethod = config.getTokenTransferMethod({ req, forCreateNewSession: true, userContext }); + if (outputTransferMethod === "any") { + outputTransferMethod = "header"; + } + logger_1.logDebugMessage("createNewSession: using transfer method " + outputTransferMethod); + if ( + outputTransferMethod === "cookie" && + config.cookieSameSite === "none" && + !config.cookieSecure && + !( + (appInfo.topLevelAPIDomain === "localhost" || utils_2.isAnIpAddress(appInfo.topLevelAPIDomain)) && + (appInfo.topLevelWebsiteDomain === "localhost" || utils_2.isAnIpAddress(appInfo.topLevelWebsiteDomain)) + ) + ) { + // We can allow insecure cookie when both website & API domain are localhost or an IP + // When either of them is a different domain, API domain needs to have https and a secure cookie to work + throw new Error( + "Since your API and website domain are different, for sessions to work, please use https on your apiDomain and dont set cookieSecure to false." + ); + } + const disableAntiCsrf = outputTransferMethod === "header"; + const session = yield recipeInstance.recipeInterfaceImpl.createNewSession({ + userId, + recipeUserId, + accessTokenPayload: finalAccessTokenPayload, + sessionDataInDatabase, + disableAntiCsrf, + userContext, + }); + logger_1.logDebugMessage("createNewSession: Session created in core built"); + for (const transferMethod of constants_1.availableTokenTransferMethods) { + if ( + transferMethod !== outputTransferMethod && + cookieAndHeaders_1.getToken(req, "access", transferMethod) !== undefined + ) { + cookieAndHeaders_1.clearSession(config, res, transferMethod); + } + } + logger_1.logDebugMessage("createNewSession: Cleared old tokens"); + yield session.attachToRequestResponse({ + req, + res, + transferMethod: outputTransferMethod, + }); + logger_1.logDebugMessage("createNewSession: Attached new tokens to res"); + return session; + }); +} +exports.createNewSessionInRequest = createNewSessionInRequest; diff --git a/lib/build/recipe/session/types.d.ts b/lib/build/recipe/session/types.d.ts index 030737476..7c13624ff 100644 --- a/lib/build/recipe/session/types.d.ts +++ b/lib/build/recipe/session/types.d.ts @@ -12,21 +12,11 @@ export declare type KeyInfo = { createdAt: number; }; export declare type AntiCsrfType = "VIA_TOKEN" | "VIA_CUSTOM_HEADER" | "NONE"; -export declare type StoredHandshakeInfo = { - antiCsrf: AntiCsrfType; - accessTokenBlacklistingEnabled: boolean; - accessTokenValidity: number; - refreshTokenValidity: number; -} & ( - | { - jwtSigningPublicKeyList: KeyInfo[]; - } - | { - jwtSigningPublicKeyList: undefined; - jwtSigningPublicKey: string; - jwtSigningPublicKeyExpiryTime: number; - } -); +export declare type TokenInfo = { + token: string; + expiry: number; + createdTime: number; +}; export declare type CreateOrRefreshAPIResponse = { session: { handle: string; @@ -34,16 +24,8 @@ export declare type CreateOrRefreshAPIResponse = { recipeUserId: string; userDataInJWT: any; }; - accessToken: { - token: string; - expiry: number; - createdTime: number; - }; - refreshToken: { - token: string; - expiry: number; - createdTime: number; - }; + accessToken: TokenInfo; + refreshToken: TokenInfo; antiCsrfToken: string | undefined; }; export interface ErrorHandlers { @@ -54,8 +36,10 @@ export interface ErrorHandlers { export declare type TokenType = "access" | "refresh"; export declare type TokenTransferMethod = "header" | "cookie"; export declare type TypeInput = { + useDynamicAccessTokenSigningKey?: boolean; sessionExpiredStatusCode?: number; invalidClaimStatusCode?: number; + accessTokenPath?: string; cookieSecure?: boolean; cookieSameSite?: "strict" | "lax" | "none"; cookieDomain?: string; @@ -66,15 +50,7 @@ export declare type TypeInput = { }) => TokenTransferMethod | "any"; errorHandlers?: ErrorHandlers; antiCsrf?: "VIA_TOKEN" | "VIA_CUSTOM_HEADER" | "NONE"; - jwt?: - | { - enable: true; - propertyNameInAccessTokenPayload?: string; - issuer?: string; - } - | { - enable: false; - }; + exposeAccessTokenToFrontendInCookieBasedAuth?: boolean; override?: { functions?: ( originalImplementation: RecipeInterface, @@ -104,7 +80,9 @@ export declare type TypeInput = { }; }; export declare type TypeNormalisedInput = { + useDynamicAccessTokenSigningKey: boolean; refreshTokenPath: NormalisedURLPath; + accessTokenPath: NormalisedURLPath; cookieDomain: string | undefined; cookieSameSite: "strict" | "lax" | "none"; cookieSecure: boolean; @@ -117,11 +95,7 @@ export declare type TypeNormalisedInput = { userContext: any; }) => TokenTransferMethod | "any"; invalidClaimStatusCode: number; - jwt: { - enable: boolean; - propertyNameInAccessTokenPayload: string; - issuer?: string; - }; + exposeAccessTokenToFrontendInCookieBasedAuth: boolean; override: { functions: ( originalImplementation: RecipeInterface, @@ -177,6 +151,7 @@ export interface NormalisedErrorHandlers { export interface VerifySessionOptions { antiCsrfCheck?: boolean; sessionRequired?: boolean; + checkDatabase?: boolean; overrideGlobalClaimValidators?: ( globalClaimValidators: SessionClaimValidator[], session: SessionContainerInterface, @@ -185,12 +160,11 @@ export interface VerifySessionOptions { } export declare type RecipeInterface = { createNewSession(input: { - req: BaseRequest; - res: BaseResponse; userId: string; - recipeUserId?: string; + recipeUserId: string | undefined; accessTokenPayload?: any; - sessionData?: any; + sessionDataInDatabase?: any; + disableAntiCsrf?: boolean; userContext: any; }): Promise; getGlobalClaimValidators(input: { @@ -200,19 +174,20 @@ export declare type RecipeInterface = { userContext: any; }): Promise | SessionClaimValidator[]; getSession(input: { - req: BaseRequest; - res: BaseResponse; + accessToken: string; + antiCsrfToken?: string; options?: VerifySessionOptions; userContext: any; }): Promise; refreshSession(input: { - req: BaseRequest; - res: BaseResponse; + refreshToken: string; + antiCsrfToken?: string; + disableAntiCsrf: boolean; userContext: any; }): Promise; /** * Used to retrieve all session information for a given session handle. Can be used in place of: - * - getSessionData + * - getSessionDataFromDatabase * - getAccessTokenPayload * * Returns undefined if the sessionHandle does not exist @@ -222,14 +197,9 @@ export declare type RecipeInterface = { getAllSessionHandlesForUser(input: { userId: string; userContext: any }): Promise; revokeSession(input: { sessionHandle: string; userContext: any }): Promise; revokeMultipleSessions(input: { sessionHandles: string[]; userContext: any }): Promise; - updateSessionData(input: { sessionHandle: string; newSessionData: any; userContext: any }): Promise; - /** - * @deprecated Use mergeIntoAccessTokenPayload instead - * @returns {Promise} Returns false if the sessionHandle does not exist - */ - updateAccessTokenPayload(input: { + updateSessionDataInDatabase(input: { sessionHandle: string; - newAccessTokenPayload: any; + newSessionData: any; userContext: any; }): Promise; mergeIntoAccessTokenPayload(input: { @@ -261,8 +231,6 @@ export declare type RecipeInterface = { } | undefined >; - getAccessTokenLifeTimeMS(input: { userContext: any }): Promise; - getRefreshTokenLifeTimeMS(input: { userContext: any }): Promise; validateClaims(input: { userId: string; recipeUserId: string; @@ -297,17 +265,20 @@ export declare type RecipeInterface = { }; export interface SessionContainerInterface { revokeSession(userContext?: any): Promise; - getSessionData(userContext?: any): Promise; - updateSessionData(newSessionData: any, userContext?: any): Promise; + getSessionDataFromDatabase(userContext?: any): Promise; + updateSessionDataInDatabase(newSessionData: any, userContext?: any): Promise; getUserId(userContext?: any): string; getRecipeUserId(userContext?: any): string; getAccessTokenPayload(userContext?: any): any; getHandle(userContext?: any): string; + getAllSessionTokensDangerously(): { + accessToken: string; + refreshToken: string | undefined; + antiCsrfToken: string | undefined; + frontToken: string; + accessAndFrontTokenUpdated: boolean; + }; getAccessToken(userContext?: any): string; - /** - * @deprecated Use mergeIntoAccessTokenPayload instead - */ - updateAccessTokenPayload(newAccessTokenPayload: any, userContext?: any): Promise; mergeIntoAccessTokenPayload(accessTokenPayloadUpdate: JSONObject, userContext?: any): Promise; getTimeCreated(userContext?: any): Promise; getExpiry(userContext?: any): Promise; @@ -316,6 +287,7 @@ export interface SessionContainerInterface { setClaimValue(claim: SessionClaim, value: T, userContext?: any): Promise; getClaimValue(claim: SessionClaim, userContext?: any): Promise; removeClaim(claim: SessionClaim, userContext?: any): Promise; + attachToRequestResponse(reqResInfo: ReqResInfo): Promise | void; } export declare type APIOptions = { recipeImplementation: RecipeInterface; @@ -354,9 +326,9 @@ export declare type SessionInformation = { sessionHandle: string; userId: string; recipeUserId: string; - sessionData: any; + sessionDataInDatabase: any; expiry: number; - accessTokenPayload: any; + customClaimsInAccessTokenPayload: any; timeCreated: number; }; export declare type ClaimValidationResult = @@ -424,3 +396,8 @@ export declare abstract class SessionClaim { abstract getValueFromPayload(payload: JSONObject, userContext: any): T | undefined; build(userId: string, recipeUserId?: string, userContext?: any): Promise; } +export declare type ReqResInfo = { + res: BaseResponse; + req: BaseRequest; + transferMethod: TokenTransferMethod; +}; diff --git a/lib/build/recipe/session/utils.d.ts b/lib/build/recipe/session/utils.d.ts index e5694ce6d..ea42d523e 100644 --- a/lib/build/recipe/session/utils.d.ts +++ b/lib/build/recipe/session/utils.d.ts @@ -1,6 +1,5 @@ // @ts-nocheck import { - CreateOrRefreshAPIResponse, TypeInput, TypeNormalisedInput, ClaimValidationError, @@ -46,10 +45,11 @@ export declare function validateAndNormaliseUserInput( config?: TypeInput ): TypeNormalisedInput; export declare function normaliseSameSiteOrThrowError(sameSite: string): "strict" | "lax" | "none"; -export declare function attachTokensToResponse( - config: TypeNormalisedInput, +export declare function setAccessTokenInResponse( res: BaseResponse, - response: CreateOrRefreshAPIResponse, + accessToken: string, + frontToken: string, + config: TypeNormalisedInput, transferMethod: TokenTransferMethod ): void; export declare function getRequiredClaimValidators( diff --git a/lib/build/recipe/session/utils.js b/lib/build/recipe/session/utils.js index 4b421d138..af80c5c47 100644 --- a/lib/build/recipe/session/utils.js +++ b/lib/build/recipe/session/utils.js @@ -50,7 +50,7 @@ var __importDefault = return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.validateClaimsInPayload = exports.getRequiredClaimValidators = exports.attachTokensToResponse = exports.normaliseSameSiteOrThrowError = exports.validateAndNormaliseUserInput = exports.getURLProtocol = exports.normaliseSessionScopeOrThrowError = exports.sendTokenTheftDetectedResponse = exports.sendInvalidClaimResponse = exports.sendUnauthorisedResponse = exports.sendTryRefreshTokenResponse = void 0; +exports.validateClaimsInPayload = exports.getRequiredClaimValidators = exports.setAccessTokenInResponse = exports.normaliseSameSiteOrThrowError = exports.validateAndNormaliseUserInput = exports.getURLProtocol = exports.normaliseSessionScopeOrThrowError = exports.sendTokenTheftDetectedResponse = exports.sendInvalidClaimResponse = exports.sendUnauthorisedResponse = exports.sendTryRefreshTokenResponse = void 0; const cookieAndHeaders_1 = require("./cookieAndHeaders"); const url_1 = require("url"); const recipe_1 = __importDefault(require("./recipe")); @@ -58,7 +58,6 @@ const constants_1 = require("./constants"); const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); const utils_1 = require("../../utils"); const utils_2 = require("../../utils"); -const constants_2 = require("./with-jwt/constants"); const logger_1 = require("../../logger"); function sendTryRefreshTokenResponse(recipeInstance, _, __, response) { return __awaiter(this, void 0, void 0, function* () { @@ -134,11 +133,15 @@ function getURLProtocol(url) { } exports.getURLProtocol = getURLProtocol; function validateAndNormaliseUserInput(recipeInstance, appInfo, config) { - var _a; + var _a, _b, _c; let cookieDomain = config === undefined || config.cookieDomain === undefined ? undefined : normaliseSessionScopeOrThrowError(config.cookieDomain); + let accessTokenPath = + config === undefined || config.accessTokenPath === undefined + ? new normalisedURLPath_1.default("/") + : new normalisedURLPath_1.default(config.accessTokenPath); let protocolOfAPIDomain = getURLProtocol(appInfo.apiDomain.getAsStringDangerous()); let protocolOfWebsiteDomain = getURLProtocol(appInfo.websiteDomain.getAsStringDangerous()); let cookieSameSite = @@ -208,20 +211,6 @@ function validateAndNormaliseUserInput(recipeInstance, appInfo, config) { errorHandlers.onInvalidClaim = config.errorHandlers.onInvalidClaim; } } - let enableJWT = false; - let accessTokenPayloadJWTPropertyName = "jwt"; - let issuer; - if (config !== undefined && config.jwt !== undefined && config.jwt.enable === true) { - enableJWT = true; - let jwtPropertyName = config.jwt.propertyNameInAccessTokenPayload; - issuer = config.jwt.issuer; - if (jwtPropertyName !== undefined) { - if (jwtPropertyName === constants_2.ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY) { - throw new Error(constants_2.JWT_RESERVED_KEY_USE_ERROR_MESSAGE); - } - accessTokenPayloadJWTPropertyName = jwtPropertyName; - } - } let override = Object.assign( { functions: (originalImplementation) => originalImplementation, @@ -230,7 +219,19 @@ function validateAndNormaliseUserInput(recipeInstance, appInfo, config) { config === null || config === void 0 ? void 0 : config.override ); return { + useDynamicAccessTokenSigningKey: + (_b = config === null || config === void 0 ? void 0 : config.useDynamicAccessTokenSigningKey) !== null && + _b !== void 0 + ? _b + : true, + exposeAccessTokenToFrontendInCookieBasedAuth: + (_c = + config === null || config === void 0 ? void 0 : config.exposeAccessTokenToFrontendInCookieBasedAuth) !== + null && _c !== void 0 + ? _c + : false, refreshTokenPath: appInfo.apiBasePath.appendPath(new normalisedURLPath_1.default(constants_1.REFRESH_API_PATH)), + accessTokenPath, getTokenTransferMethod: (config === null || config === void 0 ? void 0 : config.getTokenTransferMethod) === undefined ? defaultGetTokenTransferMethod @@ -243,11 +244,6 @@ function validateAndNormaliseUserInput(recipeInstance, appInfo, config) { antiCsrf, override, invalidClaimStatusCode, - jwt: { - enable: enableJWT, - propertyNameInAccessTokenPayload: accessTokenPayloadJWTPropertyName, - issuer, - }, }; } exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; @@ -260,33 +256,36 @@ function normaliseSameSiteOrThrowError(sameSite) { return sameSite; } exports.normaliseSameSiteOrThrowError = normaliseSameSiteOrThrowError; -function attachTokensToResponse(config, res, response, transferMethod) { - let accessToken = response.accessToken; - let refreshToken = response.refreshToken; - cookieAndHeaders_1.setFrontTokenInHeaders( - res, - response.session.userId, - response.accessToken.expiry, - response.session.userDataInJWT - ); +function setAccessTokenInResponse(res, accessToken, frontToken, config, transferMethod) { + cookieAndHeaders_1.setFrontTokenInHeaders(res, frontToken); cookieAndHeaders_1.setToken( config, res, "access", - accessToken.token, + accessToken, // We set the expiration to 100 years, because we can't really access the expiration of the refresh token everywhere we are setting it. // This should be safe to do, since this is only the validity of the cookie (set here or on the frontend) but we check the expiration of the JWT anyway. - // Even if the token is expired the presence of the token indicates that the user could have a valid refresh - // Setting them to infinity would require special case handling on the frontend and just adding 10 years seems enough. - Date.now() + 3153600000000, + // Even if the token is expired the presence of the token indicates that the user could have a valid refresh token + // Setting them to infinity would require special case handling on the frontend and just adding 100 years seems enough. + Date.now() + constants_1.hundredYearsInMs, transferMethod ); - cookieAndHeaders_1.setToken(config, res, "refresh", refreshToken.token, refreshToken.expiry, transferMethod); - if (response.antiCsrfToken !== undefined) { - cookieAndHeaders_1.setAntiCsrfTokenInHeaders(res, response.antiCsrfToken); + if (config.exposeAccessTokenToFrontendInCookieBasedAuth && transferMethod === "cookie") { + cookieAndHeaders_1.setToken( + config, + res, + "access", + accessToken, + // We set the expiration to 100 years, because we can't really access the expiration of the refresh token everywhere we are setting it. + // This should be safe to do, since this is only the validity of the cookie (set here or on the frontend) but we check the expiration of the JWT anyway. + // Even if the token is expired the presence of the token indicates that the user could have a valid refresh token + // Setting them to infinity would require special case handling on the frontend and just adding 100 years seems enough. + Date.now() + constants_1.hundredYearsInMs, + "header" + ); } } -exports.attachTokensToResponse = attachTokensToResponse; +exports.setAccessTokenInResponse = setAccessTokenInResponse; function getRequiredClaimValidators(session, overrideGlobalClaimValidators, userContext) { return __awaiter(this, void 0, void 0, function* () { const claimValidatorsAddedByOtherRecipes = recipe_1.default diff --git a/lib/build/recipe/session/with-jwt/constants.d.ts b/lib/build/recipe/session/with-jwt/constants.d.ts deleted file mode 100644 index 324030f7b..000000000 --- a/lib/build/recipe/session/with-jwt/constants.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -// @ts-nocheck -export declare const ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY = "_jwtPName"; -export declare const JWT_RESERVED_KEY_USE_ERROR_MESSAGE: string; diff --git a/lib/build/recipe/session/with-jwt/constants.js b/lib/build/recipe/session/with-jwt/constants.js deleted file mode 100644 index b3a616064..000000000 --- a/lib/build/recipe/session/with-jwt/constants.js +++ /dev/null @@ -1,41 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.JWT_RESERVED_KEY_USE_ERROR_MESSAGE = exports.ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY = void 0; -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ -/* - This key is used to determine the property name used when adding the jwt to the access token payload - For example if the Session recipe is initialised with config - { - ... - jwt: { - enable: true, - propertyNameInAccessTokenPayload: "jwtKey", - }, - ... - } - - The access token payload after creating a session would look like - { - ... - jwtKey: "JWT_STRING", - _jwtPName: "jwtKey", - } - - When trying to refresh the session or updating the access token payload, this key is used to determine and retrieve - the exsiting JWT from the access token payload. -*/ -exports.ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY = "_jwtPName"; -exports.JWT_RESERVED_KEY_USE_ERROR_MESSAGE = `${exports.ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY} is a reserved property name, please use a different key name for the jwt`; diff --git a/lib/build/recipe/session/with-jwt/index.d.ts b/lib/build/recipe/session/with-jwt/index.d.ts deleted file mode 100644 index f8ccc90af..000000000 --- a/lib/build/recipe/session/with-jwt/index.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -// @ts-nocheck -import OriginalImplementation from "./recipeImplementation"; -export default OriginalImplementation; diff --git a/lib/build/recipe/session/with-jwt/index.js b/lib/build/recipe/session/with-jwt/index.js deleted file mode 100644 index 6b58cbc0b..000000000 --- a/lib/build/recipe/session/with-jwt/index.js +++ /dev/null @@ -1,23 +0,0 @@ -"use strict"; -var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod }; - }; -Object.defineProperty(exports, "__esModule", { value: true }); -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ -const recipeImplementation_1 = __importDefault(require("./recipeImplementation")); -exports.default = recipeImplementation_1.default; diff --git a/lib/build/recipe/session/with-jwt/recipeImplementation.d.ts b/lib/build/recipe/session/with-jwt/recipeImplementation.d.ts deleted file mode 100644 index debe5ce4b..000000000 --- a/lib/build/recipe/session/with-jwt/recipeImplementation.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-nocheck -import { RecipeInterface } from "../"; -import { RecipeInterface as OpenIdRecipeInterface } from "../../openid/types"; -import { TypeNormalisedInput } from "../types"; -export declare function setJWTExpiryOffsetSecondsForTesting(offset: number): void; -export default function ( - originalImplementation: RecipeInterface, - openIdRecipeImplementation: OpenIdRecipeInterface, - config: TypeNormalisedInput -): RecipeInterface; diff --git a/lib/build/recipe/session/with-jwt/recipeImplementation.js b/lib/build/recipe/session/with-jwt/recipeImplementation.js deleted file mode 100644 index b50a2991a..000000000 --- a/lib/build/recipe/session/with-jwt/recipeImplementation.js +++ /dev/null @@ -1,243 +0,0 @@ -"use strict"; -var __createBinding = - (this && this.__createBinding) || - (Object.create - ? function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { - enumerable: true, - get: function () { - return m[k]; - }, - }); - } - : function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; - }); -var __setModuleDefault = - (this && this.__setModuleDefault) || - (Object.create - ? function (o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); - } - : function (o, v) { - o["default"] = v; - }); -var __importStar = - (this && this.__importStar) || - function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) - for (var k in mod) - if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; - }; -var __awaiter = - (this && this.__awaiter) || - function (thisArg, _arguments, P, generator) { - function adopt(value) { - return value instanceof P - ? value - : new P(function (resolve) { - resolve(value); - }); - } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { - try { - step(generator.next(value)); - } catch (e) { - reject(e); - } - } - function rejected(value) { - try { - step(generator["throw"](value)); - } catch (e) { - reject(e); - } - } - function step(result) { - result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); - } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); - }; -var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod }; - }; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.setJWTExpiryOffsetSecondsForTesting = void 0; -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ -const jsonwebtoken_1 = require("jsonwebtoken"); -const constants_1 = require("./constants"); -const sessionClass_1 = __importDefault(require("./sessionClass")); -const assert = __importStar(require("assert")); -const utils_1 = require("./utils"); -// Time difference between JWT expiry and access token expiry (JWT expiry = access token expiry + EXPIRY_OFFSET_SECONDS) -let EXPIRY_OFFSET_SECONDS = 30; -// This function should only be used during testing -function setJWTExpiryOffsetSecondsForTesting(offset) { - if (process.env.TEST_MODE !== "testing") { - throw Error("calling testing function in non testing env"); - } - EXPIRY_OFFSET_SECONDS = offset; -} -exports.setJWTExpiryOffsetSecondsForTesting = setJWTExpiryOffsetSecondsForTesting; -function default_1(originalImplementation, openIdRecipeImplementation, config) { - function getJWTExpiry(accessTokenExpiry) { - return accessTokenExpiry + EXPIRY_OFFSET_SECONDS; - } - function jwtAwareUpdateAccessTokenPayload(sessionInformation, newAccessTokenPayload, userContext) { - return __awaiter(this, void 0, void 0, function* () { - let accessTokenPayload = sessionInformation.accessTokenPayload; - let existingJwtPropertyName = accessTokenPayload[constants_1.ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY]; - if (existingJwtPropertyName === undefined) { - return yield originalImplementation.updateAccessTokenPayload({ - sessionHandle: sessionInformation.sessionHandle, - newAccessTokenPayload, - userContext, - }); - } - let existingJwt = accessTokenPayload[existingJwtPropertyName]; - assert.notStrictEqual(existingJwt, undefined); - let currentTimeInSeconds = Date.now() / 1000; - let decodedPayload = jsonwebtoken_1.decode(existingJwt, { json: true }); - // decode possibly returns null - if (decodedPayload === null || decodedPayload.exp === undefined) { - throw new Error("Error reading JWT from session"); - } - let jwtExpiry = decodedPayload.exp - currentTimeInSeconds; - if (jwtExpiry <= 0) { - // it can come here if someone calls this function well after - // the access token and the jwt payload have expired. In this case, - // we still want the jwt payload to update, but the resulting JWT should - // not be alive for too long (since it's expired already). So we set it to - // 1 second lifetime. - jwtExpiry = 1; - } - newAccessTokenPayload = yield utils_1.addJWTToAccessTokenPayload({ - accessTokenPayload: newAccessTokenPayload, - jwtExpiry, - userId: sessionInformation.userId, - jwtPropertyName: existingJwtPropertyName, - openIdRecipeImplementation, - userContext, - }); - return yield originalImplementation.updateAccessTokenPayload({ - sessionHandle: sessionInformation.sessionHandle, - newAccessTokenPayload, - userContext, - }); - }); - } - return Object.assign(Object.assign({}, originalImplementation), { - createNewSession: function ({ req, res, userId, recipeUserId, accessTokenPayload, sessionData, userContext }) { - return __awaiter(this, void 0, void 0, function* () { - accessTokenPayload = - accessTokenPayload === null || accessTokenPayload === undefined ? {} : accessTokenPayload; - let accessTokenValidityInSeconds = Math.ceil( - (yield this.getAccessTokenLifeTimeMS({ userContext })) / 1000 - ); - accessTokenPayload = yield utils_1.addJWTToAccessTokenPayload({ - accessTokenPayload, - jwtExpiry: getJWTExpiry(accessTokenValidityInSeconds), - userId, - jwtPropertyName: config.jwt.propertyNameInAccessTokenPayload, - openIdRecipeImplementation, - userContext, - }); - let sessionContainer = yield originalImplementation.createNewSession({ - req, - res, - userId, - recipeUserId, - accessTokenPayload, - sessionData, - userContext, - }); - return new sessionClass_1.default(sessionContainer, openIdRecipeImplementation); - }); - }, - getSession: function ({ req, res, options, userContext }) { - return __awaiter(this, void 0, void 0, function* () { - let sessionContainer = yield originalImplementation.getSession({ req, res, options, userContext }); - if (sessionContainer === undefined) { - return undefined; - } - return new sessionClass_1.default(sessionContainer, openIdRecipeImplementation); - }); - }, - refreshSession: function ({ req, res, userContext }) { - return __awaiter(this, void 0, void 0, function* () { - let accessTokenValidityInSeconds = Math.ceil( - (yield this.getAccessTokenLifeTimeMS({ userContext })) / 1000 - ); - // Refresh session first because this will create a new access token - let newSession = yield originalImplementation.refreshSession({ req, res, userContext }); - let accessTokenPayload = newSession.getAccessTokenPayload(); - accessTokenPayload = yield utils_1.addJWTToAccessTokenPayload({ - accessTokenPayload, - jwtExpiry: getJWTExpiry(accessTokenValidityInSeconds), - userId: newSession.getUserId(), - jwtPropertyName: config.jwt.propertyNameInAccessTokenPayload, - openIdRecipeImplementation, - userContext, - }); - yield newSession.updateAccessTokenPayload(accessTokenPayload); - return new sessionClass_1.default(newSession, openIdRecipeImplementation); - }); - }, - mergeIntoAccessTokenPayload: function ({ sessionHandle, accessTokenPayloadUpdate, userContext }) { - return __awaiter(this, void 0, void 0, function* () { - let sessionInformation = yield this.getSessionInformation({ sessionHandle, userContext }); - if (!sessionInformation) { - return false; - } - let newAccessTokenPayload = Object.assign( - Object.assign({}, sessionInformation.accessTokenPayload), - accessTokenPayloadUpdate - ); - for (const key of Object.keys(accessTokenPayloadUpdate)) { - if (accessTokenPayloadUpdate[key] === null) { - delete newAccessTokenPayload[key]; - } - } - return jwtAwareUpdateAccessTokenPayload(sessionInformation, newAccessTokenPayload, userContext); - }); - }, - /** - * @deprecated use mergeIntoAccessTokenPayload instead - */ - updateAccessTokenPayload: function ({ sessionHandle, newAccessTokenPayload, userContext }) { - return __awaiter(this, void 0, void 0, function* () { - newAccessTokenPayload = - newAccessTokenPayload === null || newAccessTokenPayload === undefined ? {} : newAccessTokenPayload; - const sessionInformation = yield this.getSessionInformation({ sessionHandle, userContext }); - if (!sessionInformation) { - return false; - } - return jwtAwareUpdateAccessTokenPayload(sessionInformation, newAccessTokenPayload, userContext); - }); - }, - }); -} -exports.default = default_1; diff --git a/lib/build/recipe/session/with-jwt/sessionClass.d.ts b/lib/build/recipe/session/with-jwt/sessionClass.d.ts deleted file mode 100644 index a354342c4..000000000 --- a/lib/build/recipe/session/with-jwt/sessionClass.d.ts +++ /dev/null @@ -1,36 +0,0 @@ -// @ts-nocheck -import { RecipeInterface as OpenIdRecipeInterface } from "../../openid/types"; -import { SessionClaim, SessionClaimValidator, SessionContainerInterface } from "../types"; -export default class SessionClassWithJWT implements SessionContainerInterface { - private readonly originalSessionClass; - private readonly openIdRecipeImplementation; - constructor(originalSessionClass: SessionContainerInterface, openIdRecipeImplementation: OpenIdRecipeInterface); - getRecipeUserId(userContext?: any): string; - revokeSession(userContext?: any): Promise; - getSessionData(userContext?: any): Promise; - updateSessionData(newSessionData: any, userContext?: any): Promise; - getUserId(userContext?: any): string; - getAccessTokenPayload(userContext?: any): any; - getHandle(userContext?: any): string; - getAccessToken(userContext?: any): string; - getTimeCreated(userContext?: any): Promise; - getExpiry(userContext?: any): Promise; - assertClaims(claimValidators: SessionClaimValidator[], userContext?: any): Promise; - fetchAndSetClaim(this: SessionClassWithJWT, claim: SessionClaim, userContext?: any): Promise; - setClaimValue(this: SessionClassWithJWT, claim: SessionClaim, value: T, userContext?: any): Promise; - getClaimValue(this: SessionClassWithJWT, claim: SessionClaim, userContext?: any): Promise; - removeClaim(this: SessionClassWithJWT, claim: SessionClaim, userContext?: any): Promise; - mergeIntoAccessTokenPayload( - this: SessionClassWithJWT, - accessTokenPayloadUpdate: any, - userContext?: any - ): Promise; - /** - * @deprecated use mergeIntoAccessTokenPayload instead - */ - updateAccessTokenPayload( - this: SessionClassWithJWT, - newAccessTokenPayload: any | undefined, - userContext?: any - ): Promise; -} diff --git a/lib/build/recipe/session/with-jwt/sessionClass.js b/lib/build/recipe/session/with-jwt/sessionClass.js deleted file mode 100644 index 9e76cb8a8..000000000 --- a/lib/build/recipe/session/with-jwt/sessionClass.js +++ /dev/null @@ -1,237 +0,0 @@ -"use strict"; -var __createBinding = - (this && this.__createBinding) || - (Object.create - ? function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { - enumerable: true, - get: function () { - return m[k]; - }, - }); - } - : function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; - }); -var __setModuleDefault = - (this && this.__setModuleDefault) || - (Object.create - ? function (o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); - } - : function (o, v) { - o["default"] = v; - }); -var __importStar = - (this && this.__importStar) || - function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) - for (var k in mod) - if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; - }; -var __awaiter = - (this && this.__awaiter) || - function (thisArg, _arguments, P, generator) { - function adopt(value) { - return value instanceof P - ? value - : new P(function (resolve) { - resolve(value); - }); - } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { - try { - step(generator.next(value)); - } catch (e) { - reject(e); - } - } - function rejected(value) { - try { - step(generator["throw"](value)); - } catch (e) { - reject(e); - } - } - function step(result) { - result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); - } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); - }; -var __importDefault = - (this && this.__importDefault) || - function (mod) { - return mod && mod.__esModule ? mod : { default: mod }; - }; -Object.defineProperty(exports, "__esModule", { value: true }); -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ -const jsonwebtoken_1 = require("jsonwebtoken"); -const assert = __importStar(require("assert")); -const constants_1 = require("./constants"); -const utils_1 = require("./utils"); -const error_1 = __importDefault(require("../error")); -const recipe_1 = __importDefault(require("../recipe")); -class SessionClassWithJWT { - constructor(originalSessionClass, openIdRecipeImplementation) { - this.originalSessionClass = originalSessionClass; - this.openIdRecipeImplementation = openIdRecipeImplementation; - } - getRecipeUserId(userContext) { - return this.originalSessionClass.getRecipeUserId(userContext); - } - revokeSession(userContext) { - return this.originalSessionClass.revokeSession(userContext); - } - getSessionData(userContext) { - return this.originalSessionClass.getSessionData(userContext); - } - updateSessionData(newSessionData, userContext) { - return this.originalSessionClass.updateSessionData(newSessionData, userContext); - } - getUserId(userContext) { - return this.originalSessionClass.getUserId(userContext); - } - getAccessTokenPayload(userContext) { - return this.originalSessionClass.getAccessTokenPayload(userContext); - } - getHandle(userContext) { - return this.originalSessionClass.getHandle(userContext); - } - getAccessToken(userContext) { - return this.originalSessionClass.getAccessToken(userContext); - } - getTimeCreated(userContext) { - return this.originalSessionClass.getTimeCreated(userContext); - } - getExpiry(userContext) { - return this.originalSessionClass.getExpiry(userContext); - } - // We copy the implementation here, since we want to override updateAccessTokenPayload - assertClaims(claimValidators, userContext) { - return __awaiter(this, void 0, void 0, function* () { - let validateClaimResponse = yield recipe_1.default - .getInstanceOrThrowError() - .recipeInterfaceImpl.validateClaims({ - accessTokenPayload: this.getAccessTokenPayload(userContext), - userId: this.getUserId(userContext), - recipeUserId: this.getRecipeUserId(userContext), - claimValidators, - userContext, - }); - if (validateClaimResponse.accessTokenPayloadUpdate !== undefined) { - yield this.mergeIntoAccessTokenPayload(validateClaimResponse.accessTokenPayloadUpdate, userContext); - } - if (validateClaimResponse.invalidClaims.length !== 0) { - throw new error_1.default({ - type: "INVALID_CLAIMS", - message: "INVALID_CLAIMS", - payload: validateClaimResponse.invalidClaims, - }); - } - }); - } - // We copy the implementation here, since we want to override updateAccessTokenPayload - fetchAndSetClaim(claim, userContext) { - return __awaiter(this, void 0, void 0, function* () { - const update = yield claim.build( - this.getUserId(userContext), - this.getRecipeUserId(userContext), - userContext - ); - return this.mergeIntoAccessTokenPayload(update, userContext); - }); - } - // We copy the implementation here, since we want to override updateAccessTokenPayload - setClaimValue(claim, value, userContext) { - const update = claim.addToPayload_internal({}, value, userContext); - return this.mergeIntoAccessTokenPayload(update, userContext); - } - // We copy the implementation here, since we want to override updateAccessTokenPayload - getClaimValue(claim, userContext) { - return __awaiter(this, void 0, void 0, function* () { - return claim.getValueFromPayload(yield this.getAccessTokenPayload(userContext), userContext); - }); - } - // We copy the implementation here, since we want to override updateAccessTokenPayload - removeClaim(claim, userContext) { - const update = claim.removeFromPayloadByMerge_internal({}, userContext); - return this.mergeIntoAccessTokenPayload(update, userContext); - } - // We copy the implementation here, since we want to override updateAccessTokenPayload - mergeIntoAccessTokenPayload(accessTokenPayloadUpdate, userContext) { - return __awaiter(this, void 0, void 0, function* () { - const updatedPayload = Object.assign( - Object.assign({}, this.getAccessTokenPayload(userContext)), - accessTokenPayloadUpdate - ); - for (const key of Object.keys(accessTokenPayloadUpdate)) { - if (accessTokenPayloadUpdate[key] === null) { - delete updatedPayload[key]; - } - } - yield this.updateAccessTokenPayload(updatedPayload, userContext); - }); - } - // TODO: figure out a proper way to override just this function - /** - * @deprecated use mergeIntoAccessTokenPayload instead - */ - updateAccessTokenPayload(newAccessTokenPayload, userContext) { - return __awaiter(this, void 0, void 0, function* () { - newAccessTokenPayload = - newAccessTokenPayload === null || newAccessTokenPayload === undefined ? {} : newAccessTokenPayload; - let accessTokenPayload = this.getAccessTokenPayload(userContext); - let jwtPropertyName = accessTokenPayload[constants_1.ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY]; - if (jwtPropertyName === undefined) { - return this.originalSessionClass.updateAccessTokenPayload(newAccessTokenPayload, userContext); - } - let existingJWT = accessTokenPayload[jwtPropertyName]; - assert.notStrictEqual(existingJWT, undefined); - let currentTimeInSeconds = Date.now() / 1000; - let decodedPayload = jsonwebtoken_1.decode(existingJWT, { json: true }); - // JsonWebToken.decode possibly returns null - if (decodedPayload === null || decodedPayload.exp === undefined) { - throw new Error("Error reading JWT from session"); - } - let jwtExpiry = decodedPayload.exp - currentTimeInSeconds; - if (jwtExpiry <= 0) { - // it can come here if someone calls this function well after - // the access token and the jwt payload have expired (which can happen if an API takes a VERY long time). In this case, we still want the jwt payload to update, but the resulting JWT should - // not be alive for too long (since it's expired already). So we set it to - // 1 second lifetime. - jwtExpiry = 1; - } - newAccessTokenPayload = yield utils_1.addJWTToAccessTokenPayload({ - accessTokenPayload: newAccessTokenPayload, - jwtExpiry, - userId: this.getUserId(), - jwtPropertyName, - openIdRecipeImplementation: this.openIdRecipeImplementation, - userContext, - }); - yield this.originalSessionClass.updateAccessTokenPayload(newAccessTokenPayload, userContext); - }); - } -} -exports.default = SessionClassWithJWT; diff --git a/lib/build/recipe/session/with-jwt/utils.d.ts b/lib/build/recipe/session/with-jwt/utils.d.ts deleted file mode 100644 index 3a4b54185..000000000 --- a/lib/build/recipe/session/with-jwt/utils.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -// @ts-nocheck -import { RecipeInterface as OpenIdRecipeInterface } from "../../openid/types"; -export declare function addJWTToAccessTokenPayload({ - accessTokenPayload, - jwtExpiry, - userId, - jwtPropertyName, - openIdRecipeImplementation, - userContext, -}: { - accessTokenPayload: any; - jwtExpiry: number; - userId: string; - jwtPropertyName: string; - openIdRecipeImplementation: OpenIdRecipeInterface; - userContext: any; -}): Promise; diff --git a/lib/build/recipe/session/with-jwt/utils.js b/lib/build/recipe/session/with-jwt/utils.js deleted file mode 100644 index 5597b5ca0..000000000 --- a/lib/build/recipe/session/with-jwt/utils.js +++ /dev/null @@ -1,109 +0,0 @@ -"use strict"; -var __awaiter = - (this && this.__awaiter) || - function (thisArg, _arguments, P, generator) { - function adopt(value) { - return value instanceof P - ? value - : new P(function (resolve) { - resolve(value); - }); - } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { - try { - step(generator.next(value)); - } catch (e) { - reject(e); - } - } - function rejected(value) { - try { - step(generator["throw"](value)); - } catch (e) { - reject(e); - } - } - function step(result) { - result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); - } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); - }; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.addJWTToAccessTokenPayload = void 0; -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ -const constants_1 = require("./constants"); -function addJWTToAccessTokenPayload({ - accessTokenPayload, - jwtExpiry, - userId, - jwtPropertyName, - openIdRecipeImplementation, - userContext, -}) { - return __awaiter(this, void 0, void 0, function* () { - // If jwtPropertyName is not undefined it means that the JWT was added to the access token payload already - let existingJwtPropertyName = accessTokenPayload[constants_1.ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY]; - if (existingJwtPropertyName !== undefined) { - // Delete the old JWT and the old property name - delete accessTokenPayload[existingJwtPropertyName]; - delete accessTokenPayload[constants_1.ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY]; - } - // Create the JWT - let jwtResponse = yield openIdRecipeImplementation.createJWT({ - payload: Object.assign( - { - /* - We add our claims before the user provided ones so that if they use the same claims - then the final payload will use the values they provide - */ - sub: userId, - }, - accessTokenPayload - ), - validitySeconds: jwtExpiry, - userContext, - }); - if (jwtResponse.status === "UNSUPPORTED_ALGORITHM_ERROR") { - // Should never come here - throw new Error("JWT Signing algorithm not supported"); - } - // Add the jwt and the property name to the access token payload - accessTokenPayload = Object.assign(Object.assign({}, accessTokenPayload), { - /* - We add the JWT after the user defined keys because we want to make sure that it never - gets overwritten by a user defined key. Using the same key as the one configured (or defaulting) - for the JWT should be considered a dev error - - ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY indicates a reserved key used to determine the property name - with which the JWT is set, used to retrieve the JWT from the access token payload during refresg and - updateAccessTokenPayload - - Note: If the user has multiple overrides each with a unique propertyNameInAccessTokenPayload, the logic - for checking the existing JWT when refreshing the session or updating the access token payload will not work. - This is because even though the jwt itself would be created with unique property names, the _jwtPName value would - always be overwritten by the override that runs last and when retrieving the jwt using that key name it cannot be - guaranteed that the right JWT is returned. This case is considered to be a rare requirement and we assume - that users will not need multiple JWT representations of their access token payload. - */ - [jwtPropertyName]: jwtResponse.jwt, - [constants_1.ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY]: jwtPropertyName, - }); - return accessTokenPayload; - }); -} -exports.addJWTToAccessTokenPayload = addJWTToAccessTokenPayload; diff --git a/lib/build/recipe/thirdparty/index.d.ts b/lib/build/recipe/thirdparty/index.d.ts index 3d49463a7..4c076142b 100644 --- a/lib/build/recipe/thirdparty/index.d.ts +++ b/lib/build/recipe/thirdparty/index.d.ts @@ -28,6 +28,8 @@ export default class Wrapper { static Apple: typeof import("./providers/apple").default; static Discord: typeof import("./providers/discord").default; static GoogleWorkspaces: typeof import("./providers/googleWorkspaces").default; + static Bitbucket: typeof import("./providers/bitbucket").default; + static GitLab: typeof import("./providers/gitlab").default; } export declare let init: typeof Recipe.init; export declare let Error: typeof SuperTokensError; @@ -41,4 +43,6 @@ export declare let Facebook: typeof import("./providers/facebook").default; export declare let Apple: typeof import("./providers/apple").default; export declare let Discord: typeof import("./providers/discord").default; export declare let GoogleWorkspaces: typeof import("./providers/googleWorkspaces").default; +export declare let Bitbucket: typeof import("./providers/bitbucket").default; +export declare let GitLab: typeof import("./providers/gitlab").default; export type { RecipeInterface, User, APIInterface, APIOptions, TypeProvider }; diff --git a/lib/build/recipe/thirdparty/index.js b/lib/build/recipe/thirdparty/index.js index f6a6ac49d..a643b1b06 100644 --- a/lib/build/recipe/thirdparty/index.js +++ b/lib/build/recipe/thirdparty/index.js @@ -86,7 +86,7 @@ var __importDefault = return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.GoogleWorkspaces = exports.Discord = exports.Apple = exports.Facebook = exports.Github = exports.Google = exports.getUserByThirdPartyInfo = exports.getUsersByEmail = exports.getUserById = exports.signInUp = exports.Error = exports.init = void 0; +exports.GitLab = exports.Bitbucket = exports.GoogleWorkspaces = exports.Discord = exports.Apple = exports.Facebook = exports.Github = exports.Google = exports.getUserByThirdPartyInfo = exports.getUsersByEmail = exports.getUserById = exports.signInUp = exports.Error = exports.init = void 0; const recipe_1 = __importDefault(require("./recipe")); const error_1 = __importDefault(require("./error")); const thirdPartyProviders = __importStar(require("./providers")); @@ -124,6 +124,8 @@ Wrapper.Facebook = thirdPartyProviders.Facebook; Wrapper.Apple = thirdPartyProviders.Apple; Wrapper.Discord = thirdPartyProviders.Discord; Wrapper.GoogleWorkspaces = thirdPartyProviders.GoogleWorkspaces; +Wrapper.Bitbucket = thirdPartyProviders.Bitbucket; +Wrapper.GitLab = thirdPartyProviders.GitLab; exports.init = Wrapper.init; exports.Error = Wrapper.Error; exports.signInUp = Wrapper.signInUp; @@ -136,3 +138,5 @@ exports.Facebook = Wrapper.Facebook; exports.Apple = Wrapper.Apple; exports.Discord = Wrapper.Discord; exports.GoogleWorkspaces = Wrapper.GoogleWorkspaces; +exports.Bitbucket = Wrapper.Bitbucket; +exports.GitLab = Wrapper.GitLab; diff --git a/lib/build/recipe/thirdparty/providers/bitbucket.d.ts b/lib/build/recipe/thirdparty/providers/bitbucket.d.ts new file mode 100644 index 000000000..1938f6c32 --- /dev/null +++ b/lib/build/recipe/thirdparty/providers/bitbucket.d.ts @@ -0,0 +1,15 @@ +// @ts-nocheck +import { TypeProvider } from "../types"; +declare type TypeThirdPartyProviderBitbucketConfig = { + clientId: string; + clientSecret: string; + scope?: string[]; + authorisationRedirect?: { + params?: { + [key: string]: string | ((request: any) => string); + }; + }; + isDefault?: boolean; +}; +export default function Bitbucket(config: TypeThirdPartyProviderBitbucketConfig): TypeProvider; +export {}; diff --git a/lib/build/recipe/thirdparty/providers/bitbucket.js b/lib/build/recipe/thirdparty/providers/bitbucket.js new file mode 100644 index 000000000..215e1acdc --- /dev/null +++ b/lib/build/recipe/thirdparty/providers/bitbucket.js @@ -0,0 +1,147 @@ +"use strict"; +/* Copyright (c) 2023, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * 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. + */ +var __awaiter = + (this && this.__awaiter) || + function (thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P + ? value + : new P(function (resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; +Object.defineProperty(exports, "__esModule", { value: true }); +const axios_1 = __importDefault(require("axios")); +function Bitbucket(config) { + const id = "bitbucket"; + function get(redirectURI, authCodeFromRequest) { + let accessTokenAPIURL = "https://bitbucket.org/site/oauth2/access_token"; + let accessTokenAPIParams = { + client_id: config.clientId, + client_secret: config.clientSecret, + grant_type: "authorization_code", + }; + if (authCodeFromRequest !== undefined) { + accessTokenAPIParams.code = authCodeFromRequest; + } + if (redirectURI !== undefined) { + accessTokenAPIParams.redirect_uri = redirectURI; + } + let authorisationRedirectURL = "https://bitbucket.org/site/oauth2/authorize"; + let scopes = ["account", "email"]; + if (config.scope !== undefined) { + scopes = config.scope; + scopes = Array.from(new Set(scopes)); + } + let additionalParams = + config.authorisationRedirect === undefined || config.authorisationRedirect.params === undefined + ? {} + : config.authorisationRedirect.params; + let authorizationRedirectParams = Object.assign( + { scope: scopes.join(" "), access_type: "offline", response_type: "code", client_id: config.clientId }, + additionalParams + ); + function getProfileInfo(accessTokenAPIResponse) { + return __awaiter(this, void 0, void 0, function* () { + let accessToken = accessTokenAPIResponse.access_token; + let authHeader = `Bearer ${accessToken}`; + let response = yield axios_1.default({ + method: "get", + url: "https://api.bitbucket.org/2.0/user", + headers: { + Authorization: authHeader, + }, + }); + let userInfo = response.data; + let id = userInfo.uuid; + let emailRes = yield axios_1.default({ + method: "get", + url: "https://api.bitbucket.org/2.0/user/emails", + headers: { + Authorization: authHeader, + }, + }); + let emailData = emailRes.data; + let email = undefined; + let isVerified = false; + emailData.values.forEach((emailInfo) => { + if (emailInfo.is_primary) { + email = emailInfo.email; + isVerified = emailInfo.is_confirmed; + } + }); + if (email === undefined) { + return { + id, + }; + } + return { + id, + email: { + id: email, + isVerified, + }, + }; + }); + } + return { + accessTokenAPI: { + url: accessTokenAPIURL, + params: accessTokenAPIParams, + }, + authorisationRedirect: { + url: authorisationRedirectURL, + params: authorizationRedirectParams, + }, + getProfileInfo, + getClientId: () => { + return config.clientId; + }, + }; + } + return { + id, + get, + isDefault: config.isDefault, + }; +} +exports.default = Bitbucket; diff --git a/lib/build/recipe/thirdparty/providers/gitlab.d.ts b/lib/build/recipe/thirdparty/providers/gitlab.d.ts new file mode 100644 index 000000000..304fde9ee --- /dev/null +++ b/lib/build/recipe/thirdparty/providers/gitlab.d.ts @@ -0,0 +1,16 @@ +// @ts-nocheck +import { TypeProvider } from "../types"; +declare type TypeThirdPartyProviderGitLabConfig = { + clientId: string; + clientSecret: string; + scope?: string[]; + authorisationRedirect?: { + params?: { + [key: string]: string | ((request: any) => string); + }; + }; + gitlabBaseUrl?: string; + isDefault?: boolean; +}; +export default function GitLab(config: TypeThirdPartyProviderGitLabConfig): TypeProvider; +export {}; diff --git a/lib/build/recipe/thirdparty/providers/gitlab.js b/lib/build/recipe/thirdparty/providers/gitlab.js new file mode 100644 index 000000000..733b1c510 --- /dev/null +++ b/lib/build/recipe/thirdparty/providers/gitlab.js @@ -0,0 +1,138 @@ +"use strict"; +/* Copyright (c) 2023, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * 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. + */ +var __awaiter = + (this && this.__awaiter) || + function (thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P + ? value + : new P(function (resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; +Object.defineProperty(exports, "__esModule", { value: true }); +const axios_1 = __importDefault(require("axios")); +const normalisedURLDomain_1 = __importDefault(require("../../../normalisedURLDomain")); +function GitLab(config) { + const id = "gitlab"; + function get(redirectURI, authCodeFromRequest) { + let baseUrl = + config.gitlabBaseUrl === undefined + ? "https://gitlab.com" // no traling slash cause we add that in the path + : new normalisedURLDomain_1.default(config.gitlabBaseUrl).getAsStringDangerous(); + let accessTokenAPIURL = baseUrl + "/oauth/token"; + let accessTokenAPIParams = { + client_id: config.clientId, + client_secret: config.clientSecret, + grant_type: "authorization_code", + }; + if (authCodeFromRequest !== undefined) { + accessTokenAPIParams.code = authCodeFromRequest; + } + if (redirectURI !== undefined) { + accessTokenAPIParams.redirect_uri = redirectURI; + } + let authorisationRedirectURL = baseUrl + "/oauth/authorize"; + let scopes = ["read_user"]; + if (config.scope !== undefined) { + scopes = config.scope; + scopes = Array.from(new Set(scopes)); + } + let additionalParams = + config.authorisationRedirect === undefined || config.authorisationRedirect.params === undefined + ? {} + : config.authorisationRedirect.params; + let authorizationRedirectParams = Object.assign( + { scope: scopes.join(" "), response_type: "code", client_id: config.clientId }, + additionalParams + ); + function getProfileInfo(accessTokenAPIResponse) { + return __awaiter(this, void 0, void 0, function* () { + let accessToken = accessTokenAPIResponse.access_token; + let authHeader = `Bearer ${accessToken}`; + let response = yield axios_1.default({ + method: "get", + url: baseUrl + "/api/v4/user", + headers: { + Authorization: authHeader, + }, + }); + let userInfo = response.data; + let id = userInfo.id + ""; + let email = userInfo.email; + if (email === undefined || email === null) { + return { + id, + }; + } + let isVerified = userInfo.confirmed_at !== null && userInfo.confirmed_at !== undefined; + return { + id, + email: { + id: email, + isVerified, + }, + }; + }); + } + return { + accessTokenAPI: { + url: accessTokenAPIURL, + params: accessTokenAPIParams, + }, + authorisationRedirect: { + url: authorisationRedirectURL, + params: authorizationRedirectParams, + }, + getProfileInfo, + getClientId: () => { + return config.clientId; + }, + }; + } + return { + id, + get, + isDefault: config.isDefault, + }; +} +exports.default = GitLab; diff --git a/lib/build/recipe/thirdparty/providers/index.d.ts b/lib/build/recipe/thirdparty/providers/index.d.ts index f1c5f5501..5b9d69353 100644 --- a/lib/build/recipe/thirdparty/providers/index.d.ts +++ b/lib/build/recipe/thirdparty/providers/index.d.ts @@ -5,9 +5,13 @@ import ProviderGithub from "./github"; import ProviderApple from "./apple"; import ProviderDiscord from "./discord"; import ProviderGoogleWorkspaces from "./googleWorkspaces"; +import ProviderBitbucket from "./bitbucket"; +import ProviderGitlab from "./gitlab"; export declare let Google: typeof ProviderGoogle; export declare let Facebook: typeof ProviderFacebook; export declare let Github: typeof ProviderGithub; export declare let Apple: typeof ProviderApple; export declare let Discord: typeof ProviderDiscord; export declare let GoogleWorkspaces: typeof ProviderGoogleWorkspaces; +export declare let Bitbucket: typeof ProviderBitbucket; +export declare let GitLab: typeof ProviderGitlab; diff --git a/lib/build/recipe/thirdparty/providers/index.js b/lib/build/recipe/thirdparty/providers/index.js index 6c796b11c..467358a5e 100644 --- a/lib/build/recipe/thirdparty/providers/index.js +++ b/lib/build/recipe/thirdparty/providers/index.js @@ -5,7 +5,7 @@ var __importDefault = return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.GoogleWorkspaces = exports.Discord = exports.Apple = exports.Github = exports.Facebook = exports.Google = void 0; +exports.GitLab = exports.Bitbucket = exports.GoogleWorkspaces = exports.Discord = exports.Apple = exports.Github = exports.Facebook = exports.Google = void 0; const google_1 = __importDefault(require("./google")); const facebook_1 = __importDefault(require("./facebook")); const github_1 = __importDefault(require("./github")); @@ -14,11 +14,15 @@ const discord_1 = __importDefault(require("./discord")); // import ProviderOkta from "./okta"; const googleWorkspaces_1 = __importDefault(require("./googleWorkspaces")); // import ProviderAD from "./activeDirectory"; +const bitbucket_1 = __importDefault(require("./bitbucket")); +const gitlab_1 = __importDefault(require("./gitlab")); exports.Google = google_1.default; exports.Facebook = facebook_1.default; exports.Github = github_1.default; exports.Apple = apple_1.default; exports.Discord = discord_1.default; exports.GoogleWorkspaces = googleWorkspaces_1.default; +exports.Bitbucket = bitbucket_1.default; +exports.GitLab = gitlab_1.default; // export let Okta = ProviderOkta; // export let ActiveDirectory = ProviderAD; diff --git a/lib/build/recipe/thirdpartyemailpassword/index.d.ts b/lib/build/recipe/thirdpartyemailpassword/index.d.ts index c9c985e29..908e7baac 100644 --- a/lib/build/recipe/thirdpartyemailpassword/index.d.ts +++ b/lib/build/recipe/thirdpartyemailpassword/index.d.ts @@ -74,11 +74,13 @@ export default class Wrapper { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR"; } >; + static Google: typeof import("../thirdparty/providers/google").default; static updateEmailOrPassword(input: { userId: string; email?: string; password?: string; userContext?: any; + applyPasswordPolicy?: boolean; }): Promise< | { status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR"; @@ -87,13 +89,18 @@ export default class Wrapper { status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; reason: string; } + | { + status: "PASSWORD_POLICY_VIOLATED_ERROR"; + failureReason: string; + } >; - static Google: typeof import("../thirdparty/providers/google").default; static Github: typeof import("../thirdparty/providers/github").default; static Facebook: typeof import("../thirdparty/providers/facebook").default; static Apple: typeof import("../thirdparty/providers/apple").default; static Discord: typeof import("../thirdparty/providers/discord").default; static GoogleWorkspaces: typeof import("../thirdparty/providers/googleWorkspaces").default; + static Bitbucket: typeof import("../thirdparty/providers/bitbucket").default; + static GitLab: typeof import("../thirdparty/providers/gitlab").default; static sendEmail( input: TypeEmailPasswordEmailDeliveryInput & { userContext?: any; @@ -115,5 +122,7 @@ export declare let Facebook: typeof import("../thirdparty/providers/facebook").d export declare let Apple: typeof import("../thirdparty/providers/apple").default; export declare let Discord: typeof import("../thirdparty/providers/discord").default; export declare let GoogleWorkspaces: typeof import("../thirdparty/providers/googleWorkspaces").default; +export declare let Bitbucket: typeof import("../thirdparty/providers/bitbucket").default; +export declare let GitLab: typeof import("../thirdparty/providers/gitlab").default; export type { RecipeInterface, TypeProvider, User, APIInterface, EmailPasswordAPIOptions, ThirdPartyAPIOptions }; export declare let sendEmail: typeof Wrapper.sendEmail; diff --git a/lib/build/recipe/thirdpartyemailpassword/index.js b/lib/build/recipe/thirdpartyemailpassword/index.js index 14d2fbb09..2c7dc26ff 100644 --- a/lib/build/recipe/thirdpartyemailpassword/index.js +++ b/lib/build/recipe/thirdpartyemailpassword/index.js @@ -86,7 +86,7 @@ var __importDefault = return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.sendEmail = exports.GoogleWorkspaces = exports.Discord = exports.Apple = exports.Facebook = exports.Github = exports.Google = exports.updateEmailOrPassword = exports.consumePasswordResetToken = exports.createResetPasswordToken = exports.getUserByThirdPartyInfo = exports.thirdPartySignInUp = exports.emailPasswordSignIn = exports.emailPasswordSignUp = exports.Error = exports.init = void 0; +exports.sendEmail = exports.GitLab = exports.Bitbucket = exports.GoogleWorkspaces = exports.Discord = exports.Apple = exports.Facebook = exports.Github = exports.Google = exports.updateEmailOrPassword = exports.consumePasswordResetToken = exports.createResetPasswordToken = exports.getUserByThirdPartyInfo = exports.thirdPartySignInUp = exports.emailPasswordSignIn = exports.emailPasswordSignUp = exports.Error = exports.init = void 0; const recipe_1 = __importDefault(require("./recipe")); const error_1 = __importDefault(require("./error")); const thirdPartyProviders = __importStar(require("../thirdparty/providers")); @@ -157,6 +157,8 @@ Wrapper.Facebook = thirdPartyProviders.Facebook; Wrapper.Apple = thirdPartyProviders.Apple; Wrapper.Discord = thirdPartyProviders.Discord; Wrapper.GoogleWorkspaces = thirdPartyProviders.GoogleWorkspaces; +Wrapper.Bitbucket = thirdPartyProviders.Bitbucket; +Wrapper.GitLab = thirdPartyProviders.GitLab; exports.init = Wrapper.init; exports.Error = Wrapper.Error; exports.emailPasswordSignUp = Wrapper.emailPasswordSignUp; @@ -172,4 +174,6 @@ exports.Facebook = Wrapper.Facebook; exports.Apple = Wrapper.Apple; exports.Discord = Wrapper.Discord; exports.GoogleWorkspaces = Wrapper.GoogleWorkspaces; +exports.Bitbucket = Wrapper.Bitbucket; +exports.GitLab = Wrapper.GitLab; exports.sendEmail = Wrapper.sendEmail; diff --git a/lib/build/recipe/thirdpartyemailpassword/recipe.js b/lib/build/recipe/thirdpartyemailpassword/recipe.js index 37614c57f..1047264c2 100644 --- a/lib/build/recipe/thirdpartyemailpassword/recipe.js +++ b/lib/build/recipe/thirdpartyemailpassword/recipe.js @@ -125,9 +125,11 @@ class Recipe extends recipeModule_1.default { this.config = utils_1.validateAndNormaliseUserInput(this, appInfo, config); this.isInServerlessEnv = isInServerlessEnv; { + const getEmailPasswordConfig = () => this.emailPasswordRecipe.config; let builder = new supertokens_js_override_1.default( recipeImplementation_1.default( querier_1.Querier.getNewInstanceOrThrowError(recipe_1.default.RECIPE_ID), + getEmailPasswordConfig, querier_1.Querier.getNewInstanceOrThrowError(recipe_2.default.RECIPE_ID) ) ); diff --git a/lib/build/recipe/thirdpartyemailpassword/recipeImplementation/index.d.ts b/lib/build/recipe/thirdpartyemailpassword/recipeImplementation/index.d.ts index d24f05e67..77b5d763c 100644 --- a/lib/build/recipe/thirdpartyemailpassword/recipeImplementation/index.d.ts +++ b/lib/build/recipe/thirdpartyemailpassword/recipeImplementation/index.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { RecipeInterface } from "../types"; import { Querier } from "../../../querier"; -export default function getRecipeInterface(emailPasswordQuerier: Querier, thirdPartyQuerier?: Querier): RecipeInterface; +import { TypeNormalisedInput } from "../../emailpassword/types"; +export default function getRecipeInterface( + emailPasswordQuerier: Querier, + getEmailPasswordConfig: () => TypeNormalisedInput, + thirdPartyQuerier?: Querier +): RecipeInterface; diff --git a/lib/build/recipe/thirdpartyemailpassword/recipeImplementation/index.js b/lib/build/recipe/thirdpartyemailpassword/recipeImplementation/index.js index 23f596161..7db0171e7 100644 --- a/lib/build/recipe/thirdpartyemailpassword/recipeImplementation/index.js +++ b/lib/build/recipe/thirdpartyemailpassword/recipeImplementation/index.js @@ -41,8 +41,11 @@ const recipeImplementation_2 = __importDefault(require("../../thirdparty/recipeI const emailPasswordRecipeImplementation_1 = __importDefault(require("./emailPasswordRecipeImplementation")); const thirdPartyRecipeImplementation_1 = __importDefault(require("./thirdPartyRecipeImplementation")); const __1 = require("../../../"); -function getRecipeInterface(emailPasswordQuerier, thirdPartyQuerier) { - let originalEmailPasswordImplementation = recipeImplementation_1.default(emailPasswordQuerier); +function getRecipeInterface(emailPasswordQuerier, getEmailPasswordConfig, thirdPartyQuerier) { + let originalEmailPasswordImplementation = recipeImplementation_1.default( + emailPasswordQuerier, + getEmailPasswordConfig + ); let originalThirdPartyImplementation; if (thirdPartyQuerier !== undefined) { originalThirdPartyImplementation = recipeImplementation_2.default(thirdPartyQuerier); diff --git a/lib/build/recipe/thirdpartyemailpassword/types.d.ts b/lib/build/recipe/thirdpartyemailpassword/types.d.ts index a65d20ba8..b6dd1ef22 100644 --- a/lib/build/recipe/thirdpartyemailpassword/types.d.ts +++ b/lib/build/recipe/thirdpartyemailpassword/types.d.ts @@ -143,6 +143,7 @@ export declare type RecipeInterface = { email?: string; password?: string; userContext: any; + applyPasswordPolicy?: boolean; }): Promise< | { status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR"; @@ -151,6 +152,10 @@ export declare type RecipeInterface = { status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; reason: string; } + | { + status: "PASSWORD_POLICY_VIOLATED_ERROR"; + failureReason: string; + } >; }; export declare type EmailPasswordAPIOptions = EmailPasswordAPIOptionsOriginal; @@ -261,6 +266,10 @@ export declare type APIInterface = { | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR"; } + | { + status: "PASSWORD_POLICY_VIOLATED_ERROR"; + failureReason: string; + } | GeneralErrorResponse >); thirdPartySignInUpPOST: diff --git a/lib/build/recipe/thirdpartypasswordless/index.d.ts b/lib/build/recipe/thirdpartypasswordless/index.d.ts index be4703e99..736f06c53 100644 --- a/lib/build/recipe/thirdpartypasswordless/index.d.ts +++ b/lib/build/recipe/thirdpartypasswordless/index.d.ts @@ -176,6 +176,8 @@ export default class Wrapper { static Apple: typeof import("../thirdparty/providers/apple").default; static Discord: typeof import("../thirdparty/providers/discord").default; static GoogleWorkspaces: typeof import("../thirdparty/providers/googleWorkspaces").default; + static Bitbucket: typeof import("../thirdparty/providers/bitbucket").default; + static GitLab: typeof import("../thirdparty/providers/gitlab").default; static sendEmail( input: TypeThirdPartyPasswordlessEmailDeliveryInput & { userContext?: any; @@ -212,6 +214,8 @@ export declare let Facebook: typeof import("../thirdparty/providers/facebook").d export declare let Apple: typeof import("../thirdparty/providers/apple").default; export declare let Discord: typeof import("../thirdparty/providers/discord").default; export declare let GoogleWorkspaces: typeof import("../thirdparty/providers/googleWorkspaces").default; +export declare let Bitbucket: typeof import("../thirdparty/providers/bitbucket").default; +export declare let GitLab: typeof import("../thirdparty/providers/gitlab").default; export type { RecipeInterface, TypeProvider, User, APIInterface, PasswordlessAPIOptions, ThirdPartyAPIOptions }; export declare let sendEmail: typeof Wrapper.sendEmail; export declare let sendSms: typeof Wrapper.sendSms; diff --git a/lib/build/recipe/thirdpartypasswordless/index.js b/lib/build/recipe/thirdpartypasswordless/index.js index 94110718d..fd5d6fd5a 100644 --- a/lib/build/recipe/thirdpartypasswordless/index.js +++ b/lib/build/recipe/thirdpartypasswordless/index.js @@ -86,7 +86,7 @@ var __importDefault = return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.sendSms = exports.sendEmail = exports.GoogleWorkspaces = exports.Discord = exports.Apple = exports.Facebook = exports.Github = exports.Google = exports.createMagicLink = exports.revokeCode = exports.revokeAllCodes = exports.updatePasswordlessUser = exports.createNewCodeForDevice = exports.listCodesByPreAuthSessionId = exports.listCodesByPhoneNumber = exports.listCodesByEmail = exports.listCodesByDeviceId = exports.getUserByPhoneNumber = exports.consumeCode = exports.createCode = exports.getUsersByEmail = exports.getUserByThirdPartyInfo = exports.getUserById = exports.passwordlessSignInUp = exports.thirdPartySignInUp = exports.Error = exports.init = void 0; +exports.sendSms = exports.sendEmail = exports.GitLab = exports.Bitbucket = exports.GoogleWorkspaces = exports.Discord = exports.Apple = exports.Facebook = exports.Github = exports.Google = exports.createMagicLink = exports.revokeCode = exports.revokeAllCodes = exports.updatePasswordlessUser = exports.createNewCodeForDevice = exports.listCodesByPreAuthSessionId = exports.listCodesByPhoneNumber = exports.listCodesByEmail = exports.listCodesByDeviceId = exports.getUserByPhoneNumber = exports.consumeCode = exports.createCode = exports.getUsersByEmail = exports.getUserByThirdPartyInfo = exports.getUserById = exports.passwordlessSignInUp = exports.thirdPartySignInUp = exports.Error = exports.init = void 0; const recipe_1 = __importDefault(require("./recipe")); const error_1 = __importDefault(require("./error")); const thirdPartyProviders = __importStar(require("../thirdparty/providers")); @@ -203,6 +203,8 @@ Wrapper.Facebook = thirdPartyProviders.Facebook; Wrapper.Apple = thirdPartyProviders.Apple; Wrapper.Discord = thirdPartyProviders.Discord; Wrapper.GoogleWorkspaces = thirdPartyProviders.GoogleWorkspaces; +Wrapper.Bitbucket = thirdPartyProviders.Bitbucket; +Wrapper.GitLab = thirdPartyProviders.GitLab; exports.init = Wrapper.init; exports.Error = Wrapper.Error; exports.thirdPartySignInUp = Wrapper.thirdPartySignInUp; @@ -228,5 +230,7 @@ exports.Facebook = Wrapper.Facebook; exports.Apple = Wrapper.Apple; exports.Discord = Wrapper.Discord; exports.GoogleWorkspaces = Wrapper.GoogleWorkspaces; +exports.Bitbucket = Wrapper.Bitbucket; +exports.GitLab = Wrapper.GitLab; exports.sendEmail = Wrapper.sendEmail; exports.sendSms = Wrapper.sendSms; diff --git a/lib/build/supertokens.d.ts b/lib/build/supertokens.d.ts index 8bdf79f64..405d4acbb 100644 --- a/lib/build/supertokens.d.ts +++ b/lib/build/supertokens.d.ts @@ -11,8 +11,8 @@ export default class SuperTokens { isInServerlessEnv: boolean; recipeModules: RecipeModule[]; supertokens: undefined | SuperTokensInfo; + telemetryEnabled: boolean; constructor(config: TypeInput); - sendTelemetry: () => Promise; static init(config: TypeInput): void; static reset(): void; static getInstanceOrThrowError(): SuperTokens; diff --git a/lib/build/supertokens.js b/lib/build/supertokens.js index 8b7d1c904..0d1089cf5 100644 --- a/lib/build/supertokens.js +++ b/lib/build/supertokens.js @@ -50,7 +50,6 @@ var __importDefault = return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -const axios_1 = __importDefault(require("axios")); const utils_1 = require("./utils"); const querier_1 = require("./querier"); const constants_1 = require("./constants"); @@ -63,29 +62,6 @@ const recipe_1 = __importDefault(require("./recipe/accountlinking/recipe")); class SuperTokens { constructor(config) { var _a, _b; - this.sendTelemetry = () => - __awaiter(this, void 0, void 0, function* () { - try { - let querier = querier_1.Querier.getNewInstanceOrThrowError(undefined); - let response = yield querier.sendGetRequest(new normalisedURLPath_1.default("/telemetry"), {}); - let telemetryId; - if (response.exists) { - telemetryId = response.telemetryId; - } - yield axios_1.default({ - method: "POST", - url: "https://api.supertokens.com/0/st/telemetry", - data: { - appName: this.appInfo.appName, - websiteDomain: this.appInfo.websiteDomain.getAsStringDangerous(), - telemetryId, - }, - headers: { - "api-version": 2, - }, - }); - } catch (ignored) {} - }); this.handleAPI = (matchedRecipe, id, request, response, path, method) => __awaiter(this, void 0, void 0, function* () { return yield matchedRecipe.handleAPIRequest(id, request, response, path, method); @@ -332,24 +308,13 @@ class SuperTokens { this.recipeModules = config.recipeList.map((func) => { return func(this.appInfo, this.isInServerlessEnv); }); - let isAccountLinkingInitialised = this.recipeModules.find( + let isAccountLinkingInitialized = this.recipeModules.find( (r) => r.getRecipeId() === recipe_1.default.RECIPE_ID ); - if (!isAccountLinkingInitialised) { + if (!isAccountLinkingInitialized) { this.recipeModules.push(recipe_1.default.init({})(this.appInfo, this.isInServerlessEnv)); } - let telemetry = config.telemetry === undefined ? process.env.TEST_MODE !== "testing" : config.telemetry; - if (telemetry) { - if (this.isInServerlessEnv) { - // see https://github.com/supertokens/supertokens-node/issues/127 - let randomNum = Math.random() * 10; - if (randomNum > 7) { - this.sendTelemetry(); - } - } else { - this.sendTelemetry(); - } - } + this.telemetryEnabled = config.telemetry === undefined ? process.env.TEST_MODE !== "testing" : config.telemetry; } static init(config) { if (SuperTokens.instance === undefined) { diff --git a/lib/build/utils.d.ts b/lib/build/utils.d.ts index c1ab0dd06..5a95076cb 100644 --- a/lib/build/utils.d.ts +++ b/lib/build/utils.d.ts @@ -13,4 +13,6 @@ export declare function getRidFromHeader(req: BaseRequest): string | undefined; export declare function frontendHasInterceptor(req: BaseRequest): boolean; export declare function humaniseMilliseconds(ms: number): string; export declare function makeDefaultUserContextFromAPI(request: BaseRequest): any; +export declare function setRequestInUserContextIfNotDefined(userContext: any | undefined, request: BaseRequest): any; export declare function getTopLevelDomainForSameSiteResolution(url: string): string; +export declare function getFromObjectCaseInsensitive(key: string, object: Record): T | undefined; diff --git a/lib/build/utils.js b/lib/build/utils.js index a35e7fb98..119069d47 100644 --- a/lib/build/utils.js +++ b/lib/build/utils.js @@ -41,7 +41,7 @@ var __importDefault = return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.getTopLevelDomainForSameSiteResolution = exports.makeDefaultUserContextFromAPI = exports.humaniseMilliseconds = exports.frontendHasInterceptor = exports.getRidFromHeader = exports.isAnIpAddress = exports.send200Response = exports.sendNon200Response = exports.sendNon200ResponseWithMessage = exports.normaliseHttpMethod = exports.normaliseInputAppInfoOrThrowError = exports.maxVersion = exports.getLargestVersionFromIntersection = void 0; +exports.getFromObjectCaseInsensitive = exports.getTopLevelDomainForSameSiteResolution = exports.setRequestInUserContextIfNotDefined = exports.makeDefaultUserContextFromAPI = exports.humaniseMilliseconds = exports.frontendHasInterceptor = exports.getRidFromHeader = exports.isAnIpAddress = exports.send200Response = exports.sendNon200Response = exports.sendNon200ResponseWithMessage = exports.normaliseHttpMethod = exports.normaliseInputAppInfoOrThrowError = exports.maxVersion = exports.getLargestVersionFromIntersection = void 0; const psl = __importStar(require("psl")); const normalisedURLDomain_1 = __importDefault(require("./normalisedURLDomain")); const normalisedURLPath_1 = __importDefault(require("./normalisedURLPath")); @@ -173,13 +173,22 @@ function humaniseMilliseconds(ms) { } exports.humaniseMilliseconds = humaniseMilliseconds; function makeDefaultUserContextFromAPI(request) { - return { - _default: { - request, - }, - }; + return setRequestInUserContextIfNotDefined({}, request); } exports.makeDefaultUserContextFromAPI = makeDefaultUserContextFromAPI; +function setRequestInUserContextIfNotDefined(userContext, request) { + if (userContext === undefined) { + userContext = {}; + } + if (userContext._default === undefined) { + userContext._default = {}; + } + if (typeof userContext._default === "object") { + userContext._default.request = request; + } + return userContext; +} +exports.setRequestInUserContextIfNotDefined = setRequestInUserContextIfNotDefined; function getTopLevelDomainForSameSiteResolution(url) { let urlObj = new URL(url); let hostname = urlObj.hostname; @@ -194,3 +203,11 @@ function getTopLevelDomainForSameSiteResolution(url) { return parsedURL.domain; } exports.getTopLevelDomainForSameSiteResolution = getTopLevelDomainForSameSiteResolution; +function getFromObjectCaseInsensitive(key, object) { + const matchedKeys = Object.keys(object).filter((i) => i.toLocaleLowerCase() === key.toLocaleLowerCase()); + if (matchedKeys.length === 0) { + return undefined; + } + return object[matchedKeys[0]]; +} +exports.getFromObjectCaseInsensitive = getFromObjectCaseInsensitive; diff --git a/lib/build/version.d.ts b/lib/build/version.d.ts index 2e5ff3046..5320542aa 100644 --- a/lib/build/version.d.ts +++ b/lib/build/version.d.ts @@ -1,4 +1,4 @@ // @ts-nocheck -export declare const version = "13.0.2"; +export declare const version = "14.0.0"; export declare const cdiSupported: string[]; -export declare const dashboardVersion = "0.3"; +export declare const dashboardVersion = "0.6"; diff --git a/lib/build/version.js b/lib/build/version.js index ba464a876..9ba5063c9 100644 --- a/lib/build/version.js +++ b/lib/build/version.js @@ -15,7 +15,7 @@ exports.dashboardVersion = exports.cdiSupported = exports.version = void 0; * License for the specific language governing permissions and limitations * under the License. */ -exports.version = "13.0.2"; -exports.cdiSupported = ["2.8", "2.9", "2.10", "2.11", "2.12", "2.13", "2.14", "2.15"]; +exports.version = "14.0.0"; +exports.cdiSupported = ["2.21"]; // Note: The actual script import for dashboard uses v{DASHBOARD_VERSION} -exports.dashboardVersion = "0.3"; +exports.dashboardVersion = "0.6"; diff --git a/lib/ts/framework/awsLambda/framework.ts b/lib/ts/framework/awsLambda/framework.ts index 317d07792..811ae2248 100644 --- a/lib/ts/framework/awsLambda/framework.ts +++ b/lib/ts/framework/awsLambda/framework.ts @@ -22,7 +22,7 @@ import type { Callback, } from "aws-lambda"; import { HTTPMethod } from "../../types"; -import { normaliseHttpMethod } from "../../utils"; +import { getFromObjectCaseInsensitive, normaliseHttpMethod } from "../../utils"; import { BaseRequest } from "../request"; import { BaseResponse } from "../response"; import { normalizeHeaderValue, getCookieValueFromHeaders, serializeCookieValue } from "../utils"; @@ -31,6 +31,7 @@ import { SessionContainerInterface } from "../../recipe/session/types"; import SuperTokens from "../../supertokens"; import { Framework } from "../types"; import { parse } from "querystring"; +import { URL } from "url"; export class AWSRequest extends BaseRequest { private event: APIGatewayProxyEventV2 | APIGatewayProxyEvent; @@ -116,17 +117,24 @@ export class AWSRequest extends BaseRequest { if (this.event.headers === undefined || this.event.headers === null) { return undefined; } - return normalizeHeaderValue(this.event.headers[key]); + return normalizeHeaderValue(getFromObjectCaseInsensitive(key, this.event.headers)); }; getOriginalURL = (): string => { let path = (this.event as APIGatewayProxyEvent).path; + let queryParams = (this.event as APIGatewayProxyEvent).queryStringParameters as { [key: string]: string }; if (path === undefined) { path = (this.event as APIGatewayProxyEventV2).requestContext.http.path; let stage = (this.event as APIGatewayProxyEventV2).requestContext.stage; if (stage !== undefined && path.startsWith(`/${stage}`)) { path = path.slice(stage.length + 1); } + if (queryParams !== undefined && queryParams !== null) { + let urlString = "https://exmaple.com" + path; + let url = new URL(urlString); + Object.keys(queryParams).forEach((el) => url.searchParams.append(el, queryParams[el])); + path = url.pathname + url.search; + } } return path; }; diff --git a/lib/ts/framework/fastify/framework.ts b/lib/ts/framework/fastify/framework.ts index c3709d802..65ccf03ae 100644 --- a/lib/ts/framework/fastify/framework.ts +++ b/lib/ts/framework/fastify/framework.ts @@ -20,7 +20,7 @@ import type { FastifyPluginCallback, } from "fastify"; import type { HTTPMethod } from "../../types"; -import { normaliseHttpMethod } from "../../utils"; +import { getFromObjectCaseInsensitive, normaliseHttpMethod } from "../../utils"; import { BaseRequest } from "../request"; import { BaseResponse } from "../response"; import { serializeCookieValue, normalizeHeaderValue, getCookieValueFromHeaders } from "../utils"; @@ -66,7 +66,7 @@ export class FastifyRequest extends BaseRequest { }; getHeaderValue = (key: string): string | undefined => { - return normalizeHeaderValue(this.request.headers[key]); + return normalizeHeaderValue(getFromObjectCaseInsensitive(key, this.request.headers)); }; getOriginalURL = (): string => { diff --git a/lib/ts/framework/utils.ts b/lib/ts/framework/utils.ts index 2358af16a..455feeaba 100644 --- a/lib/ts/framework/utils.ts +++ b/lib/ts/framework/utils.ts @@ -22,6 +22,7 @@ import STError from "../error"; import type { HTTPMethod } from "../types"; import { NextApiRequest } from "next"; import { COOKIE_HEADER } from "./constants"; +import { getFromObjectCaseInsensitive } from "../utils"; export function getCookieValueFromHeaders(headers: any, key: string): string | undefined { if (headers === undefined || headers === null) { @@ -50,7 +51,7 @@ export function getCookieValueFromIncomingMessage(request: IncomingMessage, key: } export function getHeaderValueFromIncomingMessage(request: IncomingMessage, key: string): string | undefined { - return normalizeHeaderValue(request.headers[key]); + return normalizeHeaderValue(getFromObjectCaseInsensitive(key, request.headers)); } export function normalizeHeaderValue(value: string | string[] | undefined): string | undefined { @@ -136,29 +137,16 @@ export async function assertThatBodyParserHasBeenUsedForExpressLikeRequest( let jsonParser = json(); let err = await new Promise((resolve) => { let resolvedCalled = false; - /** - * Nextjs allow users to disable the default parser. - * To handle that scenario, we are still parsing the request body - */ - if (request.__supertokensFromNextJS === true) { - /** - * the setImmediate here is to counter the next.js issue - * where the json parser would not resolve and thus the request - * just hangs forever. Next.JS does json parsing on its own. - */ - setImmediate(() => { + if (request.readable) { + jsonParser(request, new ServerResponse(request), (e) => { if (!resolvedCalled) { resolvedCalled = true; - resolve(undefined); + resolve(e); } }); + } else { + resolve(undefined); } - jsonParser(request, new ServerResponse(request), (e) => { - if (!resolvedCalled) { - resolvedCalled = true; - resolve(e); - } - }); }); if (err !== undefined) { throw new STError({ @@ -174,7 +162,7 @@ export async function assertThatBodyParserHasBeenUsedForExpressLikeRequest( if (err !== undefined) { throw new STError({ type: STError.BAD_INPUT_ERROR, - message: "API input error: Please make sure to pass valid URL query params", + message: "API input error: Please make sure to pass valid url encoded form in the request body", }); } } @@ -186,35 +174,18 @@ export async function assertFormDataBodyParserHasBeenUsedForExpressLikeRequest( ) { let parser = urlencoded({ extended: true }); let err = await new Promise((resolve) => { - let resolvedCalled = false; - /** - * Nextjs allow users to disable the default parser. - * To handle that scenario, we are still parsing the request body - */ - if (request.__supertokensFromNextJS === true) { - /** - * the setImmediate here is to counter the next.js issue - * where the json parser would not resolve and thus the request - * just hangs forever. Next.JS does json parsing on its own. - */ - setImmediate(() => { - if (!resolvedCalled) { - resolvedCalled = true; - resolve(undefined); - } + if (request.readable) { + parser(request, new ServerResponse(request), (e) => { + resolve(e); }); + } else { + resolve(undefined); } - parser(request, new ServerResponse(request), (e) => { - if (!resolvedCalled) { - resolvedCalled = true; - resolve(e); - } - }); }); if (err !== undefined) { throw new STError({ type: STError.BAD_INPUT_ERROR, - message: "API input error: Please make sure to pass valid URL query params", + message: "API input error: Please make sure to pass valid url encoded form in the request body", }); } } diff --git a/lib/ts/index.ts b/lib/ts/index.ts index bb9f6bac4..fb50e625e 100644 --- a/lib/ts/index.ts +++ b/lib/ts/index.ts @@ -37,6 +37,7 @@ export default class SuperTokensWrapper { limit?: number; paginationToken?: string; includeRecipeIds?: string[]; + query?: object; }): Promise<{ users: User[]; nextPaginationToken?: string; @@ -52,6 +53,7 @@ export default class SuperTokensWrapper { limit?: number; paginationToken?: string; includeRecipeIds?: string[]; + query?: object; }): Promise<{ users: User[]; nextPaginationToken?: string; diff --git a/lib/ts/processState.ts b/lib/ts/processState.ts index 05b9c4de0..fd8c1446b 100644 --- a/lib/ts/processState.ts +++ b/lib/ts/processState.ts @@ -15,9 +15,9 @@ export enum PROCESS_STATE { CALLING_SERVICE_IN_VERIFY, - CALLING_SERVICE_IN_GET_HANDSHAKE_INFO, CALLING_SERVICE_IN_GET_API_VERSION, CALLING_SERVICE_IN_REQUEST_HELPER, + MULTI_JWKS_VALIDATION, } export class ProcessState { diff --git a/lib/ts/querier.ts b/lib/ts/querier.ts index 9328897ac..41478e043 100644 --- a/lib/ts/querier.ts +++ b/lib/ts/querier.ts @@ -107,7 +107,7 @@ export class Querier { } // path should start with "/" - sendPostRequest = async (path: NormalisedURLPath, body: any): Promise => { + sendPostRequest = async (path: NormalisedURLPath, body: any): Promise => { return this.sendRequestHelper( path, "POST", @@ -141,7 +141,7 @@ export class Querier { }; // path should start with "/" - sendDeleteRequest = async (path: NormalisedURLPath, body: any): Promise => { + sendDeleteRequest = async (path: NormalisedURLPath, body: any, params?: any): Promise => { return this.sendRequestHelper( path, "DELETE", @@ -166,6 +166,7 @@ export class Querier { url, data: body, headers, + params, }); }, this.__hosts?.length || 0 @@ -232,6 +233,21 @@ export class Querier { ); }; + public getAllCoreUrlsForPath(path: string) { + if (this.__hosts === undefined) { + return []; + } + + const normalisedPath = new NormalisedURLPath(path); + + return this.__hosts.map((h) => { + const currentDomain: string = h.domain.getAsStringDangerous(); + const currentBasePath: string = h.basePath.getAsStringDangerous(); + + return currentDomain + currentBasePath + normalisedPath.getAsStringDangerous(); + }); + } + // path should start with "/" private sendRequestHelper = async ( path: NormalisedURLPath, @@ -249,11 +265,12 @@ export class Querier { } let currentDomain: string = this.__hosts[Querier.lastTriedIndex].domain.getAsStringDangerous(); let currentBasePath: string = this.__hosts[Querier.lastTriedIndex].basePath.getAsStringDangerous(); + const url = currentDomain + currentBasePath + path.getAsStringDangerous(); Querier.lastTriedIndex++; Querier.lastTriedIndex = Querier.lastTriedIndex % this.__hosts.length; try { ProcessState.getInstance().addState(PROCESS_STATE.CALLING_SERVICE_IN_REQUEST_HELPER); - let response = await axiosFunction(currentDomain + currentBasePath + path.getAsStringDangerous()); + let response = await axiosFunction(url); if (process.env.TEST_MODE === "testing") { Querier.hostsAliveForTesting.add(currentDomain + currentBasePath); } diff --git a/lib/ts/recipe/dashboard/api/analytics.ts b/lib/ts/recipe/dashboard/api/analytics.ts new file mode 100644 index 000000000..07df39b36 --- /dev/null +++ b/lib/ts/recipe/dashboard/api/analytics.ts @@ -0,0 +1,98 @@ +/* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * 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. + */ + +import { APIInterface, APIOptions } from "../types"; +import SuperTokens from "../../../supertokens"; +import { Querier } from "../../../querier"; +import NormalisedURLPath from "../../../normalisedURLPath"; +import { version as SDKVersion } from "../../../version"; +import STError from "../../../error"; +import axios from "axios"; + +export type Response = { + status: "OK"; +}; + +export default async function analyticsPost(_: APIInterface, options: APIOptions): Promise { + // If telemetry is disabled, dont send any event + if (!SuperTokens.getInstanceOrThrowError().telemetryEnabled) { + return { + status: "OK", + }; + } + + const { email, dashboardVersion } = await options.req.getJSONBody(); + + if (email === undefined) { + throw new STError({ + message: "Missing required property 'email'", + type: STError.BAD_INPUT_ERROR, + }); + } + + if (dashboardVersion === undefined) { + throw new STError({ + message: "Missing required property 'dashboardVersion'", + type: STError.BAD_INPUT_ERROR, + }); + } + + let telemetryId: string | undefined; + let numberOfUsers: number; + try { + let querier = Querier.getNewInstanceOrThrowError(options.recipeId); + let response = await querier.sendGetRequest(new NormalisedURLPath("/telemetry"), {}); + if (response.exists) { + telemetryId = response.telemetryId; + } + + numberOfUsers = await SuperTokens.getInstanceOrThrowError().getUserCount(); + } catch (_) { + // If either telemetry id API or user count fetch fails, no event should be sent + return { + status: "OK", + }; + } + + const { apiDomain, websiteDomain, appName } = options.appInfo; + const data = { + websiteDomain: websiteDomain.getAsStringDangerous(), + apiDomain: apiDomain.getAsStringDangerous(), + appName, + sdk: "node", + sdkVersion: SDKVersion, + telemetryId, + numberOfUsers, + email, + dashboardVersion, + }; + + try { + await axios({ + url: "https://api.supertokens.com/0/st/telemetry", + method: "POST", + data, + headers: { + "api-version": 3, + }, + }); + } catch (e) { + // Ignored + } + + return { + status: "OK", + }; +} diff --git a/lib/ts/recipe/dashboard/api/implementation.ts b/lib/ts/recipe/dashboard/api/implementation.ts index 6fa87eb9e..39adfc15c 100644 --- a/lib/ts/recipe/dashboard/api/implementation.ts +++ b/lib/ts/recipe/dashboard/api/implementation.ts @@ -15,9 +15,11 @@ import NormalisedURLDomain from "../../../normalisedURLDomain"; import NormalisedURLPath from "../../../normalisedURLPath"; +import { Querier } from "../../../querier"; import SuperTokens from "../../../supertokens"; +import { maxVersion } from "../../../utils"; import { DASHBOARD_API } from "../constants"; -import { APIInterface } from "../types"; +import { APIInterface, AuthMode } from "../types"; export default function getAPIImplementation(): APIInterface { return { @@ -33,10 +35,19 @@ export default function getAPIImplementation(): APIInterface { let connectionURI: string = ""; const superTokensInstance = SuperTokens.getInstanceOrThrowError(); + const authMode: AuthMode = input.options.config.authMode; + if (superTokensInstance.supertokens !== undefined) { connectionURI = superTokensInstance.supertokens.connectionURI; } + let isSearchEnabled = false; + const cdiVersion = await Querier.getNewInstanceOrThrowError(input.options.recipeId).getAPIVersion(); + if (maxVersion("2.20", cdiVersion) === cdiVersion) { + // Only enable search if CDI version is 2.20 or above + isSearchEnabled = true; + } + return ` @@ -47,6 +58,8 @@ export default function getAPIImplementation(): APIInterface { .appendPath(new NormalisedURLPath(DASHBOARD_API)) .getAsStringDangerous()}" window.connectionURI = "${connectionURI}" + window.authMode = "${authMode}" + window.isSearchEnabled = "${isSearchEnabled}" diff --git a/lib/ts/recipe/session/with-jwt/index.ts b/lib/ts/recipe/dashboard/api/search/tagsGet.ts similarity index 51% rename from lib/ts/recipe/session/with-jwt/index.ts rename to lib/ts/recipe/dashboard/api/search/tagsGet.ts index ac3dfdd9e..945c9eeae 100644 --- a/lib/ts/recipe/session/with-jwt/index.ts +++ b/lib/ts/recipe/dashboard/api/search/tagsGet.ts @@ -1,4 +1,4 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. +/* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. * * This software is licensed under the Apache License, Version 2.0 (the * "License") as published by the Apache Software Foundation. @@ -12,6 +12,15 @@ * License for the specific language governing permissions and limitations * under the License. */ -import OriginalImplementation from "./recipeImplementation"; -export default OriginalImplementation; +import { APIInterface, APIOptions } from "../../types"; +import { Querier } from "../../../../querier"; +import NormalisedURLPath from "../../../../normalisedURLPath"; + +type TagsResponse = { status: "OK"; tags: string[] }; + +export const getSearchTags = async (_: APIInterface, options: APIOptions): Promise => { + let querier = Querier.getNewInstanceOrThrowError(options.recipeId); + let tagsResponse = await querier.sendGetRequest(new NormalisedURLPath("/user/search/tags"), {}); + return tagsResponse; +}; diff --git a/lib/ts/recipe/dashboard/api/signIn.ts b/lib/ts/recipe/dashboard/api/signIn.ts new file mode 100644 index 000000000..8ea23793a --- /dev/null +++ b/lib/ts/recipe/dashboard/api/signIn.ts @@ -0,0 +1,56 @@ +/* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * 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. + */ + +import { APIInterface, APIOptions } from "../types"; +import { send200Response } from "../../../utils"; +import STError from "../../../error"; +import { Querier } from "../../../querier"; +import NormalisedURLPath from "../../../normalisedURLPath"; + +type SignInResponse = + | { status: "OK"; sessionId: string } + | { status: "INVALID_CREDENTIALS_ERROR" } + | { status: "USER_SUSPENDED_ERROR" }; + +export default async function signIn(_: APIInterface, options: APIOptions): Promise { + const { email, password } = await options.req.getJSONBody(); + + if (email === undefined) { + throw new STError({ + message: "Missing required parameter 'email'", + type: STError.BAD_INPUT_ERROR, + }); + } + + if (password === undefined) { + throw new STError({ + message: "Missing required parameter 'password'", + type: STError.BAD_INPUT_ERROR, + }); + } + + let querier = Querier.getNewInstanceOrThrowError(undefined); + const signInResponse = await querier.sendPostRequest( + new NormalisedURLPath("/recipe/dashboard/signin"), + { + email, + password, + } + ); + + send200Response(options.res, signInResponse); + + return true; +} diff --git a/lib/ts/recipe/dashboard/api/signOut.ts b/lib/ts/recipe/dashboard/api/signOut.ts new file mode 100644 index 000000000..5fe3a0b64 --- /dev/null +++ b/lib/ts/recipe/dashboard/api/signOut.ts @@ -0,0 +1,35 @@ +/* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * 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. + */ + +import { APIInterface, APIOptions } from "../types"; +import { send200Response } from "../../../utils"; +import { Querier } from "../../../querier"; +import NormalisedURLPath from "../../../normalisedURLPath"; + +export default async function signOut(_: APIInterface, options: APIOptions): Promise { + if (options.config.authMode === "api-key") { + send200Response(options.res, { status: "OK" }); + } else { + const sessionIdFormAuthHeader = options.req.getHeaderValue("authorization")?.split(" ")[1]; + let querier = Querier.getNewInstanceOrThrowError(undefined); + const sessionDeleteResponse = await querier.sendDeleteRequest( + new NormalisedURLPath("/recipe/dashboard/session"), + {}, + { sessionId: sessionIdFormAuthHeader } + ); + send200Response(options.res, sessionDeleteResponse); + } + return true; +} diff --git a/lib/ts/recipe/dashboard/api/userdetails/userPasswordPut.ts b/lib/ts/recipe/dashboard/api/userdetails/userPasswordPut.ts index 4e2f8b11c..2c0ef9f51 100644 --- a/lib/ts/recipe/dashboard/api/userdetails/userPasswordPut.ts +++ b/lib/ts/recipe/dashboard/api/userdetails/userPasswordPut.ts @@ -68,16 +68,12 @@ export const userPasswordPut = async (_: APIInterface, options: APIOptions): Pro ) { // Techincally it can but its an edge case so we assume that it wont throw new Error("Should never come here"); - } - // TODO: check for password policy error has well. - /** - * - * return { + } else if (updateResponse.status === "PASSWORD_POLICY_VIOLATED_ERROR") { + return { status: "INVALID_PASSWORD_ERROR", - error: passwordValidationError, + error: updateResponse.failureReason, }; - */ - + } return { status: "OK", }; @@ -95,16 +91,12 @@ export const userPasswordPut = async (_: APIInterface, options: APIOptions): Pro ) { // Techincally it can but its an edge case so we assume that it wont throw new Error("Should never come here"); - } - // TODO: check for password policy error has well. - /** - * - * return { + } else if (updateResponse.status === "PASSWORD_POLICY_VIOLATED_ERROR") { + return { status: "INVALID_PASSWORD_ERROR", - error: passwordValidationError, + error: updateResponse.failureReason, }; - */ - + } return { status: "OK", }; diff --git a/lib/ts/recipe/dashboard/api/userdetails/userPut.ts b/lib/ts/recipe/dashboard/api/userdetails/userPut.ts index 10240311a..7869bd12c 100644 --- a/lib/ts/recipe/dashboard/api/userdetails/userPut.ts +++ b/lib/ts/recipe/dashboard/api/userdetails/userPut.ts @@ -31,6 +31,10 @@ type Response = | { status: "INVALID_PHONE_ERROR"; error: string; + } + | { + status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; + reason: string; }; const updateEmailForRecipeId = async ( @@ -48,6 +52,10 @@ const updateEmailForRecipeId = async ( | { status: "EMAIL_ALREADY_EXISTS_ERROR"; } + | { + status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; + reason: string; + } > => { if (recipeId === "emailpassword") { let emailFormFields = EmailPasswordRecipe.getInstanceOrThrowError().config.signUpFeature.formFields.filter( @@ -72,6 +80,13 @@ const updateEmailForRecipeId = async ( return { status: "EMAIL_ALREADY_EXISTS_ERROR", }; + } else if (emailUpdateResponse.status === "EMAIL_CHANGE_NOT_ALLOWED_ERROR") { + return { + status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR", + reason: emailUpdateResponse.reason, + }; + } else if (emailUpdateResponse.status === "UNKNOWN_USER_ID_ERROR") { + throw new Error("Should never come here"); } return { @@ -102,9 +117,12 @@ const updateEmailForRecipeId = async ( return { status: "EMAIL_ALREADY_EXISTS_ERROR", }; - } - - if (emailUpdateResponse.status === "UNKNOWN_USER_ID_ERROR") { + } else if (emailUpdateResponse.status === "EMAIL_CHANGE_NOT_ALLOWED_ERROR") { + return { + status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR", + reason: emailUpdateResponse.reason, + }; + } else if (emailUpdateResponse.status === "UNKNOWN_USER_ID_ERROR") { throw new Error("Should never come here"); } diff --git a/lib/ts/recipe/dashboard/api/userdetails/userSessionsGet.ts b/lib/ts/recipe/dashboard/api/userdetails/userSessionsGet.ts index a68c04290..840f3697b 100644 --- a/lib/ts/recipe/dashboard/api/userdetails/userSessionsGet.ts +++ b/lib/ts/recipe/dashboard/api/userdetails/userSessionsGet.ts @@ -3,7 +3,7 @@ import STError from "../../../../error"; import Session from "../../../session"; type SessionType = { - sessionData: any; + sessionDataInDatabase: any; accessTokenPayload: any; userId: string; expiry: number; @@ -38,7 +38,9 @@ export const userSessionsGet: APIFunction = async (_: APIInterface, options: API const sessionResponse = await Session.getSessionInformation(response[i]); if (sessionResponse !== undefined) { - sessions[i] = sessionResponse; + const accessTokenPayload = sessionResponse.customClaimsInAccessTokenPayload; + delete sessionResponse.customClaimsInAccessTokenPayload; + sessions[i] = { ...sessionResponse, accessTokenPayload }; } res(); diff --git a/lib/ts/recipe/dashboard/api/usersGet.ts b/lib/ts/recipe/dashboard/api/usersGet.ts index 78539b382..df33ecfb1 100644 --- a/lib/ts/recipe/dashboard/api/usersGet.ts +++ b/lib/ts/recipe/dashboard/api/usersGet.ts @@ -67,14 +67,17 @@ export default async function usersGet(_: APIInterface, options: APIOptions): Pr } let paginationToken = options.req.getKeyValueFromQuery("paginationToken"); + const query = getSearchParamsFromURL(options.req.getOriginalURL()); let usersResponse = timeJoinedOrder === "DESC" ? await getUsersNewestFirst({ + query, limit: parseInt(limit), paginationToken, }) : await getUsersOldestFirst({ + query, limit: parseInt(limit), paginationToken, }); @@ -161,3 +164,15 @@ export default async function usersGet(_: APIInterface, options: APIOptions): Pr nextPaginationToken: usersResponse.nextPaginationToken, }; } + +export function getSearchParamsFromURL(path: string): { [key: string]: string } { + const URLObject = new URL("https://exmaple.com" + path); + const params = new URLSearchParams(URLObject.search); + const searchQuery: { [key: string]: string } = {}; + for (const [key, value] of params) { + if (!["limit", "timeJoinedOrder", "paginationToken"].includes(key)) { + searchQuery[key] = value; + } + } + return searchQuery; +} diff --git a/lib/ts/recipe/dashboard/api/validateKey.ts b/lib/ts/recipe/dashboard/api/validateKey.ts index 9676668a4..0a8d109bc 100644 --- a/lib/ts/recipe/dashboard/api/validateKey.ts +++ b/lib/ts/recipe/dashboard/api/validateKey.ts @@ -13,23 +13,19 @@ * under the License. */ -import { APIInterface, APIOptions } from "../types"; import { makeDefaultUserContextFromAPI } from "../../../utils"; -import { sendUnauthorisedAccess } from "../utils"; +import { APIInterface, APIOptions } from "../types"; +import { sendUnauthorisedAccess, validateApiKey } from "../utils"; export default async function validateKey(_: APIInterface, options: APIOptions): Promise { - const shouldAllowAccess = await options.recipeImplementation.shouldAllowAccess({ - req: options.req, - config: options.config, - userContext: makeDefaultUserContextFromAPI(options.req), - }); + const input = { req: options.req, config: options.config, userContext: makeDefaultUserContextFromAPI(options.req) }; - if (!shouldAllowAccess) { - sendUnauthorisedAccess(options.res); - } else { + if (await validateApiKey(input)) { options.res.sendJSONResponse({ status: "OK", }); + } else { + sendUnauthorisedAccess(options.res); } return true; diff --git a/lib/ts/recipe/dashboard/constants.ts b/lib/ts/recipe/dashboard/constants.ts index bde8a2a16..3a148e376 100644 --- a/lib/ts/recipe/dashboard/constants.ts +++ b/lib/ts/recipe/dashboard/constants.ts @@ -14,6 +14,8 @@ */ export const DASHBOARD_API = "/dashboard"; +export const SIGN_IN_API = "/api/signin"; +export const SIGN_OUT_API = "/api/signout"; export const VALIDATE_KEY_API = "/api/key/validate"; export const USERS_LIST_GET_API = "/api/users"; export const USERS_COUNT_API = "/api/users/count"; @@ -23,3 +25,5 @@ export const USER_METADATA_API = "/api/user/metadata"; export const USER_SESSIONS_API = "/api/user/sessions"; export const USER_PASSWORD_API = "/api/user/password"; export const USER_EMAIL_VERIFY_TOKEN_API = "/api/user/email/verify/token"; +export const SEARCH_TAGS_API = "/api/search/tags"; +export const DASHBOARD_ANALYTICS_API = "/api/analytics"; diff --git a/lib/ts/recipe/dashboard/recipe.ts b/lib/ts/recipe/dashboard/recipe.ts index 78382bf7b..6aeec1391 100644 --- a/lib/ts/recipe/dashboard/recipe.ts +++ b/lib/ts/recipe/dashboard/recipe.ts @@ -19,9 +19,13 @@ import { APIHandled, HTTPMethod, NormalisedAppinfo, RecipeListFunction } from ". import { APIFunction, APIInterface, APIOptions, RecipeInterface, TypeInput, TypeNormalisedInput } from "./types"; import RecipeImplementation from "./recipeImplementation"; import APIImplementation from "./api/implementation"; -import { getApiIdIfMatched, isApiPath, validateAndNormaliseUserInput } from "./utils"; +import { getApiIdIfMatched, getApiPathWithDashboardBase, isApiPath, validateAndNormaliseUserInput } from "./utils"; import { + DASHBOARD_ANALYTICS_API, DASHBOARD_API, + SEARCH_TAGS_API, + SIGN_IN_API, + SIGN_OUT_API, USERS_COUNT_API, USERS_LIST_GET_API, USER_API, @@ -51,6 +55,10 @@ import { userPasswordPut } from "./api/userdetails/userPasswordPut"; import { userPut } from "./api/userdetails/userPut"; import { userEmailVerifyTokenPost } from "./api/userdetails/userEmailVerifyTokenPost"; import { userSessionsPost } from "./api/userdetails/userSessionsPost"; +import signIn from "./api/signIn"; +import signOut from "./api/signOut"; +import { getSearchTags } from "./api/search/tagsGet"; +import analyticsPost from "./api/analytics"; export default class Recipe extends RecipeModule { private static instance: Recipe | undefined = undefined; @@ -64,7 +72,7 @@ export default class Recipe extends RecipeModule { isInServerlessEnv: boolean; - constructor(recipeId: string, appInfo: NormalisedAppinfo, isInServerlessEnv: boolean, config: TypeInput) { + constructor(recipeId: string, appInfo: NormalisedAppinfo, isInServerlessEnv: boolean, config?: TypeInput) { super(recipeId, appInfo); this.config = validateAndNormaliseUserInput(config); @@ -87,15 +95,13 @@ export default class Recipe extends RecipeModule { throw new Error("Initialisation not done. Did you forget to call the SuperTokens.init function?"); } - static init(config: TypeInput): RecipeListFunction { + static init(config?: TypeInput): RecipeListFunction { return (appInfo, isInServerlessEnv) => { if (Recipe.instance === undefined) { Recipe.instance = new Recipe(Recipe.RECIPE_ID, appInfo, isInServerlessEnv, config); return Recipe.instance; } else { - throw new Error( - "Emailverification recipe has already been initialised. Please check your code for bugs." - ); + throw new Error("Dashboard recipe has already been initialised. Please check your code for bugs."); } }; } @@ -115,10 +121,128 @@ export default class Recipe extends RecipeModule { * handles a specific API path and method and then returns the ID. * * For the dashboard recipe this logic is fully custom and handled inside the - * `returnAPIIdIfCanHandleRequest` method of this class. Since this array is never - * used for this recipe, we simply return an empty array. + * `returnAPIIdIfCanHandleRequest` method of this class. + * + * For most frameworks this array is redundant because the `returnAPIIdIfCanHandleRequest` is used. + * But for frameworks such as Hapi that require all APIs to be declared up front, this array is used + * to make sure that the framework does not return a 404 */ - return []; + return [ + { + id: DASHBOARD_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(DASHBOARD_API)), + disabled: false, + method: "get", + }, + { + id: SIGN_IN_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(SIGN_IN_API)), + disabled: false, + method: "post", + }, + { + id: VALIDATE_KEY_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(VALIDATE_KEY_API)), + disabled: false, + method: "post", + }, + { + id: SIGN_OUT_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(SIGN_OUT_API)), + disabled: false, + method: "post", + }, + { + id: USERS_LIST_GET_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(USERS_LIST_GET_API)), + disabled: false, + method: "get", + }, + { + id: USERS_COUNT_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(USERS_COUNT_API)), + disabled: false, + method: "get", + }, + { + id: USER_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(USER_API)), + disabled: false, + method: "get", + }, + { + id: USER_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(USER_API)), + disabled: false, + method: "post", + }, + { + id: USER_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(USER_API)), + disabled: false, + method: "delete", + }, + { + id: USER_EMAIL_VERIFY_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(USER_EMAIL_VERIFY_API)), + disabled: false, + method: "get", + }, + { + id: USER_EMAIL_VERIFY_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(USER_EMAIL_VERIFY_API)), + disabled: false, + method: "put", + }, + { + id: USER_METADATA_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(USER_METADATA_API)), + disabled: false, + method: "get", + }, + { + id: USER_METADATA_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(USER_METADATA_API)), + disabled: false, + method: "put", + }, + { + id: USER_SESSIONS_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(USER_SESSIONS_API)), + disabled: false, + method: "get", + }, + { + id: USER_SESSIONS_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(USER_SESSIONS_API)), + disabled: false, + method: "post", + }, + { + id: USER_PASSWORD_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(USER_PASSWORD_API)), + disabled: false, + method: "put", + }, + { + id: USER_EMAIL_VERIFY_TOKEN_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(USER_EMAIL_VERIFY_TOKEN_API)), + disabled: false, + method: "post", + }, + { + id: SEARCH_TAGS_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(SEARCH_TAGS_API)), + disabled: false, + method: "get", + }, + { + id: DASHBOARD_ANALYTICS_API, + pathWithoutApiBasePath: new NormalisedURLPath(getApiPathWithDashboardBase(DASHBOARD_ANALYTICS_API)), + disabled: false, + method: "post", + }, + ]; }; handleAPIRequest = async ( @@ -143,6 +267,10 @@ export default class Recipe extends RecipeModule { return await dashboard(this.apiImpl, options); } + if (id === SIGN_IN_API) { + return await signIn(this.apiImpl, options); + } + if (id === VALIDATE_KEY_API) { return await validateKey(this.apiImpl, options); } @@ -194,6 +322,12 @@ export default class Recipe extends RecipeModule { apiFunction = userPasswordPut; } else if (id === USER_EMAIL_VERIFY_TOKEN_API) { apiFunction = userEmailVerifyTokenPost; + } else if (id === SEARCH_TAGS_API) { + apiFunction = getSearchTags; + } else if (id === SIGN_OUT_API) { + apiFunction = signOut; + } else if (id === DASHBOARD_ANALYTICS_API && req.getMethod() === "post") { + apiFunction = analyticsPost; } // If the id doesnt match any APIs return false diff --git a/lib/ts/recipe/dashboard/recipeImplementation.ts b/lib/ts/recipe/dashboard/recipeImplementation.ts index 16fc302a3..d40b8297f 100644 --- a/lib/ts/recipe/dashboard/recipeImplementation.ts +++ b/lib/ts/recipe/dashboard/recipeImplementation.ts @@ -13,8 +13,11 @@ * under the License. */ +import NormalisedURLPath from "../../normalisedURLPath"; +import { Querier } from "../../querier"; import { dashboardVersion } from "../../version"; import { RecipeInterface } from "./types"; +import { validateApiKey } from "./utils"; export default function getRecipeImplementation(): RecipeInterface { return { @@ -22,16 +25,20 @@ export default function getRecipeImplementation(): RecipeInterface { return `https://cdn.jsdelivr.net/gh/supertokens/dashboard@v${dashboardVersion}/build/`; }, shouldAllowAccess: async function (input) { - let apiKeyHeaderValue: string | undefined = input.req.getHeaderValue("authorization"); - - // We receieve the api key as `Bearer API_KEY`, this retrieves just the key - apiKeyHeaderValue = apiKeyHeaderValue?.split(" ")[1]; - - if (apiKeyHeaderValue === undefined) { - return false; + // For cases where we're not using the API key, the JWT is being used; we allow their access by default + if (!input.config.apiKey) { + // make the check for the API endpoint here with querier + let querier = Querier.getNewInstanceOrThrowError(undefined); + const authHeaderValue = input.req.getHeaderValue("authorization")?.split(" ")[1]; + const sessionVerificationResponse = await querier.sendPostRequest( + new NormalisedURLPath("/recipe/dashboard/session/verify"), + { + sessionId: authHeaderValue, + } + ); + return sessionVerificationResponse.status === "OK"; } - - return apiKeyHeaderValue === input.config.apiKey; + return await validateApiKey(input); }, }; } diff --git a/lib/ts/recipe/dashboard/types.ts b/lib/ts/recipe/dashboard/types.ts index ac1b7598b..b5324d356 100644 --- a/lib/ts/recipe/dashboard/types.ts +++ b/lib/ts/recipe/dashboard/types.ts @@ -18,7 +18,7 @@ import { BaseRequest, BaseResponse } from "../../framework"; import { NormalisedAppinfo } from "../../types"; export type TypeInput = { - apiKey: string; + apiKey?: string; override?: { functions?: ( originalImplementation: RecipeInterface, @@ -29,7 +29,8 @@ export type TypeInput = { }; export type TypeNormalisedInput = { - apiKey: string; + apiKey?: string; + authMode: AuthMode; override: { functions: ( originalImplementation: RecipeInterface, @@ -62,6 +63,8 @@ export type APIFunction = (apiImplementation: APIInterface, options: APIOptions) export type RecipeIdForUser = "emailpassword" | "thirdparty" | "passwordless"; +export type AuthMode = "api-key" | "email-password"; + export type RecipeLevelUser = { recipeId: "emailpassword" | "thirdparty" | "passwordless"; timeJoined: number; diff --git a/lib/ts/recipe/dashboard/utils.ts b/lib/ts/recipe/dashboard/utils.ts index 55507a4e3..3a1945f98 100644 --- a/lib/ts/recipe/dashboard/utils.ts +++ b/lib/ts/recipe/dashboard/utils.ts @@ -13,12 +13,15 @@ * under the License. */ -import { BaseResponse } from "../../framework"; +import { BaseRequest, BaseResponse } from "../../framework"; import NormalisedURLPath from "../../normalisedURLPath"; import { HTTPMethod, NormalisedAppinfo } from "../../types"; import { sendNon200ResponseWithMessage } from "../../utils"; import { DASHBOARD_API, + SEARCH_TAGS_API, + SIGN_IN_API, + SIGN_OUT_API, USERS_COUNT_API, USERS_LIST_GET_API, USER_API, @@ -28,6 +31,7 @@ import { USER_PASSWORD_API, USER_SESSIONS_API, VALIDATE_KEY_API, + DASHBOARD_ANALYTICS_API, } from "./constants"; import { APIInterface, @@ -48,20 +52,16 @@ import ThirdParty from "../thirdparty"; import Passwordless from "../passwordless"; import ThirdPartyPasswordless from "../thirdpartypasswordless"; -export function validateAndNormaliseUserInput(config: TypeInput): TypeNormalisedInput { - if (config.apiKey.trim().length === 0) { - throw new Error("apiKey provided to Dashboard recipe cannot be empty"); - } - +export function validateAndNormaliseUserInput(config?: TypeInput): TypeNormalisedInput { let override = { functions: (originalImplementation: RecipeInterface) => originalImplementation, apis: (originalImplementation: APIInterface) => originalImplementation, - ...config.override, + ...(config === undefined ? {} : config.override), }; return { - apiKey: config.apiKey, override, + authMode: config !== undefined && config.apiKey ? "api-key" : "email-password", }; } @@ -89,6 +89,14 @@ export function getApiIdIfMatched(path: NormalisedURLPath, method: HTTPMethod): return VALIDATE_KEY_API; } + if (path.getAsStringDangerous().endsWith(SIGN_IN_API) && method === "post") { + return SIGN_IN_API; + } + + if (path.getAsStringDangerous().endsWith(SIGN_OUT_API) && method === "post") { + return SIGN_OUT_API; + } + if (path.getAsStringDangerous().endsWith(USERS_LIST_GET_API) && method === "get") { return USERS_LIST_GET_API; } @@ -132,6 +140,13 @@ export function getApiIdIfMatched(path: NormalisedURLPath, method: HTTPMethod): if (path.getAsStringDangerous().endsWith(USER_PASSWORD_API) && method === "put") { return USER_PASSWORD_API; } + if (path.getAsStringDangerous().endsWith(SEARCH_TAGS_API) && method === "get") { + return SEARCH_TAGS_API; + } + + if (path.getAsStringDangerous().endsWith(DASHBOARD_ANALYTICS_API) && method === "post") { + return DASHBOARD_ANALYTICS_API; + } return undefined; } @@ -377,3 +392,20 @@ export function isRecipeInitialised(recipeId: RecipeIdForUser): boolean { return isRecipeInitialised; } + +export async function validateApiKey(input: { req: BaseRequest; config: TypeNormalisedInput; userContext: any }) { + let apiKeyHeaderValue: string | undefined = input.req.getHeaderValue("authorization"); + + // We receieve the api key as `Bearer API_KEY`, this retrieves just the key + apiKeyHeaderValue = apiKeyHeaderValue?.split(" ")[1]; + + if (apiKeyHeaderValue === undefined) { + return false; + } + + return apiKeyHeaderValue === input.config.apiKey; +} + +export function getApiPathWithDashboardBase(path: string): string { + return DASHBOARD_API + path; +} diff --git a/lib/ts/recipe/emailpassword/api/implementation.ts b/lib/ts/recipe/emailpassword/api/implementation.ts index 404c70b06..f28173102 100644 --- a/lib/ts/recipe/emailpassword/api/implementation.ts +++ b/lib/ts/recipe/emailpassword/api/implementation.ts @@ -402,6 +402,7 @@ export default function getAPIImplementation(): APIInterface { email: string; } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" } + | { status: "PASSWORD_POLICY_VIOLATED_ERROR"; failureReason: string } | GeneralErrorResponse > { async function markEmailAsVerified(userId: string, email: string) { @@ -431,6 +432,7 @@ export default function getAPIImplementation(): APIInterface { email: string; } | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR" } + | { status: "PASSWORD_POLICY_VIOLATED_ERROR"; failureReason: string } | GeneralErrorResponse > { let updateResponse = await options.recipeImplementation.updateEmailOrPassword({ @@ -449,6 +451,11 @@ export default function getAPIImplementation(): APIInterface { return { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR", }; + } else if (updateResponse.status === "PASSWORD_POLICY_VIOLATED_ERROR") { + return { + status: "PASSWORD_POLICY_VIOLATED_ERROR", + failureReason: updateResponse.failureReason, + }; } else { // status: "OK" return { @@ -457,9 +464,6 @@ export default function getAPIImplementation(): APIInterface { email: emailForWhomTokenWasGenerated, }; } - // TODO: we need to also handle password policy error. Note that this needs - // to happen in the api file (before this function is called) as well - // cause we don't want to consume the token unnecessarily. } let newPassword = formFields.filter((f) => f.id === "password")[0].value; diff --git a/lib/ts/recipe/emailpassword/api/passwordReset.ts b/lib/ts/recipe/emailpassword/api/passwordReset.ts index 70f5c6dd6..a89234bcb 100644 --- a/lib/ts/recipe/emailpassword/api/passwordReset.ts +++ b/lib/ts/recipe/emailpassword/api/passwordReset.ts @@ -59,6 +59,21 @@ export default async function passwordReset(apiImplementation: APIInterface, opt userContext: makeDefaultUserContextFromAPI(options.req), }); + if (result.status === "PASSWORD_POLICY_VIOLATED_ERROR") { + // this error will be caught by the recipe error handler, just + // like it's done in the validateFormFieldsOrThrowError function above. + throw new STError({ + type: STError.FIELD_ERROR, + payload: [ + { + id: "password", + error: result.failureReason, + }, + ], + message: "Error in input formFields", + }); + } + send200Response( options.res, result.status === "OK" diff --git a/lib/ts/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.ts b/lib/ts/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.ts index ad04756ff..2c69d1993 100644 --- a/lib/ts/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.ts +++ b/lib/ts/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.ts @@ -933,7 +933,6 @@ export function getPasswordResetEmailHTML(appName: string, email: string, resetL - diff --git a/lib/ts/recipe/emailpassword/index.ts b/lib/ts/recipe/emailpassword/index.ts index 89c98a471..563742791 100644 --- a/lib/ts/recipe/emailpassword/index.ts +++ b/lib/ts/recipe/emailpassword/index.ts @@ -65,7 +65,13 @@ export default class Wrapper { }); } - static updateEmailOrPassword(input: { userId: string; email?: string; password?: string; userContext?: any }) { + static updateEmailOrPassword(input: { + userId: string; + email?: string; + password?: string; + userContext?: any; + applyPasswordPolicy?: boolean; + }) { return Recipe.getInstanceOrThrowError().recipeInterfaceImpl.updateEmailOrPassword({ userContext: {}, ...input, diff --git a/lib/ts/recipe/emailpassword/recipe.ts b/lib/ts/recipe/emailpassword/recipe.ts index 13ded1267..d4f0c44a6 100644 --- a/lib/ts/recipe/emailpassword/recipe.ts +++ b/lib/ts/recipe/emailpassword/recipe.ts @@ -72,7 +72,10 @@ export default class Recipe extends RecipeModule { this.isInServerlessEnv = isInServerlessEnv; this.config = validateAndNormaliseUserInput(this, appInfo, config); { - let builder = new OverrideableBuilder(RecipeImplementation(Querier.getNewInstanceOrThrowError(recipeId))); + const getEmailPasswordConfig = () => this.config; + let builder = new OverrideableBuilder( + RecipeImplementation(Querier.getNewInstanceOrThrowError(recipeId), getEmailPasswordConfig) + ); this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); } { diff --git a/lib/ts/recipe/emailpassword/recipeImplementation.ts b/lib/ts/recipe/emailpassword/recipeImplementation.ts index fbb4a74c0..542b996ee 100644 --- a/lib/ts/recipe/emailpassword/recipeImplementation.ts +++ b/lib/ts/recipe/emailpassword/recipeImplementation.ts @@ -1,11 +1,15 @@ -import { RecipeInterface } from "./types"; +import { RecipeInterface, TypeNormalisedInput } from "./types"; import AccountLinking from "../accountlinking/recipe"; import { Querier } from "../../querier"; import NormalisedURLPath from "../../normalisedURLPath"; import { getUser } from "../.."; import { User } from "../../types"; +import { FORM_FIELD_PASSWORD_ID } from "./constants"; -export default function getRecipeInterface(querier: Querier): RecipeInterface { +export default function getRecipeInterface( + querier: Querier, + getEmailPasswordConfig: () => TypeNormalisedInput +): RecipeInterface { return { signUp: async function ( this: RecipeInterface, @@ -112,6 +116,7 @@ export default function getRecipeInterface(querier: Querier): RecipeInterface { userId: string; email?: string; password?: string; + applyPasswordPolicy?: boolean; }): Promise< | { status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR"; @@ -120,8 +125,21 @@ export default function getRecipeInterface(querier: Querier): RecipeInterface { status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; reason: string; } + | { status: "PASSWORD_POLICY_VIOLATED_ERROR"; failureReason: string } > { - // the input can be primary or recipe level user id. + if (input.applyPasswordPolicy || input.applyPasswordPolicy === undefined) { + let formFields = getEmailPasswordConfig().signUpFeature.formFields; + if (input.password !== undefined) { + const passwordField = formFields.filter((el) => el.id === FORM_FIELD_PASSWORD_ID)[0]; + const error = await passwordField.validate(input.password); + if (error !== undefined) { + return { + status: "PASSWORD_POLICY_VIOLATED_ERROR", + failureReason: error, + }; + } + } + } return await querier.sendPutRequest(new NormalisedURLPath("/recipe/user"), { userId: input.userId, email: input.email, diff --git a/lib/ts/recipe/emailpassword/types.ts b/lib/ts/recipe/emailpassword/types.ts index 0fcba1e68..85c2c8392 100644 --- a/lib/ts/recipe/emailpassword/types.ts +++ b/lib/ts/recipe/emailpassword/types.ts @@ -143,6 +143,7 @@ export type RecipeInterface = { email?: string; password?: string; userContext: any; + applyPasswordPolicy?: boolean; }): Promise< | { status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR"; @@ -151,6 +152,7 @@ export type RecipeInterface = { status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; reason: string; } + | { status: "PASSWORD_POLICY_VIOLATED_ERROR"; failureReason: string } >; }; @@ -219,6 +221,7 @@ export type APIInterface = { | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR"; } + | { status: "PASSWORD_POLICY_VIOLATED_ERROR"; failureReason: string } | GeneralErrorResponse >); diff --git a/lib/ts/recipe/emailverification/emaildelivery/services/smtp/emailVerify.ts b/lib/ts/recipe/emailverification/emaildelivery/services/smtp/emailVerify.ts index 1844477c5..c9dd89285 100644 --- a/lib/ts/recipe/emailverification/emaildelivery/services/smtp/emailVerify.ts +++ b/lib/ts/recipe/emailverification/emaildelivery/services/smtp/emailVerify.ts @@ -862,7 +862,7 @@ export function getEmailVerifyEmailHTML(appName: string, email: string, verifica

    + style="max-width: 600px !important; margin: auto; font-family: 'Hevetica', sans-serif; font-size: 14px; line-height: 23px; font-weight:400; text-align: center; color: #808080;"> Alternatively, you can directly paste this link in your browser
    - diff --git a/lib/ts/recipe/jwt/api/getJWKS.ts b/lib/ts/recipe/jwt/api/getJWKS.ts index 81f38fddd..642fe5cb4 100644 --- a/lib/ts/recipe/jwt/api/getJWKS.ts +++ b/lib/ts/recipe/jwt/api/getJWKS.ts @@ -26,10 +26,10 @@ export default async function getJWKS(apiImplementation: APIInterface, options: options, userContext: makeDefaultUserContextFromAPI(options.req), }); - if (result.status === "OK") { - options.res.setHeader("Access-Control-Allow-Origin", "*", false); - send200Response(options.res, { keys: result.keys }); + if ("status" in result && result.status === "GENERAL_ERROR") { + send200Response(options.res, result); } else { + options.res.setHeader("Access-Control-Allow-Origin", "*", false); send200Response(options.res, result); } return true; diff --git a/lib/ts/recipe/jwt/api/implementation.ts b/lib/ts/recipe/jwt/api/implementation.ts index e6a48a9e6..089ed67d5 100644 --- a/lib/ts/recipe/jwt/api/implementation.ts +++ b/lib/ts/recipe/jwt/api/implementation.ts @@ -24,7 +24,7 @@ export default function getAPIImplementation(): APIInterface { }: { options: APIOptions; userContext: any; - }): Promise<{ status: "OK"; keys: JsonWebKey[] } | GeneralErrorResponse> { + }): Promise<{ keys: JsonWebKey[] } | GeneralErrorResponse> { return await options.recipeImplementation.getJWKS({ userContext }); }, }; diff --git a/lib/ts/recipe/jwt/index.ts b/lib/ts/recipe/jwt/index.ts index 147e7ce0e..7e3c39022 100644 --- a/lib/ts/recipe/jwt/index.ts +++ b/lib/ts/recipe/jwt/index.ts @@ -19,10 +19,11 @@ import { APIInterface, RecipeInterface, APIOptions, JsonWebKey } from "./types"; export default class Wrapper { static init = Recipe.init; - static async createJWT(payload: any, validitySeconds?: number, userContext?: any) { + static async createJWT(payload: any, validitySeconds?: number, useStaticSigningKey?: boolean, userContext?: any) { return await Recipe.getInstanceOrThrowError().recipeInterfaceImpl.createJWT({ payload, validitySeconds, + useStaticSigningKey, userContext: userContext === undefined ? {} : userContext, }); } diff --git a/lib/ts/recipe/jwt/recipeImplementation.ts b/lib/ts/recipe/jwt/recipeImplementation.ts index 5e7ce2e47..5f07a448e 100644 --- a/lib/ts/recipe/jwt/recipeImplementation.ts +++ b/lib/ts/recipe/jwt/recipeImplementation.ts @@ -27,8 +27,10 @@ export default function getRecipeInterface( createJWT: async function ({ payload, validitySeconds, + useStaticSigningKey, }: { payload?: any; + useStaticSigningKey?: boolean; validitySeconds?: number; }): Promise< | { @@ -47,6 +49,7 @@ export default function getRecipeInterface( let response = await querier.sendPostRequest(new NormalisedURLPath("/recipe/jwt"), { payload: payload ?? {}, validity: validitySeconds, + useStaticSigningKey: useStaticSigningKey !== false, algorithm: "RS256", jwksDomain: appInfo.apiDomain.getAsStringDangerous(), }); @@ -63,8 +66,8 @@ export default function getRecipeInterface( } }, - getJWKS: async function (): Promise<{ status: "OK"; keys: JsonWebKey[] }> { - return await querier.sendGetRequest(new NormalisedURLPath("/recipe/jwt/jwks"), {}); + getJWKS: async function (): Promise<{ keys: JsonWebKey[] }> { + return await querier.sendGetRequest(new NormalisedURLPath("/.well-known/jwks.json"), {}); }, }; } diff --git a/lib/ts/recipe/jwt/types.ts b/lib/ts/recipe/jwt/types.ts index 49b7fb57c..805641f6d 100644 --- a/lib/ts/recipe/jwt/types.ts +++ b/lib/ts/recipe/jwt/types.ts @@ -61,6 +61,7 @@ export type RecipeInterface = { createJWT(input: { payload?: any; validitySeconds?: number; + useStaticSigningKey?: boolean; userContext: any; }): Promise< | { @@ -75,7 +76,6 @@ export type RecipeInterface = { getJWKS(input: { userContext: any; }): Promise<{ - status: "OK"; keys: JsonWebKey[]; }>; }; @@ -86,5 +86,5 @@ export type APIInterface = { | ((input: { options: APIOptions; userContext: any; - }) => Promise<{ status: "OK"; keys: JsonWebKey[] } | GeneralErrorResponse>); + }) => Promise<{ keys: JsonWebKey[] } | GeneralErrorResponse>); }; diff --git a/lib/ts/recipe/openid/index.ts b/lib/ts/recipe/openid/index.ts index c90b414a7..23d835b39 100644 --- a/lib/ts/recipe/openid/index.ts +++ b/lib/ts/recipe/openid/index.ts @@ -9,10 +9,11 @@ export default class OpenIdRecipeWrapper { }); } - static createJWT(payload?: any, validitySeconds?: number, userContext?: any) { + static createJWT(payload?: any, validitySeconds?: number, useStaticSigningKey?: boolean, userContext?: any) { return OpenIdRecipe.getInstanceOrThrowError().jwtRecipe.recipeInterfaceImpl.createJWT({ payload, validitySeconds, + useStaticSigningKey, userContext: userContext === undefined ? {} : userContext, }); } diff --git a/lib/ts/recipe/openid/recipeImplementation.ts b/lib/ts/recipe/openid/recipeImplementation.ts index a5529e32a..c79fde8be 100644 --- a/lib/ts/recipe/openid/recipeImplementation.ts +++ b/lib/ts/recipe/openid/recipeImplementation.ts @@ -40,10 +40,12 @@ export default function getRecipeInterface( createJWT: async function ({ payload, validitySeconds, + useStaticSigningKey, userContext, }: { payload?: any; validitySeconds?: number; + useStaticSigningKey?: boolean; userContext: any; }): Promise< | { @@ -62,11 +64,12 @@ export default function getRecipeInterface( iss: issuer, ...payload, }, + useStaticSigningKey, validitySeconds, userContext, }); }, - getJWKS: async function (input): Promise<{ status: "OK"; keys: JsonWebKey[] }> { + getJWKS: async function (input): Promise<{ keys: JsonWebKey[] }> { return await jwtRecipeImplementation.getJWKS(input); }, }; diff --git a/lib/ts/recipe/openid/types.ts b/lib/ts/recipe/openid/types.ts index 70168efa5..b3ade8a79 100644 --- a/lib/ts/recipe/openid/types.ts +++ b/lib/ts/recipe/openid/types.ts @@ -99,6 +99,7 @@ export type RecipeInterface = { createJWT(input: { payload?: any; validitySeconds?: number; + useStaticSigningKey?: boolean; userContext: any; }): Promise< | { @@ -113,7 +114,6 @@ export type RecipeInterface = { getJWKS(input: { userContext: any; }): Promise<{ - status: "OK"; keys: JsonWebKey[]; }>; }; diff --git a/lib/ts/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.ts b/lib/ts/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.ts index 3823e56d3..10760d733 100644 --- a/lib/ts/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.ts +++ b/lib/ts/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.ts @@ -936,7 +936,6 @@ function getPasswordlessLoginOTPBody(appName: string, email: string, codeLifetim - @@ -1865,7 +1864,6 @@ function getPasswordlessLoginURLLinkBody( - @@ -2856,7 +2854,6 @@ function getPasswordlessLoginOTPAndURLLinkBody( - diff --git a/lib/ts/recipe/session/accessToken.ts b/lib/ts/recipe/session/accessToken.ts index 244f596ba..1ae9f5e2b 100644 --- a/lib/ts/recipe/session/accessToken.ts +++ b/lib/ts/recipe/session/accessToken.ts @@ -14,11 +14,13 @@ */ import STError from "./error"; -import { ParsedJWTInfo, verifyJWT } from "./jwt"; +import { ParsedJWTInfo } from "./jwt"; +import * as jose from "jose"; +import { ProcessState, PROCESS_STATE } from "../../processState"; export async function getInfoFromAccessToken( jwtInfo: ParsedJWTInfo, - jwtSigningPublicKey: string, + jwks: jose.JWTVerifyGetKey, doAntiCsrfCheck: boolean ): Promise<{ sessionHandle: string; @@ -32,22 +34,52 @@ export async function getInfoFromAccessToken( timeCreated: number; }> { try { - verifyJWT(jwtInfo, jwtSigningPublicKey); - const payload = jwtInfo.payload; + // From the library examples + let payload = undefined; + try { + payload = (await jose.jwtVerify(jwtInfo.rawTokenString, jwks)).payload; + } catch (error) { + // We only want to opt-into this for V2 access tokens + if (jwtInfo.version === 2 && error?.code === "ERR_JWKS_MULTIPLE_MATCHING_KEYS") { + ProcessState.getInstance().addState(PROCESS_STATE.MULTI_JWKS_VALIDATION); + // We are trying to validate the token with each key. + // Since the kid is missing from v2 tokens, this basically means we try all keys present in the cache. + for await (const publicKey of error) { + try { + payload = (await jose.jwtVerify(jwtInfo.rawTokenString, publicKey)).payload; + break; + } catch (innerError) { + if (innerError?.code === "ERR_JWS_SIGNATURE_VERIFICATION_FAILED") { + continue; + } + throw innerError; + } + } + if (payload === undefined) { + throw new jose.errors.JWSSignatureVerificationFailed(); + } + } else { + throw error; + } + } // This should be called before this function, but the check is very quick, so we can also do them here - validateAccessTokenStructure(payload); + validateAccessTokenStructure(payload, jwtInfo.version); // We can mark these as defined (the ! after the calls), since validateAccessTokenPayload checks this + let userId = jwtInfo.version === 2 ? sanitizeStringInput(payload.userId)! : sanitizeStringInput(payload.sub)!; + let expiryTime = + jwtInfo.version === 2 ? sanitizeNumberInput(payload.expiryTime)! : sanitizeNumberInput(payload.exp)! * 1000; + let timeCreated = + jwtInfo.version === 2 + ? sanitizeNumberInput(payload.timeCreated)! + : sanitizeNumberInput(payload.iat)! * 1000; + let userData = jwtInfo.version === 2 ? payload.userData : payload; let sessionHandle = sanitizeStringInput(payload.sessionHandle)!; - let userId = sanitizeStringInput(payload.userId)!; let recipeUserId = sanitizeStringInput(payload.recipeUserId)!; let refreshTokenHash1 = sanitizeStringInput(payload.refreshTokenHash1)!; let parentRefreshTokenHash1 = sanitizeStringInput(payload.parentRefreshTokenHash1); - let userData = payload.userData; let antiCsrfToken = sanitizeStringInput(payload.antiCsrfToken); - let expiryTime = sanitizeNumberInput(payload.expiryTime)!; - let timeCreated = sanitizeNumberInput(payload.timeCreated)!; if (antiCsrfToken === undefined && doAntiCsrfCheck) { throw Error("Access token does not contain the anti-csrf token."); @@ -75,8 +107,19 @@ export async function getInfoFromAccessToken( } } -export function validateAccessTokenStructure(payload: any) { - if ( +export function validateAccessTokenStructure(payload: any, version: number) { + if (version >= 3) { + if ( + typeof payload.sub !== "string" || + typeof payload.exp !== "number" || + typeof payload.iat !== "number" || + typeof payload.sessionHandle !== "string" || + typeof payload.refreshTokenHash1 !== "string" + ) { + // it would come here if we change the structure of the JWT. + throw Error("Access token does not contain all the information. Maybe the structure has changed?"); + } + } else if ( typeof payload.sessionHandle !== "string" || typeof payload.userId !== "string" || typeof payload.recipeUserId !== "string" || diff --git a/lib/ts/recipe/session/api/implementation.ts b/lib/ts/recipe/session/api/implementation.ts index 1d54fcb7a..224ff5d36 100644 --- a/lib/ts/recipe/session/api/implementation.ts +++ b/lib/ts/recipe/session/api/implementation.ts @@ -3,7 +3,7 @@ import { normaliseHttpMethod } from "../../../utils"; import NormalisedURLPath from "../../../normalisedURLPath"; import { SessionContainerInterface } from "../types"; import { GeneralErrorResponse } from "../../../types"; -import { getRequiredClaimValidators } from "../utils"; +import { getSessionFromRequest, refreshSessionInRequest } from "../sessionRequestFunctions"; export default function getAPIInterface(): APIInterface { return { @@ -14,10 +14,12 @@ export default function getAPIInterface(): APIInterface { options: APIOptions; userContext: any; }): Promise { - return await options.recipeImplementation.refreshSession({ + return refreshSessionInRequest({ req: options.req, res: options.res, userContext, + config: options.config, + recipeInterfaceImpl: options.recipeImplementation, }); }, @@ -40,29 +42,22 @@ export default function getAPIInterface(): APIInterface { let refreshTokenPath = options.config.refreshTokenPath; if (incomingPath.equals(refreshTokenPath) && method === "post") { - return options.recipeImplementation.refreshSession({ + return refreshSessionInRequest({ req: options.req, res: options.res, userContext, + config: options.config, + recipeInterfaceImpl: options.recipeImplementation, }); } else { - const session = await options.recipeImplementation.getSession({ + return getSessionFromRequest({ req: options.req, res: options.res, options: verifySessionOptions, + config: options.config, + recipeInterfaceImpl: options.recipeImplementation, userContext, }); - if (session !== undefined) { - const claimValidators = await getRequiredClaimValidators( - session, - verifySessionOptions?.overrideGlobalClaimValidators, - userContext - ); - - await session.assertClaims(claimValidators, userContext); - } - - return session; } }, diff --git a/lib/ts/recipe/session/api/signout.ts b/lib/ts/recipe/session/api/signout.ts index 12702f3f9..dd0ed4a4e 100644 --- a/lib/ts/recipe/session/api/signout.ts +++ b/lib/ts/recipe/session/api/signout.ts @@ -16,6 +16,7 @@ import { send200Response } from "../../../utils"; import { APIInterface, APIOptions } from "../"; import { makeDefaultUserContextFromAPI } from "../../../utils"; +import { getSessionFromRequest } from "../sessionRequestFunctions"; export default async function signOutAPI(apiImplementation: APIInterface, options: APIOptions): Promise { // Logic as per https://github.com/supertokens/supertokens-node/issues/34#issuecomment-717958537 @@ -26,9 +27,11 @@ export default async function signOutAPI(apiImplementation: APIInterface, option let defaultUserContext = makeDefaultUserContextFromAPI(options.req); - const session = await options.recipeImplementation.getSession({ + const session = await getSessionFromRequest({ req: options.req, res: options.res, + config: options.config, + recipeInterfaceImpl: options.recipeImplementation, options: { sessionRequired: false, overrideGlobalClaimValidators: () => [], diff --git a/lib/ts/recipe/session/constants.ts b/lib/ts/recipe/session/constants.ts index a8a5fb90e..d6e8ac58a 100644 --- a/lib/ts/recipe/session/constants.ts +++ b/lib/ts/recipe/session/constants.ts @@ -19,3 +19,5 @@ export const REFRESH_API_PATH = "/session/refresh"; export const SIGNOUT_API_PATH = "/signout"; export const availableTokenTransferMethods: TokenTransferMethod[] = ["cookie", "header"]; + +export const hundredYearsInMs = 3153600000000; diff --git a/lib/ts/recipe/session/cookieAndHeaders.ts b/lib/ts/recipe/session/cookieAndHeaders.ts index 480fea2a2..c41980f96 100644 --- a/lib/ts/recipe/session/cookieAndHeaders.ts +++ b/lib/ts/recipe/session/cookieAndHeaders.ts @@ -14,6 +14,7 @@ */ import { HEADER_RID } from "../../constants"; import { BaseRequest, BaseResponse } from "../../framework"; +import { logDebugMessage } from "../../logger"; import { availableTokenTransferMethods } from "./constants"; import { TokenTransferMethod, TokenType, TypeNormalisedInput } from "./types"; @@ -63,13 +64,17 @@ export function setAntiCsrfTokenInHeaders(res: BaseResponse, antiCsrfToken: stri res.setHeader("Access-Control-Expose-Headers", antiCsrfHeaderKey, true); } -export function setFrontTokenInHeaders(res: BaseResponse, userId: string, atExpiry: number, accessTokenPayload: any) { +export function buildFrontToken(userId: string, atExpiry: number, accessTokenPayload: any) { const tokenInfo = { uid: userId, ate: atExpiry, up: accessTokenPayload, }; - res.setHeader(frontTokenHeaderKey, Buffer.from(JSON.stringify(tokenInfo)).toString("base64"), false); + return Buffer.from(JSON.stringify(tokenInfo)).toString("base64"); +} + +export function setFrontTokenInHeaders(res: BaseResponse, frontToken: string) { + res.setHeader(frontTokenHeaderKey, frontToken, false); res.setHeader("Access-Control-Expose-Headers", frontTokenHeaderKey, true); } @@ -122,6 +127,7 @@ export function setToken( expires: number, transferMethod: TokenTransferMethod ) { + logDebugMessage(`setToken: Setting ${tokenType} token as ${transferMethod}`); if (transferMethod === "cookie") { setCookie( config, @@ -167,7 +173,8 @@ export function setCookie( if (pathType === "refreshTokenPath") { path = config.refreshTokenPath.getAsStringDangerous(); } else if (pathType === "accessTokenPath") { - path = "/"; + path = + config.accessTokenPath.getAsStringDangerous() === "" ? "/" : config.accessTokenPath.getAsStringDangerous(); } let httpOnly = true; diff --git a/lib/ts/recipe/session/index.ts b/lib/ts/recipe/session/index.ts index cf8ff9a75..9cc292105 100644 --- a/lib/ts/recipe/session/index.ts +++ b/lib/ts/recipe/session/index.ts @@ -16,7 +16,6 @@ import SuperTokensError from "./error"; import { VerifySessionOptions, - RecipeInterface, SessionContainerInterface as SessionContainer, SessionInformation, APIInterface, @@ -24,14 +23,12 @@ import { SessionClaimValidator, SessionClaim, ClaimValidationError, + RecipeInterface, } from "./types"; -import OpenIdRecipe from "../openid/recipe"; import Recipe from "./recipe"; import { JSONObject } from "../../types"; -import frameworks from "../../framework"; -import SuperTokens from "../../supertokens"; import { getRequiredClaimValidators } from "./utils"; - +import { createNewSessionInRequest, getSessionFromRequest, refreshSessionInRequest } from "./sessionRequestFunctions"; // For Express export default class SessionWrapper { static init = Recipe.init; @@ -44,12 +41,44 @@ export default class SessionWrapper { userId: string, recipeUserId?: string, accessTokenPayload: any = {}, - sessionData: any = {}, + sessionDataInDatabase: any = {}, userContext: any = {} ) { - const claimsAddedByOtherRecipes = Recipe.getInstanceOrThrowError().getClaimsAddedByOtherRecipes(); + const recipeInstance = Recipe.getInstanceOrThrowError(); + const config = recipeInstance.config; + const appInfo = recipeInstance.getAppInfo(); - let finalAccessTokenPayload = accessTokenPayload; + return await createNewSessionInRequest({ + req, + res, + userContext, + recipeInstance, + accessTokenPayload, + userId, + recipeUserId, + config, + appInfo, + sessionDataInDatabase, + }); + } + + static async createNewSessionWithoutRequestResponse( + userId: string, + recipeUserId?: string, + accessTokenPayload: any = {}, + sessionDataInDatabase: any = {}, + disableAntiCsrf: boolean = false, + userContext: any = {} + ) { + const recipeInstance = Recipe.getInstanceOrThrowError(); + const claimsAddedByOtherRecipes = recipeInstance.getClaimsAddedByOtherRecipes(); + const appInfo = recipeInstance.getAppInfo(); + const issuer = appInfo.apiDomain.getAsStringDangerous() + appInfo.apiBasePath.getAsStringDangerous(); + + let finalAccessTokenPayload = { + ...accessTokenPayload, + iss: issuer, + }; for (const claim of claimsAddedByOtherRecipes) { const update = await claim.build(userId, recipeUserId, userContext); @@ -59,20 +88,12 @@ export default class SessionWrapper { }; } - if (!req.wrapperUsed) { - req = frameworks[SuperTokens.getInstanceOrThrowError().framework].wrapRequest(req); - } - - if (!res.wrapperUsed) { - res = frameworks[SuperTokens.getInstanceOrThrowError().framework].wrapResponse(res); - } return Recipe.getInstanceOrThrowError().recipeInterfaceImpl.createNewSession({ - req, - res, userId, recipeUserId, accessTokenPayload: finalAccessTokenPayload, - sessionData, + sessionDataInDatabase, + disableAntiCsrf, userContext, }); } @@ -122,7 +143,7 @@ export default class SessionWrapper { let claimValidationResponse = await recipeImpl.validateClaims({ userId: sessionInfo.userId, recipeUserId: sessionInfo.recipeUserId, - accessTokenPayload: sessionInfo.accessTokenPayload, + accessTokenPayload: sessionInfo.customClaimsInAccessTokenPayload, claimValidators, userContext, }); @@ -159,15 +180,82 @@ export default class SessionWrapper { options?: VerifySessionOptions & { sessionRequired: false }, userContext?: any ): Promise; - static async getSession(req: any, res: any, options?: VerifySessionOptions, userContext: any = {}) { - if (!res.wrapperUsed) { - res = frameworks[SuperTokens.getInstanceOrThrowError().framework].wrapResponse(res); - } - if (!req.wrapperUsed) { - req = frameworks[SuperTokens.getInstanceOrThrowError().framework].wrapRequest(req); - } + static getSession( + req: any, + res: any, + options?: VerifySessionOptions, + userContext?: any + ): Promise; + static async getSession(req: any, res: any, options?: VerifySessionOptions, userContext?: any) { + const recipeInstance = Recipe.getInstanceOrThrowError(); + const config = recipeInstance.config; + const recipeInterfaceImpl = recipeInstance.recipeInterfaceImpl; + + return getSessionFromRequest({ + req, + res, + recipeInterfaceImpl, + config, + options, + userContext, + }); + } + + /** + * Tries to validate an access token and build a Session object from it. + * + * Notes about anti-csrf checking: + * - if the `antiCsrf` is set to VIA_HEADER in the Session recipe config you have to handle anti-csrf checking before calling this function and set antiCsrfCheck to false in the options. + * - you can disable anti-csrf checks by setting antiCsrf to NONE in the Session recipe config. We only recommend this if you are always getting the access-token from the Authorization header. + * - if the antiCsrf check fails the returned satatus will be TRY_REFRESH_TOKEN_ERROR + * + * Results: + * OK: The session was successfully validated, including claim validation + * CLAIM_VALIDATION_ERROR: While the access token is valid, one or more claim validators have failed. Our frontend SDKs expect a 403 response the contents matching the value returned from this function. + * TRY_REFRESH_TOKEN_ERROR: This means, that the access token structure was valid, but it didn't pass validation for some reason and the user should call the refresh API. + * You can send a 401 response to trigger this behaviour if you are using our frontend SDKs + * UNAUTHORISED: This means that the access token likely doesn't belong to a SuperTokens session. If this is unexpected, it's best handled by sending a 401 response. + * + * @param accessToken The access token extracted from the authorization header or cookies + * @param antiCsrfToken The anti-csrf token extracted from the authorization header or cookies. Can be undefined if antiCsrfCheck is false + * @param options Same options objects as getSession or verifySession takes, except the `sessionRequired` prop, which is always set to true in this function + * @param userContext User context + */ + static async getSessionWithoutRequestResponse( + accessToken: string, + antiCsrfToken?: string + ): Promise; + static async getSessionWithoutRequestResponse( + accessToken: string, + antiCsrfToken?: string, + options?: VerifySessionOptions & { sessionRequired?: true }, + userContext?: any + ): Promise; + static async getSessionWithoutRequestResponse( + accessToken: string, + antiCsrfToken?: string, + options?: VerifySessionOptions & { sessionRequired: false }, + userContext?: any + ): Promise; + static async getSessionWithoutRequestResponse( + accessToken: string, + antiCsrfToken?: string, + options?: VerifySessionOptions, + userContext?: any + ): Promise; + static async getSessionWithoutRequestResponse( + accessToken: string, + antiCsrfToken?: string, + options?: VerifySessionOptions, + userContext: any = {} + ): Promise { const recipeInterfaceImpl = Recipe.getInstanceOrThrowError().recipeInterfaceImpl; - const session = await recipeInterfaceImpl.getSession({ req, res, options, userContext }); + const session = await recipeInterfaceImpl.getSession({ + accessToken, + antiCsrfToken, + options, + userContext, + }); if (session !== undefined) { const claimValidators = await getRequiredClaimValidators( @@ -175,6 +263,7 @@ export default class SessionWrapper { options?.overrideGlobalClaimValidators, userContext ); + await session.assertClaims(claimValidators, userContext); } return session; @@ -188,15 +277,26 @@ export default class SessionWrapper { } static refreshSession(req: any, res: any, userContext: any = {}) { - if (!res.wrapperUsed) { - res = frameworks[SuperTokens.getInstanceOrThrowError().framework].wrapResponse(res); - } - if (!req.wrapperUsed) { - req = frameworks[SuperTokens.getInstanceOrThrowError().framework].wrapRequest(req); - } - return Recipe.getInstanceOrThrowError().recipeInterfaceImpl.refreshSession({ req, res, userContext }); + const recipeInstance = Recipe.getInstanceOrThrowError(); + const config = recipeInstance.config; + const recipeInterfaceImpl = recipeInstance.recipeInterfaceImpl; + + return refreshSessionInRequest({ res, req, userContext, config, recipeInterfaceImpl }); } + static refreshSessionWithoutRequestResponse( + refreshToken: string, + disableAntiCsrf: boolean = false, + antiCsrfToken?: string, + userContext: any = {} + ) { + return Recipe.getInstanceOrThrowError().recipeInterfaceImpl.refreshSession({ + refreshToken, + disableAntiCsrf, + antiCsrfToken, + userContext, + }); + } static revokeAllSessionsForUser(userId: string, userContext: any = {}) { return Recipe.getInstanceOrThrowError().recipeInterfaceImpl.revokeAllSessionsForUser({ userId, userContext }); } @@ -219,30 +319,14 @@ export default class SessionWrapper { }); } - static updateSessionData(sessionHandle: string, newSessionData: any, userContext: any = {}) { - return Recipe.getInstanceOrThrowError().recipeInterfaceImpl.updateSessionData({ + static updateSessionDataInDatabase(sessionHandle: string, newSessionData: any, userContext: any = {}) { + return Recipe.getInstanceOrThrowError().recipeInterfaceImpl.updateSessionDataInDatabase({ sessionHandle, newSessionData, userContext, }); } - static regenerateAccessToken(accessToken: string, newAccessTokenPayload?: any, userContext: any = {}) { - return Recipe.getInstanceOrThrowError().recipeInterfaceImpl.regenerateAccessToken({ - accessToken, - newAccessTokenPayload, - userContext, - }); - } - - static updateAccessTokenPayload(sessionHandle: string, newAccessTokenPayload: any, userContext: any = {}) { - return Recipe.getInstanceOrThrowError().recipeInterfaceImpl.updateAccessTokenPayload({ - sessionHandle, - newAccessTokenPayload, - userContext, - }); - } - static mergeIntoAccessTokenPayload( sessionHandle: string, accessTokenPayloadUpdate: JSONObject, @@ -255,40 +339,23 @@ export default class SessionWrapper { }); } - static createJWT(payload?: any, validitySeconds?: number, userContext: any = {}) { - let openIdRecipe: OpenIdRecipe | undefined = Recipe.getInstanceOrThrowError().openIdRecipe; - - if (openIdRecipe !== undefined) { - return openIdRecipe.recipeImplementation.createJWT({ payload, validitySeconds, userContext }); - } - - throw new global.Error( - "createJWT cannot be used without enabling the JWT feature. Please set 'enableJWT: true' when initialising the Session recipe" - ); + static createJWT(payload?: any, validitySeconds?: number, useStaticSigningKey?: boolean, userContext: any = {}) { + return Recipe.getInstanceOrThrowError().openIdRecipe.recipeImplementation.createJWT({ + payload, + validitySeconds, + useStaticSigningKey, + userContext, + }); } static getJWKS(userContext: any = {}) { - let openIdRecipe: OpenIdRecipe | undefined = Recipe.getInstanceOrThrowError().openIdRecipe; - - if (openIdRecipe !== undefined) { - return openIdRecipe.recipeImplementation.getJWKS({ userContext }); - } - - throw new global.Error( - "getJWKS cannot be used without enabling the JWT feature. Please set 'enableJWT: true' when initialising the Session recipe" - ); + return Recipe.getInstanceOrThrowError().openIdRecipe.recipeImplementation.getJWKS({ userContext }); } static getOpenIdDiscoveryConfiguration(userContext: any = {}) { - let openIdRecipe: OpenIdRecipe | undefined = Recipe.getInstanceOrThrowError().openIdRecipe; - - if (openIdRecipe !== undefined) { - return openIdRecipe.recipeImplementation.getOpenIdDiscoveryConfiguration({ userContext }); - } - - throw new global.Error( - "getOpenIdDiscoveryConfiguration cannot be used without enabling the JWT feature. Please set 'enableJWT: true' when initialising the Session recipe" - ); + return Recipe.getInstanceOrThrowError().openIdRecipe.recipeImplementation.getOpenIdDiscoveryConfiguration({ + userContext, + }); } static fetchAndSetClaim(sessionHandle: string, claim: SessionClaim, userContext: any = {}): Promise { @@ -345,12 +412,15 @@ export default class SessionWrapper { export let init = SessionWrapper.init; export let createNewSession = SessionWrapper.createNewSession; +export let createNewSessionWithoutRequestResponse = SessionWrapper.createNewSessionWithoutRequestResponse; export let getSession = SessionWrapper.getSession; +export let getSessionWithoutRequestResponse = SessionWrapper.getSessionWithoutRequestResponse; export let getSessionInformation = SessionWrapper.getSessionInformation; export let refreshSession = SessionWrapper.refreshSession; +export let refreshSessionWithoutRequestResponse = SessionWrapper.refreshSessionWithoutRequestResponse; export let revokeAllSessionsForUser = SessionWrapper.revokeAllSessionsForUser; @@ -360,9 +430,8 @@ export let revokeSession = SessionWrapper.revokeSession; export let revokeMultipleSessions = SessionWrapper.revokeMultipleSessions; -export let updateSessionData = SessionWrapper.updateSessionData; +export let updateSessionDataInDatabase = SessionWrapper.updateSessionDataInDatabase; -export let updateAccessTokenPayload = SessionWrapper.updateAccessTokenPayload; export let mergeIntoAccessTokenPayload = SessionWrapper.mergeIntoAccessTokenPayload; export let fetchAndSetClaim = SessionWrapper.fetchAndSetClaim; diff --git a/lib/ts/recipe/session/jwt.ts b/lib/ts/recipe/session/jwt.ts index f8ebf1f2b..a4ce537d7 100644 --- a/lib/ts/recipe/session/jwt.ts +++ b/lib/ts/recipe/session/jwt.ts @@ -12,7 +12,6 @@ * License for the specific language governing permissions and limitations * under the License. */ -import * as crypto from "crypto"; const HEADERS = new Set([ Buffer.from( @@ -32,11 +31,13 @@ const HEADERS = new Set([ ]); export type ParsedJWTInfo = { + version: number; rawTokenString: string; rawPayload: string; header: string; payload: any; signature: string; + kid: string | undefined; }; export function parseJWTWithoutSignatureVerification(jwt: string): ParsedJWTInfo { @@ -45,12 +46,31 @@ export function parseJWTWithoutSignatureVerification(jwt: string): ParsedJWTInfo throw new Error("Invalid JWT"); } + // V1&V2 is functionally identical, plus all legacy tokens should be V2 now. + let version = 2; + let kid = undefined; + // V2 or older tokens did not save the key id; // checking header if (!HEADERS.has(splittedInput[0])) { - throw new Error("JWT header mismatch"); + const parsedHeader = JSON.parse(Buffer.from(splittedInput[0], "base64").toString()); + + // We have to ensure version is a string, otherwise Number.parseInt can have unexpected results + if (typeof parsedHeader.version !== "string") { + throw new Error("JWT header mismatch"); + } + + version = Number.parseInt(parsedHeader.version); + kid = parsedHeader.kid; + + // Number.isInteger returns false for Number.NaN (if it fails to parse the version) + if (parsedHeader.typ !== "JWT" || !Number.isInteger(version) || version < 3 || kid === undefined) { + throw new Error("JWT header mismatch"); + } } return { + version, + kid, rawTokenString: jwt, rawPayload: splittedInput[1], header: splittedInput[0], @@ -60,19 +80,3 @@ export function parseJWTWithoutSignatureVerification(jwt: string): ParsedJWTInfo signature: splittedInput[2], }; } - -export function verifyJWT({ header, rawPayload, signature }: ParsedJWTInfo, jwtSigningPublicKey: string): void { - let verifier = crypto.createVerify("sha256"); - // convert the jwtSigningPublicKey into .pem format - - verifier.update(header + "." + rawPayload); - if ( - !verifier.verify( - "-----BEGIN PUBLIC KEY-----\n" + jwtSigningPublicKey + "\n-----END PUBLIC KEY-----", - signature, - "base64" - ) - ) { - throw new Error("JWT verification failed"); - } -} diff --git a/lib/ts/recipe/session/recipe.ts b/lib/ts/recipe/session/recipe.ts index afc115f46..12b048aaf 100644 --- a/lib/ts/recipe/session/recipe.ts +++ b/lib/ts/recipe/session/recipe.ts @@ -35,7 +35,6 @@ import { getCORSAllowedHeaders as getCORSAllowedHeadersFromCookiesAndHeaders, } from "./cookieAndHeaders"; import RecipeImplementation from "./recipeImplementation"; -import RecipeImplementationWithJWT from "./with-jwt"; import { Querier } from "../../querier"; import APIImplementation from "./api/implementation"; import { BaseRequest, BaseResponse } from "../../framework"; @@ -56,7 +55,7 @@ export default class SessionRecipe extends RecipeModule { config: TypeNormalisedInput; recipeInterfaceImpl: RecipeInterface; - openIdRecipe?: OpenIdRecipe; + openIdRecipe: OpenIdRecipe; apiImpl: APIInterface; @@ -74,44 +73,20 @@ export default class SessionRecipe extends RecipeModule { this.isInServerlessEnv = isInServerlessEnv; - if (this.config.jwt.enable === true) { - this.openIdRecipe = new OpenIdRecipe(recipeId, appInfo, isInServerlessEnv, { - issuer: this.config.jwt.issuer, - override: this.config.override.openIdFeature, - }); + this.openIdRecipe = new OpenIdRecipe(recipeId, appInfo, isInServerlessEnv, { + override: this.config.override.openIdFeature, + }); + + let builder = new OverrideableBuilder( + RecipeImplementation( + Querier.getNewInstanceOrThrowError(recipeId), + this.config, + this.getAppInfo(), + () => this.recipeInterfaceImpl + ) + ); + this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); - let builder = new OverrideableBuilder( - RecipeImplementation( - Querier.getNewInstanceOrThrowError(recipeId), - this.config, - this.getAppInfo(), - () => this.recipeInterfaceImpl - ) - ); - this.recipeInterfaceImpl = builder - .override((oI) => { - return RecipeImplementationWithJWT( - oI, - // this.jwtRecipe is never undefined here - this.openIdRecipe!.recipeImplementation, - this.config - ); - }) - .override(this.config.override.functions) - .build(); - } else { - { - let builder = new OverrideableBuilder( - RecipeImplementation( - Querier.getNewInstanceOrThrowError(recipeId), - this.config, - this.getAppInfo(), - () => this.recipeInterfaceImpl - ) - ); - this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); - } - } { let builder = new OverrideableBuilder(APIImplementation()); this.apiImpl = builder.override(this.config.override.apis).build(); @@ -183,9 +158,7 @@ export default class SessionRecipe extends RecipeModule { }, ]; - if (this.openIdRecipe !== undefined) { - apisHandled.push(...this.openIdRecipe.getAPIsHandled()); - } + apisHandled.push(...this.openIdRecipe.getAPIsHandled()); return apisHandled; }; @@ -209,10 +182,8 @@ export default class SessionRecipe extends RecipeModule { return await handleRefreshAPI(this.apiImpl, options); } else if (id === SIGNOUT_API_PATH) { return await signOutAPI(this.apiImpl, options); - } else if (this.openIdRecipe !== undefined) { - return await this.openIdRecipe.handleAPIRequest(id, req, res, path, method); } else { - return false; + return await this.openIdRecipe.handleAPIRequest(id, req, res, path, method); } }; @@ -248,19 +219,15 @@ export default class SessionRecipe extends RecipeModule { } else { throw err; } - } else if (this.openIdRecipe !== undefined) { - return await this.openIdRecipe.handleError(err, request, response); } else { - throw err; + return await this.openIdRecipe.handleError(err, request, response); } }; getAllCORSHeaders = (): string[] => { let corsHeaders: string[] = [...getCORSAllowedHeadersFromCookiesAndHeaders()]; - if (this.openIdRecipe !== undefined) { - corsHeaders.push(...this.openIdRecipe.getAllCORSHeaders()); - } + corsHeaders.push(...this.openIdRecipe.getAllCORSHeaders()); return corsHeaders; }; @@ -268,8 +235,7 @@ export default class SessionRecipe extends RecipeModule { isErrorFromThisRecipe = (err: any): err is STError => { return ( STError.isErrorFromSuperTokens(err) && - (err.fromRecipe === SessionRecipe.RECIPE_ID || - (this.openIdRecipe !== undefined && this.openIdRecipe.isErrorFromThisRecipe(err))) + (err.fromRecipe === SessionRecipe.RECIPE_ID || this.openIdRecipe.isErrorFromThisRecipe(err)) ); }; diff --git a/lib/ts/recipe/session/recipeImplementation.ts b/lib/ts/recipe/session/recipeImplementation.ts index dca5e55d5..95cda042c 100644 --- a/lib/ts/recipe/session/recipeImplementation.ts +++ b/lib/ts/recipe/session/recipeImplementation.ts @@ -1,78 +1,45 @@ +import { createRemoteJWKSet, JWTVerifyGetKey } from "jose"; import { RecipeInterface, VerifySessionOptions, TypeNormalisedInput, SessionInformation, - KeyInfo, - AntiCsrfType, SessionClaimValidator, SessionClaim, ClaimValidationError, - TokenTransferMethod, + SessionContainerInterface, } from "./types"; import * as SessionFunctions from "./sessionFunctions"; -import { - clearSession, - getAntiCsrfTokenFromHeaders, - setFrontTokenInHeaders, - getToken, - setToken, - setCookie, -} from "./cookieAndHeaders"; -import { attachTokensToResponse, validateClaimsInPayload } from "./utils"; +import { buildFrontToken } from "./cookieAndHeaders"; +import { validateClaimsInPayload } from "./utils"; import Session from "./sessionClass"; -import STError from "./error"; -import { normaliseHttpMethod, getRidFromHeader, isAnIpAddress } from "../../utils"; import { Querier } from "../../querier"; -import { PROCESS_STATE, ProcessState } from "../../processState"; import NormalisedURLPath from "../../normalisedURLPath"; import { JSONObject, NormalisedAppinfo } from "../../types"; import { logDebugMessage } from "../../logger"; -import { BaseResponse } from "../../framework/response"; -import { BaseRequest } from "../../framework/request"; -import { availableTokenTransferMethods } from "./constants"; import { ParsedJWTInfo, parseJWTWithoutSignatureVerification } from "./jwt"; import { validateAccessTokenStructure } from "./accessToken"; - -export class HandshakeInfo { - constructor( - public antiCsrf: AntiCsrfType, - public accessTokenBlacklistingEnabled: boolean, - public accessTokenValidity: number, - public refreshTokenValidity: number, - private rawJwtSigningPublicKeyList: KeyInfo[] - ) {} - - setJwtSigningPublicKeyList(updatedList: KeyInfo[]) { - this.rawJwtSigningPublicKeyList = updatedList; - } - - getJwtSigningPublicKeyList() { - return this.rawJwtSigningPublicKeyList.filter((key) => key.expiryTime > Date.now()); - } - - clone() { - return new HandshakeInfo( - this.antiCsrf, - this.accessTokenBlacklistingEnabled, - this.accessTokenValidity, - this.refreshTokenValidity, - this.rawJwtSigningPublicKeyList - ); - } -} +import SessionError from "./error"; export type Helpers = { querier: Querier; - getHandshakeInfo: (forceRefetch?: boolean) => Promise; - updateJwtSigningPublicKeyInfo: (keyList: KeyInfo[] | undefined, publicKey: string, expiryTime: number) => void; + JWKS: JWTVerifyGetKey; config: TypeNormalisedInput; appInfo: NormalisedAppinfo; getRecipeImpl: () => RecipeInterface; }; -// We are defining this here to reduce the scope of legacy code -const LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME = "sIdRefreshToken"; +export const JWKCacheMaxAgeInMs = 60000; + +export const protectedProps = [ + "sub", + "iat", + "exp", + "sessionHandle", + "parentRefreshTokenHash1", + "refreshTokenHash1", + "antiCsrfToken", +]; export default function getRecipeInterface( querier: Querier, @@ -80,113 +47,80 @@ export default function getRecipeInterface( appInfo: NormalisedAppinfo, getRecipeImplAfterOverrides: () => RecipeInterface ): RecipeInterface { - let handshakeInfo: undefined | HandshakeInfo; - - async function getHandshakeInfo(forceRefetch = false): Promise { - if (handshakeInfo === undefined || handshakeInfo.getJwtSigningPublicKeyList().length === 0 || forceRefetch) { - let antiCsrf = config.antiCsrf; - ProcessState.getInstance().addState(PROCESS_STATE.CALLING_SERVICE_IN_GET_HANDSHAKE_INFO); - let response = await querier.sendPostRequest(new NormalisedURLPath("/recipe/handshake"), {}); - - handshakeInfo = new HandshakeInfo( - antiCsrf, - response.accessTokenBlacklistingEnabled, - response.accessTokenValidity, - response.refreshTokenValidity, - response.jwtSigningPublicKeyList - ); + const JWKS: ReturnType[] = querier + .getAllCoreUrlsForPath("/.well-known/jwks.json") + .map((url) => + createRemoteJWKSet(new URL(url), { + cooldownDuration: 500, + cacheMaxAge: JWKCacheMaxAgeInMs, + }) + ); - updateJwtSigningPublicKeyInfo( - response.jwtSigningPublicKeyList, - response.jwtSigningPublicKey, - response.jwtSigningPublicKeyExpiryTime + /** + This function fetches all JWKs from the first available core instance. This combines the other JWKS functions to become + error resistant. + + Every core instance a backend is connected to is expected to connect to the same database and use the same key set for + token verification. Otherwise, the result of session verification would depend on which core is currently available. + */ + const combinedJWKS: ReturnType = async (...args) => { + let lastError = undefined; + if (JWKS.length === 0) { + throw Error( + "No SuperTokens core available to query. Please pass supertokens > connectionURI to the init function, or override all the functions of the recipe you are using." ); } - return handshakeInfo; - } - - function updateJwtSigningPublicKeyInfo(keyList: KeyInfo[] | undefined, publicKey: string, expiryTime: number) { - if (keyList === undefined) { - // Setting createdAt to Date.now() emulates the old lastUpdatedAt logic - keyList = [{ publicKey, expiryTime, createdAt: Date.now() }]; - } - - if (handshakeInfo !== undefined) { - handshakeInfo.setJwtSigningPublicKeyList(keyList); + for (const jwks of JWKS) { + try { + // We await before returning to make sure we catch the error + return await jwks(...args); + } catch (ex) { + lastError = ex; + } } - } + throw lastError; + }; let obj: RecipeInterface = { createNewSession: async function ({ - req, - res, userId, recipeUserId, accessTokenPayload = {}, - sessionData = {}, - userContext, + sessionDataInDatabase = {}, + disableAntiCsrf, }: { - req: BaseRequest; - res: BaseResponse; userId: string; recipeUserId?: string; + disableAntiCsrf?: boolean; accessTokenPayload?: any; - sessionData?: any; + sessionDataInDatabase?: any; userContext: any; - }): Promise { + }): Promise { logDebugMessage("createNewSession: Started"); - let outputTransferMethod = config.getTokenTransferMethod({ req, forCreateNewSession: true, userContext }); - if (outputTransferMethod === "any") { - outputTransferMethod = "header"; - } - logDebugMessage("createNewSession: using transfer method " + outputTransferMethod); - - if ( - outputTransferMethod === "cookie" && - helpers.config.cookieSameSite === "none" && - !helpers.config.cookieSecure && - !( - (helpers.appInfo.topLevelAPIDomain === "localhost" || - isAnIpAddress(helpers.appInfo.topLevelAPIDomain)) && - (helpers.appInfo.topLevelWebsiteDomain === "localhost" || - isAnIpAddress(helpers.appInfo.topLevelWebsiteDomain)) - ) - ) { - // We can allow insecure cookie when both website & API domain are localhost or an IP - // When either of them is a different domain, API domain needs to have https and a secure cookie to work - throw new Error( - "Since your API and website domain are different, for sessions to work, please use https on your apiDomain and dont set cookieSecure to false." - ); - } - - const disableAntiCSRF = outputTransferMethod === "header"; let response = await SessionFunctions.createNewSession( helpers, userId, - disableAntiCSRF, recipeUserId, + disableAntiCsrf === true, accessTokenPayload, - sessionData + sessionDataInDatabase ); + logDebugMessage("createNewSession: Finished"); - for (const transferMethod of availableTokenTransferMethods) { - if (transferMethod !== outputTransferMethod && getToken(req, "access", transferMethod) !== undefined) { - clearSession(config, res, transferMethod); - } - } - - attachTokensToResponse(config, res, response, outputTransferMethod); + const payload = parseJWTWithoutSignatureVerification(response.accessToken.token).payload; return new Session( helpers, response.accessToken.token, + buildFrontToken(response.session.userId, response.accessToken.expiry, payload), + response.refreshToken, + response.antiCsrfToken, response.session.handle, response.session.userId, response.session.recipeUserId, - response.session.userDataInJWT, - res, - req, - outputTransferMethod + payload, + undefined, + true ); }, @@ -196,153 +130,72 @@ export default function getRecipeInterface( return input.claimValidatorsAddedByOtherRecipes; }, - /* In all cases if sIdRefreshToken token exists (so it's a legacy session) we return TRY_REFRESH_TOKEN. The refresh endpoint will clear this cookie and try to upgrade the session. - Check https://supertokens.com/docs/contribute/decisions/session/0007 for further details and a table of expected behaviours - */ getSession: async function ({ - req, - res, + accessToken: accessTokenString, + antiCsrfToken, options, - userContext, }: { - req: BaseRequest; - res: BaseResponse; + accessToken: string; + antiCsrfToken?: string; options?: VerifySessionOptions; userContext: any; - }): Promise { - logDebugMessage("getSession: Started"); - - // This token isn't handled by getToken to limit the scope of this legacy/migration code - if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { - // This could create a spike on refresh calls during the update of the backend SDK - throw new STError({ - message: "using legacy session, please call the refresh API", - type: STError.TRY_REFRESH_TOKEN, - }); - } - - const sessionOptional = options?.sessionRequired === false; - logDebugMessage("getSession: optional validation: " + sessionOptional); - - const accessTokens: { - [key in TokenTransferMethod]?: ParsedJWTInfo; - } = {}; - - // We check all token transfer methods for available access tokens - for (const transferMethod of availableTokenTransferMethods) { - const tokenString = getToken(req, "access", transferMethod); - if (tokenString !== undefined) { - try { - const info = parseJWTWithoutSignatureVerification(tokenString); - validateAccessTokenStructure(info.payload); - logDebugMessage("getSession: got access token from " + transferMethod); - accessTokens[transferMethod] = info; - } catch { - logDebugMessage( - `getSession: ignoring token in ${transferMethod}, because it doesn't match our access token structure` - ); - } - } + }): Promise { + if (options?.antiCsrfCheck !== false && config.antiCsrf === "VIA_CUSTOM_HEADER") { + throw new Error( + "Since the anti-csrf mode is VIA_CUSTOM_HEADER getSession can't check the CSRF token. Please either use VIA_TOKEN or set antiCsrfCheck to false" + ); } + logDebugMessage("getSession: Started"); - const allowedTransferMethod = config.getTokenTransferMethod({ - req, - forCreateNewSession: false, - userContext, - }); - let requestTransferMethod: TokenTransferMethod; let accessToken: ParsedJWTInfo | undefined; - - if ( - (allowedTransferMethod === "any" || allowedTransferMethod === "header") && - accessTokens["header"] !== undefined - ) { - logDebugMessage("getSession: using header transfer method"); - requestTransferMethod = "header"; - accessToken = accessTokens["header"]; - } else if ( - (allowedTransferMethod === "any" || allowedTransferMethod === "cookie") && - accessTokens["cookie"] !== undefined - ) { - logDebugMessage("getSession: using cookie transfer method"); - requestTransferMethod = "cookie"; - accessToken = accessTokens["cookie"]; - } else { - if (sessionOptional) { + try { + accessToken = parseJWTWithoutSignatureVerification(accessTokenString); + validateAccessTokenStructure(accessToken.payload, accessToken.version); + } catch (error) { + if (options?.sessionRequired === false) { logDebugMessage( - "getSession: returning undefined because accessToken is undefined and sessionRequired is false" + "getSession: Returning undefined because parsing failed and sessionRequired is false" ); - // there is no session that exists here, and the user wants session verification - // to be optional. So we return undefined. return undefined; } - - logDebugMessage("getSession: UNAUTHORISED because accessToken in request is undefined"); - throw new STError({ - message: - "Session does not exist. Are you sending the session tokens in the request with the appropriate token transfer method?", - type: STError.UNAUTHORISED, - payload: { - // we do not clear the session here because of a - // race condition mentioned here: https://github.com/supertokens/supertokens-node/issues/17 - clearTokens: false, - }, + throw new SessionError({ + message: "Token parsing failed", + type: "UNAUTHORISED", + payload: { clearTokens: false }, }); } - let antiCsrfToken = getAntiCsrfTokenFromHeaders(req); - let doAntiCsrfCheck = options !== undefined ? options.antiCsrfCheck : undefined; - - if (doAntiCsrfCheck === undefined) { - doAntiCsrfCheck = normaliseHttpMethod(req.getMethod()) !== "get"; - } - - if (requestTransferMethod === "header") { - doAntiCsrfCheck = false; - } - - logDebugMessage("getSession: Value of doAntiCsrfCheck is: " + doAntiCsrfCheck); - - let response = await SessionFunctions.getSession( + const response = await SessionFunctions.getSession( helpers, accessToken, antiCsrfToken, - doAntiCsrfCheck, - getRidFromHeader(req) !== undefined + options?.antiCsrfCheck !== false, + options?.checkDatabase === true ); - let accessTokenString = accessToken.rawTokenString; - if (response.accessToken !== undefined) { - setFrontTokenInHeaders( - res, - response.session.userId, - response.accessToken.expiry, - response.session.userDataInJWT - ); - setToken( - config, - res, - "access", - response.accessToken.token, - // We set the expiration to 100 years, because we can't really access the expiration of the refresh token everywhere we are setting it. - // This should be safe to do, since this is only the validity of the cookie (set here or on the frontend) but we check the expiration of the JWT anyway. - // Even if the token is expired the presence of the token indicates that the user could have a valid refresh - // Setting them to infinity would require special case handling on the frontend and just adding 10 years seems enough. - Date.now() + 3153600000000, - requestTransferMethod - ); - accessTokenString = response.accessToken.token; - } + logDebugMessage("getSession: Success!"); + const payload = + accessToken.version >= 3 + ? response.accessToken !== undefined + ? parseJWTWithoutSignatureVerification(response.accessToken.token).payload + : accessToken.payload + : response.session.userDataInJWT; const session = new Session( helpers, - accessTokenString, + response.accessToken !== undefined ? response.accessToken.token : accessTokenString, + buildFrontToken( + response.session.userId, + response.accessToken !== undefined ? response.accessToken.expiry : response.session.expiryTime, + payload + ), + undefined, // refresh + antiCsrfToken, response.session.handle, response.session.userId, response.session.recipeUserId, - response.session.userDataInJWT, - res, - req, - requestTransferMethod + payload, + undefined, + response.accessToken !== undefined ); return session; @@ -407,122 +260,44 @@ export default function getRecipeInterface( return SessionFunctions.getSessionInformation(helpers, sessionHandle); }, - /* - In all cases: if sIdRefreshToken token exists (so it's a legacy session) we clear it. - Check http://localhost:3002/docs/contribute/decisions/session/0008 for further details and a table of expected behaviours - */ refreshSession: async function ( this: RecipeInterface, - { req, res, userContext }: { req: BaseRequest; res: BaseResponse; userContext: any } - ): Promise { - logDebugMessage("refreshSession: Started"); - - const refreshTokens: { - [key in TokenTransferMethod]?: string; - } = {}; - - // We check all token transfer methods for available refresh tokens - // We do this so that we can later clear all we are not overwriting - for (const transferMethod of availableTokenTransferMethods) { - refreshTokens[transferMethod] = getToken(req, "refresh", transferMethod); - if (refreshTokens[transferMethod] !== undefined) { - logDebugMessage("refreshSession: got refresh token from " + transferMethod); - } - } - - const allowedTransferMethod = config.getTokenTransferMethod({ - req, - forCreateNewSession: false, - userContext, - }); - logDebugMessage("refreshSession: getTokenTransferMethod returned " + allowedTransferMethod); - - let requestTransferMethod: TokenTransferMethod; - let refreshToken: string | undefined; - - if ( - (allowedTransferMethod === "any" || allowedTransferMethod === "header") && - refreshTokens["header"] !== undefined - ) { - logDebugMessage("refreshSession: using header transfer method"); - requestTransferMethod = "header"; - refreshToken = refreshTokens["header"]; - } else if ( - (allowedTransferMethod === "any" || allowedTransferMethod === "cookie") && - refreshTokens["cookie"] - ) { - logDebugMessage("refreshSession: using cookie transfer method"); - requestTransferMethod = "cookie"; - refreshToken = refreshTokens["cookie"]; - } else { - // This token isn't handled by getToken/setToken to limit the scope of this legacy/migration code - if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { - logDebugMessage( - "refreshSession: cleared legacy id refresh token because refresh token was not found" - ); - setCookie(config, res, LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, "", 0, "accessTokenPath"); - } - - logDebugMessage("refreshSession: UNAUTHORISED because refresh token in request is undefined"); - throw new STError({ - message: "Refresh token not found. Are you sending the refresh token in the request?", - payload: { - clearTokens: false, - }, - type: STError.UNAUTHORISED, - }); - } - - try { - let antiCsrfToken = getAntiCsrfTokenFromHeaders(req); - let response = await SessionFunctions.refreshSession( - helpers, - refreshToken, - antiCsrfToken, - getRidFromHeader(req) !== undefined, - requestTransferMethod + { + refreshToken, + antiCsrfToken, + disableAntiCsrf, + }: { refreshToken: string; antiCsrfToken?: string; disableAntiCsrf: boolean; userContext: any } + ): Promise { + if (disableAntiCsrf !== true && config.antiCsrf === "VIA_CUSTOM_HEADER") { + throw new Error( + "Since the anti-csrf mode is VIA_CUSTOM_HEADER getSession can't check the CSRF token. Please either use VIA_TOKEN or set antiCsrfCheck to false" ); - logDebugMessage("refreshSession: Attaching refreshed session info as " + requestTransferMethod); - - // We clear the tokens in all token transfer methods we are not going to overwrite - for (const transferMethod of availableTokenTransferMethods) { - if (transferMethod !== requestTransferMethod && refreshTokens[transferMethod] !== undefined) { - clearSession(config, res, transferMethod); - } - } + } + logDebugMessage("refreshSession: Started"); - attachTokensToResponse(config, res, response, requestTransferMethod); + const response = await SessionFunctions.refreshSession( + helpers, + refreshToken, + antiCsrfToken, + disableAntiCsrf + ); - logDebugMessage("refreshSession: Success!"); - // This token isn't handled by getToken/setToken to limit the scope of this legacy/migration code - if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { - logDebugMessage("refreshSession: cleared legacy id refresh token after successful refresh"); - setCookie(config, res, LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, "", 0, "accessTokenPath"); - } + logDebugMessage("refreshSession: Success!"); - return new Session( - helpers, - response.accessToken.token, - response.session.handle, - response.session.userId, - response.session.recipeUserId, - response.session.userDataInJWT, - res, - req, - requestTransferMethod - ); - } catch (err) { - if (err.type === STError.TOKEN_THEFT_DETECTED || err.payload.clearTokens) { - // This token isn't handled by getToken/setToken to limit the scope of this legacy/migration code - if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { - logDebugMessage( - "refreshSession: cleared legacy id refresh token because refresh is clearing other tokens" - ); - setCookie(config, res, LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, "", 0, "accessTokenPath"); - } - } - throw err; - } + const payload = parseJWTWithoutSignatureVerification(response.accessToken.token).payload; + return new Session( + helpers, + response.accessToken.token, + buildFrontToken(response.session.userId, response.accessToken.expiry, payload), + response.refreshToken, + response.antiCsrfToken, + response.session.handle, + response.session.userId, + response.session.recipeUserId, + payload, + undefined, + true + ); }, regenerateAccessToken: async function ( @@ -553,6 +328,7 @@ export default function getRecipeInterface( input.newAccessTokenPayload === null || input.newAccessTokenPayload === undefined ? {} : input.newAccessTokenPayload; + let response = await querier.sendPostRequest(new NormalisedURLPath("/recipe/session/regenerate"), { accessToken: input.accessToken, userDataInJWT: newAccessTokenPayload, @@ -579,24 +355,14 @@ export default function getRecipeInterface( return SessionFunctions.revokeMultipleSessions(helpers, sessionHandles); }, - updateSessionData: function ({ + updateSessionDataInDatabase: function ({ sessionHandle, newSessionData, }: { sessionHandle: string; newSessionData: any; }): Promise { - return SessionFunctions.updateSessionData(helpers, sessionHandle, newSessionData); - }, - - updateAccessTokenPayload: function ({ - sessionHandle, - newAccessTokenPayload, - }: { - sessionHandle: string; - newAccessTokenPayload: any; - }): Promise { - return SessionFunctions.updateAccessTokenPayload(helpers, sessionHandle, newAccessTokenPayload); + return SessionFunctions.updateSessionDataInDatabase(helpers, sessionHandle, newSessionData); }, mergeIntoAccessTokenPayload: async function ( @@ -615,21 +381,19 @@ export default function getRecipeInterface( if (sessionInfo === undefined) { return false; } - const newAccessTokenPayload = { ...sessionInfo.accessTokenPayload, ...accessTokenPayloadUpdate }; + let newAccessTokenPayload = { ...sessionInfo.customClaimsInAccessTokenPayload }; + for (const key of protectedProps) { + delete newAccessTokenPayload[key]; + } + + newAccessTokenPayload = { ...newAccessTokenPayload, ...accessTokenPayloadUpdate }; for (const key of Object.keys(accessTokenPayloadUpdate)) { if (accessTokenPayloadUpdate[key] === null) { delete newAccessTokenPayload[key]; } } - return this.updateAccessTokenPayload({ sessionHandle, newAccessTokenPayload, userContext }); - }, - getAccessTokenLifeTimeMS: async function (): Promise { - return (await getHandshakeInfo()).accessTokenValidity; - }, - - getRefreshTokenLifeTimeMS: async function (): Promise { - return (await getHandshakeInfo()).refreshTokenValidity; + return SessionFunctions.updateAccessTokenPayload(helpers, sessionHandle, newAccessTokenPayload); }, fetchAndSetClaim: async function ( @@ -694,7 +458,7 @@ export default function getRecipeInterface( return { status: "OK", - value: input.claim.getValueFromPayload(sessionInfo.accessTokenPayload, input.userContext), + value: input.claim.getValueFromPayload(sessionInfo.customClaimsInAccessTokenPayload, input.userContext), }; }, @@ -714,8 +478,7 @@ export default function getRecipeInterface( let helpers: Helpers = { querier, - updateJwtSigningPublicKeyInfo, - getHandshakeInfo, + JWKS: combinedJWKS, config, appInfo, getRecipeImpl: getRecipeImplAfterOverrides, @@ -723,12 +486,7 @@ export default function getRecipeInterface( if (process.env.TEST_MODE === "testing") { // testing mode, we add some of the help functions to the obj - (obj as any).getHandshakeInfo = getHandshakeInfo; - (obj as any).updateJwtSigningPublicKeyInfo = updateJwtSigningPublicKeyInfo; (obj as any).helpers = helpers; - (obj as any).setHandshakeInfo = function (info: any) { - handshakeInfo = info; - }; } return obj; diff --git a/lib/ts/recipe/session/sessionClass.ts b/lib/ts/recipe/session/sessionClass.ts index f809fdc8b..16378c739 100644 --- a/lib/ts/recipe/session/sessionClass.ts +++ b/lib/ts/recipe/session/sessionClass.ts @@ -12,23 +12,26 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { BaseRequest, BaseResponse } from "../../framework"; -import { clearSession, setFrontTokenInHeaders, setToken } from "./cookieAndHeaders"; +import { buildFrontToken, clearSession, setAntiCsrfTokenInHeaders, setToken } from "./cookieAndHeaders"; import STError from "./error"; -import { SessionClaim, SessionClaimValidator, SessionContainerInterface, TokenTransferMethod } from "./types"; -import { Helpers } from "./recipeImplementation"; +import { SessionClaim, SessionClaimValidator, SessionContainerInterface, ReqResInfo, TokenInfo } from "./types"; +import { Helpers, protectedProps } from "./recipeImplementation"; +import { setAccessTokenInResponse } from "./utils"; +import { parseJWTWithoutSignatureVerification } from "./jwt"; export default class Session implements SessionContainerInterface { constructor( protected helpers: Helpers, protected accessToken: string, + protected frontToken: string, + protected refreshToken: TokenInfo | undefined, + protected antiCsrfToken: string | undefined, protected sessionHandle: string, protected userId: string, protected recipeUserId: string, protected userDataInAccessToken: any, - protected res: BaseResponse, - protected readonly req: BaseRequest, - protected readonly transferMethod: TokenTransferMethod + protected reqResInfo: ReqResInfo | undefined, + protected accessTokenUpdated: boolean ) {} getRecipeUserId(_userContext?: any): string { @@ -41,16 +44,18 @@ export default class Session implements SessionContainerInterface { userContext: userContext === undefined ? {} : userContext, }); - // we do not check the output of calling revokeSession - // before clearing the cookies because we are revoking the - // current API request's session. - // If we instead clear the cookies only when revokeSession - // returns true, it can cause this kind of a bug: - // https://github.com/supertokens/supertokens-node/issues/343 - clearSession(this.helpers.config, this.res, this.transferMethod); + if (this.reqResInfo !== undefined) { + // we do not check the output of calling revokeSession + // before clearing the cookies because we are revoking the + // current API request's session. + // If we instead clear the cookies only when revokeSession + // returns true, it can cause this kind of a bug: + // https://github.com/supertokens/supertokens-node/issues/343 + clearSession(this.helpers.config, this.reqResInfo.res, this.reqResInfo.transferMethod); + } } - async getSessionData(userContext?: any): Promise { + async getSessionDataFromDatabase(userContext?: any): Promise { let sessionInfo = await this.helpers.getRecipeImpl().getSessionInformation({ sessionHandle: this.sessionHandle, userContext: userContext === undefined ? {} : userContext, @@ -61,12 +66,12 @@ export default class Session implements SessionContainerInterface { type: STError.UNAUTHORISED, }); } - return sessionInfo.sessionData; + return sessionInfo.sessionDataInDatabase; } - async updateSessionData(newSessionData: any, userContext?: any) { + async updateSessionDataInDatabase(newSessionData: any, userContext?: any) { if ( - !(await this.helpers.getRecipeImpl().updateSessionData({ + !(await this.helpers.getRecipeImpl().updateSessionDataInDatabase({ sessionHandle: this.sessionHandle, newSessionData, userContext: userContext === undefined ? {} : userContext, @@ -95,16 +100,70 @@ export default class Session implements SessionContainerInterface { return this.accessToken; } + getAllSessionTokensDangerously() { + return { + accessToken: this.accessToken, + accessAndFrontTokenUpdated: this.accessTokenUpdated, + refreshToken: this.refreshToken?.token, + frontToken: this.frontToken, + antiCsrfToken: this.antiCsrfToken, + }; + } + // Any update to this function should also be reflected in the respective JWT version async mergeIntoAccessTokenPayload(accessTokenPayloadUpdate: any, userContext?: any): Promise { - const updatedPayload = { ...this.getAccessTokenPayload(userContext), ...accessTokenPayloadUpdate }; + let newAccessTokenPayload = { ...this.getAccessTokenPayload(userContext) }; + for (const key of protectedProps) { + delete newAccessTokenPayload[key]; + } + + newAccessTokenPayload = { ...newAccessTokenPayload, ...accessTokenPayloadUpdate }; + for (const key of Object.keys(accessTokenPayloadUpdate)) { if (accessTokenPayloadUpdate[key] === null) { - delete updatedPayload[key]; + delete newAccessTokenPayload[key]; } } - await this.updateAccessTokenPayload(updatedPayload, userContext); + let response = await this.helpers.getRecipeImpl().regenerateAccessToken({ + accessToken: this.getAccessToken(), + newAccessTokenPayload, + userContext: userContext === undefined ? {} : userContext, + }); + + if (response === undefined) { + throw new STError({ + message: "Session does not exist anymore", + type: STError.UNAUTHORISED, + }); + } + + if (response.accessToken !== undefined) { + const respToken = parseJWTWithoutSignatureVerification(response.accessToken.token); + const payload = respToken.version < 3 ? response.session.userDataInJWT : respToken.payload; + this.userDataInAccessToken = payload; + this.accessToken = response.accessToken.token; + this.frontToken = buildFrontToken(this.userId, response.accessToken.expiry, payload); + this.accessTokenUpdated = true; + if (this.reqResInfo !== undefined) { + // We need to cast to let TS know that the accessToken in the response is defined (and we don't overwrite it with undefined) + setAccessTokenInResponse( + this.reqResInfo.res, + this.accessToken, + this.frontToken, + this.helpers.config, + this.reqResInfo.transferMethod + ); + } + } else { + // This case means that the access token has expired between the validation and this update + // We can't update the access token on the FE, as it will need to call refresh anyway but we handle this as a successful update during this request. + // the changes will be reflected on the FE after refresh is called + this.userDataInAccessToken = { + ...this.getAccessTokenPayload(), + ...response.session.userDataInJWT, + }; + } } async getTimeCreated(userContext?: any): Promise { @@ -146,6 +205,10 @@ export default class Session implements SessionContainerInterface { }); if (validateClaimResponse.accessTokenPayloadUpdate !== undefined) { + for (const key of protectedProps) { + delete validateClaimResponse.accessTokenPayloadUpdate[key]; + } + await this.mergeIntoAccessTokenPayload(validateClaimResponse.accessTokenPayloadUpdate, userContext); } @@ -181,42 +244,26 @@ export default class Session implements SessionContainerInterface { return this.mergeIntoAccessTokenPayload(update, userContext); } - /** - * @deprecated Use mergeIntoAccessTokenPayload - */ - async updateAccessTokenPayload(newAccessTokenPayload: any, userContext: any): Promise { - let response = await this.helpers.getRecipeImpl().regenerateAccessToken({ - accessToken: this.getAccessToken(), - newAccessTokenPayload, - userContext: userContext === undefined ? {} : userContext, - }); - if (response === undefined) { - throw new STError({ - message: "Session does not exist anymore", - type: STError.UNAUTHORISED, - }); - } - this.userDataInAccessToken = response.session.userDataInJWT; - if (response.accessToken !== undefined) { - this.accessToken = response.accessToken.token; - setFrontTokenInHeaders( - this.res, - response.session.userId, - response.accessToken.expiry, - response.session.userDataInJWT - ); - setToken( - this.helpers.config, - this.res, - "access", - response.accessToken.token, - // We set the expiration to 100 years, because we can't really access the expiration of the refresh token everywhere we are setting it. - // This should be safe to do, since this is only the validity of the cookie (set here or on the frontend) but we check the expiration of the JWT anyway. - // Even if the token is expired the presence of the token indicates that the user could have a valid refresh - // Setting them to infinity would require special case handling on the frontend and just adding 10 years seems enough. - Date.now() + 3153600000000, - this.transferMethod - ); + attachToRequestResponse(info: ReqResInfo) { + this.reqResInfo = info; + + if (this.accessTokenUpdated) { + const { res, transferMethod } = info; + + setAccessTokenInResponse(res, this.accessToken, this.frontToken, this.helpers.config, transferMethod); + if (this.refreshToken !== undefined) { + setToken( + this.helpers.config, + res, + "refresh", + this.refreshToken.token, + this.refreshToken.expiry, + transferMethod + ); + } + if (this.antiCsrfToken !== undefined) { + setAntiCsrfTokenInHeaders(res, this.antiCsrfToken); + } } } } diff --git a/lib/ts/recipe/session/sessionFunctions.ts b/lib/ts/recipe/session/sessionFunctions.ts index a392cd805..fb1f6f884 100644 --- a/lib/ts/recipe/session/sessionFunctions.ts +++ b/lib/ts/recipe/session/sessionFunctions.ts @@ -16,9 +16,9 @@ import { getInfoFromAccessToken, sanitizeNumberInput } from "./accessToken"; import { ParsedJWTInfo } from "./jwt"; import STError from "./error"; import { PROCESS_STATE, ProcessState } from "../../processState"; -import { CreateOrRefreshAPIResponse, SessionInformation, TokenTransferMethod } from "./types"; +import { CreateOrRefreshAPIResponse, SessionInformation } from "./types"; import NormalisedURLPath from "../../normalisedURLPath"; -import { Helpers } from "./recipeImplementation"; +import { Helpers, JWKCacheMaxAgeInMs } from "./recipeImplementation"; import { maxVersion } from "../../utils"; import { logDebugMessage } from "../../logger"; @@ -28,40 +28,26 @@ import { logDebugMessage } from "../../logger"; export async function createNewSession( helpers: Helpers, userId: string, + recipeUserId: string | undefined, disableAntiCsrf: boolean, - recipeUserId?: string, accessTokenPayload: any = {}, - sessionData: any = {} + sessionDataInDatabase: any = {} ): Promise { accessTokenPayload = accessTokenPayload === null || accessTokenPayload === undefined ? {} : accessTokenPayload; - sessionData = sessionData === null || sessionData === undefined ? {} : sessionData; + sessionDataInDatabase = + sessionDataInDatabase === null || sessionDataInDatabase === undefined ? {} : sessionDataInDatabase; - let requestBody: { - userId: string; - recipeUserId?: string; - userDataInJWT: any; - userDataInDatabase: any; - enableAntiCsrf?: boolean; - } = { + const requestBody = { userId, recipeUserId, userDataInJWT: accessTokenPayload, - userDataInDatabase: sessionData, + userDataInDatabase: sessionDataInDatabase, + useDynamicSigningKey: helpers.config.useDynamicAccessTokenSigningKey, + enableAntiCsrf: !disableAntiCsrf && helpers.config.antiCsrf === "VIA_TOKEN", }; + const response = await helpers.querier.sendPostRequest(new NormalisedURLPath("/recipe/session"), requestBody); - let handShakeInfo = await helpers.getHandshakeInfo(); - requestBody.enableAntiCsrf = !disableAntiCsrf && handShakeInfo.antiCsrf === "VIA_TOKEN"; - let response = await helpers.querier.sendPostRequest(new NormalisedURLPath("/recipe/session"), requestBody); - helpers.updateJwtSigningPublicKeyInfo( - response.jwtSigningPublicKeyList, - response.jwtSigningPublicKey, - response.jwtSigningPublicKeyExpiryTime - ); delete response.status; - delete response.jwtSigningPublicKey; - delete response.jwtSigningPublicKeyExpiryTime; - delete response.jwtSigningPublicKeyList; - return response; } @@ -73,13 +59,14 @@ export async function getSession( parsedAccessToken: ParsedJWTInfo, antiCsrfToken: string | undefined, doAntiCsrfCheck: boolean, - containsCustomHeader: boolean + alwaysCheckCore: boolean ): Promise<{ session: { handle: string; userId: string; recipeUserId: string; userDataInJWT: any; + expiryTime: number; }; accessToken?: { token: string; @@ -87,87 +74,88 @@ export async function getSession( createdTime: number; }; }> { - let handShakeInfo = await helpers.getHandshakeInfo(); let accessTokenInfo; - // If we have no key old enough to verify this access token we should reject it without calling the core - let foundASigningKeyThatIsOlderThanTheAccessToken = false; - for (const key of handShakeInfo.getJwtSigningPublicKeyList()) { - try { - /** - * get access token info using existing signingKey - */ - accessTokenInfo = await getInfoFromAccessToken( - parsedAccessToken, - key.publicKey, - handShakeInfo.antiCsrf === "VIA_TOKEN" && doAntiCsrfCheck - ); - foundASigningKeyThatIsOlderThanTheAccessToken = true; - } catch (err) { - /** - * if error type is not TRY_REFRESH_TOKEN, we return the - * error to the user - */ - if (err.type !== STError.TRY_REFRESH_TOKEN) { - throw err; - } - /** - * if it comes here, it means token verification has failed. - * It may be due to: - * - signing key was updated and this token was signed with new key - * - access token is actually expired - * - access token was signed with the older signing key - * - * if access token is actually expired, we don't need to call core and - * just return TRY_REFRESH_TOKEN to the client - * - * if access token creation time is after this signing key was created - * we need to call core as there are chances that the token - * was signed with the updated signing key - * - * if access token creation time is before oldest signing key was created, - * so if foundASigningKeyThatIsOlderThanTheAccessToken is still false after - * the loop we just return TRY_REFRESH_TOKEN - */ + try { + /** + * get access token info using jwks + */ + accessTokenInfo = await getInfoFromAccessToken( + parsedAccessToken, + helpers.JWKS, + helpers.config.antiCsrf === "VIA_TOKEN" && doAntiCsrfCheck + ); + } catch (err) { + /** + * if error type is not TRY_REFRESH_TOKEN, we return the + * error to the user + */ + if (err.type !== STError.TRY_REFRESH_TOKEN) { + throw err; + } + /** + * if it comes here, it means token verification has failed. + * It may be due to: + * - signing key was updated and this token was signed with new key + * - access token is actually expired + * - access token was signed with the older signing key + * + * if access token is actually expired, we don't need to call core and + * just return TRY_REFRESH_TOKEN to the client + * + * if access token creation time is after this signing key was created + * we need to call core as there are chances that the token + * was signed with the updated signing key + * + * if access token creation time is before oldest signing key was created, + * so if foundASigningKeyThatIsOlderThanTheAccessToken is still false after + * the loop we just return TRY_REFRESH_TOKEN + */ + + if (parsedAccessToken.version < 3) { let payload = parsedAccessToken.payload; const timeCreated = sanitizeNumberInput(payload.timeCreated); const expiryTime = sanitizeNumberInput(payload.expiryTime); - if (expiryTime === undefined || expiryTime < Date.now()) { + if (expiryTime === undefined || timeCreated == undefined) { throw err; } - if (timeCreated === undefined) { + if (expiryTime < Date.now()) { throw err; } - - // If we reached a key older than the token and failed to validate the token, - // that means it was signed by a key newer than the cached list. - // In this case we go to the server. - if (timeCreated >= key.createdAt) { - foundASigningKeyThatIsOlderThanTheAccessToken = true; - break; + // We check if the token was created since the last time we refreshed the keys from the core + // Since we do not know the exact timing of the last refresh, we check against the max age + if (timeCreated <= Date.now() - JWKCacheMaxAgeInMs) { + throw err; } + } else { + // Since v3 (and above) tokens contain a kid we can trust the cache-refresh mechanism of the jose library. + // This means we do not need to call the core since the signature wouldn't pass verification anyway. + throw err; } } - // If the token was created before the oldest key in the cache but hasn't expired, then a config value must've changed. - // E.g., the access_token_signing_key_update_interval was reduced, or access_token_signing_key_dynamic was turned on. - // Either way, the user needs to refresh the access token as validating by the server is likely to do nothing. - if (!foundASigningKeyThatIsOlderThanTheAccessToken) { - throw new STError({ - message: "Access token has expired. Please call the refresh API", - type: STError.TRY_REFRESH_TOKEN, - }); + if (parsedAccessToken.version >= 3) { + const tokenUsesDynamicKey = parsedAccessToken.kid!.startsWith("d-"); + if (tokenUsesDynamicKey !== helpers.config.useDynamicAccessTokenSigningKey) { + logDebugMessage( + "getSession: Returning TRY_REFRESH_TOKEN because the access token doesn't match the useDynamicAccessTokenSigningKey in the config" + ); + throw new STError({ + message: "The access token doesn't match the useDynamicAccessTokenSigningKey setting", + type: STError.TRY_REFRESH_TOKEN, + }); + } } - + // If we get here we either have a V2 token that doesn't pass verification or a valid V3> token /** * anti-csrf check if accesstokenInfo is not undefined, * which means token verification was successful */ if (doAntiCsrfCheck) { - if (handShakeInfo.antiCsrf === "VIA_TOKEN") { + if (helpers.config.antiCsrf === "VIA_TOKEN") { if (accessTokenInfo !== undefined) { if (antiCsrfToken === undefined || antiCsrfToken !== accessTokenInfo.antiCsrfToken) { if (antiCsrfToken === undefined) { @@ -190,57 +178,42 @@ export async function getSession( } } } - } else if (handShakeInfo.antiCsrf === "VIA_CUSTOM_HEADER") { - if (!containsCustomHeader) { - logDebugMessage("getSession: Returning TRY_REFRESH_TOKEN because custom header (rid) was not passed"); - throw new STError({ - message: - "anti-csrf check failed. Please pass 'rid: \"session\"' header in the request, or set doAntiCsrfCheck to false for this API", - type: STError.TRY_REFRESH_TOKEN, - }); - } + } else if (helpers.config.antiCsrf === "VIA_CUSTOM_HEADER") { + // The function should never be called by this (we check this outside the function as well) + // There we can add a bit more information to the error, so that's the primary check, this is just making sure. + throw new Error("Please either use VIA_TOKEN, NONE or call with doAntiCsrfCheck false"); } } - if ( - accessTokenInfo !== undefined && - !handShakeInfo.accessTokenBlacklistingEnabled && - accessTokenInfo.parentRefreshTokenHash1 === undefined - ) { + + if (accessTokenInfo !== undefined && !alwaysCheckCore && accessTokenInfo.parentRefreshTokenHash1 === undefined) { return { session: { handle: accessTokenInfo.sessionHandle, userId: accessTokenInfo.userId, recipeUserId: accessTokenInfo.recipeUserId, userDataInJWT: accessTokenInfo.userData, + expiryTime: accessTokenInfo.expiryTime, }, }; } ProcessState.getInstance().addState(PROCESS_STATE.CALLING_SERVICE_IN_VERIFY); - let requestBody: { - accessToken: string; - antiCsrfToken?: string; - doAntiCsrfCheck: boolean; - enableAntiCsrf?: boolean; - } = { + let requestBody = { accessToken: parsedAccessToken.rawTokenString, antiCsrfToken, doAntiCsrfCheck, - enableAntiCsrf: handShakeInfo.antiCsrf === "VIA_TOKEN", + enableAntiCsrf: helpers.config.antiCsrf === "VIA_TOKEN", + checkDatabase: alwaysCheckCore, }; let response = await helpers.querier.sendPostRequest(new NormalisedURLPath("/recipe/session/verify"), requestBody); if (response.status === "OK") { - helpers.updateJwtSigningPublicKeyInfo( - response.jwtSigningPublicKeyList, - response.jwtSigningPublicKey, - response.jwtSigningPublicKeyExpiryTime - ); delete response.status; - delete response.jwtSigningPublicKey; - delete response.jwtSigningPublicKeyExpiryTime; - delete response.jwtSigningPublicKeyList; + response.session.expiryTime = + response.accessToken?.expiry || // if we got a new accesstoken we take the expiry time from there + accessTokenInfo?.expiryTime || // if we didn't get a new access token but could validate the token take that info (alwaysCheckCore === true, or parentRefreshTokenHash1 !== null) + parsedAccessToken.payload["expiryTime"]; // if the token didn't pass validation, but we got here, it means it was a v2 token that we didn't have the key cached for. return response; } else if (response.status === "UNAUTHORISED") { logDebugMessage("getSession: Returning UNAUTHORISED because of core response"); @@ -249,20 +222,6 @@ export async function getSession( type: STError.UNAUTHORISED, }); } else { - if ( - response.jwtSigningPublicKeyList !== undefined || - (response.jwtSigningPublicKey !== undefined && response.jwtSigningPublicKeyExpiryTime !== undefined) - ) { - // after CDI 2.7.1, the API returns the new keys - helpers.updateJwtSigningPublicKeyInfo( - response.jwtSigningPublicKeyList, - response.jwtSigningPublicKey, - response.jwtSigningPublicKeyExpiryTime - ); - } else { - // we force update the signing keys... - await helpers.getHandshakeInfo(true); - } logDebugMessage("getSession: Returning TRY_REFRESH_TOKEN because of core response."); throw new STError({ message: response.message, @@ -291,10 +250,10 @@ export async function getSessionInformation( if (response.status === "OK") { // Change keys to make them more readable - response["sessionData"] = response.userDataInDatabase; - response["accessTokenPayload"] = response.userDataInJWT; + response["sessionDataInDatabase"] = response.userDataInDatabase; + response["customClaimsInAccessTokenPayload"] = response.userDataInJWT; - delete response.userDataInJWT; + delete response.userDataInDatabase; delete response.userDataInJWT; return response; @@ -311,11 +270,8 @@ export async function refreshSession( helpers: Helpers, refreshToken: string, antiCsrfToken: string | undefined, - containsCustomHeader: boolean, - transferMethod: TokenTransferMethod + disableAntiCsrf: boolean ): Promise { - let handShakeInfo = await helpers.getHandshakeInfo(); - let requestBody: { refreshToken: string; antiCsrfToken?: string; @@ -323,20 +279,13 @@ export async function refreshSession( } = { refreshToken, antiCsrfToken, - enableAntiCsrf: transferMethod === "cookie" && handShakeInfo.antiCsrf === "VIA_TOKEN", + enableAntiCsrf: !disableAntiCsrf && helpers.config.antiCsrf === "VIA_TOKEN", }; - if (handShakeInfo.antiCsrf === "VIA_CUSTOM_HEADER" && transferMethod === "cookie") { - if (!containsCustomHeader) { - logDebugMessage("refreshSession: Returning UNAUTHORISED because custom header (rid) was not passed"); - throw new STError({ - message: "anti-csrf check failed. Please pass 'rid: \"session\"' header in the request.", - type: STError.UNAUTHORISED, - payload: { - clearTokens: false, // see https://github.com/supertokens/supertokens-node/issues/141 - }, - }); - } + if (helpers.config.antiCsrf === "VIA_CUSTOM_HEADER" && !disableAntiCsrf) { + // The function should never be called by this (we check this outside the function as well) + // There we can add a bit more information to the error, so that's the primary check, this is just making sure. + throw new Error("Please either use VIA_TOKEN, NONE or call with doAntiCsrfCheck false"); } let response = await helpers.querier.sendPostRequest(new NormalisedURLPath("/recipe/session/refresh"), requestBody); @@ -409,7 +358,7 @@ export async function revokeMultipleSessions(helpers: Helpers, sessionHandles: s /** * @description: It provides no locking mechanism in case other processes are updating session data for this session as well. */ -export async function updateSessionData( +export async function updateSessionDataInDatabase( helpers: Helpers, sessionHandle: string, newSessionData: any diff --git a/lib/ts/recipe/session/sessionRequestFunctions.ts b/lib/ts/recipe/session/sessionRequestFunctions.ts new file mode 100644 index 000000000..0e7d9f400 --- /dev/null +++ b/lib/ts/recipe/session/sessionRequestFunctions.ts @@ -0,0 +1,420 @@ +import Recipe from "./recipe"; +import { + VerifySessionOptions, + RecipeInterface, + TokenTransferMethod, + TypeNormalisedInput, + SessionContainerInterface, +} from "./types"; +import frameworks from "../../framework"; +import SuperTokens from "../../supertokens"; +import { getRequiredClaimValidators } from "./utils"; +import { getRidFromHeader, isAnIpAddress, normaliseHttpMethod, setRequestInUserContextIfNotDefined } from "../../utils"; +import { logDebugMessage } from "../../logger"; +import { availableTokenTransferMethods } from "./constants"; +import { clearSession, getAntiCsrfTokenFromHeaders, getToken, setCookie } from "./cookieAndHeaders"; +import { ParsedJWTInfo, parseJWTWithoutSignatureVerification } from "./jwt"; +import { validateAccessTokenStructure } from "./accessToken"; +import { NormalisedAppinfo } from "../../types"; +import SessionError from "./error"; + +// We are defining this here (and not exporting it) to reduce the scope of legacy code +const LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME = "sIdRefreshToken"; + +export async function getSessionFromRequest({ + req, + res, + config, + recipeInterfaceImpl, + options, + userContext, +}: { + req: any; + res: any; + config: TypeNormalisedInput; + recipeInterfaceImpl: RecipeInterface; + options?: VerifySessionOptions; + userContext?: any; +}): Promise { + logDebugMessage("getSession: Started"); + if (!res.wrapperUsed) { + res = frameworks[SuperTokens.getInstanceOrThrowError().framework].wrapResponse(res); + } + if (!req.wrapperUsed) { + req = frameworks[SuperTokens.getInstanceOrThrowError().framework].wrapRequest(req); + } + userContext = setRequestInUserContextIfNotDefined(userContext, req); + logDebugMessage("getSession: Wrapping done"); + + // This token isn't handled by getToken to limit the scope of this legacy/migration code + if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { + // This could create a spike on refresh calls during the update of the backend SDK + throw new SessionError({ + message: "using legacy session, please call the refresh API", + type: SessionError.TRY_REFRESH_TOKEN, + }); + } + + const sessionOptional = options?.sessionRequired === false; + logDebugMessage("getSession: optional validation: " + sessionOptional); + + const accessTokens: { + [key in TokenTransferMethod]?: ParsedJWTInfo; + } = {}; + + // We check all token transfer methods for available access tokens + for (const transferMethod of availableTokenTransferMethods) { + const tokenString = getToken(req, "access", transferMethod); + if (tokenString !== undefined) { + try { + const info = parseJWTWithoutSignatureVerification(tokenString); + validateAccessTokenStructure(info.payload, info.version); + logDebugMessage("getSession: got access token from " + transferMethod); + accessTokens[transferMethod] = info; + } catch { + logDebugMessage( + `getSession: ignoring token in ${transferMethod}, because it doesn't match our access token structure` + ); + } + } + } + + const allowedTransferMethod = config.getTokenTransferMethod({ + req, + forCreateNewSession: false, + userContext, + }); + let requestTransferMethod: TokenTransferMethod; + let accessToken: ParsedJWTInfo | undefined; + + if ( + (allowedTransferMethod === "any" || allowedTransferMethod === "header") && + accessTokens["header"] !== undefined + ) { + logDebugMessage("getSession: using header transfer method"); + requestTransferMethod = "header"; + accessToken = accessTokens["header"]; + } else if ( + (allowedTransferMethod === "any" || allowedTransferMethod === "cookie") && + accessTokens["cookie"] !== undefined + ) { + logDebugMessage("getSession: using cookie transfer method"); + requestTransferMethod = "cookie"; + accessToken = accessTokens["cookie"]; + } else { + if (sessionOptional) { + logDebugMessage( + "getSession: returning undefined because accessToken is undefined and sessionRequired is false" + ); + // there is no session that exists here, and the user wants session verification + // to be optional. So we return undefined. + return undefined; + } + + logDebugMessage("getSession: UNAUTHORISED because accessToken in request is undefined"); + throw new SessionError({ + message: + "Session does not exist. Are you sending the session tokens in the request with the appropriate token transfer method?", + type: SessionError.UNAUTHORISED, + payload: { + // we do not clear the session here because of a + // race condition mentioned here: https://github.com/supertokens/supertokens-node/issues/17 + clearTokens: false, + }, + }); + } + + let antiCsrfToken = getAntiCsrfTokenFromHeaders(req); + let doAntiCsrfCheck = options !== undefined ? options.antiCsrfCheck : undefined; + + if (doAntiCsrfCheck === undefined) { + doAntiCsrfCheck = normaliseHttpMethod(req.getMethod()) !== "get"; + } + + if (requestTransferMethod === "header") { + doAntiCsrfCheck = false; + } + + if (doAntiCsrfCheck && config.antiCsrf === "VIA_CUSTOM_HEADER") { + if (config.antiCsrf === "VIA_CUSTOM_HEADER") { + if (getRidFromHeader(req) === undefined) { + logDebugMessage("getSession: Returning TRY_REFRESH_TOKEN because custom header (rid) was not passed"); + throw new SessionError({ + message: + "anti-csrf check failed. Please pass 'rid: \"session\"' header in the request, or set doAntiCsrfCheck to false for this API", + type: SessionError.TRY_REFRESH_TOKEN, + }); + } + logDebugMessage("getSession: VIA_CUSTOM_HEADER anti-csrf check passed"); + doAntiCsrfCheck = false; + } + } + + logDebugMessage("getSession: Value of doAntiCsrfCheck is: " + doAntiCsrfCheck); + const session = await recipeInterfaceImpl.getSession({ + accessToken: accessToken.rawTokenString, + antiCsrfToken, + options: { ...options, antiCsrfCheck: doAntiCsrfCheck }, + userContext, + }); + + if (session !== undefined) { + const claimValidators = await getRequiredClaimValidators( + session, + options?.overrideGlobalClaimValidators, + userContext + ); + await session.assertClaims(claimValidators, userContext); + + await session.attachToRequestResponse({ + req, + res, + transferMethod: requestTransferMethod, + }); + } + return session; +} + +/* + In all cases: if sIdRefreshToken token exists (so it's a legacy session) we clear it. + Check http://localhost:3002/docs/contribute/decisions/session/0008 for further details and a table of expected behaviours +*/ +export async function refreshSessionInRequest({ + res, + req, + userContext, + config, + recipeInterfaceImpl, +}: { + res: any; + req: any; + userContext: any; + config: TypeNormalisedInput; + recipeInterfaceImpl: RecipeInterface; +}) { + logDebugMessage("refreshSession: Started"); + if (!res.wrapperUsed) { + res = frameworks[SuperTokens.getInstanceOrThrowError().framework].wrapResponse(res); + } + if (!req.wrapperUsed) { + req = frameworks[SuperTokens.getInstanceOrThrowError().framework].wrapRequest(req); + } + userContext = setRequestInUserContextIfNotDefined(userContext, req); + logDebugMessage("refreshSession: Wrapping done"); + + const refreshTokens: { + [key in TokenTransferMethod]?: string; + } = {}; + + // We check all token transfer methods for available refresh tokens + // We do this so that we can later clear all we are not overwriting + for (const transferMethod of availableTokenTransferMethods) { + refreshTokens[transferMethod] = getToken(req, "refresh", transferMethod); + if (refreshTokens[transferMethod] !== undefined) { + logDebugMessage("refreshSession: got refresh token from " + transferMethod); + } + } + + const allowedTransferMethod = config.getTokenTransferMethod({ + req, + forCreateNewSession: false, + userContext, + }); + logDebugMessage("refreshSession: getTokenTransferMethod returned " + allowedTransferMethod); + + let requestTransferMethod: TokenTransferMethod; + let refreshToken: string | undefined; + + if ( + (allowedTransferMethod === "any" || allowedTransferMethod === "header") && + refreshTokens["header"] !== undefined + ) { + logDebugMessage("refreshSession: using header transfer method"); + requestTransferMethod = "header"; + refreshToken = refreshTokens["header"]; + } else if ((allowedTransferMethod === "any" || allowedTransferMethod === "cookie") && refreshTokens["cookie"]) { + logDebugMessage("refreshSession: using cookie transfer method"); + requestTransferMethod = "cookie"; + refreshToken = refreshTokens["cookie"]; + } else { + // This token isn't handled by getToken/setToken to limit the scope of this legacy/migration code + if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { + logDebugMessage("refreshSession: cleared legacy id refresh token because refresh token was not found"); + setCookie(config, res, LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, "", 0, "accessTokenPath"); + } + + logDebugMessage("refreshSession: UNAUTHORISED because refresh token in request is undefined"); + throw new SessionError({ + message: "Refresh token not found. Are you sending the refresh token in the request?", + payload: { + clearTokens: false, + }, + type: SessionError.UNAUTHORISED, + }); + } + let disableAntiCsrf = requestTransferMethod === "header"; + const antiCsrfToken = getAntiCsrfTokenFromHeaders(req); + + if (config.antiCsrf === "VIA_CUSTOM_HEADER" && !disableAntiCsrf) { + if (getRidFromHeader(req) === undefined) { + logDebugMessage("refreshSession: Returning UNAUTHORISED because custom header (rid) was not passed"); + throw new SessionError({ + message: "anti-csrf check failed. Please pass 'rid: \"session\"' header in the request.", + type: SessionError.UNAUTHORISED, + payload: { + clearTokens: false, // see https://github.com/supertokens/supertokens-node/issues/141 + }, + }); + } + disableAntiCsrf = true; + } + + let session; + try { + session = await recipeInterfaceImpl.refreshSession({ + refreshToken: refreshToken, + antiCsrfToken, + disableAntiCsrf, + userContext, + }); + } catch (ex) { + if ( + SessionError.isErrorFromSuperTokens(ex) && + (ex.type === SessionError.TOKEN_THEFT_DETECTED || ex.payload.clearTokens === true) + ) { + // We clear the LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME here because we want to limit the scope of this legacy/migration code + // so the token clearing functions in the error handlers do not + if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { + logDebugMessage( + "refreshSession: cleared legacy id refresh token because refresh is clearing other tokens" + ); + setCookie(config, res, LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, "", 0, "accessTokenPath"); + } + } + throw ex; + } + logDebugMessage("refreshSession: Attaching refreshed session info as " + requestTransferMethod); + + // We clear the tokens in all token transfer methods we are not going to overwrite + for (const transferMethod of availableTokenTransferMethods) { + if (transferMethod !== requestTransferMethod && refreshTokens[transferMethod] !== undefined) { + clearSession(config, res, transferMethod); + } + } + await session.attachToRequestResponse({ + req, + res, + transferMethod: requestTransferMethod, + }); + + logDebugMessage("refreshSession: Success!"); + + // This token isn't handled by getToken/setToken to limit the scope of this legacy/migration code + if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { + logDebugMessage("refreshSession: cleared legacy id refresh token after successful refresh"); + setCookie(config, res, LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, "", 0, "accessTokenPath"); + } + + return session; +} + +export async function createNewSessionInRequest({ + req, + res, + userContext, + recipeInstance, + accessTokenPayload, + userId, + recipeUserId, + config, + appInfo, + sessionDataInDatabase, +}: { + req: any; + res: any; + userContext: any; + recipeInstance: Recipe; + accessTokenPayload: any; + userId: string; + recipeUserId: string | undefined; + config: TypeNormalisedInput; + appInfo: NormalisedAppinfo; + sessionDataInDatabase: any; +}) { + logDebugMessage("createNewSession: Started"); + if (!req.wrapperUsed) { + req = frameworks[SuperTokens.getInstanceOrThrowError().framework].wrapRequest(req); + } + + if (!res.wrapperUsed) { + res = frameworks[SuperTokens.getInstanceOrThrowError().framework].wrapResponse(res); + } + logDebugMessage("createNewSession: Wrapping done"); + userContext = setRequestInUserContextIfNotDefined(userContext, req); + + const claimsAddedByOtherRecipes = recipeInstance.getClaimsAddedByOtherRecipes(); + const issuer = appInfo.apiDomain.getAsStringDangerous() + appInfo.apiBasePath.getAsStringDangerous(); + + let finalAccessTokenPayload = { + ...accessTokenPayload, + iss: issuer, + }; + + for (const claim of claimsAddedByOtherRecipes) { + const update = await claim.build(userId, userContext); + finalAccessTokenPayload = { + ...finalAccessTokenPayload, + ...update, + }; + } + logDebugMessage("createNewSession: Access token payload built"); + + let outputTransferMethod = config.getTokenTransferMethod({ req, forCreateNewSession: true, userContext }); + if (outputTransferMethod === "any") { + outputTransferMethod = "header"; + } + logDebugMessage("createNewSession: using transfer method " + outputTransferMethod); + + if ( + outputTransferMethod === "cookie" && + config.cookieSameSite === "none" && + !config.cookieSecure && + !( + (appInfo.topLevelAPIDomain === "localhost" || isAnIpAddress(appInfo.topLevelAPIDomain)) && + (appInfo.topLevelWebsiteDomain === "localhost" || isAnIpAddress(appInfo.topLevelWebsiteDomain)) + ) + ) { + // We can allow insecure cookie when both website & API domain are localhost or an IP + // When either of them is a different domain, API domain needs to have https and a secure cookie to work + throw new Error( + "Since your API and website domain are different, for sessions to work, please use https on your apiDomain and dont set cookieSecure to false." + ); + } + const disableAntiCsrf = outputTransferMethod === "header"; + const session = await recipeInstance.recipeInterfaceImpl.createNewSession({ + userId, + recipeUserId, + accessTokenPayload: finalAccessTokenPayload, + sessionDataInDatabase, + disableAntiCsrf, + userContext, + }); + + logDebugMessage("createNewSession: Session created in core built"); + + for (const transferMethod of availableTokenTransferMethods) { + if (transferMethod !== outputTransferMethod && getToken(req, "access", transferMethod) !== undefined) { + clearSession(config, res, transferMethod); + } + } + logDebugMessage("createNewSession: Cleared old tokens"); + + await session.attachToRequestResponse({ + req, + res, + transferMethod: outputTransferMethod, + }); + logDebugMessage("createNewSession: Attached new tokens to res"); + + return session; +} diff --git a/lib/ts/recipe/session/types.ts b/lib/ts/recipe/session/types.ts index 6dd69274a..a6e99ac01 100644 --- a/lib/ts/recipe/session/types.ts +++ b/lib/ts/recipe/session/types.ts @@ -27,23 +27,12 @@ export type KeyInfo = { }; export type AntiCsrfType = "VIA_TOKEN" | "VIA_CUSTOM_HEADER" | "NONE"; -export type StoredHandshakeInfo = { - antiCsrf: AntiCsrfType; - accessTokenBlacklistingEnabled: boolean; - accessTokenValidity: number; - refreshTokenValidity: number; -} & ( - | { - // Stored after 2.9 - jwtSigningPublicKeyList: KeyInfo[]; - } - | { - // Stored before 2.9 - jwtSigningPublicKeyList: undefined; - jwtSigningPublicKey: string; - jwtSigningPublicKeyExpiryTime: number; - } -); + +export type TokenInfo = { + token: string; + expiry: number; + createdTime: number; +}; export type CreateOrRefreshAPIResponse = { session: { @@ -52,16 +41,8 @@ export type CreateOrRefreshAPIResponse = { recipeUserId: string; userDataInJWT: any; }; - accessToken: { - token: string; - expiry: number; - createdTime: number; - }; - refreshToken: { - token: string; - expiry: number; - createdTime: number; - }; + accessToken: TokenInfo; + refreshToken: TokenInfo; antiCsrfToken: string | undefined; }; @@ -77,9 +58,10 @@ export type TokenType = "access" | "refresh"; export type TokenTransferMethod = "header" | "cookie"; export type TypeInput = { + useDynamicAccessTokenSigningKey?: boolean; sessionExpiredStatusCode?: number; invalidClaimStatusCode?: number; - + accessTokenPath?: string; cookieSecure?: boolean; cookieSameSite?: "strict" | "lax" | "none"; cookieDomain?: string; @@ -92,13 +74,7 @@ export type TypeInput = { errorHandlers?: ErrorHandlers; antiCsrf?: "VIA_TOKEN" | "VIA_CUSTOM_HEADER" | "NONE"; - jwt?: - | { - enable: true; - propertyNameInAccessTokenPayload?: string; - issuer?: string; - } - | { enable: false }; + exposeAccessTokenToFrontendInCookieBasedAuth?: boolean; override?: { functions?: ( originalImplementation: RecipeInterface, @@ -129,7 +105,9 @@ export type TypeInput = { }; export type TypeNormalisedInput = { + useDynamicAccessTokenSigningKey: boolean; refreshTokenPath: NormalisedURLPath; + accessTokenPath: NormalisedURLPath; cookieDomain: string | undefined; cookieSameSite: "strict" | "lax" | "none"; cookieSecure: boolean; @@ -144,11 +122,7 @@ export type TypeNormalisedInput = { }) => TokenTransferMethod | "any"; invalidClaimStatusCode: number; - jwt: { - enable: boolean; - propertyNameInAccessTokenPayload: string; - issuer?: string; - }; + exposeAccessTokenToFrontendInCookieBasedAuth: boolean; override: { functions: ( originalImplementation: RecipeInterface, @@ -210,6 +184,7 @@ export interface NormalisedErrorHandlers { export interface VerifySessionOptions { antiCsrfCheck?: boolean; sessionRequired?: boolean; + checkDatabase?: boolean; overrideGlobalClaimValidators?: ( globalClaimValidators: SessionClaimValidator[], session: SessionContainerInterface, @@ -219,12 +194,11 @@ export interface VerifySessionOptions { export type RecipeInterface = { createNewSession(input: { - req: BaseRequest; - res: BaseResponse; userId: string; - recipeUserId?: string; + recipeUserId: string | undefined; accessTokenPayload?: any; - sessionData?: any; + sessionDataInDatabase?: any; + disableAntiCsrf?: boolean; userContext: any; }): Promise; @@ -236,20 +210,22 @@ export type RecipeInterface = { }): Promise | SessionClaimValidator[]; getSession(input: { - req: BaseRequest; - res: BaseResponse; + accessToken: string; + antiCsrfToken?: string; options?: VerifySessionOptions; userContext: any; }): Promise; refreshSession(input: { - req: BaseRequest; - res: BaseResponse; + refreshToken: string; + antiCsrfToken?: string; + disableAntiCsrf: boolean; userContext: any; }): Promise; + /** * Used to retrieve all session information for a given session handle. Can be used in place of: - * - getSessionData + * - getSessionDataFromDatabase * - getAccessTokenPayload * * Returns undefined if the sessionHandle does not exist @@ -265,15 +241,9 @@ export type RecipeInterface = { revokeMultipleSessions(input: { sessionHandles: string[]; userContext: any }): Promise; // Returns false if the sessionHandle does not exist - updateSessionData(input: { sessionHandle: string; newSessionData: any; userContext: any }): Promise; - - /** - * @deprecated Use mergeIntoAccessTokenPayload instead - * @returns {Promise} Returns false if the sessionHandle does not exist - */ - updateAccessTokenPayload(input: { + updateSessionDataInDatabase(input: { sessionHandle: string; - newAccessTokenPayload: any; + newSessionData: any; userContext: any; }): Promise; @@ -308,10 +278,6 @@ export type RecipeInterface = { | undefined >; - getAccessTokenLifeTimeMS(input: { userContext: any }): Promise; - - getRefreshTokenLifeTimeMS(input: { userContext: any }): Promise; - validateClaims(input: { userId: string; recipeUserId: string; @@ -350,9 +316,9 @@ export type RecipeInterface = { export interface SessionContainerInterface { revokeSession(userContext?: any): Promise; - getSessionData(userContext?: any): Promise; + getSessionDataFromDatabase(userContext?: any): Promise; - updateSessionData(newSessionData: any, userContext?: any): Promise; + updateSessionDataInDatabase(newSessionData: any, userContext?: any): Promise; getUserId(userContext?: any): string; @@ -362,12 +328,16 @@ export interface SessionContainerInterface { getHandle(userContext?: any): string; + getAllSessionTokensDangerously(): { + accessToken: string; + refreshToken: string | undefined; + antiCsrfToken: string | undefined; + frontToken: string; + accessAndFrontTokenUpdated: boolean; + }; + getAccessToken(userContext?: any): string; - /** - * @deprecated Use mergeIntoAccessTokenPayload instead - */ - updateAccessTokenPayload(newAccessTokenPayload: any, userContext?: any): Promise; mergeIntoAccessTokenPayload(accessTokenPayloadUpdate: JSONObject, userContext?: any): Promise; getTimeCreated(userContext?: any): Promise; @@ -379,6 +349,7 @@ export interface SessionContainerInterface { setClaimValue(claim: SessionClaim, value: T, userContext?: any): Promise; getClaimValue(claim: SessionClaim, userContext?: any): Promise; removeClaim(claim: SessionClaim, userContext?: any): Promise; + attachToRequestResponse(reqResInfo: ReqResInfo): Promise | void; } export type APIOptions = { @@ -426,9 +397,9 @@ export type SessionInformation = { sessionHandle: string; userId: string; recipeUserId: string; - sessionData: any; + sessionDataInDatabase: any; expiry: number; - accessTokenPayload: any; + customClaimsInAccessTokenPayload: any; timeCreated: number; }; @@ -505,3 +476,9 @@ export abstract class SessionClaim { return this.addToPayload_internal({}, value, userContext); } } + +export type ReqResInfo = { + res: BaseResponse; + req: BaseRequest; + transferMethod: TokenTransferMethod; +}; diff --git a/lib/ts/recipe/session/utils.ts b/lib/ts/recipe/session/utils.ts index 528b4f8bb..3fe27cf45 100644 --- a/lib/ts/recipe/session/utils.ts +++ b/lib/ts/recipe/session/utils.ts @@ -14,7 +14,6 @@ */ import { - CreateOrRefreshAPIResponse, TypeInput, TypeNormalisedInput, NormalisedErrorHandlers, @@ -24,17 +23,16 @@ import { VerifySessionOptions, TokenTransferMethod, } from "./types"; -import { setFrontTokenInHeaders, setAntiCsrfTokenInHeaders, setToken, getAuthModeFromHeader } from "./cookieAndHeaders"; +import { setFrontTokenInHeaders, setToken, getAuthModeFromHeader } from "./cookieAndHeaders"; import { URL } from "url"; import SessionRecipe from "./recipe"; -import { REFRESH_API_PATH } from "./constants"; +import { REFRESH_API_PATH, hundredYearsInMs } from "./constants"; import NormalisedURLPath from "../../normalisedURLPath"; import { NormalisedAppinfo } from "../../types"; import { isAnIpAddress } from "../../utils"; import { RecipeInterface, APIInterface } from "./types"; import { BaseRequest, BaseResponse } from "../../framework"; import { sendNon200ResponseWithMessage, sendNon200Response } from "../../utils"; -import { ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY, JWT_RESERVED_KEY_USE_ERROR_MESSAGE } from "./with-jwt/constants"; import { logDebugMessage } from "../../logger"; export async function sendTryRefreshTokenResponse( @@ -134,7 +132,10 @@ export function validateAndNormaliseUserInput( config === undefined || config.cookieDomain === undefined ? undefined : normaliseSessionScopeOrThrowError(config.cookieDomain); - + let accessTokenPath = + config === undefined || config.accessTokenPath === undefined + ? new NormalisedURLPath("/") + : new NormalisedURLPath(config.accessTokenPath); let protocolOfAPIDomain = getURLProtocol(appInfo.apiDomain.getAsStringDangerous()); let protocolOfWebsiteDomain = getURLProtocol(appInfo.websiteDomain.getAsStringDangerous()); @@ -212,24 +213,6 @@ export function validateAndNormaliseUserInput( } } - let enableJWT = false; - let accessTokenPayloadJWTPropertyName = "jwt"; - let issuer: string | undefined; - - if (config !== undefined && config.jwt !== undefined && config.jwt.enable === true) { - enableJWT = true; - let jwtPropertyName = config.jwt.propertyNameInAccessTokenPayload; - issuer = config.jwt.issuer; - - if (jwtPropertyName !== undefined) { - if (jwtPropertyName === ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY) { - throw new Error(JWT_RESERVED_KEY_USE_ERROR_MESSAGE); - } - - accessTokenPayloadJWTPropertyName = jwtPropertyName; - } - } - let override = { functions: (originalImplementation: RecipeInterface) => originalImplementation, apis: (originalImplementation: APIInterface) => originalImplementation, @@ -237,7 +220,10 @@ export function validateAndNormaliseUserInput( }; return { + useDynamicAccessTokenSigningKey: config?.useDynamicAccessTokenSigningKey ?? true, + exposeAccessTokenToFrontendInCookieBasedAuth: config?.exposeAccessTokenToFrontendInCookieBasedAuth ?? false, refreshTokenPath: appInfo.apiBasePath.appendPath(new NormalisedURLPath(REFRESH_API_PATH)), + accessTokenPath, getTokenTransferMethod: config?.getTokenTransferMethod === undefined ? defaultGetTokenTransferMethod @@ -250,11 +236,6 @@ export function validateAndNormaliseUserInput( antiCsrf, override, invalidClaimStatusCode, - jwt: { - enable: enableJWT, - propertyNameInAccessTokenPayload: accessTokenPayloadJWTPropertyName, - issuer, - }, }; } @@ -267,30 +248,40 @@ export function normaliseSameSiteOrThrowError(sameSite: string): "strict" | "lax return sameSite; } -export function attachTokensToResponse( - config: TypeNormalisedInput, +export function setAccessTokenInResponse( res: BaseResponse, - response: CreateOrRefreshAPIResponse, + accessToken: string, + frontToken: string, + config: TypeNormalisedInput, transferMethod: TokenTransferMethod ) { - let accessToken = response.accessToken; - let refreshToken = response.refreshToken; - setFrontTokenInHeaders(res, response.session.userId, response.accessToken.expiry, response.session.userDataInJWT); + setFrontTokenInHeaders(res, frontToken); setToken( config, res, "access", - accessToken.token, + accessToken, // We set the expiration to 100 years, because we can't really access the expiration of the refresh token everywhere we are setting it. // This should be safe to do, since this is only the validity of the cookie (set here or on the frontend) but we check the expiration of the JWT anyway. - // Even if the token is expired the presence of the token indicates that the user could have a valid refresh - // Setting them to infinity would require special case handling on the frontend and just adding 10 years seems enough. - Date.now() + 3153600000000, + // Even if the token is expired the presence of the token indicates that the user could have a valid refresh token + // Setting them to infinity would require special case handling on the frontend and just adding 100 years seems enough. + Date.now() + hundredYearsInMs, transferMethod ); - setToken(config, res, "refresh", refreshToken.token, refreshToken.expiry, transferMethod); - if (response.antiCsrfToken !== undefined) { - setAntiCsrfTokenInHeaders(res, response.antiCsrfToken); + + if (config.exposeAccessTokenToFrontendInCookieBasedAuth && transferMethod === "cookie") { + setToken( + config, + res, + "access", + accessToken, + // We set the expiration to 100 years, because we can't really access the expiration of the refresh token everywhere we are setting it. + // This should be safe to do, since this is only the validity of the cookie (set here or on the frontend) but we check the expiration of the JWT anyway. + // Even if the token is expired the presence of the token indicates that the user could have a valid refresh token + // Setting them to infinity would require special case handling on the frontend and just adding 100 years seems enough. + Date.now() + hundredYearsInMs, + "header" + ); } } diff --git a/lib/ts/recipe/session/with-jwt/constants.ts b/lib/ts/recipe/session/with-jwt/constants.ts deleted file mode 100644 index 1ec1b8482..000000000 --- a/lib/ts/recipe/session/with-jwt/constants.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ -/* - This key is used to determine the property name used when adding the jwt to the access token payload - For example if the Session recipe is initialised with config - { - ... - jwt: { - enable: true, - propertyNameInAccessTokenPayload: "jwtKey", - }, - ... - } - - The access token payload after creating a session would look like - { - ... - jwtKey: "JWT_STRING", - _jwtPName: "jwtKey", - } - - When trying to refresh the session or updating the access token payload, this key is used to determine and retrieve - the exsiting JWT from the access token payload. -*/ -export const ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY = "_jwtPName"; -export const JWT_RESERVED_KEY_USE_ERROR_MESSAGE = `${ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY} is a reserved property name, please use a different key name for the jwt`; diff --git a/lib/ts/recipe/session/with-jwt/recipeImplementation.ts b/lib/ts/recipe/session/with-jwt/recipeImplementation.ts deleted file mode 100644 index 699a62281..000000000 --- a/lib/ts/recipe/session/with-jwt/recipeImplementation.ts +++ /dev/null @@ -1,259 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ -import { decode } from "jsonwebtoken"; - -import { RecipeInterface } from "../"; -import { RecipeInterface as OpenIdRecipeInterface } from "../../openid/types"; -import { SessionContainerInterface, SessionInformation, TypeNormalisedInput, VerifySessionOptions } from "../types"; -import { ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY } from "./constants"; -import SessionClassWithJWT from "./sessionClass"; -import * as assert from "assert"; -import { addJWTToAccessTokenPayload } from "./utils"; -import { JSONObject } from "../../../types"; -import { BaseResponse } from "../../../framework/response"; -import { BaseRequest } from "../../../framework/request"; - -// Time difference between JWT expiry and access token expiry (JWT expiry = access token expiry + EXPIRY_OFFSET_SECONDS) -let EXPIRY_OFFSET_SECONDS = 30; - -// This function should only be used during testing -export function setJWTExpiryOffsetSecondsForTesting(offset: number) { - if (process.env.TEST_MODE !== "testing") { - throw Error("calling testing function in non testing env"); - } - EXPIRY_OFFSET_SECONDS = offset; -} - -export default function ( - originalImplementation: RecipeInterface, - openIdRecipeImplementation: OpenIdRecipeInterface, - config: TypeNormalisedInput -): RecipeInterface { - function getJWTExpiry(accessTokenExpiry: number): number { - return accessTokenExpiry + EXPIRY_OFFSET_SECONDS; - } - - async function jwtAwareUpdateAccessTokenPayload( - sessionInformation: SessionInformation, - newAccessTokenPayload: any, - userContext: any - ) { - let accessTokenPayload = sessionInformation.accessTokenPayload; - - let existingJwtPropertyName = accessTokenPayload[ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY]; - - if (existingJwtPropertyName === undefined) { - return await originalImplementation.updateAccessTokenPayload({ - sessionHandle: sessionInformation.sessionHandle, - newAccessTokenPayload, - userContext, - }); - } - - let existingJwt = accessTokenPayload[existingJwtPropertyName]; - assert.notStrictEqual(existingJwt, undefined); - - let currentTimeInSeconds = Date.now() / 1000; - let decodedPayload = decode(existingJwt, { json: true }); - - // decode possibly returns null - if (decodedPayload === null || decodedPayload.exp === undefined) { - throw new Error("Error reading JWT from session"); - } - - let jwtExpiry = decodedPayload.exp - currentTimeInSeconds; - - if (jwtExpiry <= 0) { - // it can come here if someone calls this function well after - // the access token and the jwt payload have expired. In this case, - // we still want the jwt payload to update, but the resulting JWT should - // not be alive for too long (since it's expired already). So we set it to - // 1 second lifetime. - jwtExpiry = 1; - } - - newAccessTokenPayload = await addJWTToAccessTokenPayload({ - accessTokenPayload: newAccessTokenPayload, - jwtExpiry, - userId: sessionInformation.userId, - jwtPropertyName: existingJwtPropertyName, - openIdRecipeImplementation, - userContext, - }); - - return await originalImplementation.updateAccessTokenPayload({ - sessionHandle: sessionInformation.sessionHandle, - newAccessTokenPayload, - userContext, - }); - } - - return { - ...originalImplementation, - createNewSession: async function ( - this: RecipeInterface, - { - req, - res, - userId, - recipeUserId, - accessTokenPayload, - sessionData, - userContext, - }: { - req: BaseRequest; - res: BaseResponse; - userId: string; - recipeUserId?: string; - accessTokenPayload?: any; - sessionData?: any; - userContext: any; - } - ): Promise { - accessTokenPayload = - accessTokenPayload === null || accessTokenPayload === undefined ? {} : accessTokenPayload; - let accessTokenValidityInSeconds = Math.ceil((await this.getAccessTokenLifeTimeMS({ userContext })) / 1000); - - accessTokenPayload = await addJWTToAccessTokenPayload({ - accessTokenPayload, - jwtExpiry: getJWTExpiry(accessTokenValidityInSeconds), - userId, - jwtPropertyName: config.jwt.propertyNameInAccessTokenPayload, - openIdRecipeImplementation, - userContext, - }); - - let sessionContainer = await originalImplementation.createNewSession({ - req, - res, - userId, - recipeUserId, - accessTokenPayload, - sessionData, - userContext, - }); - - return new SessionClassWithJWT(sessionContainer, openIdRecipeImplementation); - }, - getSession: async function ( - this: RecipeInterface, - { - req, - res, - options, - userContext, - }: { - req: BaseRequest; - res: BaseResponse; - options?: VerifySessionOptions; - userContext: any; - } - ): Promise { - let sessionContainer = await originalImplementation.getSession({ req, res, options, userContext }); - - if (sessionContainer === undefined) { - return undefined; - } - - return new SessionClassWithJWT(sessionContainer, openIdRecipeImplementation); - }, - refreshSession: async function ( - this: RecipeInterface, - { - req, - res, - userContext, - }: { - req: BaseRequest; - res: BaseResponse; - userContext: any; - } - ): Promise { - let accessTokenValidityInSeconds = Math.ceil((await this.getAccessTokenLifeTimeMS({ userContext })) / 1000); - - // Refresh session first because this will create a new access token - let newSession = await originalImplementation.refreshSession({ req, res, userContext }); - let accessTokenPayload = newSession.getAccessTokenPayload(); - - accessTokenPayload = await addJWTToAccessTokenPayload({ - accessTokenPayload, - jwtExpiry: getJWTExpiry(accessTokenValidityInSeconds), - userId: newSession.getUserId(), - jwtPropertyName: config.jwt.propertyNameInAccessTokenPayload, - openIdRecipeImplementation, - userContext, - }); - - await newSession.updateAccessTokenPayload(accessTokenPayload); - - return new SessionClassWithJWT(newSession, openIdRecipeImplementation); - }, - - mergeIntoAccessTokenPayload: async function ( - this: RecipeInterface, - { - sessionHandle, - accessTokenPayloadUpdate, - userContext, - }: { - sessionHandle: string; - accessTokenPayloadUpdate: JSONObject; - userContext: any; - } - ): Promise { - let sessionInformation = await this.getSessionInformation({ sessionHandle, userContext }); - - if (!sessionInformation) { - return false; - } - - let newAccessTokenPayload = { ...sessionInformation.accessTokenPayload, ...accessTokenPayloadUpdate }; - for (const key of Object.keys(accessTokenPayloadUpdate)) { - if (accessTokenPayloadUpdate[key] === null) { - delete newAccessTokenPayload[key]; - } - } - - return jwtAwareUpdateAccessTokenPayload(sessionInformation, newAccessTokenPayload, userContext); - }, - - /** - * @deprecated use mergeIntoAccessTokenPayload instead - */ - updateAccessTokenPayload: async function ( - this: RecipeInterface, - { - sessionHandle, - newAccessTokenPayload, - userContext, - }: { - sessionHandle: string; - newAccessTokenPayload: any; - userContext: any; - } - ): Promise { - newAccessTokenPayload = - newAccessTokenPayload === null || newAccessTokenPayload === undefined ? {} : newAccessTokenPayload; - - const sessionInformation = await this.getSessionInformation({ sessionHandle, userContext }); - - if (!sessionInformation) { - return false; - } - - return jwtAwareUpdateAccessTokenPayload(sessionInformation, newAccessTokenPayload, userContext); - }, - }; -} diff --git a/lib/ts/recipe/session/with-jwt/sessionClass.ts b/lib/ts/recipe/session/with-jwt/sessionClass.ts deleted file mode 100644 index 2875f5908..000000000 --- a/lib/ts/recipe/session/with-jwt/sessionClass.ts +++ /dev/null @@ -1,175 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ -import { decode } from "jsonwebtoken"; -import * as assert from "assert"; - -import { RecipeInterface as OpenIdRecipeInterface } from "../../openid/types"; -import { SessionClaim, SessionClaimValidator, SessionContainerInterface } from "../types"; -import { ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY } from "./constants"; -import { addJWTToAccessTokenPayload } from "./utils"; -import STError from "../error"; -import SessionRecipe from "../recipe"; - -export default class SessionClassWithJWT implements SessionContainerInterface { - constructor( - private readonly originalSessionClass: SessionContainerInterface, - private readonly openIdRecipeImplementation: OpenIdRecipeInterface - ) {} - - getRecipeUserId(userContext?: any): string { - return this.originalSessionClass.getRecipeUserId(userContext); - } - - revokeSession(userContext?: any): Promise { - return this.originalSessionClass.revokeSession(userContext); - } - getSessionData(userContext?: any): Promise { - return this.originalSessionClass.getSessionData(userContext); - } - updateSessionData(newSessionData: any, userContext?: any): Promise { - return this.originalSessionClass.updateSessionData(newSessionData, userContext); - } - getUserId(userContext?: any): string { - return this.originalSessionClass.getUserId(userContext); - } - getAccessTokenPayload(userContext?: any) { - return this.originalSessionClass.getAccessTokenPayload(userContext); - } - getHandle(userContext?: any): string { - return this.originalSessionClass.getHandle(userContext); - } - getAccessToken(userContext?: any): string { - return this.originalSessionClass.getAccessToken(userContext); - } - getTimeCreated(userContext?: any): Promise { - return this.originalSessionClass.getTimeCreated(userContext); - } - getExpiry(userContext?: any): Promise { - return this.originalSessionClass.getExpiry(userContext); - } - - // We copy the implementation here, since we want to override updateAccessTokenPayload - async assertClaims(claimValidators: SessionClaimValidator[], userContext?: any): Promise { - let validateClaimResponse = await SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.validateClaims({ - accessTokenPayload: this.getAccessTokenPayload(userContext), - userId: this.getUserId(userContext), - recipeUserId: this.getRecipeUserId(userContext), - claimValidators, - userContext, - }); - - if (validateClaimResponse.accessTokenPayloadUpdate !== undefined) { - await this.mergeIntoAccessTokenPayload(validateClaimResponse.accessTokenPayloadUpdate, userContext); - } - - if (validateClaimResponse.invalidClaims.length !== 0) { - throw new STError({ - type: "INVALID_CLAIMS", - message: "INVALID_CLAIMS", - payload: validateClaimResponse.invalidClaims, - }); - } - } - - // We copy the implementation here, since we want to override updateAccessTokenPayload - async fetchAndSetClaim(this: SessionClassWithJWT, claim: SessionClaim, userContext?: any) { - const update = await claim.build(this.getUserId(userContext), this.getRecipeUserId(userContext), userContext); - return this.mergeIntoAccessTokenPayload(update, userContext); - } - - // We copy the implementation here, since we want to override updateAccessTokenPayload - setClaimValue(this: SessionClassWithJWT, claim: SessionClaim, value: T, userContext?: any) { - const update = claim.addToPayload_internal({}, value, userContext); - return this.mergeIntoAccessTokenPayload(update, userContext); - } - - // We copy the implementation here, since we want to override updateAccessTokenPayload - async getClaimValue(this: SessionClassWithJWT, claim: SessionClaim, userContext?: any) { - return claim.getValueFromPayload(await this.getAccessTokenPayload(userContext), userContext); - } - - // We copy the implementation here, since we want to override updateAccessTokenPayload - removeClaim(this: SessionClassWithJWT, claim: SessionClaim, userContext?: any) { - const update = claim.removeFromPayloadByMerge_internal({}, userContext); - return this.mergeIntoAccessTokenPayload(update, userContext); - } - - // We copy the implementation here, since we want to override updateAccessTokenPayload - async mergeIntoAccessTokenPayload( - this: SessionClassWithJWT, - accessTokenPayloadUpdate: any, - userContext?: any - ): Promise { - const updatedPayload = { ...this.getAccessTokenPayload(userContext), ...accessTokenPayloadUpdate }; - for (const key of Object.keys(accessTokenPayloadUpdate)) { - if (accessTokenPayloadUpdate[key] === null) { - delete updatedPayload[key]; - } - } - - await this.updateAccessTokenPayload(updatedPayload, userContext); - } - - // TODO: figure out a proper way to override just this function - /** - * @deprecated use mergeIntoAccessTokenPayload instead - */ - async updateAccessTokenPayload( - this: SessionClassWithJWT, - newAccessTokenPayload: any | undefined, - userContext?: any - ): Promise { - newAccessTokenPayload = - newAccessTokenPayload === null || newAccessTokenPayload === undefined ? {} : newAccessTokenPayload; - let accessTokenPayload = this.getAccessTokenPayload(userContext); - let jwtPropertyName = accessTokenPayload[ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY]; - - if (jwtPropertyName === undefined) { - return this.originalSessionClass.updateAccessTokenPayload(newAccessTokenPayload, userContext); - } - - let existingJWT = accessTokenPayload[jwtPropertyName]; - assert.notStrictEqual(existingJWT, undefined); - - let currentTimeInSeconds = Date.now() / 1000; - let decodedPayload = decode(existingJWT, { json: true }); - - // JsonWebToken.decode possibly returns null - if (decodedPayload === null || decodedPayload.exp === undefined) { - throw new Error("Error reading JWT from session"); - } - - let jwtExpiry = decodedPayload.exp - currentTimeInSeconds; - - if (jwtExpiry <= 0) { - // it can come here if someone calls this function well after - // the access token and the jwt payload have expired (which can happen if an API takes a VERY long time). In this case, we still want the jwt payload to update, but the resulting JWT should - // not be alive for too long (since it's expired already). So we set it to - // 1 second lifetime. - jwtExpiry = 1; - } - - newAccessTokenPayload = await addJWTToAccessTokenPayload({ - accessTokenPayload: newAccessTokenPayload, - jwtExpiry, - userId: this.getUserId(), - jwtPropertyName, - openIdRecipeImplementation: this.openIdRecipeImplementation, - userContext, - }); - - await this.originalSessionClass.updateAccessTokenPayload(newAccessTokenPayload, userContext); - } -} diff --git a/lib/ts/recipe/session/with-jwt/utils.ts b/lib/ts/recipe/session/with-jwt/utils.ts deleted file mode 100644 index f83b49658..000000000 --- a/lib/ts/recipe/session/with-jwt/utils.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ -import { ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY } from "./constants"; -import { RecipeInterface as OpenIdRecipeInterface } from "../../openid/types"; - -export async function addJWTToAccessTokenPayload({ - accessTokenPayload, - jwtExpiry, - userId, - jwtPropertyName, - openIdRecipeImplementation, - userContext, -}: { - accessTokenPayload: any; - jwtExpiry: number; - userId: string; - jwtPropertyName: string; - openIdRecipeImplementation: OpenIdRecipeInterface; - userContext: any; -}): Promise { - // If jwtPropertyName is not undefined it means that the JWT was added to the access token payload already - let existingJwtPropertyName = accessTokenPayload[ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY]; - - if (existingJwtPropertyName !== undefined) { - // Delete the old JWT and the old property name - delete accessTokenPayload[existingJwtPropertyName]; - delete accessTokenPayload[ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY]; - } - - // Create the JWT - let jwtResponse = await openIdRecipeImplementation.createJWT({ - payload: { - /* - We add our claims before the user provided ones so that if they use the same claims - then the final payload will use the values they provide - */ - sub: userId, - ...accessTokenPayload, - }, - validitySeconds: jwtExpiry, - userContext, - }); - - if (jwtResponse.status === "UNSUPPORTED_ALGORITHM_ERROR") { - // Should never come here - throw new Error("JWT Signing algorithm not supported"); - } - - // Add the jwt and the property name to the access token payload - accessTokenPayload = { - ...accessTokenPayload, - /* - We add the JWT after the user defined keys because we want to make sure that it never - gets overwritten by a user defined key. Using the same key as the one configured (or defaulting) - for the JWT should be considered a dev error - - ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY indicates a reserved key used to determine the property name - with which the JWT is set, used to retrieve the JWT from the access token payload during refresg and - updateAccessTokenPayload - - Note: If the user has multiple overrides each with a unique propertyNameInAccessTokenPayload, the logic - for checking the existing JWT when refreshing the session or updating the access token payload will not work. - This is because even though the jwt itself would be created with unique property names, the _jwtPName value would - always be overwritten by the override that runs last and when retrieving the jwt using that key name it cannot be - guaranteed that the right JWT is returned. This case is considered to be a rare requirement and we assume - that users will not need multiple JWT representations of their access token payload. - */ - [jwtPropertyName]: jwtResponse.jwt, - [ACCESS_TOKEN_PAYLOAD_JWT_PROPERTY_NAME_KEY]: jwtPropertyName, - }; - - return accessTokenPayload; -} diff --git a/lib/ts/recipe/thirdparty/index.ts b/lib/ts/recipe/thirdparty/index.ts index 15b14df73..c4af54b2d 100644 --- a/lib/ts/recipe/thirdparty/index.ts +++ b/lib/ts/recipe/thirdparty/index.ts @@ -60,6 +60,10 @@ export default class Wrapper { static GoogleWorkspaces = thirdPartyProviders.GoogleWorkspaces; + static Bitbucket = thirdPartyProviders.Bitbucket; + + static GitLab = thirdPartyProviders.GitLab; + // static Okta = thirdPartyProviders.Okta; // static ActiveDirectory = thirdPartyProviders.ActiveDirectory; @@ -89,6 +93,10 @@ export let Discord = Wrapper.Discord; export let GoogleWorkspaces = Wrapper.GoogleWorkspaces; +export let Bitbucket = Wrapper.Bitbucket; + +export let GitLab = Wrapper.GitLab; + // export let Okta = Wrapper.Okta; // export let ActiveDirectory = Wrapper.ActiveDirectory; diff --git a/lib/ts/recipe/thirdparty/providers/bitbucket.ts b/lib/ts/recipe/thirdparty/providers/bitbucket.ts new file mode 100644 index 000000000..bcb467286 --- /dev/null +++ b/lib/ts/recipe/thirdparty/providers/bitbucket.ts @@ -0,0 +1,133 @@ +/* Copyright (c) 2023, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * 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. + */ + +import { TypeProvider, TypeProviderGetResponse } from "../types"; +import axios from "axios"; + +type TypeThirdPartyProviderBitbucketConfig = { + clientId: string; + clientSecret: string; + scope?: string[]; + authorisationRedirect?: { + params?: { [key: string]: string | ((request: any) => string) }; + }; + isDefault?: boolean; +}; + +export default function Bitbucket(config: TypeThirdPartyProviderBitbucketConfig): TypeProvider { + const id = "bitbucket"; + + function get(redirectURI: string | undefined, authCodeFromRequest: string | undefined): TypeProviderGetResponse { + let accessTokenAPIURL = "https://bitbucket.org/site/oauth2/access_token"; + let accessTokenAPIParams: { [key: string]: string } = { + client_id: config.clientId, + client_secret: config.clientSecret, + grant_type: "authorization_code", + }; + if (authCodeFromRequest !== undefined) { + accessTokenAPIParams.code = authCodeFromRequest; + } + if (redirectURI !== undefined) { + accessTokenAPIParams.redirect_uri = redirectURI; + } + let authorisationRedirectURL = "https://bitbucket.org/site/oauth2/authorize"; + let scopes = ["account", "email"]; + if (config.scope !== undefined) { + scopes = config.scope; + scopes = Array.from(new Set(scopes)); + } + let additionalParams = + config.authorisationRedirect === undefined || config.authorisationRedirect.params === undefined + ? {} + : config.authorisationRedirect.params; + let authorizationRedirectParams: { [key: string]: string } = { + scope: scopes.join(" "), + access_type: "offline", + response_type: "code", + client_id: config.clientId, + ...additionalParams, + }; + + async function getProfileInfo(accessTokenAPIResponse: { + access_token: string; + expires_in: number; + token_type: string; + refresh_token?: string; + }) { + let accessToken = accessTokenAPIResponse.access_token; + let authHeader = `Bearer ${accessToken}`; + let response = await axios({ + method: "get", + url: "https://api.bitbucket.org/2.0/user", + headers: { + Authorization: authHeader, + }, + }); + let userInfo = response.data; + let id = userInfo.uuid; + + let emailRes = await axios({ + method: "get", + url: "https://api.bitbucket.org/2.0/user/emails", + headers: { + Authorization: authHeader, + }, + }); + let emailData = emailRes.data; + let email = undefined; + let isVerified = false; + emailData.values.forEach((emailInfo: any) => { + if (emailInfo.is_primary) { + email = emailInfo.email; + isVerified = emailInfo.is_confirmed; + } + }); + + if (email === undefined) { + return { + id, + }; + } + return { + id, + email: { + id: email, + isVerified, + }, + }; + } + + return { + accessTokenAPI: { + url: accessTokenAPIURL, + params: accessTokenAPIParams, + }, + authorisationRedirect: { + url: authorisationRedirectURL, + params: authorizationRedirectParams, + }, + getProfileInfo, + getClientId: () => { + return config.clientId; + }, + }; + } + + return { + id, + get, + isDefault: config.isDefault, + }; +} diff --git a/lib/ts/recipe/thirdparty/providers/gitlab.ts b/lib/ts/recipe/thirdparty/providers/gitlab.ts new file mode 100644 index 000000000..efe755631 --- /dev/null +++ b/lib/ts/recipe/thirdparty/providers/gitlab.ts @@ -0,0 +1,122 @@ +/* Copyright (c) 2023, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * 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. + */ + +import { TypeProvider, TypeProviderGetResponse } from "../types"; +import axios from "axios"; +import NormalisedURLDomain from "../../../normalisedURLDomain"; + +type TypeThirdPartyProviderGitLabConfig = { + clientId: string; + clientSecret: string; + scope?: string[]; + authorisationRedirect?: { + params?: { [key: string]: string | ((request: any) => string) }; + }; + gitlabBaseUrl?: string; + isDefault?: boolean; +}; + +export default function GitLab(config: TypeThirdPartyProviderGitLabConfig): TypeProvider { + const id = "gitlab"; + + function get(redirectURI: string | undefined, authCodeFromRequest: string | undefined): TypeProviderGetResponse { + let baseUrl = + config.gitlabBaseUrl === undefined + ? "https://gitlab.com" // no traling slash cause we add that in the path + : new NormalisedURLDomain(config.gitlabBaseUrl).getAsStringDangerous(); + let accessTokenAPIURL = baseUrl + "/oauth/token"; + let accessTokenAPIParams: { [key: string]: string } = { + client_id: config.clientId, + client_secret: config.clientSecret, + grant_type: "authorization_code", + }; + if (authCodeFromRequest !== undefined) { + accessTokenAPIParams.code = authCodeFromRequest; + } + if (redirectURI !== undefined) { + accessTokenAPIParams.redirect_uri = redirectURI; + } + let authorisationRedirectURL = baseUrl + "/oauth/authorize"; + let scopes = ["read_user"]; + if (config.scope !== undefined) { + scopes = config.scope; + scopes = Array.from(new Set(scopes)); + } + let additionalParams = + config.authorisationRedirect === undefined || config.authorisationRedirect.params === undefined + ? {} + : config.authorisationRedirect.params; + let authorizationRedirectParams: { [key: string]: string } = { + scope: scopes.join(" "), + response_type: "code", + client_id: config.clientId, + ...additionalParams, + }; + + async function getProfileInfo(accessTokenAPIResponse: { + access_token: string; + expires_in: number; + token_type: string; + refresh_token?: string; + }) { + let accessToken = accessTokenAPIResponse.access_token; + let authHeader = `Bearer ${accessToken}`; + let response = await axios({ + method: "get", + url: baseUrl + "/api/v4/user", + headers: { + Authorization: authHeader, + }, + }); + let userInfo = response.data; + let id = userInfo.id + ""; + let email = userInfo.email; + if (email === undefined || email === null) { + return { + id, + }; + } + let isVerified = userInfo.confirmed_at !== null && userInfo.confirmed_at !== undefined; + return { + id, + email: { + id: email, + isVerified, + }, + }; + } + + return { + accessTokenAPI: { + url: accessTokenAPIURL, + params: accessTokenAPIParams, + }, + authorisationRedirect: { + url: authorisationRedirectURL, + params: authorizationRedirectParams, + }, + getProfileInfo, + getClientId: () => { + return config.clientId; + }, + }; + } + + return { + id, + get, + isDefault: config.isDefault, + }; +} diff --git a/lib/ts/recipe/thirdparty/providers/index.ts b/lib/ts/recipe/thirdparty/providers/index.ts index 42d35ebac..af2dcee4c 100644 --- a/lib/ts/recipe/thirdparty/providers/index.ts +++ b/lib/ts/recipe/thirdparty/providers/index.ts @@ -6,6 +6,8 @@ import ProviderDiscord from "./discord"; // import ProviderOkta from "./okta"; import ProviderGoogleWorkspaces from "./googleWorkspaces"; // import ProviderAD from "./activeDirectory"; +import ProviderBitbucket from "./bitbucket"; +import ProviderGitlab from "./gitlab"; export let Google = ProviderGoogle; export let Facebook = ProviderFacebook; @@ -13,5 +15,7 @@ export let Github = ProviderGithub; export let Apple = ProviderApple; export let Discord = ProviderDiscord; export let GoogleWorkspaces = ProviderGoogleWorkspaces; +export let Bitbucket = ProviderBitbucket; +export let GitLab = ProviderGitlab; // export let Okta = ProviderOkta; // export let ActiveDirectory = ProviderAD; diff --git a/lib/ts/recipe/thirdpartyemailpassword/index.ts b/lib/ts/recipe/thirdpartyemailpassword/index.ts index 87b4ab4d7..54e0bc9b5 100644 --- a/lib/ts/recipe/thirdpartyemailpassword/index.ts +++ b/lib/ts/recipe/thirdpartyemailpassword/index.ts @@ -73,15 +73,21 @@ export default class Wrapper { }); } - static updateEmailOrPassword(input: { userId: string; email?: string; password?: string; userContext?: any }) { + static Google = thirdPartyProviders.Google; + + static updateEmailOrPassword(input: { + userId: string; + email?: string; + password?: string; + userContext?: any; + applyPasswordPolicy?: boolean; + }) { return Recipe.getInstanceOrThrowError().recipeInterfaceImpl.updateEmailOrPassword({ userContext: {}, ...input, }); } - static Google = thirdPartyProviders.Google; - static Github = thirdPartyProviders.Github; static Facebook = thirdPartyProviders.Facebook; @@ -92,6 +98,10 @@ export default class Wrapper { static GoogleWorkspaces = thirdPartyProviders.GoogleWorkspaces; + static Bitbucket = thirdPartyProviders.Bitbucket; + + static GitLab = thirdPartyProviders.GitLab; + // static Okta = thirdPartyProviders.Okta; // static ActiveDirectory = thirdPartyProviders.ActiveDirectory; @@ -134,6 +144,10 @@ export let Discord = Wrapper.Discord; export let GoogleWorkspaces = Wrapper.GoogleWorkspaces; +export let Bitbucket = Wrapper.Bitbucket; + +export let GitLab = Wrapper.GitLab; + // export let Okta = Wrapper.Okta; // export let ActiveDirectory = Wrapper.ActiveDirectory; diff --git a/lib/ts/recipe/thirdpartyemailpassword/recipe.ts b/lib/ts/recipe/thirdpartyemailpassword/recipe.ts index 38779aa7a..858d39a38 100644 --- a/lib/ts/recipe/thirdpartyemailpassword/recipe.ts +++ b/lib/ts/recipe/thirdpartyemailpassword/recipe.ts @@ -74,9 +74,11 @@ export default class Recipe extends RecipeModule { this.config = validateAndNormaliseUserInput(this, appInfo, config); this.isInServerlessEnv = isInServerlessEnv; { + const getEmailPasswordConfig = () => this.emailPasswordRecipe.config; let builder = new OverrideableBuilder( RecipeImplementation( Querier.getNewInstanceOrThrowError(EmailPasswordRecipe.RECIPE_ID), + getEmailPasswordConfig, Querier.getNewInstanceOrThrowError(ThirdPartyRecipe.RECIPE_ID) ) ); diff --git a/lib/ts/recipe/thirdpartyemailpassword/recipeImplementation/emailPasswordRecipeImplementation.ts b/lib/ts/recipe/thirdpartyemailpassword/recipeImplementation/emailPasswordRecipeImplementation.ts index e9b7afa3b..fc61d5d9d 100644 --- a/lib/ts/recipe/thirdpartyemailpassword/recipeImplementation/emailPasswordRecipeImplementation.ts +++ b/lib/ts/recipe/thirdpartyemailpassword/recipeImplementation/emailPasswordRecipeImplementation.ts @@ -51,6 +51,7 @@ export default function getRecipeInterface(recipeInterface: ThirdPartyEmailPassw email?: string; password?: string; userContext: any; + applyPasswordPolicy: boolean; }): Promise< | { status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR"; @@ -59,6 +60,7 @@ export default function getRecipeInterface(recipeInterface: ThirdPartyEmailPassw status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; reason: string; } + | { status: "PASSWORD_POLICY_VIOLATED_ERROR"; failureReason: string } > { return recipeInterface.updateEmailOrPassword(input); }, diff --git a/lib/ts/recipe/thirdpartyemailpassword/recipeImplementation/index.ts b/lib/ts/recipe/thirdpartyemailpassword/recipeImplementation/index.ts index 913cafa6f..f755cc216 100644 --- a/lib/ts/recipe/thirdpartyemailpassword/recipeImplementation/index.ts +++ b/lib/ts/recipe/thirdpartyemailpassword/recipeImplementation/index.ts @@ -8,12 +8,14 @@ import DerivedEP from "./emailPasswordRecipeImplementation"; import DerivedTP from "./thirdPartyRecipeImplementation"; import { User as GlobalUser } from "../../../types"; import { getUser } from "../../../"; +import { TypeNormalisedInput } from "../../emailpassword/types"; export default function getRecipeInterface( emailPasswordQuerier: Querier, + getEmailPasswordConfig: () => TypeNormalisedInput, thirdPartyQuerier?: Querier ): RecipeInterface { - let originalEmailPasswordImplementation = EmailPasswordImplemenation(emailPasswordQuerier); + let originalEmailPasswordImplementation = EmailPasswordImplemenation(emailPasswordQuerier, getEmailPasswordConfig); let originalThirdPartyImplementation: undefined | ThirdPartyRecipeInterface; if (thirdPartyQuerier !== undefined) { originalThirdPartyImplementation = ThirdPartyImplemenation(thirdPartyQuerier); @@ -92,6 +94,7 @@ export default function getRecipeInterface( email?: string; password?: string; userContext: any; + applyPasswordPolicy?: boolean; } ): Promise< | { @@ -101,6 +104,7 @@ export default function getRecipeInterface( status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; reason: string; } + | { status: "PASSWORD_POLICY_VIOLATED_ERROR"; failureReason: string } > { let user = await getUser(input.userId, input.userContext); if (user === undefined) { diff --git a/lib/ts/recipe/thirdpartyemailpassword/types.ts b/lib/ts/recipe/thirdpartyemailpassword/types.ts index 70d5fd12a..94668bc1b 100644 --- a/lib/ts/recipe/thirdpartyemailpassword/types.ts +++ b/lib/ts/recipe/thirdpartyemailpassword/types.ts @@ -137,6 +137,7 @@ export type RecipeInterface = { email?: string; password?: string; userContext: any; + applyPasswordPolicy?: boolean; }): Promise< | { status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR"; @@ -145,6 +146,7 @@ export type RecipeInterface = { status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; reason: string; } + | { status: "PASSWORD_POLICY_VIOLATED_ERROR"; failureReason: string } >; }; @@ -261,6 +263,7 @@ export type APIInterface = { | { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR"; } + | { status: "PASSWORD_POLICY_VIOLATED_ERROR"; failureReason: string } | GeneralErrorResponse >); diff --git a/lib/ts/recipe/thirdpartypasswordless/index.ts b/lib/ts/recipe/thirdpartypasswordless/index.ts index e1a708166..3423ddcde 100644 --- a/lib/ts/recipe/thirdpartypasswordless/index.ts +++ b/lib/ts/recipe/thirdpartypasswordless/index.ts @@ -193,6 +193,10 @@ export default class Wrapper { static GoogleWorkspaces = thirdPartyProviders.GoogleWorkspaces; + static Bitbucket = thirdPartyProviders.Bitbucket; + + static GitLab = thirdPartyProviders.GitLab; + // static Okta = thirdPartyProviders.Okta; // static ActiveDirectory = thirdPartyProviders.ActiveDirectory; @@ -262,6 +266,10 @@ export let Discord = Wrapper.Discord; export let GoogleWorkspaces = Wrapper.GoogleWorkspaces; +export let Bitbucket = Wrapper.Bitbucket; + +export let GitLab = Wrapper.GitLab; + // export let Okta = Wrapper.Okta; // export let ActiveDirectory = Wrapper.ActiveDirectory; diff --git a/lib/ts/supertokens.ts b/lib/ts/supertokens.ts index 19fbb59dc..7d3873690 100644 --- a/lib/ts/supertokens.ts +++ b/lib/ts/supertokens.ts @@ -14,7 +14,6 @@ */ import { TypeInput, NormalisedAppinfo, HTTPMethod, SuperTokensInfo } from "./types"; -import axios from "axios"; import { normaliseInputAppInfoOrThrowError, maxVersion, @@ -47,6 +46,8 @@ export default class SuperTokens { supertokens: undefined | SuperTokensInfo; + telemetryEnabled: boolean; + constructor(config: TypeInput) { logDebugMessage("Started SuperTokens with debug logging (supertokens.init called)"); logDebugMessage("appInfo: " + JSON.stringify(config.appInfo)); @@ -84,47 +85,13 @@ export default class SuperTokens { return func(this.appInfo, this.isInServerlessEnv); }); - let isAccountLinkingInitialised = this.recipeModules.find((r) => r.getRecipeId() === AccountLinking.RECIPE_ID); - if (!isAccountLinkingInitialised) { + let isAccountLinkingInitialized = this.recipeModules.find((r) => r.getRecipeId() === AccountLinking.RECIPE_ID); + if (!isAccountLinkingInitialized) { this.recipeModules.push(AccountLinking.init({})(this.appInfo, this.isInServerlessEnv)); } - let telemetry = config.telemetry === undefined ? process.env.TEST_MODE !== "testing" : config.telemetry; - - if (telemetry) { - if (this.isInServerlessEnv) { - // see https://github.com/supertokens/supertokens-node/issues/127 - let randomNum = Math.random() * 10; - if (randomNum > 7) { - this.sendTelemetry(); - } - } else { - this.sendTelemetry(); - } - } - } - sendTelemetry = async () => { - try { - let querier = Querier.getNewInstanceOrThrowError(undefined); - let response = await querier.sendGetRequest(new NormalisedURLPath("/telemetry"), {}); - let telemetryId: string | undefined; - if (response.exists) { - telemetryId = response.telemetryId; - } - await axios({ - method: "POST", - url: "https://api.supertokens.com/0/st/telemetry", - data: { - appName: this.appInfo.appName, - websiteDomain: this.appInfo.websiteDomain.getAsStringDangerous(), - telemetryId, - }, - headers: { - "api-version": 2, - }, - }); - } catch (ignored) {} - }; + this.telemetryEnabled = config.telemetry === undefined ? process.env.TEST_MODE !== "testing" : config.telemetry; + } static init(config: TypeInput) { if (SuperTokens.instance === undefined) { diff --git a/lib/ts/utils.ts b/lib/ts/utils.ts index d62e72a3a..6f67fded7 100644 --- a/lib/ts/utils.ts +++ b/lib/ts/utils.ts @@ -136,11 +136,23 @@ export function humaniseMilliseconds(ms: number): string { } export function makeDefaultUserContextFromAPI(request: BaseRequest): any { - return { - _default: { - request, - }, - }; + return setRequestInUserContextIfNotDefined({}, request); +} + +export function setRequestInUserContextIfNotDefined(userContext: any | undefined, request: BaseRequest) { + if (userContext === undefined) { + userContext = {}; + } + + if (userContext._default === undefined) { + userContext._default = {}; + } + + if (typeof userContext._default === "object") { + userContext._default.request = request; + } + + return userContext; } export function getTopLevelDomainForSameSiteResolution(url: string): string { @@ -156,3 +168,13 @@ export function getTopLevelDomainForSameSiteResolution(url: string): string { } return parsedURL.domain; } + +export function getFromObjectCaseInsensitive(key: string, object: Record): T | undefined { + const matchedKeys = Object.keys(object).filter((i) => i.toLocaleLowerCase() === key.toLocaleLowerCase()); + + if (matchedKeys.length === 0) { + return undefined; + } + + return object[matchedKeys[0]]; +} diff --git a/lib/ts/version.ts b/lib/ts/version.ts index 532658f6f..8c29bb5ef 100644 --- a/lib/ts/version.ts +++ b/lib/ts/version.ts @@ -12,9 +12,9 @@ * License for the specific language governing permissions and limitations * under the License. */ -export const version = "13.0.2"; +export const version = "14.0.0"; -export const cdiSupported = ["2.8", "2.9", "2.10", "2.11", "2.12", "2.13", "2.14", "2.15"]; +export const cdiSupported = ["2.21"]; // Note: The actual script import for dashboard uses v{DASHBOARD_VERSION} -export const dashboardVersion = "0.3"; +export const dashboardVersion = "0.6"; diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index b556bccf3..000000000 --- a/package-lock.json +++ /dev/null @@ -1,17489 +0,0 @@ -{ - "name": "supertokens-node", - "version": "13.0.2", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "supertokens-node", - "version": "13.0.2", - "license": "Apache-2.0", - "dependencies": { - "axios": "0.21.4", - "body-parser": "1.20.1", - "co-body": "6.1.0", - "cookie": "0.4.0", - "debug": "^4.3.3", - "jsonwebtoken": "^9.0.0", - "jwks-rsa": "^2.0.5", - "libphonenumber-js": "^1.9.44", - "nodemailer": "^6.7.2", - "psl": "1.8.0", - "supertokens-js-override": "^0.0.4", - "twilio": "^4.7.2", - "verify-apple-id-token": "^3.0.1" - }, - "devDependencies": { - "@hapi/hapi": "^20.2.0", - "@koa/router": "^10.1.1", - "@loopback/core": "2.16.2", - "@loopback/repository": "3.7.1", - "@loopback/rest": "9.3.0", - "@types/aws-lambda": "8.10.77", - "@types/co-body": "^5.1.1", - "@types/cookie": "0.3.3", - "@types/express": "4.16.1", - "@types/hapi__hapi": "20.0.8", - "@types/jsonwebtoken": "9.0.0", - "@types/koa": "^2.13.4", - "@types/koa-bodyparser": "^4.3.3", - "@types/nodemailer": "^6.4.4", - "@types/psl": "1.1.0", - "@types/validator": "10.11.0", - "aws-sdk-mock": "^5.4.0", - "cookie-parser": "^1.4.5", - "express": "^4.18.2", - "fastify": "3.18.1", - "glob": "7.1.7", - "koa": "^2.13.3", - "lambda-tester": "^4.0.1", - "loopback-datasource-juggler": "^4.26.0", - "mocha": "6.1.4", - "next": "11.1.3", - "nock": "11.7.0", - "node-mocks-http": "^1.11.0", - "prettier": "2.0.5", - "pretty-quick": "^3.1.1", - "react": "^17.0.2", - "sinon": "^14.0.0", - "supertest": "4.0.2", - "typedoc": "^0.22.5", - "typescript": "4.2" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", - "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.0.tgz", - "integrity": "sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.17.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz", - "integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==", - "dev": true, - "peer": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helpers": "^7.17.2", - "@babel/parser": "^7.17.3", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/highlight": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz", - "integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", - "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/compat-data": "^7.16.4", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.17.5", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/browserslist": { - "version": "4.19.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz", - "integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==", - "dev": true, - "peer": true, - "dependencies": { - "caniuse-lite": "^1.0.30001312", - "electron-to-chromium": "^1.4.71", - "escalade": "^3.1.1", - "node-releases": "^2.0.2", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/node-releases": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", - "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", - "dev": true, - "peer": true - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-environment-visitor/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", - "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-get-function-arity": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", - "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-get-function-arity/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz", - "integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", - "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", - "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.17.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz", - "integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.0", - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz", - "integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==", - "dev": true, - "peer": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz", - "integrity": "sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz", - "integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template/node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/highlight": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", - "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.3", - "@babel/types": "^7.17.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/highlight": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@extra-number/significant-digits": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/@extra-number/significant-digits/-/significant-digits-1.3.9.tgz", - "integrity": "sha512-E5PY/bCwrNqEHh4QS6AQBinLZ+sxM1lT8tsSVYk8VwhWIPp6fCU/BMRVq0V8iJ8LwS3FHmaA4vUzb78s4BIIyA==", - "dev": true - }, - "node_modules/@fastify/ajv-compiler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-1.1.0.tgz", - "integrity": "sha512-gvCOUNpXsWrIQ3A4aXCLIdblL0tDq42BG/2Xw7oxbil9h11uow10ztS2GuFazNBfjbrsZ5nl+nPl5jDSjj5TSg==", - "dev": true, - "dependencies": { - "ajv": "^6.12.6" - } - }, - "node_modules/@hapi/accept": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@hapi/accept/-/accept-5.0.2.tgz", - "integrity": "sha512-CmzBx/bXUR8451fnZRuZAJRlzgm0Jgu5dltTX/bszmR2lheb9BpyN47Q1RbaGTsvFzn0PXAEs+lXDKfshccYZw==", - "dev": true, - "dependencies": { - "@hapi/boom": "9.x.x", - "@hapi/hoek": "9.x.x" - } - }, - "node_modules/@hapi/ammo": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@hapi/ammo/-/ammo-5.0.1.tgz", - "integrity": "sha512-FbCNwcTbnQP4VYYhLNGZmA76xb2aHg9AMPiy18NZyWMG310P5KdFGyA9v2rm5ujrIny77dEEIkMOwl0Xv+fSSA==", - "dev": true, - "dependencies": { - "@hapi/hoek": "9.x.x" - } - }, - "node_modules/@hapi/b64": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@hapi/b64/-/b64-5.0.0.tgz", - "integrity": "sha512-ngu0tSEmrezoiIaNGG6rRvKOUkUuDdf4XTPnONHGYfSGRmDqPZX5oJL6HAdKTo1UQHECbdB4OzhWrfgVppjHUw==", - "dev": true, - "dependencies": { - "@hapi/hoek": "9.x.x" - } - }, - "node_modules/@hapi/boom": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-9.1.4.tgz", - "integrity": "sha512-Ls1oH8jaN1vNsqcaHVYJrKmgMcKsC1wcp8bujvXrHaAqD2iDYq3HoOwsxwo09Cuda5R5nC0o0IxlrlTuvPuzSw==", - "dev": true, - "dependencies": { - "@hapi/hoek": "9.x.x" - } - }, - "node_modules/@hapi/bounce": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@hapi/bounce/-/bounce-2.0.0.tgz", - "integrity": "sha512-JesW92uyzOOyuzJKjoLHM1ThiOvHPOLDHw01YV8yh5nCso7sDwJho1h0Ad2N+E62bZyz46TG3xhAi/78Gsct6A==", - "dev": true, - "dependencies": { - "@hapi/boom": "9.x.x", - "@hapi/hoek": "9.x.x" - } - }, - "node_modules/@hapi/bourne": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.0.0.tgz", - "integrity": "sha512-WEezM1FWztfbzqIUbsDzFRVMxSoLy3HugVcux6KDDtTqzPsLE8NDRHfXvev66aH1i2oOKKar3/XDjbvh/OUBdg==", - "dev": true - }, - "node_modules/@hapi/call": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@hapi/call/-/call-8.0.1.tgz", - "integrity": "sha512-bOff6GTdOnoe5b8oXRV3lwkQSb/LAWylvDMae6RgEWWntd0SHtkYbQukDHKlfaYtVnSAgIavJ0kqszF/AIBb6g==", - "dev": true, - "dependencies": { - "@hapi/boom": "9.x.x", - "@hapi/hoek": "9.x.x" - } - }, - "node_modules/@hapi/catbox": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/@hapi/catbox/-/catbox-11.1.1.tgz", - "integrity": "sha512-u/8HvB7dD/6X8hsZIpskSDo4yMKpHxFd7NluoylhGrL6cUfYxdQPnvUp9YU2C6F9hsyBVLGulBd9vBN1ebfXOQ==", - "dev": true, - "dependencies": { - "@hapi/boom": "9.x.x", - "@hapi/hoek": "9.x.x", - "@hapi/podium": "4.x.x", - "@hapi/validate": "1.x.x" - } - }, - "node_modules/@hapi/catbox-memory": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@hapi/catbox-memory/-/catbox-memory-5.0.1.tgz", - "integrity": "sha512-QWw9nOYJq5PlvChLWV8i6hQHJYfvdqiXdvTupJFh0eqLZ64Xir7mKNi96d5/ZMUAqXPursfNDIDxjFgoEDUqeQ==", - "dev": true, - "dependencies": { - "@hapi/boom": "9.x.x", - "@hapi/hoek": "9.x.x" - } - }, - "node_modules/@hapi/content": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@hapi/content/-/content-5.0.2.tgz", - "integrity": "sha512-mre4dl1ygd4ZyOH3tiYBrOUBzV7Pu/EOs8VLGf58vtOEECWed8Uuw6B4iR9AN/8uQt42tB04qpVaMyoMQh0oMw==", - "dev": true, - "dependencies": { - "@hapi/boom": "9.x.x" - } - }, - "node_modules/@hapi/cryptiles": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/cryptiles/-/cryptiles-5.1.0.tgz", - "integrity": "sha512-fo9+d1Ba5/FIoMySfMqPBR/7Pa29J2RsiPrl7bkwo5W5o+AN1dAYQRi4SPrPwwVxVGKjgLOEWrsvt1BonJSfLA==", - "dev": true, - "dependencies": { - "@hapi/boom": "9.x.x" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@hapi/file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@hapi/file/-/file-2.0.0.tgz", - "integrity": "sha512-WSrlgpvEqgPWkI18kkGELEZfXr0bYLtr16iIN4Krh9sRnzBZN6nnWxHFxtsnP684wueEySBbXPDg/WfA9xJdBQ==", - "dev": true - }, - "node_modules/@hapi/hapi": { - "version": "20.2.1", - "resolved": "https://registry.npmjs.org/@hapi/hapi/-/hapi-20.2.1.tgz", - "integrity": "sha512-OXAU+yWLwkMfPFic+KITo+XPp6Oxpgc9WUH+pxXWcTIuvWbgco5TC/jS8UDvz+NFF5IzRgF2CL6UV/KLdQYUSQ==", - "dev": true, - "dependencies": { - "@hapi/accept": "^5.0.1", - "@hapi/ammo": "^5.0.1", - "@hapi/boom": "^9.1.0", - "@hapi/bounce": "^2.0.0", - "@hapi/call": "^8.0.0", - "@hapi/catbox": "^11.1.1", - "@hapi/catbox-memory": "^5.0.0", - "@hapi/heavy": "^7.0.1", - "@hapi/hoek": "^9.0.4", - "@hapi/mimos": "^6.0.0", - "@hapi/podium": "^4.1.1", - "@hapi/shot": "^5.0.5", - "@hapi/somever": "^3.0.0", - "@hapi/statehood": "^7.0.3", - "@hapi/subtext": "^7.0.3", - "@hapi/teamwork": "^5.1.0", - "@hapi/topo": "^5.0.0", - "@hapi/validate": "^1.1.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@hapi/heavy": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@hapi/heavy/-/heavy-7.0.1.tgz", - "integrity": "sha512-vJ/vzRQ13MtRzz6Qd4zRHWS3FaUc/5uivV2TIuExGTM9Qk+7Zzqj0e2G7EpE6KztO9SalTbiIkTh7qFKj/33cA==", - "dev": true, - "dependencies": { - "@hapi/boom": "9.x.x", - "@hapi/hoek": "9.x.x", - "@hapi/validate": "1.x.x" - } - }, - "node_modules/@hapi/hoek": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", - "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==", - "dev": true - }, - "node_modules/@hapi/iron": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hapi/iron/-/iron-6.0.0.tgz", - "integrity": "sha512-zvGvWDufiTGpTJPG1Y/McN8UqWBu0k/xs/7l++HVU535NLHXsHhy54cfEMdW7EjwKfbBfM9Xy25FmTiobb7Hvw==", - "dev": true, - "dependencies": { - "@hapi/b64": "5.x.x", - "@hapi/boom": "9.x.x", - "@hapi/bourne": "2.x.x", - "@hapi/cryptiles": "5.x.x", - "@hapi/hoek": "9.x.x" - } - }, - "node_modules/@hapi/mimos": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hapi/mimos/-/mimos-6.0.0.tgz", - "integrity": "sha512-Op/67tr1I+JafN3R3XN5DucVSxKRT/Tc+tUszDwENoNpolxeXkhrJ2Czt6B6AAqrespHoivhgZBWYSuANN9QXg==", - "dev": true, - "dependencies": { - "@hapi/hoek": "9.x.x", - "mime-db": "1.x.x" - } - }, - "node_modules/@hapi/nigel": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@hapi/nigel/-/nigel-4.0.2.tgz", - "integrity": "sha512-ht2KoEsDW22BxQOEkLEJaqfpoKPXxi7tvabXy7B/77eFtOyG5ZEstfZwxHQcqAiZhp58Ae5vkhEqI03kawkYNw==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.4", - "@hapi/vise": "^4.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@hapi/pez": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@hapi/pez/-/pez-5.0.3.tgz", - "integrity": "sha512-mpikYRJjtrbJgdDHG/H9ySqYqwJ+QU/D7FXsYciS9P7NYBXE2ayKDAy3H0ou6CohOCaxPuTV4SZ0D936+VomHA==", - "dev": true, - "dependencies": { - "@hapi/b64": "5.x.x", - "@hapi/boom": "9.x.x", - "@hapi/content": "^5.0.2", - "@hapi/hoek": "9.x.x", - "@hapi/nigel": "4.x.x" - } - }, - "node_modules/@hapi/podium": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@hapi/podium/-/podium-4.1.3.tgz", - "integrity": "sha512-ljsKGQzLkFqnQxE7qeanvgGj4dejnciErYd30dbrYzUOF/FyS/DOF97qcrT3bhoVwCYmxa6PEMhxfCPlnUcD2g==", - "dev": true, - "dependencies": { - "@hapi/hoek": "9.x.x", - "@hapi/teamwork": "5.x.x", - "@hapi/validate": "1.x.x" - } - }, - "node_modules/@hapi/shot": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@hapi/shot/-/shot-5.0.5.tgz", - "integrity": "sha512-x5AMSZ5+j+Paa8KdfCoKh+klB78otxF+vcJR/IoN91Vo2e5ulXIW6HUsFTCU+4W6P/Etaip9nmdAx2zWDimB2A==", - "dev": true, - "dependencies": { - "@hapi/hoek": "9.x.x", - "@hapi/validate": "1.x.x" - } - }, - "node_modules/@hapi/somever": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@hapi/somever/-/somever-3.0.1.tgz", - "integrity": "sha512-4ZTSN3YAHtgpY/M4GOtHUXgi6uZtG9nEZfNI6QrArhK0XN/RDVgijlb9kOmXwCR5VclDSkBul9FBvhSuKXx9+w==", - "dev": true, - "dependencies": { - "@hapi/bounce": "2.x.x", - "@hapi/hoek": "9.x.x" - } - }, - "node_modules/@hapi/statehood": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@hapi/statehood/-/statehood-7.0.3.tgz", - "integrity": "sha512-pYB+pyCHkf2Amh67QAXz7e/DN9jcMplIL7Z6N8h0K+ZTy0b404JKPEYkbWHSnDtxLjJB/OtgElxocr2fMH4G7w==", - "dev": true, - "dependencies": { - "@hapi/boom": "9.x.x", - "@hapi/bounce": "2.x.x", - "@hapi/bourne": "2.x.x", - "@hapi/cryptiles": "5.x.x", - "@hapi/hoek": "9.x.x", - "@hapi/iron": "6.x.x", - "@hapi/validate": "1.x.x" - } - }, - "node_modules/@hapi/subtext": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@hapi/subtext/-/subtext-7.0.3.tgz", - "integrity": "sha512-CekDizZkDGERJ01C0+TzHlKtqdXZxzSWTOaH6THBrbOHnsr3GY+yiMZC+AfNCypfE17RaIakGIAbpL2Tk1z2+A==", - "dev": true, - "dependencies": { - "@hapi/boom": "9.x.x", - "@hapi/bourne": "2.x.x", - "@hapi/content": "^5.0.2", - "@hapi/file": "2.x.x", - "@hapi/hoek": "9.x.x", - "@hapi/pez": "^5.0.1", - "@hapi/wreck": "17.x.x" - } - }, - "node_modules/@hapi/teamwork": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/teamwork/-/teamwork-5.1.0.tgz", - "integrity": "sha512-llqoQTrAJDTXxG3c4Kz/uzhBS1TsmSBa/XG5SPcVXgmffHE1nFtyLIK0hNJHCB3EuBKT84adzd1hZNY9GJLWtg==", - "dev": true, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@hapi/validate": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@hapi/validate/-/validate-1.1.3.tgz", - "integrity": "sha512-/XMR0N0wjw0Twzq2pQOzPBZlDzkekGcoCtzO314BpIEsbXdYGthQUbxgkGDf4nhk1+IPDAsXqWjMohRQYO06UA==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0" - } - }, - "node_modules/@hapi/vise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@hapi/vise/-/vise-4.0.0.tgz", - "integrity": "sha512-eYyLkuUiFZTer59h+SGy7hUm+qE9p+UemePTHLlIWppEd+wExn3Df5jO04bFQTm7nleF5V8CtuYQYb+VFpZ6Sg==", - "dev": true, - "dependencies": { - "@hapi/hoek": "9.x.x" - } - }, - "node_modules/@hapi/wreck": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@hapi/wreck/-/wreck-17.1.0.tgz", - "integrity": "sha512-nx6sFyfqOpJ+EFrHX+XWwJAxs3ju4iHdbB/bwR8yTNZOiYmuhA8eCe7lYPtYmb4j7vyK/SlbaQsmTtUrMvPEBw==", - "dev": true, - "dependencies": { - "@hapi/boom": "9.x.x", - "@hapi/bourne": "2.x.x", - "@hapi/hoek": "9.x.x" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", - "dev": true, - "peer": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", - "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@koa/router": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/@koa/router/-/router-10.1.1.tgz", - "integrity": "sha512-ORNjq5z4EmQPriKbR0ER3k4Gh7YGNhWDL7JBW+8wXDrHLbWYKYSJaOJ9aN06npF5tbTxe2JBOsurpJDAvjiXKw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "http-errors": "^1.7.3", - "koa-compose": "^4.1.0", - "methods": "^1.1.2", - "path-to-regexp": "^6.1.0" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/@loopback/context": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@loopback/context/-/context-3.18.0.tgz", - "integrity": "sha512-PKx0rTguqBj6mUHBbEHLF031MnP6KiSkMLE4E8Hpy2KPJxG97HUT2ZUACHCP6qm8yS9spWQQ6g72VYAWxDrN+g==", - "dev": true, - "dependencies": { - "@loopback/metadata": "^3.3.4", - "@types/debug": "^4.1.7", - "debug": "^4.3.2", - "hyperid": "^2.3.1", - "p-event": "^4.2.0", - "tslib": "^2.3.1", - "uuid": "^8.3.2" - }, - "engines": { - "node": "^10.16 || 12 || 14 || 16" - } - }, - "node_modules/@loopback/core": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@loopback/core/-/core-2.16.2.tgz", - "integrity": "sha512-KtkNv6HIh8TFBOxTkfPp/BQbVqjDsGef/DtbNHH1ZHs3gSbofhkZs3IqQdYQzpkUq71mQjz5RJ/yUYY5Sqva9w==", - "dev": true, - "dependencies": { - "@loopback/context": "^3.17.1", - "debug": "^4.3.1", - "tslib": "^2.3.0" - }, - "engines": { - "node": "^10.16 || 12 || 14 || 16" - } - }, - "node_modules/@loopback/filter": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@loopback/filter/-/filter-1.5.4.tgz", - "integrity": "sha512-kfdCgSy0YoAFNYXJOpag5uJnlErYcROIeJqeAglkwOa3hSw2BYIudurU8hoqsiOBIGhI5BF4A3S8u4q089xWlg==", - "dev": true, - "dependencies": { - "tslib": "^2.3.1" - }, - "engines": { - "node": "^10.16 || 12 || 14 || 16" - } - }, - "node_modules/@loopback/http-server": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@loopback/http-server/-/http-server-2.5.4.tgz", - "integrity": "sha512-M7w+4AEhwDn7q00soCe8yYQDUS+n87ppuXQ1rJ9a1b9TdnEh+7nPFVrVpwiEKBGyVGIJWDq5BMSZYo1zMIPFUA==", - "dev": true, - "dependencies": { - "debug": "^4.3.2", - "stoppable": "^1.1.0", - "tslib": "^2.3.1" - }, - "engines": { - "node": "^10.16 || 12 || 14 || 16" - } - }, - "node_modules/@loopback/metadata": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@loopback/metadata/-/metadata-3.3.4.tgz", - "integrity": "sha512-FISs8OVYKB+wmL0VZdsDZzMOc/KC6anOf3ORpFRO2Mgl9dKCOD8IELKc8r/nr2kyD4r7/pjr5GfLy4nirS1vnQ==", - "dev": true, - "dependencies": { - "debug": "^4.3.2", - "lodash": "^4.17.21", - "reflect-metadata": "^0.1.13", - "tslib": "^2.3.1" - }, - "engines": { - "node": "^10.16 || 12 || 14 || 16" - } - }, - "node_modules/@loopback/repository": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@loopback/repository/-/repository-3.7.1.tgz", - "integrity": "sha512-q9vpgQ5MSZqI/ww2TTuDy0Y34NZaapS0+4ZKcwVgwH0XJFxgGwznc5W0l1Esu1lplijejpza4ItKwnlGmvYcJg==", - "dev": true, - "dependencies": { - "@loopback/filter": "^1.5.2", - "@types/debug": "^4.1.5", - "debug": "^4.3.1", - "lodash": "^4.17.21", - "loopback-datasource-juggler": "^4.26.0", - "tslib": "^2.3.0" - }, - "engines": { - "node": "^10.16 || 12 || 14 || 16" - }, - "peerDependencies": { - "@loopback/core": "^2.16.2" - } - }, - "node_modules/@loopback/rest": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@loopback/rest/-/rest-9.3.0.tgz", - "integrity": "sha512-Qwn5WXctQ2AV6Duze/x7ks9Tb/Oy6FSs0Hhyuhzz7aassKbu1m/GiJLB7bvpJVUN+qVZ2+vQZZ6Y3F+znzH4og==", - "dev": true, - "dependencies": { - "@loopback/express": "^3.3.0", - "@loopback/http-server": "^2.5.0", - "@loopback/openapi-v3": "^5.3.0", - "@openapi-contrib/openapi-schema-to-json-schema": "^3.1.0", - "@types/body-parser": "^1.19.0", - "@types/cors": "^2.8.10", - "@types/express": "^4.17.11", - "@types/express-serve-static-core": "^4.17.19", - "@types/http-errors": "^1.8.0", - "@types/on-finished": "^2.3.1", - "@types/serve-static": "1.13.9", - "@types/type-is": "^1.6.3", - "ajv": "^6.12.6", - "ajv-errors": "^1.0.1", - "ajv-keywords": "^3.5.2", - "body-parser": "^1.19.0", - "cors": "^2.8.5", - "debug": "^4.3.1", - "express": "^4.17.1", - "http-errors": "^1.8.0", - "js-yaml": "^4.1.0", - "json-schema-compare": "^0.2.2", - "lodash": "^4.17.21", - "on-finished": "^2.3.0", - "path-to-regexp": "^6.2.0", - "qs": "^6.10.1", - "strong-error-handler": "^4.0.0", - "tslib": "^2.2.0", - "type-is": "^1.6.18", - "validator": "^13.6.0" - }, - "engines": { - "node": "^10.16 || 12 || 14 || 16" - }, - "peerDependencies": { - "@loopback/core": "^2.16.0" - } - }, - "node_modules/@loopback/rest/node_modules/@loopback/express": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@loopback/express/-/express-3.3.4.tgz", - "integrity": "sha512-y+7fu/aXGp7+5QhEnKhwmI/vKLAQtsyvEXTiT8stbj4VHWvNbUbYVwfud5IOeH7d+lhxlNQ5aEJ7IDwoM8xD6Q==", - "dev": true, - "dependencies": { - "@loopback/http-server": "^2.5.4", - "@types/body-parser": "^1.19.1", - "@types/express": "^4.17.13", - "@types/express-serve-static-core": "^4.17.24", - "@types/http-errors": "^1.8.1", - "body-parser": "^1.19.0", - "debug": "^4.3.2", - "express": "^4.17.1", - "http-errors": "^1.8.0", - "on-finished": "^2.3.0", - "toposort": "^2.0.2", - "tslib": "^2.3.1" - }, - "engines": { - "node": "^10.16 || 12 || 14 || 16" - }, - "peerDependencies": { - "@loopback/core": "^2.18.0" - } - }, - "node_modules/@loopback/rest/node_modules/@loopback/openapi-v3": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@loopback/openapi-v3/-/openapi-v3-5.3.1.tgz", - "integrity": "sha512-MBVamgxDDbgQQlQjIxSOnaVXLx6plxzn3e8CW8YbNc3TNiS1P8EFa5vNBp8wIzSDTeEd3ic6qzUxCUZIICiFNA==", - "dev": true, - "dependencies": { - "@loopback/repository-json-schema": "^3.4.1", - "debug": "^4.3.1", - "http-status": "^1.5.0", - "json-merge-patch": "^1.0.1", - "lodash": "^4.17.21", - "openapi3-ts": "^2.0.1", - "tslib": "^2.2.0" - }, - "engines": { - "node": "^10.16 || 12 || 14 || 16" - }, - "peerDependencies": { - "@loopback/core": "^2.16.1" - } - }, - "node_modules/@loopback/rest/node_modules/@loopback/openapi-v3/node_modules/@loopback/repository-json-schema": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@loopback/repository-json-schema/-/repository-json-schema-3.4.1.tgz", - "integrity": "sha512-E9UKegav+8Bp0MLPQu33c7tWUmWbnKARy0Uu2m7nvP3e3t3WOwB8U9hMjX/wBOhJ4UFJCXAXlq1MulQ/R3dyTw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.7", - "debug": "^4.3.1", - "tslib": "^2.2.0" - }, - "engines": { - "node": "^10.16 || 12 || 14 || 16" - }, - "peerDependencies": { - "@loopback/core": "^2.16.1", - "@loopback/repository": "^3.7.0" - } - }, - "node_modules/@loopback/rest/node_modules/@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@napi-rs/triples": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@napi-rs/triples/-/triples-1.1.0.tgz", - "integrity": "sha512-XQr74QaLeMiqhStEhLn1im9EOMnkypp7MZOwQhGzqp2Weu5eQJbpPxWxixxlYRKWPOmJjsk6qYfYH9kq43yc2w==", - "dev": true - }, - "node_modules/@next/env": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/env/-/env-11.1.3.tgz", - "integrity": "sha512-5+vaeooJuWmICSlmVaAC8KG3O8hwKasACVfkHj58xQuCB5SW0TKW3hWxgxkBuefMBn1nM0yEVPKokXCsYjBtng==", - "dev": true - }, - "node_modules/@next/polyfill-module": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/polyfill-module/-/polyfill-module-11.1.3.tgz", - "integrity": "sha512-7yr9cr4a0SrBoVE8psxXWK1wTFc8UzsY8Wc2cWGL7qA0hgtqACHaXC47M1ByJB410hFZenGrpE+KFaT1unQMyw==", - "dev": true - }, - "node_modules/@next/react-dev-overlay": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/react-dev-overlay/-/react-dev-overlay-11.1.3.tgz", - "integrity": "sha512-zIwtMliSUR+IKl917ToFNB+0fD7bI5kYMdjHU/UEKpfIXAZPnXRHHISCvPDsczlr+bRsbjlUFW1CsNiuFedeuQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "7.12.11", - "anser": "1.4.9", - "chalk": "4.0.0", - "classnames": "2.2.6", - "css.escape": "1.5.1", - "data-uri-to-buffer": "3.0.1", - "platform": "1.3.6", - "shell-quote": "1.7.2", - "source-map": "0.8.0-beta.0", - "stacktrace-parser": "0.1.10", - "strip-ansi": "6.0.0" - }, - "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" - } - }, - "node_modules/@next/react-dev-overlay/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@next/react-dev-overlay/node_modules/chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@next/react-dev-overlay/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@next/react-dev-overlay/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@next/react-dev-overlay/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@next/react-dev-overlay/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@next/react-refresh-utils": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/react-refresh-utils/-/react-refresh-utils-11.1.3.tgz", - "integrity": "sha512-144kD8q2nChw67V3AJJlPQ6NUJVFczyn10bhTynn9o2rY5DEnkzuBipcyMuQl2DqfxMkV7sn+yOCOYbrLCk9zg==", - "dev": true, - "peerDependencies": { - "react-refresh": "0.8.3", - "webpack": "^4 || ^5" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } - } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-11.1.3.tgz", - "integrity": "sha512-TwP4krjhs+uU9pesDYCShEXZrLSbJr78p12e7XnLBBaNf20SgWLlVmQUT9gX9KbWan5V0sUbJfmcS8MRNHgYuA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-11.1.3.tgz", - "integrity": "sha512-ZSWmkg/PxccHFNUSeBdrfaH8KwSkoeUtewXKvuYYt7Ph0yRsbqSyNIvhUezDua96lApiXXq6EL2d1THfeWomvw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-11.1.3.tgz", - "integrity": "sha512-PrTBN0iZudAuj4jSbtXcdBdmfpaDCPIneG4Oms4zcs93KwMgLhivYW082Mvlgx9QVEiRm7+RkFpIVtG/i7JitA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-11.1.3.tgz", - "integrity": "sha512-mRwbscVjRoHk+tDY7XbkT5d9FCwujFIQJpGp0XNb1i5OHCSDO8WW/C9cLEWS4LxKRbIZlTLYg1MTXqLQkvva8w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/helper": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@node-rs/helper/-/helper-1.2.1.tgz", - "integrity": "sha512-R5wEmm8nbuQU0YGGmYVjEc0OHtYsuXdpRG+Ut/3wZ9XAvQWyThN08bTh2cBJgoZxHQUPtvRfeQuxcAgLuiBISg==", - "dev": true, - "dependencies": { - "@napi-rs/triples": "^1.0.3" - } - }, - "node_modules/@openapi-contrib/openapi-schema-to-json-schema": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@openapi-contrib/openapi-schema-to-json-schema/-/openapi-schema-to-json-schema-3.1.1.tgz", - "integrity": "sha512-FMvdhv9Jr9tULjJAQaQzhCmNYYj2vQFVnl7CGlLAImZvJal71oedXMGszpPaZTLftAk5TCHqjnirig+P6LZxug==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - } - }, - "node_modules/@panva/asn1.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz", - "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@sideway/address": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz", - "integrity": "sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@sideway/formula": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", - "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==", - "dev": true - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", - "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.1.tgz", - "integrity": "sha512-cZ7rKJTLiE7u7Wi/v9Hc2fs3Ucc3jrWeMgPHbbTCeVAB2S0wOBbYlkJVeNSL04i7fdhT8wIbDq1zhC/PXTD2SA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "node_modules/@types/accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/aws-lambda": { - "version": "8.10.77", - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.77.tgz", - "integrity": "sha512-n0EMFJU/7u3KvHrR83l/zrKOVURXl5pUJPNED/Bzjah89QKCHwCiKCBoVUXRwTGRfCYGIDdinJaAlKDHZdp/Ng==", - "dev": true - }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/co-body": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/co-body/-/co-body-5.1.1.tgz", - "integrity": "sha512-0/6AjTfQc5OJUchOS4OHiXNPZVuk+5XvEC2vdcizw/bwx0yb0xY7TKSf8JYvQYZ/OJDiAEjWzxnMjGPnSVlPmA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-0mPF08jn9zYI0n0Q/Pnz7C4kThdSt+6LD4amsrYDDpgBfrVWa3TcCOxKX1zkGgYniGagRv8heN2cbh+CAn+uuQ==", - "dev": true - }, - "node_modules/@types/cookie": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz", - "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==", - "dev": true - }, - "node_modules/@types/cookies": { - "version": "0.7.7", - "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.7.tgz", - "integrity": "sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==", - "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/express": "*", - "@types/keygrip": "*", - "@types/node": "*" - } - }, - "node_modules/@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", - "dev": true - }, - "node_modules/@types/debug": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", - "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", - "dev": true, - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/express": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.1.tgz", - "integrity": "sha512-V0clmJow23WeyblmACoxbHBu2JKlE5TiIme6Lem14FnPW9gsttyHtk6wq7njcdIWH1njAaFgR8gW09lgY98gQg==", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-jwt": { - "version": "0.0.42", - "resolved": "https://registry.npmjs.org/@types/express-jwt/-/express-jwt-0.0.42.tgz", - "integrity": "sha512-WszgUddvM1t5dPpJ3LhWNH8kfNN8GPIBrAGxgIYXVCEGx6Bx4A036aAuf/r5WH9DIEdlmp7gHOYvSM6U87B0ag==", - "dependencies": { - "@types/express": "*", - "@types/express-unless": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.33", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz", - "integrity": "sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "node_modules/@types/express-unless": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@types/express-unless/-/express-unless-0.5.3.tgz", - "integrity": "sha512-TyPLQaF6w8UlWdv4gj8i46B+INBVzURBNRahCozCSXfsK2VTlL1wNyTlMKw817VHygBtlcl5jfnPadlydr06Yw==", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/hapi__catbox": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/@types/hapi__catbox/-/hapi__catbox-10.2.4.tgz", - "integrity": "sha512-A6ivRrXD5glmnJna1UAGw87QNZRp/vdFO9U4GS+WhOMWzHnw+oTGkMvg0g6y1930CbeheGOCm7A1qHsqH7AXqg==", - "dev": true - }, - "node_modules/@types/hapi__hapi": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@types/hapi__hapi/-/hapi__hapi-20.0.8.tgz", - "integrity": "sha512-NNslrYq2XQwm4uOqNcSWKpYtaeMr4DkQdrFzSB7p9rKB9ppJLh3mgP2wak9vBZl7/Cnhhb+JVBcUZCOUcW0JPA==", - "dev": true, - "dependencies": { - "@hapi/boom": "^9.0.0", - "@hapi/iron": "^6.0.0", - "@hapi/podium": "^4.1.3", - "@types/hapi__catbox": "*", - "@types/hapi__mimos": "*", - "@types/hapi__shot": "*", - "@types/node": "*", - "joi": "^17.3.0" - } - }, - "node_modules/@types/hapi__mimos": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@types/hapi__mimos/-/hapi__mimos-4.1.4.tgz", - "integrity": "sha512-i9hvJpFYTT/qzB5xKWvDYaSXrIiNqi4ephi+5Lo6+DoQdwqPXQgmVVOZR+s3MBiHoFqsCZCX9TmVWG3HczmTEQ==", - "dev": true, - "dependencies": { - "@types/mime-db": "*" - } - }, - "node_modules/@types/hapi__shot": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@types/hapi__shot/-/hapi__shot-4.1.2.tgz", - "integrity": "sha512-8wWgLVP1TeGqgzZtCdt+F+k15DWQvLG1Yv6ZzPfb3D5WIo5/S+GGKtJBVo2uNEcqabP5Ifc71QnJTDnTmw1axA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/http-assert": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.3.tgz", - "integrity": "sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA==", - "dev": true - }, - "node_modules/@types/http-errors": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.2.tgz", - "integrity": "sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==", - "dev": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "dev": true - }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", - "integrity": "sha512-mM4TkDpA9oixqg1Fv2vVpOFyIVLJjm5x4k0V+K/rEsizfjD7Tk7LKk3GTtbB7KCfP0FEHQtsZqFxYA0+sijNVg==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/keygrip": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", - "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==", - "dev": true - }, - "node_modules/@types/koa": { - "version": "2.13.4", - "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.13.4.tgz", - "integrity": "sha512-dfHYMfU+z/vKtQB7NUrthdAEiSvnLebvBjwHtfFmpZmB7em2N3WVQdHgnFq+xvyVgxW5jKDmjWfLD3lw4g4uTw==", - "dev": true, - "dependencies": { - "@types/accepts": "*", - "@types/content-disposition": "*", - "@types/cookies": "*", - "@types/http-assert": "*", - "@types/http-errors": "*", - "@types/keygrip": "*", - "@types/koa-compose": "*", - "@types/node": "*" - } - }, - "node_modules/@types/koa-bodyparser": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@types/koa-bodyparser/-/koa-bodyparser-4.3.5.tgz", - "integrity": "sha512-NRqqoTtt7cfdDk/KNo+EwCIKRuzPAu/wsaZ7tgIvSIBtNfxuZHYueaLoWdxX3ZftWavQv07NE46TcpyoZGqpgQ==", - "dev": true, - "dependencies": { - "@types/koa": "*" - } - }, - "node_modules/@types/koa-compose": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", - "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", - "dev": true, - "dependencies": { - "@types/koa": "*" - } - }, - "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" - }, - "node_modules/@types/mime-db": { - "version": "1.43.1", - "resolved": "https://registry.npmjs.org/@types/mime-db/-/mime-db-1.43.1.tgz", - "integrity": "sha512-kGZJY+R+WnR5Rk+RPHUMERtb2qBRViIHCBdtUrY+NmwuGb8pQdfTqQiCKPrxpdoycl8KWm2DLdkpoSdt479XoQ==", - "dev": true - }, - "node_modules/@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", - "dev": true - }, - "node_modules/@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "17.0.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz", - "integrity": "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==" - }, - "node_modules/@types/nodemailer": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.4.tgz", - "integrity": "sha512-Ksw4t7iliXeYGvIQcSIgWQ5BLuC/mljIEbjf615svhZL10PE9t+ei8O9gDaD3FPCasUJn9KTLwz2JFJyiiyuqw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/on-finished": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@types/on-finished/-/on-finished-2.3.1.tgz", - "integrity": "sha512-mzVYaYcFs5Jd2n/O6uYIRUsFRR1cHyZLRvkLCU0E7+G5WhY0qBDAR5fUCeZbvecYOSh9ikhlesyi2UfI8B9ckQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/psl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@types/psl/-/psl-1.1.0.tgz", - "integrity": "sha512-HhZnoLAvI2koev3czVPzBNRYvdrzJGLjQbWZhqFmS9Q6a0yumc5qtfSahBGb5g+6qWvA8iiQktqGkwoIXa/BNQ==", - "dev": true - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" - }, - "node_modules/@types/serve-static": { - "version": "1.13.9", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz", - "integrity": "sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/type-is": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@types/type-is/-/type-is-1.6.3.tgz", - "integrity": "sha512-PNs5wHaNcBgCQG5nAeeZ7OvosrEsI9O4W2jAOO9BCCg4ux9ZZvH2+0iSCOIDBiKuQsiNS8CBlmfX9f5YBQ22cA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/validator": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-10.11.0.tgz", - "integrity": "sha512-i1aY7RKb6HmQIEnK0cBmUZUp1URx0riIHw/GYNoZ46Su0GWfLiDmMI8zMRmaauMnOTg2bQag0qfwcyUFC9Tn+A==", - "dev": true - }, - "node_modules/abstract-logging": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", - "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==", - "dev": true - }, - "node_modules/accept-language": { - "version": "3.0.18", - "resolved": "https://registry.npmjs.org/accept-language/-/accept-language-3.0.18.tgz", - "integrity": "sha1-9QJfF79lpGaoRYOMz5jNuHfYM4Q=", - "dev": true, - "dependencies": { - "bcp47": "^1.1.2", - "stable": "^0.1.6" - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true, - "peerDependencies": { - "ajv": ">=5.0.0" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/anser": { - "version": "1.4.9", - "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.9.tgz", - "integrity": "sha512-AI+BjTeGt2+WFk4eWcqbQ7snZpDBt8SaLlj0RT2h5xfdWaiy51OjYvqwMrNzJLGy8iOAL6nKDITWO+rd4MkYEA==", - "dev": true - }, - "node_modules/ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/app-root-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz", - "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==", - "dev": true, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-differ": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", - "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/assert": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", - "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", - "dev": true, - "dependencies": { - "es6-object-assign": "^1.1.0", - "is-nan": "^1.2.1", - "object-is": "^1.0.1", - "util": "^0.12.0" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/ast-types": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.2.tgz", - "integrity": "sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", - "dev": true - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "node_modules/atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/avvio": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/avvio/-/avvio-7.2.2.tgz", - "integrity": "sha512-XW2CMCmZaCmCCsIaJaLKxAzPwF37fXi1KGxNOvedOpeisLdmxZnblGc3hpHWYnlP+KOUxZsazh43WXNHgXpbqw==", - "dev": true, - "dependencies": { - "archy": "^1.0.0", - "debug": "^4.0.0", - "fastq": "^1.6.1", - "queue-microtask": "^1.1.2" - } - }, - "node_modules/aws-sdk": { - "version": "2.1077.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1077.0.tgz", - "integrity": "sha512-orJvJROs8hJaQRfHsX7Zl5PxEgrD/uTXyqXz9Yu9Io5VVxzvnOty9oHmvEMSlgTIf1qd01gnev/vpvP1HgzKtw==", - "dev": true, - "dependencies": { - "buffer": "4.9.2", - "events": "1.1.1", - "ieee754": "1.1.13", - "jmespath": "0.16.0", - "querystring": "0.2.0", - "sax": "1.2.1", - "url": "0.10.3", - "uuid": "3.3.2", - "xml2js": "0.4.19" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/aws-sdk-mock": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/aws-sdk-mock/-/aws-sdk-mock-5.6.2.tgz", - "integrity": "sha512-GRJg8kjRJFLm2aLiPkYSqe/RreHqlqncAeFtWdAbtSxzBdct9EaV6rqSqjyWXKNJG45Rzn2Ojo3F6qVIgkQnSg==", - "dev": true, - "dependencies": { - "aws-sdk": "^2.928.0", - "sinon": "^11.1.1", - "traverse": "^0.6.6" - } - }, - "node_modules/aws-sdk-mock/node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/aws-sdk-mock/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/aws-sdk-mock/node_modules/sinon": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz", - "integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": "^7.1.2", - "@sinonjs/samsam": "^6.0.2", - "diff": "^5.0.0", - "nise": "^5.1.0", - "supports-color": "^7.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/aws-sdk-mock/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/aws-sdk/node_modules/uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dependencies": { - "follow-redirects": "^1.14.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bcp47": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/bcp47/-/bcp47-1.1.2.tgz", - "integrity": "sha1-NUvjMH/9CEM6ePXh4glYRfifx/4=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "dev": true, - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/bl/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/bl/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", - "dev": true - }, - "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/body-parser/node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/body-parser/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "dependencies": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "node_modules/browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", - "dev": true, - "dependencies": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" - } - }, - "node_modules/browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "dev": true, - "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - } - }, - "node_modules/browserify-sign/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "dependencies": { - "pako": "~1.0.5" - } - }, - "node_modules/browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "node_modules/builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true - }, - "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cache-content-type": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", - "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", - "dev": true, - "dependencies": { - "mime-types": "^2.1.18", - "ylru": "^1.2.0" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001312", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz", - "integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/capital-case": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", - "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" - } - }, - "node_modules/chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/change-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", - "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", - "dev": true, - "dependencies": { - "camel-case": "^4.1.2", - "capital-case": "^1.0.4", - "constant-case": "^3.0.4", - "dot-case": "^3.0.4", - "header-case": "^2.0.4", - "no-case": "^3.0.4", - "param-case": "^3.0.4", - "pascal-case": "^3.1.2", - "path-case": "^3.0.4", - "sentence-case": "^3.0.4", - "snake-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.1" - } - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/classnames": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", - "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==", - "dev": true - }, - "node_modules/cldrjs": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/cldrjs/-/cldrjs-0.5.5.tgz", - "integrity": "sha512-KDwzwbmLIPfCgd8JERVDpQKrUUM1U4KpFJJg2IROv89rF172lLufoJnqJ/Wea6fXL5bO6WjuLMzY8V52UWPvkA==", - "dev": true - }, - "node_modules/cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "dependencies": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/co-body": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/co-body/-/co-body-6.1.0.tgz", - "integrity": "sha512-m7pOT6CdLN7FuXUcpuz/8lfQ/L77x8SchHCF4G0RBTJO20Wzmhn5Sp4/5WsKy8OSpifBSUrmg83qEqaDHdyFuQ==", - "dependencies": { - "inflation": "^2.0.0", - "qs": "^6.5.2", - "raw-body": "^2.3.3", - "type-is": "^1.6.16" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/colorette": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", - "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", - "dev": true - }, - "node_modules/constant-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", - "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case": "^2.0.2" - } - }, - "node_modules/constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-disposition/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-parser": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", - "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", - "dev": true, - "dependencies": { - "cookie": "0.4.1", - "cookie-signature": "1.0.6" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/cookie-parser/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "node_modules/cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", - "dev": true - }, - "node_modules/cookies": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", - "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", - "dev": true, - "dependencies": { - "depd": "~2.0.0", - "keygrip": "~1.1.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cookies/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - } - }, - "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s=", - "dev": true - }, - "node_modules/cssnano-preset-simple": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssnano-preset-simple/-/cssnano-preset-simple-3.0.0.tgz", - "integrity": "sha512-vxQPeoMRqUT3c/9f0vWeVa2nKQIHFpogtoBvFdW4GQ3IvEJ6uauCP6p3Y5zQDLFcI7/+40FTgX12o7XUL0Ko+w==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30001202" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-simple": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssnano-simple/-/cssnano-simple-3.0.0.tgz", - "integrity": "sha512-oU3ueli5Dtwgh0DyeohcIEE00QVfbPR3HzyXdAl89SfnQG3y0/qcpfLVW+jPIh3/rgMZGwuW96rejZGaYE9eUg==", - "dev": true, - "dependencies": { - "cssnano-preset-simple": "^3.0.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - } - } - }, - "node_modules/data-uri-to-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", - "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/dayjs": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.0.tgz", - "integrity": "sha512-JLC809s6Y948/FuCZPm5IX8rRhQwOiyMb2TfVVQEixG7P8Lm/gt5S7yoQZmC8x1UehI9Pb7sksEt4xx14m+7Ug==" - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/domain-browser": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.19.0.tgz", - "integrity": "sha512-fRA+BaAWOR/yr/t7T9E9GJztHPeFjj8U35ajyAjCDtAAnTn1Rc1f6W6VGPJrO1tkQv9zWu+JRof7z6oQtiYVFQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://bevry.me/fund" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/dotenv-json": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dotenv-json/-/dotenv-json-1.0.0.tgz", - "integrity": "sha512-jAssr+6r4nKhKRudQ0HOzMskOFFi9+ubXWwmrSGJFgTvpjyPXCXsCsYbjif6mXp7uxA7xY3/LGaiTQukZzSbOQ==", - "dev": true - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "node_modules/ejs": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", - "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", - "dev": true, - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.71", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.71.tgz", - "integrity": "sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw==", - "dev": true - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", - "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-abstract/node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es6-object-assign": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", - "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true, - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dev": true, - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "node_modules/express/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/express/node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/express/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/fast-decode-uri-component": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", - "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==", - "dev": true - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-json-stringify": { - "version": "2.7.13", - "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.7.13.tgz", - "integrity": "sha512-ar+hQ4+OIurUGjSJD1anvYSDcUflywhKjfxnsW4TBTD7+u0tJufv6DKRWoQk3vI6YBOWMoz0TQtfbe7dxbQmvA==", - "dev": true, - "dependencies": { - "ajv": "^6.11.0", - "deepmerge": "^4.2.2", - "rfdc": "^1.2.0", - "string-similarity": "^4.0.1" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/fast-redact": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.0.tgz", - "integrity": "sha512-dir8LOnvialLxiXDPESMDHGp82CHi6ZEYTVkcvdn5d7psdv9ZkkButXrOeXST4aqreIRR+N7CYlsrwFuorurVg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true - }, - "node_modules/fastify": { - "version": "3.18.1", - "resolved": "https://registry.npmjs.org/fastify/-/fastify-3.18.1.tgz", - "integrity": "sha512-OA0imy/bQCMzf7LUCb/1JI3ZSoA0Jo0MLpYULxV7gpppOpJ8NBxDp2PQoQ0FDqJevZPb7tlZf5JacIQft8x9yw==", - "dev": true, - "dependencies": { - "@fastify/ajv-compiler": "^1.0.0", - "abstract-logging": "^2.0.0", - "avvio": "^7.1.2", - "fast-json-stringify": "^2.5.2", - "fastify-error": "^0.3.0", - "fastify-warning": "^0.2.0", - "find-my-way": "^4.0.0", - "flatstr": "^1.0.12", - "light-my-request": "^4.2.0", - "pino": "^6.2.1", - "proxy-addr": "^2.0.7", - "readable-stream": "^3.4.0", - "rfdc": "^1.1.4", - "secure-json-parse": "^2.0.0", - "semver": "^7.3.2", - "tiny-lru": "^7.0.0" - } - }, - "node_modules/fastify-error": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.1.tgz", - "integrity": "sha512-oCfpcsDndgnDVgiI7bwFKAun2dO+4h84vBlkWsWnz/OUK9Reff5UFoFl241xTiLeHWX/vU9zkDVXqYUxjOwHcQ==", - "dev": true - }, - "node_modules/fastify-warning": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/fastify-warning/-/fastify-warning-0.2.0.tgz", - "integrity": "sha512-s1EQguBw/9qtc1p/WTY4eq9WMRIACkj+HTcOIK1in4MV5aFaQC9ZCIt0dJ7pr5bIf4lPpHvAtP2ywpTNgs7hqw==", - "deprecated": "This module renamed to process-warning", - "dev": true - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dev": true, - "dependencies": { - "minimatch": "^5.0.1" - } - }, - "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz", - "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/finalhandler/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-my-way": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-4.5.1.tgz", - "integrity": "sha512-kE0u7sGoUFbMXcOG/xpkmz4sRLCklERnBcg7Ftuu1iAxsfEt2S46RLJ3Sq7vshsEy2wJT2hZxE58XZK27qa8kg==", - "dev": true, - "dependencies": { - "fast-decode-uri-component": "^1.0.1", - "fast-deep-equal": "^3.1.3", - "safe-regex2": "^2.0.0", - "semver-store": "^0.3.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", - "dev": true, - "dependencies": { - "is-buffer": "~2.0.3" - }, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat/node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, - "node_modules/flatstr": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", - "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, - "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/formidable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", - "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", - "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", - "dev": true, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-orientation": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/get-orientation/-/get-orientation-1.1.2.tgz", - "integrity": "sha512-/pViTfifW+gBbh/RnlFYHINvELT9Znt+SYyDKAUL6uV6By019AK/s+i9XP4jSwq7lwP38Fd8HVeTxym3+hkwmQ==", - "dev": true, - "dependencies": { - "stream-parser": "^0.3.1" - } - }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/globalize": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/globalize/-/globalize-1.7.0.tgz", - "integrity": "sha512-faR46vTIbFCeAemyuc9E6/d7Wrx9k2ae2L60UhakztFg6VuE42gENVJNuPFtt7Sdjrk9m2w8+py7Jj+JTNy59w==", - "dev": true, - "dependencies": { - "cldrjs": "^0.5.4" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", - "dev": true - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "engines": { - "node": ">=4.x" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-base/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/header-case": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", - "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", - "dev": true, - "dependencies": { - "capital-case": "^1.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/http-assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", - "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", - "dev": true, - "dependencies": { - "deep-equal": "~1.0.1", - "http-errors": "~1.8.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-errors/node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/http-status": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/http-status/-/http-status-1.5.0.tgz", - "integrity": "sha512-wcGvY31MpFNHIkUcXHHnvrE4IKYlpvitJw5P/1u892gMBAM46muQ+RH7UN1d+Ntnfx5apnOnVY6vcLmrWHOLwg==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true, - "engines": { - "node": ">=8.12.0" - } - }, - "node_modules/hyperid": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/hyperid/-/hyperid-2.3.1.tgz", - "integrity": "sha512-mIbI7Ymn6MCdODaW1/6wdf5lvvXzmPsARN4zTLakMmcziBOuP4PxCBJvHF6kbAIHX6H4vAELx/pDmt0j6Th5RQ==", - "dev": true, - "dependencies": { - "uuid": "^8.3.2", - "uuid-parse": "^1.1.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true - }, - "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/image-size": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.0.tgz", - "integrity": "sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw==", - "dev": true, - "dependencies": { - "queue": "6.0.2" - }, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/inflation": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz", - "integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8=", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/inflection": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.2.tgz", - "integrity": "sha512-cmZlljCRTBFouT8UzMzrGcVEvkv6D/wBdcdKG7J1QH5cXjtU75Dm+P27v9EKu/Y43UYyCJd1WC4zLebRrC8NBw==", - "dev": true, - "engines": [ - "node >= 0.4.0" - ] - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/invert-kv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-3.0.1.tgz", - "integrity": "sha512-CYdFeFexxhv/Bcny+Q0BfOV+ltRlJcd4BBZBYFX/O0u4npJrgZtIcjokegtiSMAvlMTJ+Koq0GBCc//3bueQxw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sindresorhus/invert-kv?sponsor=1" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", - "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jake": { - "version": "10.8.5", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", - "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", - "dev": true, - "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jake/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jake/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jake/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jake/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jake/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jake/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker": { - "version": "27.0.0-next.5", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.0.0-next.5.tgz", - "integrity": "sha512-mk0umAQ5lT+CaOJ+Qp01N6kz48sJG2kr2n1rX0koqKf6FIygQV0qLOdN9SCYID4IVeSigDOcPeGLozdMLYfb5g==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jmespath": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", - "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/joi": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz", - "integrity": "sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.0", - "@sideway/pinpoint": "^2.0.0" - } - }, - "node_modules/jose": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.6.tgz", - "integrity": "sha512-FVoPY7SflDodE4lknJmbAHSUjLCzE2H1F6MS0RYKMQ8SR+lNccpMf8R4eqkNYyyUjR5qZReOzZo5C5YiHOCjjg==", - "dependencies": { - "@panva/asn1.js": "^1.0.0" - }, - "engines": { - "node": ">=10.13.0 < 13 || >=13.7.0" - }, - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/js2xmlparser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", - "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", - "dev": true, - "dependencies": { - "xmlcreate": "^2.0.4" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "peer": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-merge-patch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-merge-patch/-/json-merge-patch-1.0.2.tgz", - "integrity": "sha512-M6Vp2GN9L7cfuMXiWOmHj9bEFbeC250iVtcKQbqVgEsDVYnIsrNsbU+h/Y/PkbBQCtEa4Bez+Ebv0zfbC8ObLg==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - } - }, - "node_modules/json-schema-compare": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz", - "integrity": "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==", - "dev": true, - "dependencies": { - "lodash": "^4.17.4" - } - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "peer": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json5/node_modules/minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true, - "peer": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", - "dev": true - }, - "node_modules/jsonwebtoken": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", - "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", - "dependencies": { - "jws": "^3.2.2", - "lodash": "^4.17.21", - "ms": "^2.1.1", - "semver": "^7.3.8" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jwks-rsa": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-2.0.5.tgz", - "integrity": "sha512-fliHfsiBRzEU0nXzSvwnh0hynzGB0WihF+CinKbSRlaqRxbqqKf2xbBPgwc8mzf18/WgwlG8e5eTpfSTBcU4DQ==", - "dependencies": { - "@types/express-jwt": "0.0.42", - "debug": "^4.3.2", - "jose": "^2.0.5", - "limiter": "^1.1.5", - "lru-memoizer": "^2.1.4" - }, - "engines": { - "node": ">=10 < 13 || >=14" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/keygrip": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", - "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", - "dev": true, - "dependencies": { - "tsscmp": "1.0.6" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/koa": { - "version": "2.13.4", - "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.4.tgz", - "integrity": "sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g==", - "dev": true, - "dependencies": { - "accepts": "^1.3.5", - "cache-content-type": "^1.0.0", - "content-disposition": "~0.5.2", - "content-type": "^1.0.4", - "cookies": "~0.8.0", - "debug": "^4.3.2", - "delegates": "^1.0.0", - "depd": "^2.0.0", - "destroy": "^1.0.4", - "encodeurl": "^1.0.2", - "escape-html": "^1.0.3", - "fresh": "~0.5.2", - "http-assert": "^1.3.0", - "http-errors": "^1.6.3", - "is-generator-function": "^1.0.7", - "koa-compose": "^4.1.0", - "koa-convert": "^2.0.0", - "on-finished": "^2.3.0", - "only": "~0.0.2", - "parseurl": "^1.3.2", - "statuses": "^1.5.0", - "type-is": "^1.6.16", - "vary": "^1.1.2" - }, - "engines": { - "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" - } - }, - "node_modules/koa-compose": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", - "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", - "dev": true - }, - "node_modules/koa-convert": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-2.0.0.tgz", - "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==", - "dev": true, - "dependencies": { - "co": "^4.6.0", - "koa-compose": "^4.1.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/koa/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/lambda-event-mock": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lambda-event-mock/-/lambda-event-mock-1.5.0.tgz", - "integrity": "sha512-vx1d+vZqi7FF6B3+mAfHnY/6Tlp6BheL2ta0MJS0cIRB3Rc4I5cviHTkiJxHdE156gXx3ZjlQRJrS4puXvtrhA==", - "dev": true, - "dependencies": { - "@extra-number/significant-digits": "^1.1.1", - "clone-deep": "^4.0.1", - "uuid": "^3.3.3", - "vandium-utils": "^1.2.0" - }, - "engines": { - "node": ">=12.13" - } - }, - "node_modules/lambda-event-mock/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/lambda-event-mock/node_modules/vandium-utils": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vandium-utils/-/vandium-utils-1.2.0.tgz", - "integrity": "sha1-RHNd5LdkGgXeWevpRfF05YLbT1k=", - "dev": true - }, - "node_modules/lambda-leak": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lambda-leak/-/lambda-leak-2.0.0.tgz", - "integrity": "sha1-dxmF02KEh/boha+uK1RRDc+yzX4=", - "dev": true, - "engines": { - "node": ">=6.10.0" - } - }, - "node_modules/lambda-tester": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lambda-tester/-/lambda-tester-4.0.1.tgz", - "integrity": "sha512-ft6XHk84B6/dYEzyI3anKoGWz08xQ5allEHiFYDUzaYTymgVK7tiBkCEbuWx+MFvH7OpFNsJXVtjXm0X8iH3Iw==", - "dev": true, - "dependencies": { - "app-root-path": "^3.0.0", - "dotenv": "^8.0.0", - "dotenv-json": "^1.0.0", - "lambda-event-mock": "^1.5.0", - "lambda-leak": "^2.0.0", - "semver": "^6.1.1", - "uuid": "^3.3.3", - "vandium-utils": "^2.0.0" - }, - "engines": { - "node": ">=10.0" - } - }, - "node_modules/lambda-tester/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/lambda-tester/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/lcid": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-3.1.1.tgz", - "integrity": "sha512-M6T051+5QCGLBQb8id3hdvIW8+zeFV2FyBGFS9IEK5H9Wt4MueD4bW1eWikpHgZp+5xR3l5c8pZUkQsIA0BFZg==", - "dev": true, - "dependencies": { - "invert-kv": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/libphonenumber-js": { - "version": "1.9.49", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.49.tgz", - "integrity": "sha512-/wEOIONcVboFky+lWlCaF7glm1FhBz11M5PHeCApA+xDdVfmhKjHktHS8KjyGxouV5CSXIr4f3GvLSpJa4qMSg==" - }, - "node_modules/light-my-request": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-4.8.0.tgz", - "integrity": "sha512-C2XESrTRsZnI59NSQigOsS6IuTxpj8OhSBvZS9fhgBMsamBsAuWN1s4hj/nCi8EeZcyAA6xbROhsZy7wKdfckg==", - "dev": true, - "dependencies": { - "ajv": "^8.1.0", - "cookie": "^0.4.0", - "process-warning": "^1.0.0", - "set-cookie-parser": "^2.4.1" - } - }, - "node_modules/light-my-request/node_modules/ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/light-my-request/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/limiter": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", - "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" - }, - "node_modules/loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^2.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/loader-utils/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/loader-utils/node_modules/minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true - }, - "node_modules/log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "dependencies": { - "chalk": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/loopback-connector": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/loopback-connector/-/loopback-connector-5.0.1.tgz", - "integrity": "sha512-aSPT6x5WZdoW9ylyNE4CxGqFbIqC9cSEZJwWkCincso27PXlZPj52POoF6pgxug9mkH7MrbXuP3SSDLkLq5oQQ==", - "dev": true, - "dependencies": { - "async": "^3.2.0", - "bluebird": "^3.7.2", - "debug": "^4.1.1", - "msgpack5": "^4.2.0", - "strong-globalize": "^6.0.4", - "uuid": "^8.3.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/loopback-datasource-juggler": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/loopback-datasource-juggler/-/loopback-datasource-juggler-4.26.0.tgz", - "integrity": "sha512-/R40jUGDrnRBgTh121L4Y7sHDF0KxbgSAN4gLJKp8xGNQ6KpkSQyqZkmap98eN7B75RES78DS3MGghsYMvAJ3Q==", - "dev": true, - "dependencies": { - "async": "^3.1.0", - "change-case": "^4.1.1", - "debug": "^4.1.0", - "depd": "^2.0.0", - "inflection": "^1.6.0", - "lodash": "^4.17.11", - "loopback-connector": "^5.0.0", - "minimatch": "^3.0.3", - "qs": "^6.5.0", - "shortid": "^2.2.6", - "strong-globalize": "^6.0.5", - "traverse": "^0.6.6", - "uuid": "^8.3.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/loopback-datasource-juggler/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.0" - } - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lru-cache": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", - "integrity": "sha1-HRdnnAac2l0ECZGgnbwsDbN35V4=", - "dependencies": { - "pseudomap": "^1.0.1", - "yallist": "^2.0.0" - } - }, - "node_modules/lru-memoizer": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.1.4.tgz", - "integrity": "sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ==", - "dependencies": { - "lodash.clonedeep": "^4.5.0", - "lru-cache": "~4.0.0" - } - }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "dependencies": { - "p-defer": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/marked": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", - "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", - "dev": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/md5": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", - "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", - "dev": true, - "dependencies": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "~1.1.6" - } - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mem": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/mem/-/mem-5.1.1.tgz", - "integrity": "sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==", - "dev": true, - "dependencies": { - "map-age-cleaner": "^0.1.3", - "mimic-fn": "^2.1.0", - "p-is-promise": "^2.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "bin": { - "miller-rabin": "bin/miller-rabin" - } - }, - "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dependencies": { - "mime-db": "1.51.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==", - "dev": true - }, - "node_modules/mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "dev": true, - "dependencies": { - "minimist": "0.0.8" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mocha": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz", - "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==", - "dev": true, - "dependencies": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.2.2", - "yargs-parser": "13.0.0", - "yargs-unparser": "1.5.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/mocha/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/mocha/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/msgpack5": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/msgpack5/-/msgpack5-4.5.1.tgz", - "integrity": "sha512-zC1vkcliryc4JGlL6OfpHumSYUHWFGimSI+OgfRCjTFLmKA2/foR9rMTOhWiqfOrfxJOctrpWPvrppf8XynJxw==", - "dev": true, - "dependencies": { - "bl": "^2.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.3.6", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/msgpack5/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/msgpack5/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/multimatch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", - "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", - "dev": true, - "dependencies": { - "@types/minimatch": "^3.0.3", - "array-differ": "^3.0.0", - "array-union": "^2.1.0", - "arrify": "^2.0.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/native-url": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/native-url/-/native-url-0.3.4.tgz", - "integrity": "sha512-6iM8R99ze45ivyH8vybJ7X0yekIcPf5GgLV5K0ENCbmRcaRIDoj37BC8iLEmaaBfqqb8enuZ5p0uhY+lVAbAcA==", - "dev": true, - "dependencies": { - "querystring": "^0.2.0" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/next": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/next/-/next-11.1.3.tgz", - "integrity": "sha512-ud/gKmnKQ8wtHC+pd1ZiqPRa7DdgulPkAk94MbpsspfNliwZkYs9SIYWhlLSyg+c661LzdUI2nZshvrtggSYWA==", - "dev": true, - "dependencies": { - "@babel/runtime": "7.15.3", - "@hapi/accept": "5.0.2", - "@next/env": "11.1.3", - "@next/polyfill-module": "11.1.3", - "@next/react-dev-overlay": "11.1.3", - "@next/react-refresh-utils": "11.1.3", - "@node-rs/helper": "1.2.1", - "assert": "2.0.0", - "ast-types": "0.13.2", - "browserify-zlib": "0.2.0", - "browserslist": "4.16.6", - "buffer": "5.6.0", - "caniuse-lite": "^1.0.30001228", - "chalk": "2.4.2", - "chokidar": "3.5.1", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.12.0", - "cssnano-simple": "3.0.0", - "domain-browser": "4.19.0", - "encoding": "0.1.13", - "etag": "1.8.1", - "find-cache-dir": "3.3.1", - "get-orientation": "1.1.2", - "https-browserify": "1.0.0", - "image-size": "1.0.0", - "jest-worker": "27.0.0-next.5", - "native-url": "0.3.4", - "node-fetch": "2.6.1", - "node-html-parser": "1.4.9", - "node-libs-browser": "^2.2.1", - "os-browserify": "0.3.0", - "p-limit": "3.1.0", - "path-browserify": "1.0.1", - "pnp-webpack-plugin": "1.6.4", - "postcss": "8.2.15", - "process": "0.11.10", - "querystring-es3": "0.2.1", - "raw-body": "2.4.1", - "react-is": "17.0.2", - "react-refresh": "0.8.3", - "stream-browserify": "3.0.0", - "stream-http": "3.1.1", - "string_decoder": "1.3.0", - "styled-jsx": "4.0.1", - "timers-browserify": "2.0.12", - "tty-browserify": "0.0.1", - "use-subscription": "1.5.1", - "util": "0.12.4", - "vm-browserify": "1.1.2", - "watchpack": "2.1.1" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=12.0.0" - }, - "optionalDependencies": { - "@next/swc-darwin-arm64": "11.1.3", - "@next/swc-darwin-x64": "11.1.3", - "@next/swc-linux-x64-gnu": "11.1.3", - "@next/swc-win32-x64-msvc": "11.1.3" - }, - "peerDependencies": { - "fibers": ">= 3.1.0", - "node-sass": "^4.0.0 || ^5.0.0", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "fibers": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "node_modules/next/node_modules/buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", - "dev": true, - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "node_modules/next/node_modules/http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/next/node_modules/raw-body": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", - "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", - "dev": true, - "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.3", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/next/node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/nise": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.1.tgz", - "integrity": "sha512-yr5kW2THW1AkxVmCnKEh4nbYkJdB3I7LUkiUgOvEkOp414mc2UMaHMA7pjq1nYowhdoJZGwEKGaQVbxfpWj10A==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": ">=5", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/nise/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/nise/node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/nock": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/nock/-/nock-11.7.0.tgz", - "integrity": "sha512-7c1jhHew74C33OBeRYyQENT+YXQiejpwIrEjinh6dRurBae+Ei4QjeUaPlkptIF0ZacEiVCnw8dWaxqepkiihg==", - "dev": true, - "dependencies": { - "chai": "^4.1.2", - "debug": "^4.1.0", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.13", - "mkdirp": "^0.5.0", - "propagate": "^2.0.0" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true, - "dependencies": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, - "node_modules/node-environment-flags/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", - "dev": true, - "engines": { - "node": "4.x || >=6.0.0" - } - }, - "node_modules/node-html-parser": { - "version": "1.4.9", - "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-1.4.9.tgz", - "integrity": "sha512-UVcirFD1Bn0O+TSmloHeHqZZCxHjvtIeGdVdGMhyZ8/PWlEiZaZ5iJzR189yKZr8p0FXN58BUeC7RHRkf/KYGw==", - "dev": true, - "dependencies": { - "he": "1.2.0" - } - }, - "node_modules/node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", - "dev": true, - "dependencies": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - } - }, - "node_modules/node-libs-browser/node_modules/assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "dev": true, - "dependencies": { - "object-assign": "^4.1.1", - "util": "0.10.3" - } - }, - "node_modules/node-libs-browser/node_modules/assert/node_modules/inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "node_modules/node-libs-browser/node_modules/assert/node_modules/util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "dependencies": { - "inherits": "2.0.1" - } - }, - "node_modules/node-libs-browser/node_modules/domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true, - "engines": { - "node": ">=0.4", - "npm": ">=1.2" - } - }, - "node_modules/node-libs-browser/node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/node-libs-browser/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "node_modules/node-libs-browser/node_modules/path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", - "dev": true - }, - "node_modules/node-libs-browser/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - }, - "node_modules/node-libs-browser/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/node-libs-browser/node_modules/stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true, - "dependencies": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "node_modules/node-libs-browser/node_modules/stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "dependencies": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "node_modules/node-libs-browser/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/node-libs-browser/node_modules/tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "node_modules/node-libs-browser/node_modules/url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "node_modules/node-libs-browser/node_modules/util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "dependencies": { - "inherits": "2.0.3" - } - }, - "node_modules/node-mocks-http": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/node-mocks-http/-/node-mocks-http-1.11.0.tgz", - "integrity": "sha512-jS/WzSOcKbOeGrcgKbenZeNhxUNnP36Yw11+hL4TTxQXErGfqYZ+MaYNNvhaTiGIJlzNSqgQkk9j8dSu1YWSuw==", - "dev": true, - "dependencies": { - "accepts": "^1.3.7", - "content-disposition": "^0.5.3", - "depd": "^1.1.0", - "fresh": "^0.5.2", - "merge-descriptors": "^1.0.1", - "methods": "^1.1.2", - "mime": "^1.3.4", - "parseurl": "^1.3.3", - "range-parser": "^1.2.0", - "type-is": "^1.6.18" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/node-releases": { - "version": "1.1.77", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.77.tgz", - "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==", - "dev": true - }, - "node_modules/nodemailer": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.7.3.tgz", - "integrity": "sha512-KUdDsspqx89sD4UUyUKzdlUOper3hRkDVkrKh/89G+d9WKsU5ox51NWS4tB1XR5dPUdR4SP0E3molyEfOvSa3g==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", - "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/only": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", - "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=", - "dev": true - }, - "node_modules/openapi3-ts": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/openapi3-ts/-/openapi3-ts-2.0.2.tgz", - "integrity": "sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw==", - "dev": true, - "dependencies": { - "yaml": "^1.10.2" - } - }, - "node_modules/os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "node_modules/os-locale": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-5.0.0.tgz", - "integrity": "sha512-tqZcNEDAIZKBEPnHPlVDvKrp7NzgLi7jRmhKiUoa2NUmhl13FtkAGLUVR+ZsYvApBQdBfYm43A4tXXQ4IrYLBA==", - "dev": true, - "dependencies": { - "execa": "^4.0.0", - "lcid": "^3.0.0", - "mem": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-event": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", - "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", - "dev": true, - "dependencies": { - "p-timeout": "^3.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "dev": true, - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dev": true, - "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, - "node_modules/path-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", - "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-to-regexp": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.0.tgz", - "integrity": "sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg==", - "dev": true - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dev": true, - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true, - "peer": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pino": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-6.14.0.tgz", - "integrity": "sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==", - "dev": true, - "dependencies": { - "fast-redact": "^3.0.0", - "fast-safe-stringify": "^2.0.8", - "flatstr": "^1.0.12", - "pino-std-serializers": "^3.1.0", - "process-warning": "^1.0.0", - "quick-format-unescaped": "^4.0.3", - "sonic-boom": "^1.0.2" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/pino-std-serializers": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz", - "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==", - "dev": true - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/platform": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", - "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", - "dev": true - }, - "node_modules/pnp-webpack-plugin": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz", - "integrity": "sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==", - "dev": true, - "dependencies": { - "ts-pnp": "^1.1.6" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/postcss": { - "version": "8.2.15", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz", - "integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==", - "dev": true, - "dependencies": { - "colorette": "^1.2.2", - "nanoid": "^3.1.23", - "source-map": "^0.6.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/postcss/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prettier": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz", - "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/pretty-quick": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.3.tgz", - "integrity": "sha512-kOCi2FJabvuh1as9enxYmrnBC6tVMoVOenMaBqRfsvBHB0cbpYHjdQEpSglpASDFEXVwplpcGR4CLEaisYAFcA==", - "dev": true, - "dependencies": { - "chalk": "^3.0.0", - "execa": "^4.0.0", - "find-up": "^4.1.0", - "ignore": "^5.1.4", - "mri": "^1.1.5", - "multimatch": "^4.0.0" - }, - "bin": { - "pretty-quick": "bin/pretty-quick.js" - }, - "engines": { - "node": ">=10.13" - }, - "peerDependencies": { - "prettier": ">=2.0.0" - } - }, - "node_modules/pretty-quick/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/pretty-quick/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/pretty-quick/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/pretty-quick/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pretty-quick/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/process-warning": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", - "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==", - "dev": true - }, - "node_modules/propagate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", - "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "node_modules/public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "dev": true, - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true, - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" - }, - "node_modules/queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "dev": true, - "dependencies": { - "inherits": "~2.0.3" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-format-unescaped": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", - "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", - "dev": true - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/raw-body/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", - "dev": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", - "dev": true, - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" - }, - "peerDependencies": { - "react": "17.0.2" - } - }, - "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "node_modules/react-refresh": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz", - "integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", - "dev": true - }, - "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" - }, - "node_modules/ret": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", - "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safe-regex2": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz", - "integrity": "sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==", - "dev": true, - "dependencies": { - "ret": "~0.2.0" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sax": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=", - "dev": true - }, - "node_modules/scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", - "dev": true, - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "node_modules/scmp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz", - "integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==" - }, - "node_modules/secure-json-parse": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.4.0.tgz", - "integrity": "sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg==", - "dev": true - }, - "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-store": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/semver-store/-/semver-store-0.3.0.tgz", - "integrity": "sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg==", - "dev": true - }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/send/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/send/node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/send/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/sentence-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", - "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" - } - }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/set-cookie-parser": { - "version": "2.4.8", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz", - "integrity": "sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg==", - "dev": true - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", - "dev": true - }, - "node_modules/shiki": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", - "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", - "dev": true, - "dependencies": { - "jsonc-parser": "^3.0.0", - "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "5.2.0" - } - }, - "node_modules/shortid": { - "version": "2.2.16", - "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz", - "integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==", - "dev": true, - "dependencies": { - "nanoid": "^2.1.0" - } - }, - "node_modules/shortid/node_modules/nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", - "dev": true - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sinon": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-14.0.0.tgz", - "integrity": "sha512-ugA6BFmE+WrJdh0owRZHToLd32Uw3Lxq6E6LtNRU+xTVBefx632h03Q7apXWRsRdZAJ41LB8aUfn2+O4jsDNMw==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": "^9.1.2", - "@sinonjs/samsam": "^6.1.1", - "diff": "^5.0.0", - "nise": "^5.1.1", - "supports-color": "^7.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/sinon/node_modules/@sinonjs/fake-timers": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", - "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/sinon/node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/sinon/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/sinon/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/sonic-boom": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", - "integrity": "sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==", - "dev": true, - "dependencies": { - "atomic-sleep": "^1.0.0", - "flatstr": "^1.0.12" - } - }, - "node_modules/source-map": { - "version": "0.8.0-beta.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", - "dev": true, - "dependencies": { - "whatwg-url": "^7.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/source-map/node_modules/tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/source-map/node_modules/webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true - }, - "node_modules/source-map/node_modules/whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "dev": true, - "dependencies": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, - "node_modules/stacktrace-parser": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", - "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", - "dev": true, - "dependencies": { - "type-fest": "^0.7.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/stoppable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", - "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", - "dev": true, - "engines": { - "node": ">=4", - "npm": ">=6" - } - }, - "node_modules/stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "dev": true, - "dependencies": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - } - }, - "node_modules/stream-http": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.1.1.tgz", - "integrity": "sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg==", - "dev": true, - "dependencies": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "xtend": "^4.0.2" - } - }, - "node_modules/stream-parser": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz", - "integrity": "sha1-FhhUhpRCACGhGC/wrxkRwSl2F3M=", - "dev": true, - "dependencies": { - "debug": "2" - } - }, - "node_modules/stream-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/stream-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/string-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", - "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=", - "dev": true - }, - "node_modules/string-similarity": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-4.0.4.tgz", - "integrity": "sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==", - "dev": true - }, - "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strong-error-handler": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strong-error-handler/-/strong-error-handler-4.0.0.tgz", - "integrity": "sha512-Ki59WSOfSEod6IkDUB4uf9+DwkCLQRbEdYqen167I/zyPps9x9gS+UzhLZOcer58RA6iFmoGg/+CN/x5d+Cv3Q==", - "dev": true, - "dependencies": { - "@types/express": "^4.16.0", - "accepts": "^1.3.3", - "debug": "^4.1.1", - "ejs": "^3.1.3", - "fast-safe-stringify": "^2.0.6", - "http-status": "^1.1.2", - "js2xmlparser": "^4.0.0", - "strong-globalize": "^6.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/strong-globalize": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/strong-globalize/-/strong-globalize-6.0.5.tgz", - "integrity": "sha512-7nfUli41TieV9/TSc0N62ve5Q4nfrpy/T0nNNy6TyD3vst79QWmeylCyd3q1gDxh8dqGEtabLNCdPQP1Iuvecw==", - "dev": true, - "dependencies": { - "accept-language": "^3.0.18", - "debug": "^4.2.0", - "globalize": "^1.6.0", - "lodash": "^4.17.20", - "md5": "^2.3.0", - "mkdirp": "^1.0.4", - "os-locale": "^5.0.0", - "yamljs": "^0.3.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/strong-globalize/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/styled-jsx": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-4.0.1.tgz", - "integrity": "sha512-Gcb49/dRB1k8B4hdK8vhW27Rlb2zujCk1fISrizCcToIs+55B4vmUM0N9Gi4nnVfFZWe55jRdWpAqH1ldAKWvQ==", - "dev": true, - "dependencies": { - "@babel/plugin-syntax-jsx": "7.14.5", - "@babel/types": "7.15.0", - "convert-source-map": "1.7.0", - "loader-utils": "1.2.3", - "source-map": "0.7.3", - "string-hash": "1.1.3", - "stylis": "3.5.4", - "stylis-rule-sheet": "0.0.10" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || 18.x.x" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - } - } - }, - "node_modules/styled-jsx/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/stylis": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", - "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==", - "dev": true - }, - "node_modules/stylis-rule-sheet": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz", - "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==", - "dev": true, - "peerDependencies": { - "stylis": "^3.5.0" - } - }, - "node_modules/superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", - "deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at . Thanks to @shadowgate15, @spence-s, and @niftylettuce. Superagent is sponsored by Forward Email at .", - "dev": true, - "dependencies": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/superagent/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/superagent/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/superagent/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/supertest": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz", - "integrity": "sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ==", - "dev": true, - "dependencies": { - "methods": "^1.1.2", - "superagent": "^3.8.3" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/supertokens-js-override": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/supertokens-js-override/-/supertokens-js-override-0.0.4.tgz", - "integrity": "sha512-r0JFBjkMIdep3Lbk3JA+MpnpuOtw4RSyrlRAbrzMcxwiYco3GFWl/daimQZ5b1forOiUODpOlXbSOljP/oyurg==" - }, - "node_modules/supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/timers-browserify": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", - "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", - "dev": true, - "dependencies": { - "setimmediate": "^1.0.4" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/tiny-lru": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-7.0.6.tgz", - "integrity": "sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/toposort": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=", - "dev": true - }, - "node_modules/traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", - "dev": true - }, - "node_modules/ts-pnp": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", - "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "node_modules/tsscmp": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", - "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", - "dev": true, - "engines": { - "node": ">=0.6.x" - } - }, - "node_modules/tty-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", - "dev": true - }, - "node_modules/twilio": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/twilio/-/twilio-4.7.2.tgz", - "integrity": "sha512-sTdEwAhkDzoDoXE3i83F/CdZegZ5O1FPDY0hAnJmGr/TjDqGl+Q6WzjC0+9cTmQnjCaDg6H4L97UZeJLFFEh3A==", - "dependencies": { - "axios": "^0.26.1", - "dayjs": "^1.8.29", - "https-proxy-agent": "^5.0.0", - "jsonwebtoken": "^9.0.0", - "qs": "^6.9.4", - "scmp": "^2.1.0", - "url-parse": "^1.5.9", - "xmlbuilder": "^13.0.2" - }, - "engines": { - "node": ">=14.0" - } - }, - "node_modules/twilio/node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, - "node_modules/twilio/node_modules/jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=4", - "npm": ">=1.4.28" - } - }, - "node_modules/twilio/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/twilio/node_modules/xmlbuilder": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", - "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==", - "engines": { - "node": ">=6.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", - "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typedoc": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.12.tgz", - "integrity": "sha512-FcyC+YuaOpr3rB9QwA1IHOi9KnU2m50sPJW5vcNRPCIdecp+3bFkh7Rq5hBU1Fyn29UR2h4h/H7twZHWDhL0sw==", - "dev": true, - "dependencies": { - "glob": "^7.2.0", - "lunr": "^2.3.9", - "marked": "^4.0.10", - "minimatch": "^3.0.4", - "shiki": "^0.10.0" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 12.10.0" - }, - "peerDependencies": { - "typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x" - } - }, - "node_modules/typedoc/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/typescript": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", - "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/upper-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", - "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/upper-case-first": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", - "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", - "dev": true, - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - }, - "node_modules/use-subscription": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/use-subscription/-/use-subscription-1.5.1.tgz", - "integrity": "sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA==", - "dev": true, - "dependencies": { - "object-assign": "^4.1.1" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0" - } - }, - "node_modules/util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/uuid-parse": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/uuid-parse/-/uuid-parse-1.1.0.tgz", - "integrity": "sha512-OdmXxA8rDsQ7YpNVbKSJkNzTw2I+S5WsbMDnCtIWSQaosNAcWtFuI/YK1TjzUI6nbkgiqEyh8gWngfcv8Asd9A==", - "dev": true - }, - "node_modules/validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vandium-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/vandium-utils/-/vandium-utils-2.0.0.tgz", - "integrity": "sha512-XWbQ/0H03TpYDXk8sLScBEZpE7TbA0CHDL6/Xjt37IBYKLsHUQuBlL44ttAUs9zoBOLFxsW7HehXcuWCNyqOxQ==", - "dev": true, - "engines": { - "node": ">=10.16" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/verify-apple-id-token": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/verify-apple-id-token/-/verify-apple-id-token-3.0.1.tgz", - "integrity": "sha512-q91pG1e52TpEzXldMirWYNWcSQC4WuzgG0y/ZnBhzjfk0pSxi4YlGh5OTVRlodBenayGHfSDn5VseG9QDuqOew==", - "dependencies": { - "jsonwebtoken": "^9.0.0", - "jwks-rsa": "^3.0.0" - } - }, - "node_modules/verify-apple-id-token/node_modules/@types/express": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", - "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/verify-apple-id-token/node_modules/jose": { - "version": "4.11.4", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.11.4.tgz", - "integrity": "sha512-94FdcR8felat4vaTJyL/WVdtlWLlsnLMZP8v+A0Vru18K3bQ22vn7TtpVh3JlgBFNIlYOUlGqwp/MjRPOnIyCQ==", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/verify-apple-id-token/node_modules/jwks-rsa": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.0.1.tgz", - "integrity": "sha512-UUOZ0CVReK1QVU3rbi9bC7N5/le8ziUj0A2ef1Q0M7OPD2KvjEYizptqIxGIo6fSLYDkqBrazILS18tYuRc8gw==", - "dependencies": { - "@types/express": "^4.17.14", - "@types/jsonwebtoken": "^9.0.0", - "debug": "^4.3.4", - "jose": "^4.10.4", - "limiter": "^1.1.5", - "lru-memoizer": "^2.1.4" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/verify-apple-id-token/node_modules/jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=4", - "npm": ">=1.4.28" - } - }, - "node_modules/verify-apple-id-token/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", - "dev": true - }, - "node_modules/vscode-oniguruma": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.1.tgz", - "integrity": "sha512-vc4WhSIaVpgJ0jJIejjYxPvURJavX6QG41vu0mGhqywMkQqulezEqEQ3cO3gc8GvcOpX6ycmKGqRoROEMBNXTQ==", - "dev": true - }, - "node_modules/vscode-textmate": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", - "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", - "dev": true - }, - "node_modules/watchpack": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.1.tgz", - "integrity": "sha512-Oo7LXCmc1eE1AjyuSBmtC3+Wy4HcV8PxWh2kP6fOl8yTlNS7r0K9l1ao2lrrUza7V39Y3D/BbJgY8VeSlc5JKw==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "node_modules/which-typed-array": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", - "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", - "dev": true, - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" - } - }, - "node_modules/xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xmlcreate": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", - "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", - "dev": true - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/yamljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", - "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "glob": "^7.0.5" - }, - "bin": { - "json2yaml": "bin/json2yaml", - "yaml2json": "bin/yaml2json" - } - }, - "node_modules/yamljs/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/yargs": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", - "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", - "dev": true, - "dependencies": { - "cliui": "^4.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.0.0" - } - }, - "node_modules/yargs-parser": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", - "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs-unparser": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", - "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", - "dev": true, - "dependencies": { - "flat": "^4.1.0", - "lodash": "^4.17.11", - "yargs": "^12.0.5" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/yargs-unparser/node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "node_modules/yargs-unparser/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs-unparser/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yargs-unparser/node_modules/lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "dependencies": { - "invert-kv": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "dependencies": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs-unparser/node_modules/os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "dependencies": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs-unparser/node_modules/require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "node_modules/yargs-unparser/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/yargs-unparser/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yargs-unparser/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yargs-unparser/node_modules/yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "dependencies": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - }, - "node_modules/yargs-unparser/node_modules/yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/yargs/node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yargs/node_modules/lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "dependencies": { - "invert-kv": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "dependencies": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs/node_modules/os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "dependencies": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/yargs/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yargs/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ylru": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz", - "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@ampproject/remapping": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", - "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.0" - } - }, - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/compat-data": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.0.tgz", - "integrity": "sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==", - "dev": true, - "peer": true - }, - "@babel/core": { - "version": "7.17.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz", - "integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==", - "dev": true, - "peer": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helpers": "^7.17.2", - "@babel/parser": "^7.17.3", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "peer": true, - "requires": { - "@babel/highlight": "^7.16.7" - } - }, - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "peer": true - } - } - }, - "@babel/generator": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz", - "integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==", - "dev": true, - "peer": true, - "requires": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "peer": true - } - } - }, - "@babel/helper-compilation-targets": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", - "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", - "dev": true, - "peer": true, - "requires": { - "@babel/compat-data": "^7.16.4", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.17.5", - "semver": "^6.3.0" - }, - "dependencies": { - "browserslist": { - "version": "4.19.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz", - "integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==", - "dev": true, - "peer": true, - "requires": { - "caniuse-lite": "^1.0.30001312", - "electron-to-chromium": "^1.4.71", - "escalade": "^3.1.1", - "node-releases": "^2.0.2", - "picocolors": "^1.0.0" - } - }, - "node-releases": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", - "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", - "dev": true, - "peer": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "peer": true - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "dev": true, - "peer": true, - "requires": { - "@babel/types": "^7.16.7" - }, - "dependencies": { - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", - "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-get-function-arity": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "dependencies": { - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-get-function-arity": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", - "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", - "dev": true, - "peer": true, - "requires": { - "@babel/types": "^7.16.7" - }, - "dependencies": { - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, - "peer": true, - "requires": { - "@babel/types": "^7.16.7" - }, - "dependencies": { - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, - "peer": true, - "requires": { - "@babel/types": "^7.16.7" - }, - "dependencies": { - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-module-transforms": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz", - "integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "dependencies": { - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-plugin-utils": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", - "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", - "dev": true - }, - "@babel/helper-simple-access": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", - "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", - "dev": true, - "peer": true, - "requires": { - "@babel/types": "^7.16.7" - }, - "dependencies": { - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, - "peer": true, - "requires": { - "@babel/types": "^7.16.7" - }, - "dependencies": { - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true, - "peer": true - }, - "@babel/helpers": { - "version": "7.17.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz", - "integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==", - "dev": true, - "peer": true, - "requires": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.0", - "@babel/types": "^7.17.0" - }, - "dependencies": { - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz", - "integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==", - "dev": true, - "peer": true - }, - "@babel/plugin-syntax-jsx": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz", - "integrity": "sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/runtime": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz", - "integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, - "peer": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "peer": true, - "requires": { - "@babel/highlight": "^7.16.7" - } - }, - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/traverse": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", - "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", - "dev": true, - "peer": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.3", - "@babel/types": "^7.17.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "peer": true, - "requires": { - "@babel/highlight": "^7.16.7" - } - }, - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - }, - "@extra-number/significant-digits": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/@extra-number/significant-digits/-/significant-digits-1.3.9.tgz", - "integrity": "sha512-E5PY/bCwrNqEHh4QS6AQBinLZ+sxM1lT8tsSVYk8VwhWIPp6fCU/BMRVq0V8iJ8LwS3FHmaA4vUzb78s4BIIyA==", - "dev": true - }, - "@fastify/ajv-compiler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-1.1.0.tgz", - "integrity": "sha512-gvCOUNpXsWrIQ3A4aXCLIdblL0tDq42BG/2Xw7oxbil9h11uow10ztS2GuFazNBfjbrsZ5nl+nPl5jDSjj5TSg==", - "dev": true, - "requires": { - "ajv": "^6.12.6" - } - }, - "@hapi/accept": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@hapi/accept/-/accept-5.0.2.tgz", - "integrity": "sha512-CmzBx/bXUR8451fnZRuZAJRlzgm0Jgu5dltTX/bszmR2lheb9BpyN47Q1RbaGTsvFzn0PXAEs+lXDKfshccYZw==", - "dev": true, - "requires": { - "@hapi/boom": "9.x.x", - "@hapi/hoek": "9.x.x" - } - }, - "@hapi/ammo": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@hapi/ammo/-/ammo-5.0.1.tgz", - "integrity": "sha512-FbCNwcTbnQP4VYYhLNGZmA76xb2aHg9AMPiy18NZyWMG310P5KdFGyA9v2rm5ujrIny77dEEIkMOwl0Xv+fSSA==", - "dev": true, - "requires": { - "@hapi/hoek": "9.x.x" - } - }, - "@hapi/b64": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@hapi/b64/-/b64-5.0.0.tgz", - "integrity": "sha512-ngu0tSEmrezoiIaNGG6rRvKOUkUuDdf4XTPnONHGYfSGRmDqPZX5oJL6HAdKTo1UQHECbdB4OzhWrfgVppjHUw==", - "dev": true, - "requires": { - "@hapi/hoek": "9.x.x" - } - }, - "@hapi/boom": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-9.1.4.tgz", - "integrity": "sha512-Ls1oH8jaN1vNsqcaHVYJrKmgMcKsC1wcp8bujvXrHaAqD2iDYq3HoOwsxwo09Cuda5R5nC0o0IxlrlTuvPuzSw==", - "dev": true, - "requires": { - "@hapi/hoek": "9.x.x" - } - }, - "@hapi/bounce": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@hapi/bounce/-/bounce-2.0.0.tgz", - "integrity": "sha512-JesW92uyzOOyuzJKjoLHM1ThiOvHPOLDHw01YV8yh5nCso7sDwJho1h0Ad2N+E62bZyz46TG3xhAi/78Gsct6A==", - "dev": true, - "requires": { - "@hapi/boom": "9.x.x", - "@hapi/hoek": "9.x.x" - } - }, - "@hapi/bourne": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.0.0.tgz", - "integrity": "sha512-WEezM1FWztfbzqIUbsDzFRVMxSoLy3HugVcux6KDDtTqzPsLE8NDRHfXvev66aH1i2oOKKar3/XDjbvh/OUBdg==", - "dev": true - }, - "@hapi/call": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@hapi/call/-/call-8.0.1.tgz", - "integrity": "sha512-bOff6GTdOnoe5b8oXRV3lwkQSb/LAWylvDMae6RgEWWntd0SHtkYbQukDHKlfaYtVnSAgIavJ0kqszF/AIBb6g==", - "dev": true, - "requires": { - "@hapi/boom": "9.x.x", - "@hapi/hoek": "9.x.x" - } - }, - "@hapi/catbox": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/@hapi/catbox/-/catbox-11.1.1.tgz", - "integrity": "sha512-u/8HvB7dD/6X8hsZIpskSDo4yMKpHxFd7NluoylhGrL6cUfYxdQPnvUp9YU2C6F9hsyBVLGulBd9vBN1ebfXOQ==", - "dev": true, - "requires": { - "@hapi/boom": "9.x.x", - "@hapi/hoek": "9.x.x", - "@hapi/podium": "4.x.x", - "@hapi/validate": "1.x.x" - } - }, - "@hapi/catbox-memory": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@hapi/catbox-memory/-/catbox-memory-5.0.1.tgz", - "integrity": "sha512-QWw9nOYJq5PlvChLWV8i6hQHJYfvdqiXdvTupJFh0eqLZ64Xir7mKNi96d5/ZMUAqXPursfNDIDxjFgoEDUqeQ==", - "dev": true, - "requires": { - "@hapi/boom": "9.x.x", - "@hapi/hoek": "9.x.x" - } - }, - "@hapi/content": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@hapi/content/-/content-5.0.2.tgz", - "integrity": "sha512-mre4dl1ygd4ZyOH3tiYBrOUBzV7Pu/EOs8VLGf58vtOEECWed8Uuw6B4iR9AN/8uQt42tB04qpVaMyoMQh0oMw==", - "dev": true, - "requires": { - "@hapi/boom": "9.x.x" - } - }, - "@hapi/cryptiles": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/cryptiles/-/cryptiles-5.1.0.tgz", - "integrity": "sha512-fo9+d1Ba5/FIoMySfMqPBR/7Pa29J2RsiPrl7bkwo5W5o+AN1dAYQRi4SPrPwwVxVGKjgLOEWrsvt1BonJSfLA==", - "dev": true, - "requires": { - "@hapi/boom": "9.x.x" - } - }, - "@hapi/file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@hapi/file/-/file-2.0.0.tgz", - "integrity": "sha512-WSrlgpvEqgPWkI18kkGELEZfXr0bYLtr16iIN4Krh9sRnzBZN6nnWxHFxtsnP684wueEySBbXPDg/WfA9xJdBQ==", - "dev": true - }, - "@hapi/hapi": { - "version": "20.2.1", - "resolved": "https://registry.npmjs.org/@hapi/hapi/-/hapi-20.2.1.tgz", - "integrity": "sha512-OXAU+yWLwkMfPFic+KITo+XPp6Oxpgc9WUH+pxXWcTIuvWbgco5TC/jS8UDvz+NFF5IzRgF2CL6UV/KLdQYUSQ==", - "dev": true, - "requires": { - "@hapi/accept": "^5.0.1", - "@hapi/ammo": "^5.0.1", - "@hapi/boom": "^9.1.0", - "@hapi/bounce": "^2.0.0", - "@hapi/call": "^8.0.0", - "@hapi/catbox": "^11.1.1", - "@hapi/catbox-memory": "^5.0.0", - "@hapi/heavy": "^7.0.1", - "@hapi/hoek": "^9.0.4", - "@hapi/mimos": "^6.0.0", - "@hapi/podium": "^4.1.1", - "@hapi/shot": "^5.0.5", - "@hapi/somever": "^3.0.0", - "@hapi/statehood": "^7.0.3", - "@hapi/subtext": "^7.0.3", - "@hapi/teamwork": "^5.1.0", - "@hapi/topo": "^5.0.0", - "@hapi/validate": "^1.1.1" - } - }, - "@hapi/heavy": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@hapi/heavy/-/heavy-7.0.1.tgz", - "integrity": "sha512-vJ/vzRQ13MtRzz6Qd4zRHWS3FaUc/5uivV2TIuExGTM9Qk+7Zzqj0e2G7EpE6KztO9SalTbiIkTh7qFKj/33cA==", - "dev": true, - "requires": { - "@hapi/boom": "9.x.x", - "@hapi/hoek": "9.x.x", - "@hapi/validate": "1.x.x" - } - }, - "@hapi/hoek": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", - "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==", - "dev": true - }, - "@hapi/iron": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hapi/iron/-/iron-6.0.0.tgz", - "integrity": "sha512-zvGvWDufiTGpTJPG1Y/McN8UqWBu0k/xs/7l++HVU535NLHXsHhy54cfEMdW7EjwKfbBfM9Xy25FmTiobb7Hvw==", - "dev": true, - "requires": { - "@hapi/b64": "5.x.x", - "@hapi/boom": "9.x.x", - "@hapi/bourne": "2.x.x", - "@hapi/cryptiles": "5.x.x", - "@hapi/hoek": "9.x.x" - } - }, - "@hapi/mimos": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hapi/mimos/-/mimos-6.0.0.tgz", - "integrity": "sha512-Op/67tr1I+JafN3R3XN5DucVSxKRT/Tc+tUszDwENoNpolxeXkhrJ2Czt6B6AAqrespHoivhgZBWYSuANN9QXg==", - "dev": true, - "requires": { - "@hapi/hoek": "9.x.x", - "mime-db": "1.x.x" - } - }, - "@hapi/nigel": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@hapi/nigel/-/nigel-4.0.2.tgz", - "integrity": "sha512-ht2KoEsDW22BxQOEkLEJaqfpoKPXxi7tvabXy7B/77eFtOyG5ZEstfZwxHQcqAiZhp58Ae5vkhEqI03kawkYNw==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.4", - "@hapi/vise": "^4.0.0" - } - }, - "@hapi/pez": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@hapi/pez/-/pez-5.0.3.tgz", - "integrity": "sha512-mpikYRJjtrbJgdDHG/H9ySqYqwJ+QU/D7FXsYciS9P7NYBXE2ayKDAy3H0ou6CohOCaxPuTV4SZ0D936+VomHA==", - "dev": true, - "requires": { - "@hapi/b64": "5.x.x", - "@hapi/boom": "9.x.x", - "@hapi/content": "^5.0.2", - "@hapi/hoek": "9.x.x", - "@hapi/nigel": "4.x.x" - } - }, - "@hapi/podium": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@hapi/podium/-/podium-4.1.3.tgz", - "integrity": "sha512-ljsKGQzLkFqnQxE7qeanvgGj4dejnciErYd30dbrYzUOF/FyS/DOF97qcrT3bhoVwCYmxa6PEMhxfCPlnUcD2g==", - "dev": true, - "requires": { - "@hapi/hoek": "9.x.x", - "@hapi/teamwork": "5.x.x", - "@hapi/validate": "1.x.x" - } - }, - "@hapi/shot": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@hapi/shot/-/shot-5.0.5.tgz", - "integrity": "sha512-x5AMSZ5+j+Paa8KdfCoKh+klB78otxF+vcJR/IoN91Vo2e5ulXIW6HUsFTCU+4W6P/Etaip9nmdAx2zWDimB2A==", - "dev": true, - "requires": { - "@hapi/hoek": "9.x.x", - "@hapi/validate": "1.x.x" - } - }, - "@hapi/somever": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@hapi/somever/-/somever-3.0.1.tgz", - "integrity": "sha512-4ZTSN3YAHtgpY/M4GOtHUXgi6uZtG9nEZfNI6QrArhK0XN/RDVgijlb9kOmXwCR5VclDSkBul9FBvhSuKXx9+w==", - "dev": true, - "requires": { - "@hapi/bounce": "2.x.x", - "@hapi/hoek": "9.x.x" - } - }, - "@hapi/statehood": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@hapi/statehood/-/statehood-7.0.3.tgz", - "integrity": "sha512-pYB+pyCHkf2Amh67QAXz7e/DN9jcMplIL7Z6N8h0K+ZTy0b404JKPEYkbWHSnDtxLjJB/OtgElxocr2fMH4G7w==", - "dev": true, - "requires": { - "@hapi/boom": "9.x.x", - "@hapi/bounce": "2.x.x", - "@hapi/bourne": "2.x.x", - "@hapi/cryptiles": "5.x.x", - "@hapi/hoek": "9.x.x", - "@hapi/iron": "6.x.x", - "@hapi/validate": "1.x.x" - } - }, - "@hapi/subtext": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@hapi/subtext/-/subtext-7.0.3.tgz", - "integrity": "sha512-CekDizZkDGERJ01C0+TzHlKtqdXZxzSWTOaH6THBrbOHnsr3GY+yiMZC+AfNCypfE17RaIakGIAbpL2Tk1z2+A==", - "dev": true, - "requires": { - "@hapi/boom": "9.x.x", - "@hapi/bourne": "2.x.x", - "@hapi/content": "^5.0.2", - "@hapi/file": "2.x.x", - "@hapi/hoek": "9.x.x", - "@hapi/pez": "^5.0.1", - "@hapi/wreck": "17.x.x" - } - }, - "@hapi/teamwork": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/teamwork/-/teamwork-5.1.0.tgz", - "integrity": "sha512-llqoQTrAJDTXxG3c4Kz/uzhBS1TsmSBa/XG5SPcVXgmffHE1nFtyLIK0hNJHCB3EuBKT84adzd1hZNY9GJLWtg==", - "dev": true - }, - "@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@hapi/validate": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@hapi/validate/-/validate-1.1.3.tgz", - "integrity": "sha512-/XMR0N0wjw0Twzq2pQOzPBZlDzkekGcoCtzO314BpIEsbXdYGthQUbxgkGDf4nhk1+IPDAsXqWjMohRQYO06UA==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0" - } - }, - "@hapi/vise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@hapi/vise/-/vise-4.0.0.tgz", - "integrity": "sha512-eYyLkuUiFZTer59h+SGy7hUm+qE9p+UemePTHLlIWppEd+wExn3Df5jO04bFQTm7nleF5V8CtuYQYb+VFpZ6Sg==", - "dev": true, - "requires": { - "@hapi/hoek": "9.x.x" - } - }, - "@hapi/wreck": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@hapi/wreck/-/wreck-17.1.0.tgz", - "integrity": "sha512-nx6sFyfqOpJ+EFrHX+XWwJAxs3ju4iHdbB/bwR8yTNZOiYmuhA8eCe7lYPtYmb4j7vyK/SlbaQsmTtUrMvPEBw==", - "dev": true, - "requires": { - "@hapi/boom": "9.x.x", - "@hapi/bourne": "2.x.x", - "@hapi/hoek": "9.x.x" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", - "dev": true, - "peer": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", - "dev": true, - "peer": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", - "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@koa/router": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/@koa/router/-/router-10.1.1.tgz", - "integrity": "sha512-ORNjq5z4EmQPriKbR0ER3k4Gh7YGNhWDL7JBW+8wXDrHLbWYKYSJaOJ9aN06npF5tbTxe2JBOsurpJDAvjiXKw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "http-errors": "^1.7.3", - "koa-compose": "^4.1.0", - "methods": "^1.1.2", - "path-to-regexp": "^6.1.0" - } - }, - "@loopback/context": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@loopback/context/-/context-3.18.0.tgz", - "integrity": "sha512-PKx0rTguqBj6mUHBbEHLF031MnP6KiSkMLE4E8Hpy2KPJxG97HUT2ZUACHCP6qm8yS9spWQQ6g72VYAWxDrN+g==", - "dev": true, - "requires": { - "@loopback/metadata": "^3.3.4", - "@types/debug": "^4.1.7", - "debug": "^4.3.2", - "hyperid": "^2.3.1", - "p-event": "^4.2.0", - "tslib": "^2.3.1", - "uuid": "^8.3.2" - } - }, - "@loopback/core": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@loopback/core/-/core-2.16.2.tgz", - "integrity": "sha512-KtkNv6HIh8TFBOxTkfPp/BQbVqjDsGef/DtbNHH1ZHs3gSbofhkZs3IqQdYQzpkUq71mQjz5RJ/yUYY5Sqva9w==", - "dev": true, - "requires": { - "@loopback/context": "^3.17.1", - "debug": "^4.3.1", - "tslib": "^2.3.0" - } - }, - "@loopback/filter": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@loopback/filter/-/filter-1.5.4.tgz", - "integrity": "sha512-kfdCgSy0YoAFNYXJOpag5uJnlErYcROIeJqeAglkwOa3hSw2BYIudurU8hoqsiOBIGhI5BF4A3S8u4q089xWlg==", - "dev": true, - "requires": { - "tslib": "^2.3.1" - } - }, - "@loopback/http-server": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@loopback/http-server/-/http-server-2.5.4.tgz", - "integrity": "sha512-M7w+4AEhwDn7q00soCe8yYQDUS+n87ppuXQ1rJ9a1b9TdnEh+7nPFVrVpwiEKBGyVGIJWDq5BMSZYo1zMIPFUA==", - "dev": true, - "requires": { - "debug": "^4.3.2", - "stoppable": "^1.1.0", - "tslib": "^2.3.1" - } - }, - "@loopback/metadata": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@loopback/metadata/-/metadata-3.3.4.tgz", - "integrity": "sha512-FISs8OVYKB+wmL0VZdsDZzMOc/KC6anOf3ORpFRO2Mgl9dKCOD8IELKc8r/nr2kyD4r7/pjr5GfLy4nirS1vnQ==", - "dev": true, - "requires": { - "debug": "^4.3.2", - "lodash": "^4.17.21", - "reflect-metadata": "^0.1.13", - "tslib": "^2.3.1" - } - }, - "@loopback/repository": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@loopback/repository/-/repository-3.7.1.tgz", - "integrity": "sha512-q9vpgQ5MSZqI/ww2TTuDy0Y34NZaapS0+4ZKcwVgwH0XJFxgGwznc5W0l1Esu1lplijejpza4ItKwnlGmvYcJg==", - "dev": true, - "requires": { - "@loopback/filter": "^1.5.2", - "@types/debug": "^4.1.5", - "debug": "^4.3.1", - "lodash": "^4.17.21", - "loopback-datasource-juggler": "^4.26.0", - "tslib": "^2.3.0" - } - }, - "@loopback/rest": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@loopback/rest/-/rest-9.3.0.tgz", - "integrity": "sha512-Qwn5WXctQ2AV6Duze/x7ks9Tb/Oy6FSs0Hhyuhzz7aassKbu1m/GiJLB7bvpJVUN+qVZ2+vQZZ6Y3F+znzH4og==", - "dev": true, - "requires": { - "@loopback/express": "^3.3.0", - "@loopback/http-server": "^2.5.0", - "@loopback/openapi-v3": "^5.3.0", - "@openapi-contrib/openapi-schema-to-json-schema": "^3.1.0", - "@types/body-parser": "^1.19.0", - "@types/cors": "^2.8.10", - "@types/express": "^4.17.11", - "@types/express-serve-static-core": "^4.17.19", - "@types/http-errors": "^1.8.0", - "@types/on-finished": "^2.3.1", - "@types/serve-static": "1.13.9", - "@types/type-is": "^1.6.3", - "ajv": "^6.12.6", - "ajv-errors": "^1.0.1", - "ajv-keywords": "^3.5.2", - "body-parser": "^1.19.0", - "cors": "^2.8.5", - "debug": "^4.3.1", - "express": "^4.17.1", - "http-errors": "^1.8.0", - "js-yaml": "^4.1.0", - "json-schema-compare": "^0.2.2", - "lodash": "^4.17.21", - "on-finished": "^2.3.0", - "path-to-regexp": "^6.2.0", - "qs": "^6.10.1", - "strong-error-handler": "^4.0.0", - "tslib": "^2.2.0", - "type-is": "^1.6.18", - "validator": "^13.6.0" - }, - "dependencies": { - "@loopback/express": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@loopback/express/-/express-3.3.4.tgz", - "integrity": "sha512-y+7fu/aXGp7+5QhEnKhwmI/vKLAQtsyvEXTiT8stbj4VHWvNbUbYVwfud5IOeH7d+lhxlNQ5aEJ7IDwoM8xD6Q==", - "dev": true, - "requires": { - "@loopback/http-server": "^2.5.4", - "@types/body-parser": "^1.19.1", - "@types/express": "^4.17.13", - "@types/express-serve-static-core": "^4.17.24", - "@types/http-errors": "^1.8.1", - "body-parser": "^1.19.0", - "debug": "^4.3.2", - "express": "^4.17.1", - "http-errors": "^1.8.0", - "on-finished": "^2.3.0", - "toposort": "^2.0.2", - "tslib": "^2.3.1" - } - }, - "@loopback/openapi-v3": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@loopback/openapi-v3/-/openapi-v3-5.3.1.tgz", - "integrity": "sha512-MBVamgxDDbgQQlQjIxSOnaVXLx6plxzn3e8CW8YbNc3TNiS1P8EFa5vNBp8wIzSDTeEd3ic6qzUxCUZIICiFNA==", - "dev": true, - "requires": { - "@loopback/repository-json-schema": "^3.4.1", - "debug": "^4.3.1", - "http-status": "^1.5.0", - "json-merge-patch": "^1.0.1", - "lodash": "^4.17.21", - "openapi3-ts": "^2.0.1", - "tslib": "^2.2.0" - }, - "dependencies": { - "@loopback/repository-json-schema": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@loopback/repository-json-schema/-/repository-json-schema-3.4.1.tgz", - "integrity": "sha512-E9UKegav+8Bp0MLPQu33c7tWUmWbnKARy0Uu2m7nvP3e3t3WOwB8U9hMjX/wBOhJ4UFJCXAXlq1MulQ/R3dyTw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.7", - "debug": "^4.3.1", - "tslib": "^2.2.0" - } - } - } - }, - "@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - } - } - }, - "@napi-rs/triples": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@napi-rs/triples/-/triples-1.1.0.tgz", - "integrity": "sha512-XQr74QaLeMiqhStEhLn1im9EOMnkypp7MZOwQhGzqp2Weu5eQJbpPxWxixxlYRKWPOmJjsk6qYfYH9kq43yc2w==", - "dev": true - }, - "@next/env": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/env/-/env-11.1.3.tgz", - "integrity": "sha512-5+vaeooJuWmICSlmVaAC8KG3O8hwKasACVfkHj58xQuCB5SW0TKW3hWxgxkBuefMBn1nM0yEVPKokXCsYjBtng==", - "dev": true - }, - "@next/polyfill-module": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/polyfill-module/-/polyfill-module-11.1.3.tgz", - "integrity": "sha512-7yr9cr4a0SrBoVE8psxXWK1wTFc8UzsY8Wc2cWGL7qA0hgtqACHaXC47M1ByJB410hFZenGrpE+KFaT1unQMyw==", - "dev": true - }, - "@next/react-dev-overlay": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/react-dev-overlay/-/react-dev-overlay-11.1.3.tgz", - "integrity": "sha512-zIwtMliSUR+IKl917ToFNB+0fD7bI5kYMdjHU/UEKpfIXAZPnXRHHISCvPDsczlr+bRsbjlUFW1CsNiuFedeuQ==", - "dev": true, - "requires": { - "@babel/code-frame": "7.12.11", - "anser": "1.4.9", - "chalk": "4.0.0", - "classnames": "2.2.6", - "css.escape": "1.5.1", - "data-uri-to-buffer": "3.0.1", - "platform": "1.3.6", - "shell-quote": "1.7.2", - "source-map": "0.8.0-beta.0", - "stacktrace-parser": "0.1.10", - "strip-ansi": "6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@next/react-refresh-utils": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/react-refresh-utils/-/react-refresh-utils-11.1.3.tgz", - "integrity": "sha512-144kD8q2nChw67V3AJJlPQ6NUJVFczyn10bhTynn9o2rY5DEnkzuBipcyMuQl2DqfxMkV7sn+yOCOYbrLCk9zg==", - "dev": true, - "requires": {} - }, - "@next/swc-darwin-arm64": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-11.1.3.tgz", - "integrity": "sha512-TwP4krjhs+uU9pesDYCShEXZrLSbJr78p12e7XnLBBaNf20SgWLlVmQUT9gX9KbWan5V0sUbJfmcS8MRNHgYuA==", - "dev": true, - "optional": true - }, - "@next/swc-darwin-x64": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-11.1.3.tgz", - "integrity": "sha512-ZSWmkg/PxccHFNUSeBdrfaH8KwSkoeUtewXKvuYYt7Ph0yRsbqSyNIvhUezDua96lApiXXq6EL2d1THfeWomvw==", - "dev": true, - "optional": true - }, - "@next/swc-linux-x64-gnu": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-11.1.3.tgz", - "integrity": "sha512-PrTBN0iZudAuj4jSbtXcdBdmfpaDCPIneG4Oms4zcs93KwMgLhivYW082Mvlgx9QVEiRm7+RkFpIVtG/i7JitA==", - "dev": true, - "optional": true - }, - "@next/swc-win32-x64-msvc": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-11.1.3.tgz", - "integrity": "sha512-mRwbscVjRoHk+tDY7XbkT5d9FCwujFIQJpGp0XNb1i5OHCSDO8WW/C9cLEWS4LxKRbIZlTLYg1MTXqLQkvva8w==", - "dev": true, - "optional": true - }, - "@node-rs/helper": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@node-rs/helper/-/helper-1.2.1.tgz", - "integrity": "sha512-R5wEmm8nbuQU0YGGmYVjEc0OHtYsuXdpRG+Ut/3wZ9XAvQWyThN08bTh2cBJgoZxHQUPtvRfeQuxcAgLuiBISg==", - "dev": true, - "requires": { - "@napi-rs/triples": "^1.0.3" - } - }, - "@openapi-contrib/openapi-schema-to-json-schema": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@openapi-contrib/openapi-schema-to-json-schema/-/openapi-schema-to-json-schema-3.1.1.tgz", - "integrity": "sha512-FMvdhv9Jr9tULjJAQaQzhCmNYYj2vQFVnl7CGlLAImZvJal71oedXMGszpPaZTLftAk5TCHqjnirig+P6LZxug==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "@panva/asn1.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz", - "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==" - }, - "@sideway/address": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz", - "integrity": "sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@sideway/formula": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", - "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==", - "dev": true - }, - "@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true - }, - "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", - "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "@sinonjs/samsam": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.1.tgz", - "integrity": "sha512-cZ7rKJTLiE7u7Wi/v9Hc2fs3Ucc3jrWeMgPHbbTCeVAB2S0wOBbYlkJVeNSL04i7fdhT8wIbDq1zhC/PXTD2SA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "@types/accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/aws-lambda": { - "version": "8.10.77", - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.77.tgz", - "integrity": "sha512-n0EMFJU/7u3KvHrR83l/zrKOVURXl5pUJPNED/Bzjah89QKCHwCiKCBoVUXRwTGRfCYGIDdinJaAlKDHZdp/Ng==", - "dev": true - }, - "@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/co-body": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/co-body/-/co-body-5.1.1.tgz", - "integrity": "sha512-0/6AjTfQc5OJUchOS4OHiXNPZVuk+5XvEC2vdcizw/bwx0yb0xY7TKSf8JYvQYZ/OJDiAEjWzxnMjGPnSVlPmA==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*" - } - }, - "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "requires": { - "@types/node": "*" - } - }, - "@types/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-0mPF08jn9zYI0n0Q/Pnz7C4kThdSt+6LD4amsrYDDpgBfrVWa3TcCOxKX1zkGgYniGagRv8heN2cbh+CAn+uuQ==", - "dev": true - }, - "@types/cookie": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz", - "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==", - "dev": true - }, - "@types/cookies": { - "version": "0.7.7", - "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.7.tgz", - "integrity": "sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/express": "*", - "@types/keygrip": "*", - "@types/node": "*" - } - }, - "@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", - "dev": true - }, - "@types/debug": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", - "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", - "dev": true, - "requires": { - "@types/ms": "*" - } - }, - "@types/express": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.1.tgz", - "integrity": "sha512-V0clmJow23WeyblmACoxbHBu2JKlE5TiIme6Lem14FnPW9gsttyHtk6wq7njcdIWH1njAaFgR8gW09lgY98gQg==", - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "*", - "@types/serve-static": "*" - } - }, - "@types/express-jwt": { - "version": "0.0.42", - "resolved": "https://registry.npmjs.org/@types/express-jwt/-/express-jwt-0.0.42.tgz", - "integrity": "sha512-WszgUddvM1t5dPpJ3LhWNH8kfNN8GPIBrAGxgIYXVCEGx6Bx4A036aAuf/r5WH9DIEdlmp7gHOYvSM6U87B0ag==", - "requires": { - "@types/express": "*", - "@types/express-unless": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.33", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz", - "integrity": "sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==", - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "@types/express-unless": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@types/express-unless/-/express-unless-0.5.3.tgz", - "integrity": "sha512-TyPLQaF6w8UlWdv4gj8i46B+INBVzURBNRahCozCSXfsK2VTlL1wNyTlMKw817VHygBtlcl5jfnPadlydr06Yw==", - "requires": { - "@types/express": "*" - } - }, - "@types/hapi__catbox": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/@types/hapi__catbox/-/hapi__catbox-10.2.4.tgz", - "integrity": "sha512-A6ivRrXD5glmnJna1UAGw87QNZRp/vdFO9U4GS+WhOMWzHnw+oTGkMvg0g6y1930CbeheGOCm7A1qHsqH7AXqg==", - "dev": true - }, - "@types/hapi__hapi": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@types/hapi__hapi/-/hapi__hapi-20.0.8.tgz", - "integrity": "sha512-NNslrYq2XQwm4uOqNcSWKpYtaeMr4DkQdrFzSB7p9rKB9ppJLh3mgP2wak9vBZl7/Cnhhb+JVBcUZCOUcW0JPA==", - "dev": true, - "requires": { - "@hapi/boom": "^9.0.0", - "@hapi/iron": "^6.0.0", - "@hapi/podium": "^4.1.3", - "@types/hapi__catbox": "*", - "@types/hapi__mimos": "*", - "@types/hapi__shot": "*", - "@types/node": "*", - "joi": "^17.3.0" - } - }, - "@types/hapi__mimos": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@types/hapi__mimos/-/hapi__mimos-4.1.4.tgz", - "integrity": "sha512-i9hvJpFYTT/qzB5xKWvDYaSXrIiNqi4ephi+5Lo6+DoQdwqPXQgmVVOZR+s3MBiHoFqsCZCX9TmVWG3HczmTEQ==", - "dev": true, - "requires": { - "@types/mime-db": "*" - } - }, - "@types/hapi__shot": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@types/hapi__shot/-/hapi__shot-4.1.2.tgz", - "integrity": "sha512-8wWgLVP1TeGqgzZtCdt+F+k15DWQvLG1Yv6ZzPfb3D5WIo5/S+GGKtJBVo2uNEcqabP5Ifc71QnJTDnTmw1axA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/http-assert": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.3.tgz", - "integrity": "sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA==", - "dev": true - }, - "@types/http-errors": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.2.tgz", - "integrity": "sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==", - "dev": true - }, - "@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "dev": true - }, - "@types/jsonwebtoken": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", - "integrity": "sha512-mM4TkDpA9oixqg1Fv2vVpOFyIVLJjm5x4k0V+K/rEsizfjD7Tk7LKk3GTtbB7KCfP0FEHQtsZqFxYA0+sijNVg==", - "requires": { - "@types/node": "*" - } - }, - "@types/keygrip": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", - "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==", - "dev": true - }, - "@types/koa": { - "version": "2.13.4", - "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.13.4.tgz", - "integrity": "sha512-dfHYMfU+z/vKtQB7NUrthdAEiSvnLebvBjwHtfFmpZmB7em2N3WVQdHgnFq+xvyVgxW5jKDmjWfLD3lw4g4uTw==", - "dev": true, - "requires": { - "@types/accepts": "*", - "@types/content-disposition": "*", - "@types/cookies": "*", - "@types/http-assert": "*", - "@types/http-errors": "*", - "@types/keygrip": "*", - "@types/koa-compose": "*", - "@types/node": "*" - } - }, - "@types/koa-bodyparser": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@types/koa-bodyparser/-/koa-bodyparser-4.3.5.tgz", - "integrity": "sha512-NRqqoTtt7cfdDk/KNo+EwCIKRuzPAu/wsaZ7tgIvSIBtNfxuZHYueaLoWdxX3ZftWavQv07NE46TcpyoZGqpgQ==", - "dev": true, - "requires": { - "@types/koa": "*" - } - }, - "@types/koa-compose": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", - "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", - "dev": true, - "requires": { - "@types/koa": "*" - } - }, - "@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" - }, - "@types/mime-db": { - "version": "1.43.1", - "resolved": "https://registry.npmjs.org/@types/mime-db/-/mime-db-1.43.1.tgz", - "integrity": "sha512-kGZJY+R+WnR5Rk+RPHUMERtb2qBRViIHCBdtUrY+NmwuGb8pQdfTqQiCKPrxpdoycl8KWm2DLdkpoSdt479XoQ==", - "dev": true - }, - "@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", - "dev": true - }, - "@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", - "dev": true - }, - "@types/node": { - "version": "17.0.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz", - "integrity": "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==" - }, - "@types/nodemailer": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.4.tgz", - "integrity": "sha512-Ksw4t7iliXeYGvIQcSIgWQ5BLuC/mljIEbjf615svhZL10PE9t+ei8O9gDaD3FPCasUJn9KTLwz2JFJyiiyuqw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/on-finished": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@types/on-finished/-/on-finished-2.3.1.tgz", - "integrity": "sha512-mzVYaYcFs5Jd2n/O6uYIRUsFRR1cHyZLRvkLCU0E7+G5WhY0qBDAR5fUCeZbvecYOSh9ikhlesyi2UfI8B9ckQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/psl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@types/psl/-/psl-1.1.0.tgz", - "integrity": "sha512-HhZnoLAvI2koev3czVPzBNRYvdrzJGLjQbWZhqFmS9Q6a0yumc5qtfSahBGb5g+6qWvA8iiQktqGkwoIXa/BNQ==", - "dev": true - }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" - }, - "@types/serve-static": { - "version": "1.13.9", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz", - "integrity": "sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==", - "requires": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "@types/type-is": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@types/type-is/-/type-is-1.6.3.tgz", - "integrity": "sha512-PNs5wHaNcBgCQG5nAeeZ7OvosrEsI9O4W2jAOO9BCCg4ux9ZZvH2+0iSCOIDBiKuQsiNS8CBlmfX9f5YBQ22cA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/validator": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-10.11.0.tgz", - "integrity": "sha512-i1aY7RKb6HmQIEnK0cBmUZUp1URx0riIHw/GYNoZ46Su0GWfLiDmMI8zMRmaauMnOTg2bQag0qfwcyUFC9Tn+A==", - "dev": true - }, - "abstract-logging": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", - "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==", - "dev": true - }, - "accept-language": { - "version": "3.0.18", - "resolved": "https://registry.npmjs.org/accept-language/-/accept-language-3.0.18.tgz", - "integrity": "sha1-9QJfF79lpGaoRYOMz5jNuHfYM4Q=", - "dev": true, - "requires": { - "bcp47": "^1.1.2", - "stable": "^0.1.6" - } - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true, - "requires": {} - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "anser": { - "version": "1.4.9", - "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.9.tgz", - "integrity": "sha512-AI+BjTeGt2+WFk4eWcqbQ7snZpDBt8SaLlj0RT2h5xfdWaiy51OjYvqwMrNzJLGy8iOAL6nKDITWO+rd4MkYEA==", - "dev": true - }, - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "app-root-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz", - "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==", - "dev": true - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-differ": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", - "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", - "dev": true - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "dev": true - }, - "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - } - } - }, - "assert": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", - "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", - "dev": true, - "requires": { - "es6-object-assign": "^1.1.0", - "is-nan": "^1.2.1", - "object-is": "^1.0.1", - "util": "^0.12.0" - } - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "ast-types": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.2.tgz", - "integrity": "sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA==", - "dev": true - }, - "async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", - "dev": true - }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true - }, - "avvio": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/avvio/-/avvio-7.2.2.tgz", - "integrity": "sha512-XW2CMCmZaCmCCsIaJaLKxAzPwF37fXi1KGxNOvedOpeisLdmxZnblGc3hpHWYnlP+KOUxZsazh43WXNHgXpbqw==", - "dev": true, - "requires": { - "archy": "^1.0.0", - "debug": "^4.0.0", - "fastq": "^1.6.1", - "queue-microtask": "^1.1.2" - } - }, - "aws-sdk": { - "version": "2.1077.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1077.0.tgz", - "integrity": "sha512-orJvJROs8hJaQRfHsX7Zl5PxEgrD/uTXyqXz9Yu9Io5VVxzvnOty9oHmvEMSlgTIf1qd01gnev/vpvP1HgzKtw==", - "dev": true, - "requires": { - "buffer": "4.9.2", - "events": "1.1.1", - "ieee754": "1.1.13", - "jmespath": "0.16.0", - "querystring": "0.2.0", - "sax": "1.2.1", - "url": "0.10.3", - "uuid": "3.3.2", - "xml2js": "0.4.19" - }, - "dependencies": { - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true - } - } - }, - "aws-sdk-mock": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/aws-sdk-mock/-/aws-sdk-mock-5.6.2.tgz", - "integrity": "sha512-GRJg8kjRJFLm2aLiPkYSqe/RreHqlqncAeFtWdAbtSxzBdct9EaV6rqSqjyWXKNJG45Rzn2Ojo3F6qVIgkQnSg==", - "dev": true, - "requires": { - "aws-sdk": "^2.928.0", - "sinon": "^11.1.1", - "traverse": "^0.6.6" - }, - "dependencies": { - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "sinon": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz", - "integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": "^7.1.2", - "@sinonjs/samsam": "^6.0.2", - "diff": "^5.0.0", - "nise": "^5.1.0", - "supports-color": "^7.2.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "requires": { - "follow-redirects": "^1.14.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true - }, - "bcp47": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/bcp47/-/bcp47-1.1.2.tgz", - "integrity": "sha1-NUvjMH/9CEM6ePXh4glYRfifx/4=", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "dev": true, - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", - "dev": true - }, - "body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - } - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", - "dev": true, - "requires": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" - } - }, - "browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "dev": true, - "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "~1.0.5" - } - }, - "browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - } - }, - "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true - }, - "cache-content-type": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", - "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", - "dev": true, - "requires": { - "mime-types": "^2.1.18", - "ylru": "^1.2.0" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "requires": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001312", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz", - "integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==", - "dev": true - }, - "capital-case": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", - "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" - } - }, - "chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "change-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", - "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", - "dev": true, - "requires": { - "camel-case": "^4.1.2", - "capital-case": "^1.0.4", - "constant-case": "^3.0.4", - "dot-case": "^3.0.4", - "header-case": "^2.0.4", - "no-case": "^3.0.4", - "param-case": "^3.0.4", - "pascal-case": "^3.1.2", - "path-case": "^3.0.4", - "sentence-case": "^3.0.4", - "snake-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - } - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "classnames": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", - "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==", - "dev": true - }, - "cldrjs": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/cldrjs/-/cldrjs-0.5.5.tgz", - "integrity": "sha512-KDwzwbmLIPfCgd8JERVDpQKrUUM1U4KpFJJg2IROv89rF172lLufoJnqJ/Wea6fXL5bO6WjuLMzY8V52UWPvkA==", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "co-body": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/co-body/-/co-body-6.1.0.tgz", - "integrity": "sha512-m7pOT6CdLN7FuXUcpuz/8lfQ/L77x8SchHCF4G0RBTJO20Wzmhn5Sp4/5WsKy8OSpifBSUrmg83qEqaDHdyFuQ==", - "requires": { - "inflation": "^2.0.0", - "qs": "^6.5.2", - "raw-body": "^2.3.3", - "type-is": "^1.6.16" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "colorette": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", - "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", - "dev": true - }, - "constant-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", - "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case": "^2.0.2" - } - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "requires": { - "safe-buffer": "5.2.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" - }, - "cookie-parser": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", - "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", - "dev": true, - "requires": { - "cookie": "0.4.1", - "cookie-signature": "1.0.6" - }, - "dependencies": { - "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", - "dev": true - } - } - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", - "dev": true - }, - "cookies": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", - "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", - "dev": true, - "requires": { - "depd": "~2.0.0", - "keygrip": "~1.1.0" - }, - "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - } - } - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - } - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "dependencies": { - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, - "css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s=", - "dev": true - }, - "cssnano-preset-simple": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssnano-preset-simple/-/cssnano-preset-simple-3.0.0.tgz", - "integrity": "sha512-vxQPeoMRqUT3c/9f0vWeVa2nKQIHFpogtoBvFdW4GQ3IvEJ6uauCP6p3Y5zQDLFcI7/+40FTgX12o7XUL0Ko+w==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001202" - } - }, - "cssnano-simple": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssnano-simple/-/cssnano-simple-3.0.0.tgz", - "integrity": "sha512-oU3ueli5Dtwgh0DyeohcIEE00QVfbPR3HzyXdAl89SfnQG3y0/qcpfLVW+jPIh3/rgMZGwuW96rejZGaYE9eUg==", - "dev": true, - "requires": { - "cssnano-preset-simple": "^3.0.0" - } - }, - "data-uri-to-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", - "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", - "dev": true - }, - "dayjs": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.0.tgz", - "integrity": "sha512-JLC809s6Y948/FuCZPm5IX8rRhQwOiyMb2TfVVQEixG7P8Lm/gt5S7yoQZmC8x1UehI9Pb7sksEt4xx14m+7Ug==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - } - } - }, - "domain-browser": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.19.0.tgz", - "integrity": "sha512-fRA+BaAWOR/yr/t7T9E9GJztHPeFjj8U35ajyAjCDtAAnTn1Rc1f6W6VGPJrO1tkQv9zWu+JRof7z6oQtiYVFQ==", - "dev": true - }, - "dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", - "dev": true - }, - "dotenv-json": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dotenv-json/-/dotenv-json-1.0.0.tgz", - "integrity": "sha512-jAssr+6r4nKhKRudQ0HOzMskOFFi9+ubXWwmrSGJFgTvpjyPXCXsCsYbjif6mXp7uxA7xY3/LGaiTQukZzSbOQ==", - "dev": true - }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "ejs": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", - "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", - "dev": true, - "requires": { - "jake": "^10.8.5" - } - }, - "electron-to-chromium": { - "version": "1.4.71", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.71.tgz", - "integrity": "sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw==", - "dev": true - }, - "elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, - "requires": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - } - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "requires": { - "iconv-lite": "^0.6.2" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", - "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - }, - "dependencies": { - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - } - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es6-object-assign": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", - "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - } - }, - "express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dev": true, - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "fast-decode-uri-component": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", - "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-json-stringify": { - "version": "2.7.13", - "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.7.13.tgz", - "integrity": "sha512-ar+hQ4+OIurUGjSJD1anvYSDcUflywhKjfxnsW4TBTD7+u0tJufv6DKRWoQk3vI6YBOWMoz0TQtfbe7dxbQmvA==", - "dev": true, - "requires": { - "ajv": "^6.11.0", - "deepmerge": "^4.2.2", - "rfdc": "^1.2.0", - "string-similarity": "^4.0.1" - } - }, - "fast-redact": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.0.tgz", - "integrity": "sha512-dir8LOnvialLxiXDPESMDHGp82CHi6ZEYTVkcvdn5d7psdv9ZkkButXrOeXST4aqreIRR+N7CYlsrwFuorurVg==", - "dev": true - }, - "fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true - }, - "fastify": { - "version": "3.18.1", - "resolved": "https://registry.npmjs.org/fastify/-/fastify-3.18.1.tgz", - "integrity": "sha512-OA0imy/bQCMzf7LUCb/1JI3ZSoA0Jo0MLpYULxV7gpppOpJ8NBxDp2PQoQ0FDqJevZPb7tlZf5JacIQft8x9yw==", - "dev": true, - "requires": { - "@fastify/ajv-compiler": "^1.0.0", - "abstract-logging": "^2.0.0", - "avvio": "^7.1.2", - "fast-json-stringify": "^2.5.2", - "fastify-error": "^0.3.0", - "fastify-warning": "^0.2.0", - "find-my-way": "^4.0.0", - "flatstr": "^1.0.12", - "light-my-request": "^4.2.0", - "pino": "^6.2.1", - "proxy-addr": "^2.0.7", - "readable-stream": "^3.4.0", - "rfdc": "^1.1.4", - "secure-json-parse": "^2.0.0", - "semver": "^7.3.2", - "tiny-lru": "^7.0.0" - } - }, - "fastify-error": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.1.tgz", - "integrity": "sha512-oCfpcsDndgnDVgiI7bwFKAun2dO+4h84vBlkWsWnz/OUK9Reff5UFoFl241xTiLeHWX/vU9zkDVXqYUxjOwHcQ==", - "dev": true - }, - "fastify-warning": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/fastify-warning/-/fastify-warning-0.2.0.tgz", - "integrity": "sha512-s1EQguBw/9qtc1p/WTY4eq9WMRIACkj+HTcOIK1in4MV5aFaQC9ZCIt0dJ7pr5bIf4lPpHvAtP2ywpTNgs7hqw==", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dev": true, - "requires": { - "minimatch": "^5.0.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz", - "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true - } - } - }, - "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-my-way": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-4.5.1.tgz", - "integrity": "sha512-kE0u7sGoUFbMXcOG/xpkmz4sRLCklERnBcg7Ftuu1iAxsfEt2S46RLJ3Sq7vshsEy2wJT2hZxE58XZK27qa8kg==", - "dev": true, - "requires": { - "fast-decode-uri-component": "^1.0.1", - "fast-deep-equal": "^3.1.3", - "safe-regex2": "^2.0.0", - "semver-store": "^0.3.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true - } - } - }, - "flatstr": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", - "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==", - "dev": true - }, - "follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" - }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "formidable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", - "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", - "dev": true - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "peer": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-orientation": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/get-orientation/-/get-orientation-1.1.2.tgz", - "integrity": "sha512-/pViTfifW+gBbh/RnlFYHINvELT9Znt+SYyDKAUL6uV6By019AK/s+i9XP4jSwq7lwP38Fd8HVeTxym3+hkwmQ==", - "dev": true, - "requires": { - "stream-parser": "^0.3.1" - } - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "globalize": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/globalize/-/globalize-1.7.0.tgz", - "integrity": "sha512-faR46vTIbFCeAemyuc9E6/d7Wrx9k2ae2L60UhakztFg6VuE42gENVJNuPFtt7Sdjrk9m2w8+py7Jj+JTNy59w==", - "dev": true, - "requires": { - "cldrjs": "^0.5.4" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "peer": true - }, - "graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "header-case": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", - "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", - "dev": true, - "requires": { - "capital-case": "^1.0.4", - "tslib": "^2.0.3" - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "http-assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", - "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", - "dev": true, - "requires": { - "deep-equal": "~1.0.1", - "http-errors": "~1.8.0" - } - }, - "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "dependencies": { - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - } - } - }, - "http-status": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/http-status/-/http-status-1.5.0.tgz", - "integrity": "sha512-wcGvY31MpFNHIkUcXHHnvrE4IKYlpvitJw5P/1u892gMBAM46muQ+RH7UN1d+Ntnfx5apnOnVY6vcLmrWHOLwg==", - "dev": true - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true - }, - "hyperid": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/hyperid/-/hyperid-2.3.1.tgz", - "integrity": "sha512-mIbI7Ymn6MCdODaW1/6wdf5lvvXzmPsARN4zTLakMmcziBOuP4PxCBJvHF6kbAIHX6H4vAELx/pDmt0j6Th5RQ==", - "dev": true, - "requires": { - "uuid": "^8.3.2", - "uuid-parse": "^1.1.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "image-size": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.0.tgz", - "integrity": "sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw==", - "dev": true, - "requires": { - "queue": "6.0.2" - } - }, - "inflation": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz", - "integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8=" - }, - "inflection": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.2.tgz", - "integrity": "sha512-cmZlljCRTBFouT8UzMzrGcVEvkv6D/wBdcdKG7J1QH5cXjtU75Dm+P27v9EKu/Y43UYyCJd1WC4zLebRrC8NBw==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, - "invert-kv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-3.0.1.tgz", - "integrity": "sha512-CYdFeFexxhv/Bcny+Q0BfOV+ltRlJcd4BBZBYFX/O0u4npJrgZtIcjokegtiSMAvlMTJ+Koq0GBCc//3bueQxw==", - "dev": true - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true - }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "dev": true - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - } - }, - "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", - "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0" - } - }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "jake": { - "version": "10.8.5", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", - "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", - "dev": true, - "requires": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-worker": { - "version": "27.0.0-next.5", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.0.0-next.5.tgz", - "integrity": "sha512-mk0umAQ5lT+CaOJ+Qp01N6kz48sJG2kr2n1rX0koqKf6FIygQV0qLOdN9SCYID4IVeSigDOcPeGLozdMLYfb5g==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jmespath": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", - "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", - "dev": true - }, - "joi": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz", - "integrity": "sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.0", - "@sideway/pinpoint": "^2.0.0" - } - }, - "jose": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.6.tgz", - "integrity": "sha512-FVoPY7SflDodE4lknJmbAHSUjLCzE2H1F6MS0RYKMQ8SR+lNccpMf8R4eqkNYyyUjR5qZReOzZo5C5YiHOCjjg==", - "requires": { - "@panva/asn1.js": "^1.0.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "js2xmlparser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", - "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", - "dev": true, - "requires": { - "xmlcreate": "^2.0.4" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "peer": true - }, - "json-merge-patch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-merge-patch/-/json-merge-patch-1.0.2.tgz", - "integrity": "sha512-M6Vp2GN9L7cfuMXiWOmHj9bEFbeC250iVtcKQbqVgEsDVYnIsrNsbU+h/Y/PkbBQCtEa4Bez+Ebv0zfbC8ObLg==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-compare": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz", - "integrity": "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==", - "dev": true, - "requires": { - "lodash": "^4.17.4" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "peer": true, - "requires": { - "minimist": "^1.2.5" - }, - "dependencies": { - "minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true, - "peer": true - } - } - }, - "jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", - "dev": true - }, - "jsonwebtoken": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", - "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", - "requires": { - "jws": "^3.2.2", - "lodash": "^4.17.21", - "ms": "^2.1.1", - "semver": "^7.3.8" - } - }, - "just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jwks-rsa": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-2.0.5.tgz", - "integrity": "sha512-fliHfsiBRzEU0nXzSvwnh0hynzGB0WihF+CinKbSRlaqRxbqqKf2xbBPgwc8mzf18/WgwlG8e5eTpfSTBcU4DQ==", - "requires": { - "@types/express-jwt": "0.0.42", - "debug": "^4.3.2", - "jose": "^2.0.5", - "limiter": "^1.1.5", - "lru-memoizer": "^2.1.4" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "keygrip": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", - "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", - "dev": true, - "requires": { - "tsscmp": "1.0.6" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "koa": { - "version": "2.13.4", - "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.4.tgz", - "integrity": "sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g==", - "dev": true, - "requires": { - "accepts": "^1.3.5", - "cache-content-type": "^1.0.0", - "content-disposition": "~0.5.2", - "content-type": "^1.0.4", - "cookies": "~0.8.0", - "debug": "^4.3.2", - "delegates": "^1.0.0", - "depd": "^2.0.0", - "destroy": "^1.0.4", - "encodeurl": "^1.0.2", - "escape-html": "^1.0.3", - "fresh": "~0.5.2", - "http-assert": "^1.3.0", - "http-errors": "^1.6.3", - "is-generator-function": "^1.0.7", - "koa-compose": "^4.1.0", - "koa-convert": "^2.0.0", - "on-finished": "^2.3.0", - "only": "~0.0.2", - "parseurl": "^1.3.2", - "statuses": "^1.5.0", - "type-is": "^1.6.16", - "vary": "^1.1.2" - }, - "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - } - } - }, - "koa-compose": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", - "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", - "dev": true - }, - "koa-convert": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-2.0.0.tgz", - "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==", - "dev": true, - "requires": { - "co": "^4.6.0", - "koa-compose": "^4.1.0" - } - }, - "lambda-event-mock": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lambda-event-mock/-/lambda-event-mock-1.5.0.tgz", - "integrity": "sha512-vx1d+vZqi7FF6B3+mAfHnY/6Tlp6BheL2ta0MJS0cIRB3Rc4I5cviHTkiJxHdE156gXx3ZjlQRJrS4puXvtrhA==", - "dev": true, - "requires": { - "@extra-number/significant-digits": "^1.1.1", - "clone-deep": "^4.0.1", - "uuid": "^3.3.3", - "vandium-utils": "^1.2.0" - }, - "dependencies": { - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "vandium-utils": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vandium-utils/-/vandium-utils-1.2.0.tgz", - "integrity": "sha1-RHNd5LdkGgXeWevpRfF05YLbT1k=", - "dev": true - } - } - }, - "lambda-leak": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lambda-leak/-/lambda-leak-2.0.0.tgz", - "integrity": "sha1-dxmF02KEh/boha+uK1RRDc+yzX4=", - "dev": true - }, - "lambda-tester": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lambda-tester/-/lambda-tester-4.0.1.tgz", - "integrity": "sha512-ft6XHk84B6/dYEzyI3anKoGWz08xQ5allEHiFYDUzaYTymgVK7tiBkCEbuWx+MFvH7OpFNsJXVtjXm0X8iH3Iw==", - "dev": true, - "requires": { - "app-root-path": "^3.0.0", - "dotenv": "^8.0.0", - "dotenv-json": "^1.0.0", - "lambda-event-mock": "^1.5.0", - "lambda-leak": "^2.0.0", - "semver": "^6.1.1", - "uuid": "^3.3.3", - "vandium-utils": "^2.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - } - } - }, - "lcid": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-3.1.1.tgz", - "integrity": "sha512-M6T051+5QCGLBQb8id3hdvIW8+zeFV2FyBGFS9IEK5H9Wt4MueD4bW1eWikpHgZp+5xR3l5c8pZUkQsIA0BFZg==", - "dev": true, - "requires": { - "invert-kv": "^3.0.0" - } - }, - "libphonenumber-js": { - "version": "1.9.49", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.49.tgz", - "integrity": "sha512-/wEOIONcVboFky+lWlCaF7glm1FhBz11M5PHeCApA+xDdVfmhKjHktHS8KjyGxouV5CSXIr4f3GvLSpJa4qMSg==" - }, - "light-my-request": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-4.8.0.tgz", - "integrity": "sha512-C2XESrTRsZnI59NSQigOsS6IuTxpj8OhSBvZS9fhgBMsamBsAuWN1s4hj/nCi8EeZcyAA6xbROhsZy7wKdfckg==", - "dev": true, - "requires": { - "ajv": "^8.1.0", - "cookie": "^0.4.0", - "process-warning": "^1.0.0", - "set-cookie-parser": "^2.4.1" - }, - "dependencies": { - "ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } - } - }, - "limiter": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", - "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" - }, - "loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^2.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true - } - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } - }, - "loopback-connector": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/loopback-connector/-/loopback-connector-5.0.1.tgz", - "integrity": "sha512-aSPT6x5WZdoW9ylyNE4CxGqFbIqC9cSEZJwWkCincso27PXlZPj52POoF6pgxug9mkH7MrbXuP3SSDLkLq5oQQ==", - "dev": true, - "requires": { - "async": "^3.2.0", - "bluebird": "^3.7.2", - "debug": "^4.1.1", - "msgpack5": "^4.2.0", - "strong-globalize": "^6.0.4", - "uuid": "^8.3.0" - } - }, - "loopback-datasource-juggler": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/loopback-datasource-juggler/-/loopback-datasource-juggler-4.26.0.tgz", - "integrity": "sha512-/R40jUGDrnRBgTh121L4Y7sHDF0KxbgSAN4gLJKp8xGNQ6KpkSQyqZkmap98eN7B75RES78DS3MGghsYMvAJ3Q==", - "dev": true, - "requires": { - "async": "^3.1.0", - "change-case": "^4.1.1", - "debug": "^4.1.0", - "depd": "^2.0.0", - "inflection": "^1.6.0", - "lodash": "^4.17.11", - "loopback-connector": "^5.0.0", - "minimatch": "^3.0.3", - "qs": "^6.5.0", - "shortid": "^2.2.6", - "strong-globalize": "^6.0.5", - "traverse": "^0.6.6", - "uuid": "^8.3.1" - }, - "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - } - } - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", - "dev": true, - "requires": { - "get-func-name": "^2.0.0" - } - }, - "lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "requires": { - "tslib": "^2.0.3" - } - }, - "lru-cache": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", - "integrity": "sha1-HRdnnAac2l0ECZGgnbwsDbN35V4=", - "requires": { - "pseudomap": "^1.0.1", - "yallist": "^2.0.0" - } - }, - "lru-memoizer": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.1.4.tgz", - "integrity": "sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ==", - "requires": { - "lodash.clonedeep": "^4.5.0", - "lru-cache": "~4.0.0" - } - }, - "lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, - "marked": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", - "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", - "dev": true - }, - "md5": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", - "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", - "dev": true, - "requires": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "~1.1.6" - } - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "mem": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/mem/-/mem-5.1.1.tgz", - "integrity": "sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.3", - "mimic-fn": "^2.1.0", - "p-is-promise": "^2.1.0" - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - } - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" - }, - "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "requires": { - "mime-db": "1.51.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "mocha": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz", - "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==", - "dev": true, - "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.2.2", - "yargs-parser": "13.0.0", - "yargs-unparser": "1.5.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "dependencies": { - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "msgpack5": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/msgpack5/-/msgpack5-4.5.1.tgz", - "integrity": "sha512-zC1vkcliryc4JGlL6OfpHumSYUHWFGimSI+OgfRCjTFLmKA2/foR9rMTOhWiqfOrfxJOctrpWPvrppf8XynJxw==", - "dev": true, - "requires": { - "bl": "^2.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.3.6", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "multimatch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", - "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", - "dev": true, - "requires": { - "@types/minimatch": "^3.0.3", - "array-differ": "^3.0.0", - "array-union": "^2.1.0", - "arrify": "^2.0.1", - "minimatch": "^3.0.4" - } - }, - "nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", - "dev": true - }, - "native-url": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/native-url/-/native-url-0.3.4.tgz", - "integrity": "sha512-6iM8R99ze45ivyH8vybJ7X0yekIcPf5GgLV5K0ENCbmRcaRIDoj37BC8iLEmaaBfqqb8enuZ5p0uhY+lVAbAcA==", - "dev": true, - "requires": { - "querystring": "^0.2.0" - } - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true - }, - "next": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/next/-/next-11.1.3.tgz", - "integrity": "sha512-ud/gKmnKQ8wtHC+pd1ZiqPRa7DdgulPkAk94MbpsspfNliwZkYs9SIYWhlLSyg+c661LzdUI2nZshvrtggSYWA==", - "dev": true, - "requires": { - "@babel/runtime": "7.15.3", - "@hapi/accept": "5.0.2", - "@next/env": "11.1.3", - "@next/polyfill-module": "11.1.3", - "@next/react-dev-overlay": "11.1.3", - "@next/react-refresh-utils": "11.1.3", - "@next/swc-darwin-arm64": "11.1.3", - "@next/swc-darwin-x64": "11.1.3", - "@next/swc-linux-x64-gnu": "11.1.3", - "@next/swc-win32-x64-msvc": "11.1.3", - "@node-rs/helper": "1.2.1", - "assert": "2.0.0", - "ast-types": "0.13.2", - "browserify-zlib": "0.2.0", - "browserslist": "4.16.6", - "buffer": "5.6.0", - "caniuse-lite": "^1.0.30001228", - "chalk": "2.4.2", - "chokidar": "3.5.1", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.12.0", - "cssnano-simple": "3.0.0", - "domain-browser": "4.19.0", - "encoding": "0.1.13", - "etag": "1.8.1", - "find-cache-dir": "3.3.1", - "get-orientation": "1.1.2", - "https-browserify": "1.0.0", - "image-size": "1.0.0", - "jest-worker": "27.0.0-next.5", - "native-url": "0.3.4", - "node-fetch": "2.6.1", - "node-html-parser": "1.4.9", - "node-libs-browser": "^2.2.1", - "os-browserify": "0.3.0", - "p-limit": "3.1.0", - "path-browserify": "1.0.1", - "pnp-webpack-plugin": "1.6.4", - "postcss": "8.2.15", - "process": "0.11.10", - "querystring-es3": "0.2.1", - "raw-body": "2.4.1", - "react-is": "17.0.2", - "react-refresh": "0.8.3", - "stream-browserify": "3.0.0", - "stream-http": "3.1.1", - "string_decoder": "1.3.0", - "styled-jsx": "4.0.1", - "timers-browserify": "2.0.12", - "tty-browserify": "0.0.1", - "use-subscription": "1.5.1", - "util": "0.12.4", - "vm-browserify": "1.1.2", - "watchpack": "2.1.1" - }, - "dependencies": { - "buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "raw-body": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", - "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.3", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true - } - } - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "nise": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.1.tgz", - "integrity": "sha512-yr5kW2THW1AkxVmCnKEh4nbYkJdB3I7LUkiUgOvEkOp414mc2UMaHMA7pjq1nYowhdoJZGwEKGaQVbxfpWj10A==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": ">=5", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "requires": { - "isarray": "0.0.1" - } - } - } - }, - "no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "requires": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "nock": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/nock/-/nock-11.7.0.tgz", - "integrity": "sha512-7c1jhHew74C33OBeRYyQENT+YXQiejpwIrEjinh6dRurBae+Ei4QjeUaPlkptIF0ZacEiVCnw8dWaxqepkiihg==", - "dev": true, - "requires": { - "chai": "^4.1.2", - "debug": "^4.1.0", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.13", - "mkdirp": "^0.5.0", - "propagate": "^2.0.0" - } - }, - "node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", - "dev": true - }, - "node-html-parser": { - "version": "1.4.9", - "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-1.4.9.tgz", - "integrity": "sha512-UVcirFD1Bn0O+TSmloHeHqZZCxHjvtIeGdVdGMhyZ8/PWlEiZaZ5iJzR189yKZr8p0FXN58BUeC7RHRkf/KYGw==", - "dev": true, - "requires": { - "he": "1.2.0" - } - }, - "node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - }, - "dependencies": { - "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } - } - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", - "dev": true - }, - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - } - } - }, - "node-mocks-http": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/node-mocks-http/-/node-mocks-http-1.11.0.tgz", - "integrity": "sha512-jS/WzSOcKbOeGrcgKbenZeNhxUNnP36Yw11+hL4TTxQXErGfqYZ+MaYNNvhaTiGIJlzNSqgQkk9j8dSu1YWSuw==", - "dev": true, - "requires": { - "accepts": "^1.3.7", - "content-disposition": "^0.5.3", - "depd": "^1.1.0", - "fresh": "^0.5.2", - "merge-descriptors": "^1.0.1", - "methods": "^1.1.2", - "mime": "^1.3.4", - "parseurl": "^1.3.3", - "range-parser": "^1.2.0", - "type-is": "^1.6.18" - } - }, - "node-releases": { - "version": "1.1.77", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.77.tgz", - "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==", - "dev": true - }, - "nodemailer": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.7.3.tgz", - "integrity": "sha512-KUdDsspqx89sD4UUyUKzdlUOper3hRkDVkrKh/89G+d9WKsU5ox51NWS4tB1XR5dPUdR4SP0E3molyEfOvSa3g==" - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" - }, - "object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.getownpropertydescriptors": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", - "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - } - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "only": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", - "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=", - "dev": true - }, - "openapi3-ts": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/openapi3-ts/-/openapi3-ts-2.0.2.tgz", - "integrity": "sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw==", - "dev": true, - "requires": { - "yaml": "^1.10.2" - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "os-locale": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-5.0.0.tgz", - "integrity": "sha512-tqZcNEDAIZKBEPnHPlVDvKrp7NzgLi7jRmhKiUoa2NUmhl13FtkAGLUVR+ZsYvApBQdBfYm43A4tXXQ4IrYLBA==", - "dev": true, - "requires": { - "execa": "^4.0.0", - "lcid": "^3.0.0", - "mem": "^5.0.0" - } - }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true - }, - "p-event": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", - "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", - "dev": true, - "requires": { - "p-timeout": "^3.1.0" - } - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - }, - "dependencies": { - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - } - } - }, - "p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "dev": true, - "requires": { - "p-finally": "^1.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dev": true, - "requires": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, - "path-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", - "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", - "dev": true, - "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-to-regexp": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.0.tgz", - "integrity": "sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg==", - "dev": true - }, - "pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true - }, - "pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true, - "peer": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pino": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-6.14.0.tgz", - "integrity": "sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==", - "dev": true, - "requires": { - "fast-redact": "^3.0.0", - "fast-safe-stringify": "^2.0.8", - "flatstr": "^1.0.12", - "pino-std-serializers": "^3.1.0", - "process-warning": "^1.0.0", - "quick-format-unescaped": "^4.0.3", - "sonic-boom": "^1.0.2" - } - }, - "pino-std-serializers": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz", - "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - } - } - }, - "platform": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", - "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", - "dev": true - }, - "pnp-webpack-plugin": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz", - "integrity": "sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==", - "dev": true, - "requires": { - "ts-pnp": "^1.1.6" - } - }, - "postcss": { - "version": "8.2.15", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz", - "integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==", - "dev": true, - "requires": { - "colorette": "^1.2.2", - "nanoid": "^3.1.23", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "prettier": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz", - "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==", - "dev": true - }, - "pretty-quick": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.3.tgz", - "integrity": "sha512-kOCi2FJabvuh1as9enxYmrnBC6tVMoVOenMaBqRfsvBHB0cbpYHjdQEpSglpASDFEXVwplpcGR4CLEaisYAFcA==", - "dev": true, - "requires": { - "chalk": "^3.0.0", - "execa": "^4.0.0", - "find-up": "^4.1.0", - "ignore": "^5.1.4", - "mri": "^1.1.5", - "multimatch": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "process-warning": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", - "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==", - "dev": true - }, - "propagate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", - "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", - "dev": true - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - } - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "requires": { - "side-channel": "^1.0.4" - } - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" - }, - "queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "dev": true, - "requires": { - "inherits": "~2.0.3" - } - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "quick-format-unescaped": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", - "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - } - } - }, - "react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", - "dev": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", - "dev": true, - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" - } - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "react-refresh": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz", - "integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", - "dev": true - }, - "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" - }, - "ret": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", - "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safe-regex2": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz", - "integrity": "sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==", - "dev": true, - "requires": { - "ret": "~0.2.0" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sax": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=", - "dev": true - }, - "scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", - "dev": true, - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "scmp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz", - "integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==" - }, - "secure-json-parse": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.4.0.tgz", - "integrity": "sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg==", - "dev": true - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "semver-store": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/semver-store/-/semver-store-0.3.0.tgz", - "integrity": "sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg==", - "dev": true - }, - "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true - } - } - }, - "sentence-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", - "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" - } - }, - "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-cookie-parser": { - "version": "2.4.8", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz", - "integrity": "sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg==", - "dev": true - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", - "dev": true - }, - "shiki": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", - "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", - "dev": true, - "requires": { - "jsonc-parser": "^3.0.0", - "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "5.2.0" - } - }, - "shortid": { - "version": "2.2.16", - "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz", - "integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==", - "dev": true, - "requires": { - "nanoid": "^2.1.0" - }, - "dependencies": { - "nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", - "dev": true - } - } - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "sinon": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-14.0.0.tgz", - "integrity": "sha512-ugA6BFmE+WrJdh0owRZHToLd32Uw3Lxq6E6LtNRU+xTVBefx632h03Q7apXWRsRdZAJ41LB8aUfn2+O4jsDNMw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": "^9.1.2", - "@sinonjs/samsam": "^6.1.1", - "diff": "^5.0.0", - "nise": "^5.1.1", - "supports-color": "^7.2.0" - }, - "dependencies": { - "@sinonjs/fake-timers": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", - "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "dev": true, - "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "sonic-boom": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", - "integrity": "sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==", - "dev": true, - "requires": { - "atomic-sleep": "^1.0.0", - "flatstr": "^1.0.12" - } - }, - "source-map": { - "version": "0.8.0-beta.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", - "dev": true, - "requires": { - "whatwg-url": "^7.0.0" - }, - "dependencies": { - "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true - }, - "whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - } - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, - "stacktrace-parser": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", - "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", - "dev": true, - "requires": { - "type-fest": "^0.7.1" - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "stoppable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", - "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", - "dev": true - }, - "stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "dev": true, - "requires": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - } - }, - "stream-http": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.1.1.tgz", - "integrity": "sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "xtend": "^4.0.2" - } - }, - "stream-parser": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz", - "integrity": "sha1-FhhUhpRCACGhGC/wrxkRwSl2F3M=", - "dev": true, - "requires": { - "debug": "2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "string-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", - "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=", - "dev": true - }, - "string-similarity": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-4.0.4.tgz", - "integrity": "sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "strong-error-handler": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strong-error-handler/-/strong-error-handler-4.0.0.tgz", - "integrity": "sha512-Ki59WSOfSEod6IkDUB4uf9+DwkCLQRbEdYqen167I/zyPps9x9gS+UzhLZOcer58RA6iFmoGg/+CN/x5d+Cv3Q==", - "dev": true, - "requires": { - "@types/express": "^4.16.0", - "accepts": "^1.3.3", - "debug": "^4.1.1", - "ejs": "^3.1.3", - "fast-safe-stringify": "^2.0.6", - "http-status": "^1.1.2", - "js2xmlparser": "^4.0.0", - "strong-globalize": "^6.0.1" - } - }, - "strong-globalize": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/strong-globalize/-/strong-globalize-6.0.5.tgz", - "integrity": "sha512-7nfUli41TieV9/TSc0N62ve5Q4nfrpy/T0nNNy6TyD3vst79QWmeylCyd3q1gDxh8dqGEtabLNCdPQP1Iuvecw==", - "dev": true, - "requires": { - "accept-language": "^3.0.18", - "debug": "^4.2.0", - "globalize": "^1.6.0", - "lodash": "^4.17.20", - "md5": "^2.3.0", - "mkdirp": "^1.0.4", - "os-locale": "^5.0.0", - "yamljs": "^0.3.0" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "styled-jsx": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-4.0.1.tgz", - "integrity": "sha512-Gcb49/dRB1k8B4hdK8vhW27Rlb2zujCk1fISrizCcToIs+55B4vmUM0N9Gi4nnVfFZWe55jRdWpAqH1ldAKWvQ==", - "dev": true, - "requires": { - "@babel/plugin-syntax-jsx": "7.14.5", - "@babel/types": "7.15.0", - "convert-source-map": "1.7.0", - "loader-utils": "1.2.3", - "source-map": "0.7.3", - "string-hash": "1.1.3", - "stylis": "3.5.4", - "stylis-rule-sheet": "0.0.10" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, - "stylis": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", - "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==", - "dev": true - }, - "stylis-rule-sheet": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz", - "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==", - "dev": true, - "requires": {} - }, - "superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", - "dev": true, - "requires": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "supertest": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz", - "integrity": "sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ==", - "dev": true, - "requires": { - "methods": "^1.1.2", - "superagent": "^3.8.3" - } - }, - "supertokens-js-override": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/supertokens-js-override/-/supertokens-js-override-0.0.4.tgz", - "integrity": "sha512-r0JFBjkMIdep3Lbk3JA+MpnpuOtw4RSyrlRAbrzMcxwiYco3GFWl/daimQZ5b1forOiUODpOlXbSOljP/oyurg==" - }, - "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "timers-browserify": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", - "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } - }, - "tiny-lru": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-7.0.6.tgz", - "integrity": "sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow==", - "dev": true - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "toposort": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=", - "dev": true - }, - "traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", - "dev": true - }, - "ts-pnp": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", - "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==", - "dev": true - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "tsscmp": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", - "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", - "dev": true - }, - "tty-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", - "dev": true - }, - "twilio": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/twilio/-/twilio-4.7.2.tgz", - "integrity": "sha512-sTdEwAhkDzoDoXE3i83F/CdZegZ5O1FPDY0hAnJmGr/TjDqGl+Q6WzjC0+9cTmQnjCaDg6H4L97UZeJLFFEh3A==", - "requires": { - "axios": "^0.26.1", - "dayjs": "^1.8.29", - "https-proxy-agent": "^5.0.0", - "jsonwebtoken": "^9.0.0", - "qs": "^6.9.4", - "scmp": "^2.1.0", - "url-parse": "^1.5.9", - "xmlbuilder": "^13.0.2" - }, - "dependencies": { - "axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "requires": { - "follow-redirects": "^1.14.8" - } - }, - "jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "requires": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - }, - "xmlbuilder": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", - "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==" - } - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", - "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typedoc": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.12.tgz", - "integrity": "sha512-FcyC+YuaOpr3rB9QwA1IHOi9KnU2m50sPJW5vcNRPCIdecp+3bFkh7Rq5hBU1Fyn29UR2h4h/H7twZHWDhL0sw==", - "dev": true, - "requires": { - "glob": "^7.2.0", - "lunr": "^2.3.9", - "marked": "^4.0.10", - "minimatch": "^3.0.4", - "shiki": "^0.10.0" - }, - "dependencies": { - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "typescript": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", - "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", - "dev": true - }, - "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "upper-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", - "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", - "dev": true, - "requires": { - "tslib": "^2.0.3" - } - }, - "upper-case-first": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", - "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", - "dev": true, - "requires": { - "tslib": "^2.0.3" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "use-subscription": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/use-subscription/-/use-subscription-1.5.1.tgz", - "integrity": "sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA==", - "dev": true, - "requires": { - "object-assign": "^4.1.1" - } - }, - "util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - }, - "uuid-parse": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/uuid-parse/-/uuid-parse-1.1.0.tgz", - "integrity": "sha512-OdmXxA8rDsQ7YpNVbKSJkNzTw2I+S5WsbMDnCtIWSQaosNAcWtFuI/YK1TjzUI6nbkgiqEyh8gWngfcv8Asd9A==", - "dev": true - }, - "validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", - "dev": true - }, - "vandium-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/vandium-utils/-/vandium-utils-2.0.0.tgz", - "integrity": "sha512-XWbQ/0H03TpYDXk8sLScBEZpE7TbA0CHDL6/Xjt37IBYKLsHUQuBlL44ttAUs9zoBOLFxsW7HehXcuWCNyqOxQ==", - "dev": true - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - }, - "verify-apple-id-token": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/verify-apple-id-token/-/verify-apple-id-token-3.0.1.tgz", - "integrity": "sha512-q91pG1e52TpEzXldMirWYNWcSQC4WuzgG0y/ZnBhzjfk0pSxi4YlGh5OTVRlodBenayGHfSDn5VseG9QDuqOew==", - "requires": { - "jsonwebtoken": "^9.0.0", - "jwks-rsa": "^3.0.0" - }, - "dependencies": { - "@types/express": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", - "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "jose": { - "version": "4.11.4", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.11.4.tgz", - "integrity": "sha512-94FdcR8felat4vaTJyL/WVdtlWLlsnLMZP8v+A0Vru18K3bQ22vn7TtpVh3JlgBFNIlYOUlGqwp/MjRPOnIyCQ==" - }, - "jwks-rsa": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.0.1.tgz", - "integrity": "sha512-UUOZ0CVReK1QVU3rbi9bC7N5/le8ziUj0A2ef1Q0M7OPD2KvjEYizptqIxGIo6fSLYDkqBrazILS18tYuRc8gw==", - "requires": { - "@types/express": "^4.17.14", - "@types/jsonwebtoken": "^9.0.0", - "debug": "^4.3.4", - "jose": "^4.10.4", - "limiter": "^1.1.5", - "lru-memoizer": "^2.1.4" - } - } - } - }, - "vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", - "dev": true - }, - "vscode-oniguruma": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.1.tgz", - "integrity": "sha512-vc4WhSIaVpgJ0jJIejjYxPvURJavX6QG41vu0mGhqywMkQqulezEqEQ3cO3gc8GvcOpX6ycmKGqRoROEMBNXTQ==", - "dev": true - }, - "vscode-textmate": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", - "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", - "dev": true - }, - "watchpack": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.1.tgz", - "integrity": "sha512-Oo7LXCmc1eE1AjyuSBmtC3+Wy4HcV8PxWh2kP6fOl8yTlNS7r0K9l1ao2lrrUza7V39Y3D/BbJgY8VeSlc5JKw==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "which-typed-array": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", - "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.7" - } - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" - } - }, - "xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", - "dev": true - }, - "xmlcreate": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", - "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - }, - "yamljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", - "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "glob": "^7.0.5" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - } - } - }, - "yargs": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", - "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "yargs-parser": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", - "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yargs-unparser": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", - "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", - "dev": true, - "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.11", - "yargs": "^12.0.5" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - }, - "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "ylru": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz", - "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/package.json b/package.json index 99be694ac..6c6552730 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "supertokens-node", - "version": "13.0.2", + "version": "14.0.0", "description": "NodeJS driver for SuperTokens core", "main": "index.js", "scripts": { @@ -39,6 +39,7 @@ "co-body": "6.1.0", "cookie": "0.4.0", "debug": "^4.3.3", + "jose": "^4.13.1", "jsonwebtoken": "^9.0.0", "jwks-rsa": "^2.0.5", "libphonenumber-js": "^1.9.44", @@ -75,8 +76,8 @@ "loopback-datasource-juggler": "^4.26.0", "mocha": "6.1.4", "next": "11.1.3", + "next-test-api-route-handler": "^3.1.8", "nock": "11.7.0", - "node-mocks-http": "^1.11.0", "prettier": "2.0.5", "pretty-quick": "^3.1.1", "react": "^17.0.2", diff --git a/test/auth-react-server/index.js b/test/auth-react-server/index.js index 3d46a8e8e..5f5b0672c 100644 --- a/test/auth-react-server/index.js +++ b/test/auth-react-server/index.js @@ -36,6 +36,7 @@ let { default: SuperTokensRaw } = require("../../lib/build/supertokens"); const { default: EmailPasswordRaw } = require("../../lib/build/recipe/emailpassword/recipe"); const { default: ThirdPartyRaw } = require("../../lib/build/recipe/thirdparty/recipe"); const { default: ThirdPartyEmailPasswordRaw } = require("../../lib/build/recipe/thirdpartyemailpassword/recipe"); +const { default: DashboardRaw } = require("../../lib/build/recipe/dashboard/recipe"); const { default: ThirdPartyPasswordlessRaw } = require("../../lib/build/recipe/thirdpartypasswordless/recipe"); const { default: SessionRaw } = require("../../lib/build/recipe/session/recipe"); @@ -170,14 +171,14 @@ app.get("/sessioninfo", verifySession(), async (req, res) => { sessionHandle: session.getHandle(), userId: session.getUserId(), accessTokenPayload: session.getJWTPayload(), - sessionData: await session.getSessionData(), + sessionData: await session.getSessionDataFromDatabase(), }); } else { res.send({ sessionHandle: session.getHandle(), userId: session.getUserId(), accessTokenPayload: session.getAccessTokenPayload(), - sessionData: await session.getSessionData(), + sessionData: await session.getSessionDataFromDatabase(), }); } }); @@ -285,6 +286,7 @@ function initST({ passwordlessConfig } = {}) { ThirdPartyRaw.reset(); ThirdPartyEmailPasswordRaw.reset(); SessionRaw.reset(); + DashboardRaw.reset(); SuperTokensRaw.reset(); diff --git a/test/config.test.js b/test/config.test.js index e16dbdc4a..5b8e71f76 100644 --- a/test/config.test.js +++ b/test/config.test.js @@ -681,6 +681,38 @@ describe(`configTest: ${printPath("[test/config.test.js]")}`, function () { it("various config values", async function () { await startST(); + { + STExpress.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init({ getTokenTransferMethod: () => "cookie", accessTokenPath: "/access" })], + }); + assert(SessionRecipe.getInstanceOrThrowError().config.accessTokenPath.getAsStringDangerous() === "/access"); + resetAll(); + } + + { + STExpress.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init({ getTokenTransferMethod: () => "cookie" })], + }); + assert(SessionRecipe.getInstanceOrThrowError().config.accessTokenPath.getAsStringDangerous() === ""); + resetAll(); + } + { STExpress.init({ supertokens: { @@ -1163,7 +1195,7 @@ describe(`configTest: ${printPath("[test/config.test.js]")}`, function () { assert.equal(SessionRecipe.getInstanceOrThrowError().config.sessionExpiredStatusCode, 401); }); - it("Test that the jwt feature is disabled by default", async function () { + it("Test that the JWKS and OpenId endpoints are exposed by Session", async function () { await startST(); STExpress.init({ supertokens: { @@ -1176,115 +1208,13 @@ describe(`configTest: ${printPath("[test/config.test.js]")}`, function () { }, recipeList: [Session.init({ getTokenTransferMethod: () => "cookie" })], }); - assert.notStrictEqual(SessionRecipe.getInstanceOrThrowError().config.jwt, undefined); - assert.strictEqual(SessionRecipe.getInstanceOrThrowError().config.jwt.enable, false); - }); - - it("Test that the jwt feature is disabled when explicitly set to false", async function () { - await startST(); - STExpress.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [Session.init({ getTokenTransferMethod: () => "cookie", jwt: { enable: false } })], - }); - assert.notStrictEqual(SessionRecipe.getInstanceOrThrowError().config.jwt, undefined); - assert.strictEqual(SessionRecipe.getInstanceOrThrowError().config.jwt.enable, false); - }); - - it("Test that the jwt feature is enabled when explicitly set to true", async function () { - await startST(); - STExpress.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [Session.init({ getTokenTransferMethod: () => "cookie", jwt: { enable: true } })], - }); - - assert.notStrictEqual(SessionRecipe.getInstanceOrThrowError().config.jwt, undefined); - assert.strictEqual(SessionRecipe.getInstanceOrThrowError().config.jwt.enable, true); - }); - - it("Test that the custom jwt property name in access token payload is set correctly in config", async function () { - await startST(); - STExpress.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true, propertyNameInAccessTokenPayload: "customJWTKey" }, - }), - ], - }); - - assert.notStrictEqual(SessionRecipe.getInstanceOrThrowError().config.jwt, undefined); - assert.strictEqual( - SessionRecipe.getInstanceOrThrowError().config.jwt.propertyNameInAccessTokenPayload, - "customJWTKey" - ); - }); - - it("Test that the the jwt property name uses default value when not set in config", async function () { - await startST(); - STExpress.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [Session.init({ getTokenTransferMethod: () => "cookie", jwt: { enable: true } })], - }); - - assert.notStrictEqual(SessionRecipe.getInstanceOrThrowError().config.jwt, undefined); - assert.strictEqual(SessionRecipe.getInstanceOrThrowError().config.jwt.propertyNameInAccessTokenPayload, "jwt"); - }); - - it("Test that when setting jwt property name with the same value as the reserved property, init throws an error", async function () { - try { - await startST(); - STExpress.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true, propertyNameInAccessTokenPayload: "_jwtPName" }, - }), - ], - }); - - throw new Error("Init succeeded when it should have failed"); - } catch (e) { - if (e.message !== "_jwtPName is a reserved property name, please use a different key name for the jwt") { - throw e; - } - } + const apis = SessionRecipe.getInstanceOrThrowError().getAPIsHandled(); + const jwksApi = apis.find((f) => f.id === "/jwt/jwks.json"); + assert.ok(jwksApi); + assert.equal(jwksApi.pathWithoutApiBasePath.getAsStringDangerous(), "/jwt/jwks.json"); + const openidApi = apis.find((f) => f.id === "/.well-known/openid-configuration"); + assert.ok(openidApi); + assert.equal(openidApi.pathWithoutApiBasePath.getAsStringDangerous(), "/.well-known/openid-configuration"); }); it("testing getTopLevelDomainForSameSiteResolution function", async function () { @@ -1505,4 +1435,57 @@ describe(`configTest: ${printPath("[test/config.test.js]")}`, function () { } assert(errorCaught); }); + + it("Check that telemetry is set to true properly", async function () { + await startST(); + STExpress.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + telemetry: true, + }); + + assert(SuperTokens.getInstanceOrThrowError().telemetryEnabled === true); + }); + + it("Check that telemetry is set to false by default", async function () { + await startST(); + STExpress.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + }); + + assert(SuperTokens.getInstanceOrThrowError().telemetryEnabled === false); + }); + + it("Check that telemetry is set to false properly", async function () { + await startST(); + STExpress.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + telemetry: false, + }); + + assert(SuperTokens.getInstanceOrThrowError().telemetryEnabled === false); + }); }); diff --git a/test/emailpassword/signoutFeature.test.js b/test/emailpassword/signoutFeature.test.js index b1c3918b7..b7ab1f39e 100644 --- a/test/emailpassword/signoutFeature.test.js +++ b/test/emailpassword/signoutFeature.test.js @@ -182,13 +182,13 @@ describe(`signoutFeature: ${printPath("[test/emailpassword/signoutFeature.test.j app.use(errorHandler()); - let response = await new Promise((resolve) => + let response = await new Promise((resolve, reject) => request(app) .post("/auth/signout") .expect(200) .end((err, res) => { if (err) { - resolve(undefined); + reject(err); } else { resolve(res); } diff --git a/test/emailpassword/updateEmailPass.test.js b/test/emailpassword/updateEmailPass.test.js index 227da56c4..4c5fd4612 100644 --- a/test/emailpassword/updateEmailPass.test.js +++ b/test/emailpassword/updateEmailPass.test.js @@ -22,6 +22,7 @@ let EmailPassword = require("../../recipe/emailpassword"); let { maxVersion } = require("../../lib/build/utils"); let { Querier } = require("../../lib/build/querier"); let { middleware, errorHandler } = require("../../framework/express"); +const express = require("express"); describe(`updateEmailPassTest: ${printPath("[test/emailpassword/updateEmailPass.test.js]")}`, function () { beforeEach(async function () { @@ -69,10 +70,166 @@ describe(`updateEmailPassTest: ${printPath("[test/emailpassword/updateEmailPass. userId: res.user.id, email: "test2@gmail.com", password: "testPass", + applyPasswordPolicy: false, }); let res2 = await signIn("test2@gmail.com", "testPass"); assert(res2.user.id === res2.user.id); }); + + it("test updateEmailPass with failing password validation", async function () { + await startST(); + STExpress.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + EmailPassword.init({ + signUpFeature: { + formFields: [ + { + id: "email", + }, + { + id: "password", + validate: async (value) => { + if (value.length < 5) return "Password should be greater than 5 characters"; + return undefined; + }, + }, + ], + }, + }), + Session.init({ getTokenTransferMethod: () => "cookie" }), + ], + }); + + let apiVersion = await Querier.getNewInstanceOrThrowError(undefined).getAPIVersion(); + if (maxVersion(apiVersion, "2.7") === "2.7") { + return; + } + + const express = require("express"); + const app = express(); + + app.use(middleware()); + + app.use(errorHandler()); + + await signUPRequest(app, "test@gmail.com", "testPass123"); + + let res = await signIn("test@gmail.com", "testPass123"); + + const res2 = await updateEmailOrPassword({ + userId: res.user.id, + email: "test2@gmail.com", + password: "test", + }); + + assert(res2.status === "PASSWORD_POLICY_VIOLATED_ERROR"); + assert(res2.failureReason === "Password should be greater than 5 characters"); + }); + + it("test updateEmailPass with passing password validation", async function () { + await startST(); + STExpress.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + EmailPassword.init({ + signUpFeature: { + formFields: [ + { + id: "email", + }, + { + id: "password", + validate: async (value) => { + if (value.length < 5) return "Password should be greater than 5 characters"; + return undefined; + }, + }, + ], + }, + }), + Session.init({ getTokenTransferMethod: () => "cookie" }), + ], + }); + + let apiVersion = await Querier.getNewInstanceOrThrowError(undefined).getAPIVersion(); + if (maxVersion(apiVersion, "2.7") === "2.7") { + return; + } + + const express = require("express"); + const app = express(); + + app.use(middleware()); + + app.use(errorHandler()); + + await signUPRequest(app, "test@gmail.com", "testPass123"); + + let res = await signIn("test@gmail.com", "testPass123"); + + const res2 = await updateEmailOrPassword({ + userId: res.user.id, + email: "test2@gmail.com", + password: "testPass2", + }); + + assert(res2.status === "OK"); + }); + + it("test updateEmailPass with failing default password validation", async function () { + await startST(); + STExpress.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [EmailPassword.init(), Session.init({ getTokenTransferMethod: () => "cookie" })], + }); + + let apiVersion = await Querier.getNewInstanceOrThrowError(undefined).getAPIVersion(); + if (maxVersion(apiVersion, "2.7") === "2.7") { + return; + } + + const express = require("express"); + const app = express(); + + app.use(middleware()); + + app.use(errorHandler()); + + await signUPRequest(app, "test@gmail.com", "testPass123"); + + let res = await signIn("test@gmail.com", "testPass123"); + + const res2 = await updateEmailOrPassword({ + userId: res.user.id, + email: "test2@gmail.com", + password: "1", + }); + + assert(res2.status === "PASSWORD_POLICY_VIOLATED_ERROR"); + assert(res2.failureReason === "Password must contain at least 8 characters, including a number"); + }); }); diff --git a/test/emailpassword/users.test.js b/test/emailpassword/users.test.js index 886c2060e..f2d3a1ab7 100644 --- a/test/emailpassword/users.test.js +++ b/test/emailpassword/users.test.js @@ -22,6 +22,7 @@ let EmailPassword = require("../../recipe/emailpassword"); let { maxVersion } = require("../../lib/build/utils"); let { Querier } = require("../../lib/build/querier"); let { middleware, errorHandler } = require("../../framework/express"); +const express = require("express"); describe(`usersTest: ${printPath("[test/emailpassword/users.test.js]")}`, function () { beforeEach(async function () { @@ -99,6 +100,45 @@ describe(`usersTest: ${printPath("[test/emailpassword/users.test.js]")}`, functi } }); + it("test getUsersOldestFirst with search queries", async function () { + await startST(); + STExpress.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [EmailPassword.init(), Session.init({ getTokenTransferMethod: () => "cookie" })], + }); + + const express = require("express"); + const app = express(); + + app.use(middleware()); + + app.use(errorHandler()); + + const cdiVersion = await Querier.getNewInstanceOrThrowError("emailpassword").getAPIVersion(); + if (maxVersion("2.20", cdiVersion) !== cdiVersion) { + return; + } + + await signUPRequest(app, "test@gmail.com", "testPass123"); + await signUPRequest(app, "test1@gmail.com", "testPass123"); + await signUPRequest(app, "test2@gmail.com", "testPass123"); + await signUPRequest(app, "test3@gmail.com", "testPass123"); + await signUPRequest(app, "john@gmail.com", "testPass123"); + + let users = await getUsersOldestFirst({ query: { email: "doe" } }); + assert.strictEqual(users.users.length, 0); + + users = await getUsersOldestFirst({ query: { email: "john" } }); + assert.strictEqual(users.users.length, 1); + }); + it("test getUsersNewestFirst", async function () { await startST(); STExpress.init({ @@ -163,6 +203,45 @@ describe(`usersTest: ${printPath("[test/emailpassword/users.test.js]")}`, functi } }); + it("test getUsersNewestFirst with search queries", async function () { + await startST(); + STExpress.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [EmailPassword.init(), Session.init({ getTokenTransferMethod: () => "cookie" })], + }); + + const express = require("express"); + const app = express(); + + app.use(middleware()); + + app.use(errorHandler()); + + const cdiVersion = await Querier.getNewInstanceOrThrowError("emailpassword").getAPIVersion(); + if (maxVersion("2.20", cdiVersion) !== cdiVersion) { + return; + } + + await signUPRequest(app, "test@gmail.com", "testPass123"); + await signUPRequest(app, "test1@gmail.com", "testPass123"); + await signUPRequest(app, "test2@gmail.com", "testPass123"); + await signUPRequest(app, "test3@gmail.com", "testPass123"); + await signUPRequest(app, "john@gmail.com", "testPass123"); + + let users = await getUsersNewestFirst({ query: { email: "doe" } }); + assert.strictEqual(users.users.length, 0); + + users = await getUsersNewestFirst({ query: { email: "john" } }); + assert.strictEqual(users.users.length, 1); + }); + it("test getUserCount", async function () { await startST(); STExpress.init({ diff --git a/test/framework/awsLambda.test.js b/test/framework/awsLambda.test.js index 20bf1524b..a6fb35686 100644 --- a/test/framework/awsLambda.test.js +++ b/test/framework/awsLambda.test.js @@ -28,7 +28,14 @@ let SuperTokens = require("../../"); let { middleware } = require("../../framework/awsLambda"); let Session = require("../../recipe/session"); let EmailPassword = require("../../recipe/emailpassword"); +let Passwordless = require("../../recipe/passwordless"); +let ThirdParty = require("../../recipe/thirdparty"); +let { Apple, Google, Github } = require("../../recipe/thirdparty"); let { verifySession } = require("../../recipe/session/framework/awsLambda"); +let Dashboard = require("../../recipe/dashboard"); +let { createUsers } = require("../utils"); +const { Querier } = require("../../lib/build/querier"); +const { maxVersion } = require("../../lib/build/utils"); describe(`AWS Lambda: ${printPath("[test/framework/awsLambda.test.js]")}`, function () { beforeEach(async function () { @@ -578,4 +585,606 @@ describe(`AWS Lambda: ${printPath("[test/framework/awsLambda.test.js]")}`, funct }); }); } + + it("test that authorization header is read correctly in dashboard recipe", async function () { + await startST(); + SuperTokens.init({ + framework: "awsLambda", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "http://api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "http://supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + if (authHeader === "Bearer testapikey") { + return true; + } + + return false; + }, + }; + }, + }, + }), + ], + }); + + let proxy = "/dev"; + + let event = mockLambdaProxyEventV2( + "/auth/dashboard/api/users/count", + "GET", + { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + null, + proxy, + null, + null + ); + + let result = await middleware()(event, undefined); + assert(result.statusCode === 200); + }); + + it("test that tags request respond with correct tags", async function () { + await startST(); + SuperTokens.init({ + framework: "awsLambda", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "http://api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "http://supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + let proxy = "/dev"; + + let event = mockLambdaProxyEventV2( + "/auth/dashboard/api/search/tags", + "GET", + { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + null, + proxy, + null, + null + ); + + let result = await middleware()(event, undefined); + assert(result.statusCode === 200); + const body = JSON.parse(result.body); + assert(body.tags.length !== 0); + }); + + it("test that search results correct output for 'email: t", async function () { + await startST(); + SuperTokens.init({ + framework: "awsLambda", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "http://api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "http://supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + let proxy = "/dev"; + + await createUsers(EmailPassword); + + let event = mockLambdaProxyEventV2( + "/auth/dashboard/api/users", + "GET", + { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + null, + proxy, + null, + { + limit: "10", + email: "t", + } + ); + + let result = await middleware()(event, undefined); + assert(result.statusCode === 200); + const body = JSON.parse(result.body); + assert(body.users.length === 5); + }); + + it("test that search results correct output for multiple search items", async function () { + await startST(); + SuperTokens.init({ + framework: "awsLambda", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "http://api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "http://supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + let proxy = "/dev"; + + await createUsers(EmailPassword); + + let event = mockLambdaProxyEventV2( + "/auth/dashboard/api/users", + "GET", + { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + null, + proxy, + null, + { + limit: "10", + email: "john;iresh", + } + ); + + let result = await middleware()(event, undefined); + assert(result.statusCode === 200); + const body = JSON.parse(result.body); + assert(body.users.length === 1); + }); + + it("test that search results correct output for 'email: iresh", async function () { + await startST(); + SuperTokens.init({ + framework: "awsLambda", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "http://api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "http://supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + let proxy = "/dev"; + + await createUsers(EmailPassword); + + let event = mockLambdaProxyEventV2( + "/auth/dashboard/api/users", + "GET", + { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + null, + proxy, + null, + { + limit: "10", + email: "iresh", + } + ); + + let result = await middleware()(event, undefined); + assert(result.statusCode === 200); + const body = JSON.parse(result.body); + assert(body.users.length === 0); + }); + + it("test that search results correct output for 'phone: +1", async function () { + await startST(); + SuperTokens.init({ + framework: "awsLambda", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "http://api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "http://supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + Passwordless.init({ + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + let proxy = "/dev"; + + await createUsers(null, Passwordless); + + let event = mockLambdaProxyEventV2( + "/auth/dashboard/api/users", + "GET", + { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + null, + proxy, + null, + { + limit: "10", + phone: "+1", + } + ); + + let result = await middleware()(event, undefined); + assert(result.statusCode === 200); + const body = JSON.parse(result.body); + assert(body.users.length === 3); + }); + + it("test that search results correct output for 'phone: 1(", async function () { + await startST(); + SuperTokens.init({ + framework: "awsLambda", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "http://api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "http://supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + Passwordless.init({ + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + let proxy = "/dev"; + + await createUsers(null, Passwordless); + + let event = mockLambdaProxyEventV2( + "/auth/dashboard/api/users", + "GET", + { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + null, + proxy, + null, + { + limit: "10", + phone: "1(", + } + ); + + let result = await middleware()(event, undefined); + assert(result.statusCode === 200); + const body = JSON.parse(result.body); + assert(body.users.length === 0); + }); + + it("test that search results correct output for 'provider: google'", async function () { + await startST(); + SuperTokens.init({ + framework: "awsLambda", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "http://api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "http://supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + ThirdParty.init({ + signInAndUpFeature: { + providers: [ + Google({ + clientId: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + clientSecret: "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", + }), + Github({ + clientId: "467101b197249757c71f", + clientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }), + Apple({ + clientId: "4398792-io.supertokens.example.service", + clientSecret: { + keyId: "7M48Y4RYDL", + privateKey: + "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + teamId: "YWQCXGJRJL", + }, + }), + ], + }, + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + let proxy = "/dev"; + + await createUsers(null, null, ThirdParty); + + let event = mockLambdaProxyEventV2( + "/auth/dashboard/api/users", + "GET", + { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + null, + proxy, + null, + { + limit: "10", + provider: "google", + } + ); + + let result = await middleware()(event, undefined); + assert(result.statusCode === 200); + const body = JSON.parse(result.body); + assert(body.users.length === 3); + }); + + it("test that search results correct output for 'provider: google, phone: 1'", async function () { + await startST(); + SuperTokens.init({ + framework: "awsLambda", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "http://api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "http://supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + Passwordless.init({ + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }), + ThirdParty.init({ + signInAndUpFeature: { + providers: [ + Google({ + clientId: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + clientSecret: "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", + }), + Github({ + clientId: "467101b197249757c71f", + clientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }), + Apple({ + clientId: "4398792-io.supertokens.example.service", + clientSecret: { + keyId: "7M48Y4RYDL", + privateKey: + "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + teamId: "YWQCXGJRJL", + }, + }), + ], + }, + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + let proxy = "/dev"; + + await createUsers(null, null, ThirdParty); + + let event = mockLambdaProxyEventV2( + "/auth/dashboard/api/users", + "GET", + { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + null, + proxy, + null, + { + limit: "10", + provider: "google", + phone: "1", + } + ); + + let result = await middleware()(event, undefined); + assert(result.statusCode === 200); + const body = JSON.parse(result.body); + assert(body.users.length === 0); + }); }); diff --git a/test/framework/fastify.test.js b/test/framework/fastify.test.js index df6151cb9..0f329b26d 100644 --- a/test/framework/fastify.test.js +++ b/test/framework/fastify.test.js @@ -30,6 +30,13 @@ let EmailPassword = require("../../recipe/emailpassword"); const EmailVerification = require("../../recipe/emailverification"); let Session = require("../../recipe/session"); let { verifySession } = require("../../recipe/session/framework/fastify"); +let Dashboard = require("../../recipe/dashboard"); +let { createUsers } = require("../utils"); +const { Querier } = require("../../lib/build/querier"); +const { maxVersion } = require("../../lib/build/utils"); +const Passwordless = require("../../recipe/passwordless"); +const ThirdParty = require("../../recipe/thirdparty"); +const { Apple, Google, Github } = require("../../recipe/thirdparty"); describe(`Fastify: ${printPath("[test/framework/fastify.test.js]")}`, function () { beforeEach(async function () { @@ -668,9 +675,10 @@ describe(`Fastify: ${printPath("[test/framework/fastify.test.js]")}`, function ( }, }) ); - assert(res2.accessToken !== undefined); - assert(res2.antiCsrf !== undefined); - assert(res2.refreshToken !== undefined); + + assert.notStrictEqual(res2.accessToken, undefined); + assert.notStrictEqual(res2.antiCsrf, undefined); + assert.notStrictEqual(res2.refreshToken, undefined); let res3 = extractInfoFromResponse( await this.server.inject({ @@ -957,7 +965,7 @@ describe(`Fastify: ${printPath("[test/framework/fastify.test.js]")}`, function ( preHandler: verifySession(), }, async (req, res) => { - await req.session.updateSessionData({ key: "value" }); + await req.session.updateSessionDataInDatabase({ key: "value" }); return res.send("").code(200); } ); @@ -968,7 +976,7 @@ describe(`Fastify: ${printPath("[test/framework/fastify.test.js]")}`, function ( preHandler: verifySession(), }, async (req, res) => { - let sessionData = await req.session.getSessionData(); + let sessionData = await req.session.getSessionDataFromDatabase(); return res.send(sessionData).code(200); } ); @@ -979,14 +987,14 @@ describe(`Fastify: ${printPath("[test/framework/fastify.test.js]")}`, function ( preHandler: verifySession(), }, async (req, res) => { - await req.session.updateSessionData(null); + await req.session.updateSessionDataInDatabase(null); return res.send("").code(200); } ); this.server.post("/updateSessionDataInvalidSessionHandle", async (req, res) => { return res - .send({ success: !(await Session.updateSessionData("InvalidHandle", { key: "value3" })) }) + .send({ success: !(await Session.updateSessionDataInDatabase("InvalidHandle", { key: "value3" })) }) .code(200); }); @@ -1085,7 +1093,7 @@ describe(`Fastify: ${printPath("[test/framework/fastify.test.js]")}`, function ( }, async (req, res) => { let accessTokenBefore = req.session.accessToken; - await req.session.updateAccessTokenPayload({ key: "value" }); + await req.session.mergeIntoAccessTokenPayload({ key: "value" }); let accessTokenAfter = req.session.accessToken; let statusCode = accessTokenBefore !== accessTokenAfter && typeof accessTokenAfter === "string" ? 200 : 500; @@ -1110,14 +1118,14 @@ describe(`Fastify: ${printPath("[test/framework/fastify.test.js]")}`, function ( preHandler: verifySession(), }, async (req, res) => { - await req.session.updateAccessTokenPayload(null); + await req.session.mergeIntoAccessTokenPayload({ key: null }); return res.send("").code(200); } ); this.server.post("/updateAccessTokenPayloadInvalidSessionHandle", async (req, res) => { return res - .send({ success: !(await Session.updateSessionData("InvalidHandle", { key: "value3" })) }) + .send({ success: !(await Session.updateSessionDataInDatabase("InvalidHandle", { key: "value3" })) }) .code(200); }); @@ -1133,7 +1141,9 @@ describe(`Fastify: ${printPath("[test/framework/fastify.test.js]")}`, function ( let frontendInfo = JSON.parse(new Buffer.from(response.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, {}); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 8); //call the updateAccessTokenPayload api to add jwt payload let updatedResponse = extractInfoFromResponse( @@ -1149,7 +1159,10 @@ describe(`Fastify: ${printPath("[test/framework/fastify.test.js]")}`, function ( frontendInfo = JSON.parse(new Buffer.from(updatedResponse.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, { key: "value" }); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.key, "value"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 9); //call the getAccessTokenPayload api to get jwt payload let response2 = await this.server.inject({ @@ -1177,7 +1190,10 @@ describe(`Fastify: ${printPath("[test/framework/fastify.test.js]")}`, function ( frontendInfo = JSON.parse(new Buffer.from(response2.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, { key: "value" }); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.key, "value"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 9); // change the value of the inserted jwt payload let updatedResponse2 = extractInfoFromResponse( @@ -1193,7 +1209,9 @@ describe(`Fastify: ${printPath("[test/framework/fastify.test.js]")}`, function ( frontendInfo = JSON.parse(new Buffer.from(updatedResponse2.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, {}); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 8); //retrieve the changed jwt payload let response3 = await this.server.inject({ @@ -1206,7 +1224,19 @@ describe(`Fastify: ${printPath("[test/framework/fastify.test.js]")}`, function ( }); //check the value of the retrieved - assert.deepStrictEqual(response3.json(), {}); + assert.deepStrictEqual( + new Set(Object.keys(response3.json())), + new Set([ + "antiCsrfToken", + "exp", + "iat", + "parentRefreshTokenHash1", + "refreshTokenHash1", + "sessionHandle", + "sub", + "iss", + ]) + ); //invalid session handle when updating the jwt payload let invalidSessionResponse = await this.server.inject({ method: "post", @@ -1351,4 +1381,527 @@ describe(`Fastify: ${printPath("[test/framework/fastify.test.js]")}`, function ( assert.strictEqual(res.accessToken, 1); assert.strictEqual(res.refreshToken, 1); }); + + it("test that authorization header is read correctly in dashboard recipe", async function () { + await startST(); + SuperTokens.init({ + framework: "fastify", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + if (authHeader === "Bearer testapikey") { + return true; + } + + return false; + }, + }; + }, + }, + }), + ], + }); + await this.server.register(FastifyFramework.plugin); + + let res2 = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users/count", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + + assert(res2.statusCode === 200); + }); + + it("test that tags request respond with correct tags", async function () { + await startST(); + SuperTokens.init({ + framework: "fastify", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.server.register(FastifyFramework.plugin); + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/search/tags", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + + assert(resp.statusCode === 200); + const body = resp.json(); + assert(body.tags.length !== 0); + }); + + it("test that search results correct output for 'email: t'", async function () { + await startST(); + SuperTokens.init({ + framework: "fastify", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.server.register(FastifyFramework.plugin); + await createUsers(EmailPassword); + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users?limit=10&email=t", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + + assert(resp.statusCode === 200); + const body = resp.json(); + assert(body.users.length === 5); + }); + + it("test that search results correct output for multiple search terms", async function () { + await startST(); + SuperTokens.init({ + framework: "fastify", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.server.register(FastifyFramework.plugin); + await createUsers(EmailPassword); + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users?limit=10&email=iresh;john", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + + assert(resp.statusCode === 200); + const body = resp.json(); + assert(body.users.length === 1); + }); + + it("test that search results correct output for 'email: iresh'", async function () { + await startST(); + SuperTokens.init({ + framework: "fastify", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.server.register(FastifyFramework.plugin); + await createUsers(EmailPassword); + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users?limit=10&email=iresh", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + + assert(resp.statusCode === 200); + const body = resp.json(); + assert(body.users.length === 0); + }); + + it("test that search results correct output for 'phone: +1'", async function () { + await startST(); + SuperTokens.init({ + framework: "fastify", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + Passwordless.init({ + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await createUsers(null, Passwordless); + await this.server.register(FastifyFramework.plugin); + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users?limit=10&phone=%2B1", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + + assert(resp.statusCode === 200); + const body = resp.json(); + assert(body.users.length === 3); + }); + + it("test that search results correct output for 'phone: 1('", async function () { + await startST(); + SuperTokens.init({ + framework: "fastify", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + Passwordless.init({ + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await createUsers(null, null); + await this.server.register(FastifyFramework.plugin); + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users?limit=10&phone=1%28", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + + assert(resp.statusCode === 200); + const body = resp.json(); + assert(body.users.length === 0); + }); + + it("test that search results correct output for 'provider: google'", async function () { + await startST(); + SuperTokens.init({ + framework: "fastify", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + ThirdParty.init({ + signInAndUpFeature: { + providers: [ + Google({ + clientId: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + clientSecret: "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", + }), + Github({ + clientId: "467101b197249757c71f", + clientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }), + Apple({ + clientId: "4398792-io.supertokens.example.service", + clientSecret: { + keyId: "7M48Y4RYDL", + privateKey: + "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + teamId: "YWQCXGJRJL", + }, + }), + ], + }, + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await createUsers(null, null, ThirdParty); + await this.server.register(FastifyFramework.plugin); + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users?limit=10&provider=google", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + + assert(resp.statusCode === 200); + const body = resp.json(); + assert(body.users.length === 3); + }); + + it("test that search results correct output for 'provider: google, phone: 1'", async function () { + await startST(); + SuperTokens.init({ + framework: "fastify", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + Passwordless.init({ + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }), + ThirdParty.init({ + signInAndUpFeature: { + providers: [ + Google({ + clientId: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + clientSecret: "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", + }), + Github({ + clientId: "467101b197249757c71f", + clientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }), + Apple({ + clientId: "4398792-io.supertokens.example.service", + clientSecret: { + keyId: "7M48Y4RYDL", + privateKey: + "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + teamId: "YWQCXGJRJL", + }, + }), + ], + }, + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await createUsers(null, Passwordless, ThirdParty); + await this.server.register(FastifyFramework.plugin); + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users?limit=10&provider=google&phone=1", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + + assert(resp.statusCode === 200); + const body = resp.json(); + assert(body.users.length === 0); + }); }); diff --git a/test/framework/hapi.test.js b/test/framework/hapi.test.js index 5dad9e56e..854461d46 100644 --- a/test/framework/hapi.test.js +++ b/test/framework/hapi.test.js @@ -21,6 +21,14 @@ const Hapi = require("@hapi/hapi"); let Session = require("../../recipe/session"); let ThirdpartyEmailPassword = require("../../recipe/thirdpartyemailpassword"); let { verifySession } = require("../../recipe/session/framework/hapi"); +let Dashboard = require("../../recipe/dashboard"); +let EmailPassword = require("../../recipe/emailpassword"); +const { createUsers } = require("../utils.js"); +const { Querier } = require("../../lib/build/querier"); +const { maxVersion } = require("../../lib/build/utils"); +const Passwordless = require("../../recipe/passwordless"); +const ThirdParty = require("../../recipe/thirdparty"); +const { Apple, Google, Github } = require("../../recipe/thirdparty"); describe(`Hapi: ${printPath("[test/framework/hapi.test.js]")}`, function () { beforeEach(async function () { @@ -958,7 +966,7 @@ describe(`Hapi: ${printPath("[test/framework/hapi.test.js]")}`, function () { path: "/updateSessionData", method: "post", handler: async (req, res) => { - await req.session.updateSessionData({ key: "value" }); + await req.session.updateSessionDataInDatabase({ key: "value" }); return res.response("").code(200); }, options: { @@ -970,7 +978,7 @@ describe(`Hapi: ${printPath("[test/framework/hapi.test.js]")}`, function () { path: "/getSessionData", method: "post", handler: async (req, res) => { - let sessionData = await req.session.getSessionData(); + let sessionData = await req.session.getSessionDataFromDatabase(); return res.response(sessionData).code(200); }, options: { @@ -982,7 +990,7 @@ describe(`Hapi: ${printPath("[test/framework/hapi.test.js]")}`, function () { path: "/updateSessionData2", method: "post", handler: async (req, res) => { - await req.session.updateSessionData(null); + await req.session.updateSessionDataInDatabase(null); return res.response("").code(200); }, options: { @@ -995,7 +1003,9 @@ describe(`Hapi: ${printPath("[test/framework/hapi.test.js]")}`, function () { method: "post", handler: async (req, res) => { return res - .response({ success: !(await Session.updateSessionData("InvalidHandle", { key: "value3" })) }) + .response({ + success: !(await Session.updateSessionDataInDatabase("InvalidHandle", { key: "value3" })), + }) .code(200); }, }); @@ -1099,7 +1109,7 @@ describe(`Hapi: ${printPath("[test/framework/hapi.test.js]")}`, function () { method: "post", handler: async (req, res) => { let accessTokenBefore = req.session.accessToken; - await req.session.updateAccessTokenPayload({ key: "value" }); + await req.session.mergeIntoAccessTokenPayload({ key: "value" }); let accessTokenAfter = req.session.accessToken; let statusCode = accessTokenBefore !== accessTokenAfter && typeof accessTokenAfter === "string" ? 200 : 500; @@ -1126,7 +1136,7 @@ describe(`Hapi: ${printPath("[test/framework/hapi.test.js]")}`, function () { path: "/updateAccessTokenPayload2", method: "post", handler: async (req, res) => { - await req.session.updateAccessTokenPayload(null); + await req.session.mergeIntoAccessTokenPayload({ key: null }); return res.response("").code(200); }, options: { @@ -1145,7 +1155,9 @@ describe(`Hapi: ${printPath("[test/framework/hapi.test.js]")}`, function () { method: "post", handler: async (req, res) => { return res - .response({ success: !(await Session.updateSessionData("InvalidHandle", { key: "value3" })) }) + .response({ + success: !(await Session.updateSessionDataInDatabase("InvalidHandle", { key: "value3" })), + }) .code(200); }, }); @@ -1164,7 +1176,9 @@ describe(`Hapi: ${printPath("[test/framework/hapi.test.js]")}`, function () { let frontendInfo = JSON.parse(new Buffer.from(response.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, {}); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 8); //call the updateAccessTokenPayload api to add jwt payload let updatedResponse = extractInfoFromResponse( @@ -1180,7 +1194,10 @@ describe(`Hapi: ${printPath("[test/framework/hapi.test.js]")}`, function () { frontendInfo = JSON.parse(new Buffer.from(updatedResponse.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, { key: "value" }); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.key, "value"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 9); //call the getAccessTokenPayload api to get jwt payload let response2 = await this.server.inject({ @@ -1208,7 +1225,10 @@ describe(`Hapi: ${printPath("[test/framework/hapi.test.js]")}`, function () { frontendInfo = JSON.parse(new Buffer.from(response2.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, { key: "value" }); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.key, "value"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 9); // change the value of the inserted jwt payload let updatedResponse2 = extractInfoFromResponse( @@ -1224,7 +1244,9 @@ describe(`Hapi: ${printPath("[test/framework/hapi.test.js]")}`, function () { frontendInfo = JSON.parse(new Buffer.from(updatedResponse2.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, {}); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 8); //retrieve the changed jwt payload let response3 = await this.server.inject({ @@ -1237,7 +1259,20 @@ describe(`Hapi: ${printPath("[test/framework/hapi.test.js]")}`, function () { }); //check the value of the retrieved - assert.deepStrictEqual(response3.result, {}); + assert.deepStrictEqual( + new Set(Object.keys(response3.result)), + new Set([ + "antiCsrfToken", + "exp", + "iat", + "parentRefreshTokenHash1", + "refreshTokenHash1", + "sessionHandle", + "sub", + "iss", + ]) + ); + //invalid session handle when updating the jwt payload let invalidSessionResponse = await this.server.inject({ method: "post", @@ -1295,4 +1330,597 @@ describe(`Hapi: ${printPath("[test/framework/hapi.test.js]")}`, function () { assert(response.statusCode === 203); assert(response.result.custom); }); + + it("test that authorization header is read correctly in dashboard recipe", async function () { + await startST(); + SuperTokens.init({ + framework: "hapi", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + ], + }); + + await this.server.register(HapiFramework.plugin); + + await this.server.initialize(); + + let res2 = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users/count", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + + assert(res2.statusCode === 200); + }); + + it("test verifySession/getSession without accessToken", async function () { + await startST(); + SuperTokens.init({ + framework: "hapi", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init({ getTokenTransferMethod: () => "cookie", antiCsrf: "VIA_TOKEN" })], + }); + + this.server.route({ + path: "/getSessionV1", + method: "get", + handler: async (req, res) => { + return res.response({}).code(200); + }, + options: { + pre: [{ method: verifySession() }], + }, + }); + + this.server.route({ + path: "/getSessionV2", + method: "get", + handler: async (req, res) => { + await Session.getSession(req, res); + return res.response({}).code(200); + }, + }); + + await this.server.register(HapiFramework.plugin); + + await this.server.initialize(); + + let response1 = await this.server.inject({ + method: "get", + url: "/getSessionV1", + }); + + assert.strictEqual(response1.statusCode, 401); + + let response2 = await this.server.inject({ + method: "get", + url: "/getSessionV2", + }); + + assert.strictEqual(response2.statusCode, 401); + }); + + it("test that tags request respond with correct tags", async function () { + await startST(); + SuperTokens.init({ + framework: "hapi", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.server.register(HapiFramework.plugin); + + await this.server.initialize(); + + await createUsers(EmailPassword); + + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/search/tags", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + assert(resp.statusCode === 200); + assert(resp.result.tags.length !== 0); + }); + + it("test that search results correct output for 'email: t'", async function () { + await startST(); + SuperTokens.init({ + framework: "hapi", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.server.register(HapiFramework.plugin); + + await this.server.initialize(); + + await createUsers(EmailPassword); + + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users?limit=10&email=t", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + assert(resp.statusCode === 200); + assert(resp.result.users.length === 5); + }); + + it("test that search results correct output for 'email: iresh'", async function () { + await startST(); + SuperTokens.init({ + framework: "hapi", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.server.register(HapiFramework.plugin); + + await this.server.initialize(); + + await createUsers(EmailPassword); + + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users?limit=10&email=iresh", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + assert(resp.statusCode === 200); + assert(resp.result.users.length === 0); + }); + it("test that search results correct output for multiple search items", async function () { + await startST(); + SuperTokens.init({ + framework: "hapi", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.server.register(HapiFramework.plugin); + + await this.server.initialize(); + + await createUsers(EmailPassword); + + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users?limit=10&email=john;iresh", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + assert(resp.statusCode === 200); + assert(resp.result.users.length === 1); + }); + + it("test that search results correct output for 'phone: +1'", async function () { + await startST(); + SuperTokens.init({ + framework: "hapi", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + Passwordless.init({ + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.server.register(HapiFramework.plugin); + + await this.server.initialize(); + + await createUsers(null, Passwordless); + + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users?limit=10&phone=%2B1", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + assert(resp.statusCode === 200); + assert(resp.result.users.length === 3); + }); + + it("test that search results correct output for 'phone: 1('", async function () { + await startST(); + SuperTokens.init({ + framework: "hapi", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + Passwordless.init({ + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.server.register(HapiFramework.plugin); + + await this.server.initialize(); + + await createUsers(null, Passwordless); + + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users?limit=10&phone=1%28", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + assert(resp.statusCode === 200); + assert(resp.result.users.length === 0); + }); + + it("test that search results correct output for 'provider: google, phone: 1'", async function () { + await startST(); + SuperTokens.init({ + framework: "hapi", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + ThirdParty.init({ + signInAndUpFeature: { + providers: [ + Google({ + clientId: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + clientSecret: "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", + }), + Github({ + clientId: "467101b197249757c71f", + clientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }), + Apple({ + clientId: "4398792-io.supertokens.example.service", + clientSecret: { + keyId: "7M48Y4RYDL", + privateKey: + "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + teamId: "YWQCXGJRJL", + }, + }), + ], + }, + }), + Passwordless.init({ + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.server.register(HapiFramework.plugin); + + await this.server.initialize(); + + await createUsers(null, Passwordless, ThirdParty); + + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users?limit=10&provider=google&phone=1", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + assert(resp.statusCode === 200); + assert(resp.result.users.length === 0); + }); + + it("test that search results correct output for 'provider: google'", async function () { + await startST(); + SuperTokens.init({ + framework: "hapi", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + ThirdParty.init({ + signInAndUpFeature: { + providers: [ + Google({ + clientId: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + clientSecret: "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", + }), + Github({ + clientId: "467101b197249757c71f", + clientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }), + Apple({ + clientId: "4398792-io.supertokens.example.service", + clientSecret: { + keyId: "7M48Y4RYDL", + privateKey: + "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + teamId: "YWQCXGJRJL", + }, + }), + ], + }, + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.server.register(HapiFramework.plugin); + + await this.server.initialize(); + + await createUsers(null, null, ThirdParty); + + let resp = await this.server.inject({ + method: "get", + url: "/auth/dashboard/api/users?limit=10&provider=google", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + assert(resp.statusCode === 200); + assert(resp.result.users.length === 3); + }); }); diff --git a/test/framework/koa.test.js b/test/framework/koa.test.js index 7a6c85c6f..c1e2f975c 100644 --- a/test/framework/koa.test.js +++ b/test/framework/koa.test.js @@ -23,6 +23,13 @@ let Koa = require("koa"); const Router = require("@koa/router"); let { verifySession } = require("../../recipe/session/framework/koa"); const request = require("supertest"); +let Dashboard = require("../../recipe/dashboard"); +const { createUsers } = require("../utils.js"); +const { Querier } = require("../../lib/build/querier"); +const { maxVersion } = require("../../lib/build/utils"); +const Passwordless = require("../../recipe/passwordless"); +const ThirdParty = require("../../recipe/thirdparty"); +const { Google, Github, Apple } = require("../../recipe/thirdparty"); describe(`Koa: ${printPath("[test/framework/koa.test.js]")}`, function () { beforeEach(async function () { @@ -1108,23 +1115,23 @@ describe(`Koa: ${printPath("[test/framework/koa.test.js]")}`, function () { }); router.post("/updateSessionData", async (ctx, _) => { let session = await Session.getSession(ctx, ctx, true); - await session.updateSessionData({ key: "value" }); + await session.updateSessionDataInDatabase({ key: "value" }); ctx.body = ""; }); router.post("/getSessionData", async (ctx, _) => { let session = await Session.getSession(ctx, ctx, true); - let sessionData = await session.getSessionData(); + let sessionData = await session.getSessionDataFromDatabase(); ctx.body = sessionData; }); router.post("/updateSessionData2", async (ctx, _) => { let session = await Session.getSession(ctx, ctx, true); - await session.updateSessionData(null); + await session.updateSessionDataInDatabase(null); ctx.body = ""; }); router.post("/updateSessionDataInvalidSessionHandle", async (ctx, _) => { - ctx.body = { success: !(await Session.updateSessionData("InvalidHandle", { key: "value3" })) }; + ctx.body = { success: !(await Session.updateSessionDataInDatabase("InvalidHandle", { key: "value3" })) }; }); app.use(router.routes()); @@ -1258,7 +1265,7 @@ describe(`Koa: ${printPath("[test/framework/koa.test.js]")}`, function () { router.post("/updateAccessTokenPayload", async (ctx, _) => { let session = await Session.getSession(ctx, ctx, true); let accessTokenBefore = session.accessToken; - await session.updateAccessTokenPayload({ key: "value" }); + await session.mergeIntoAccessTokenPayload({ key: "value" }); let accessTokenAfter = session.accessToken; let statusCode = accessTokenBefore !== accessTokenAfter && typeof accessTokenAfter === "string" ? 200 : 500; ctx.status = statusCode; @@ -1272,13 +1279,13 @@ describe(`Koa: ${printPath("[test/framework/koa.test.js]")}`, function () { router.post("/updateAccessTokenPayload2", async (ctx, _) => { let session = await Session.getSession(ctx, ctx, true); - await session.updateAccessTokenPayload(null); + await session.mergeIntoAccessTokenPayload({ key: null }); ctx.body = ""; }); router.post("/updateAccessTokenPayloadInvalidSessionHandle", async (ctx, _) => { ctx.body = { - success: !(await Session.updateAccessTokenPayload("InvalidHandle", { key: "value3" })), + success: !(await Session.mergeIntoAccessTokenPayload("InvalidHandle", { key: "value3" })), }; }); @@ -1303,7 +1310,9 @@ describe(`Koa: ${printPath("[test/framework/koa.test.js]")}`, function () { let frontendInfo = JSON.parse(new Buffer.from(response.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, {}); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 8); //call the updateAccessTokenPayload api to add jwt payload let updatedResponse = extractInfoFromResponse( @@ -1325,7 +1334,10 @@ describe(`Koa: ${printPath("[test/framework/koa.test.js]")}`, function () { frontendInfo = JSON.parse(new Buffer.from(updatedResponse.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, { key: "value" }); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.key, "value"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 9); //call the getAccessTokenPayload api to get jwt payload let response2 = await new Promise((resolve) => @@ -1365,7 +1377,10 @@ describe(`Koa: ${printPath("[test/framework/koa.test.js]")}`, function () { frontendInfo = JSON.parse(new Buffer.from(response2.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, { key: "value" }); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.key, "value"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 9); // change the value of the inserted jwt payload let updatedResponse2 = extractInfoFromResponse( @@ -1387,7 +1402,9 @@ describe(`Koa: ${printPath("[test/framework/koa.test.js]")}`, function () { frontendInfo = JSON.parse(new Buffer.from(updatedResponse2.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, {}); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 8); //retrieve the changed jwt payload response2 = await new Promise((resolve) => @@ -1406,7 +1423,19 @@ describe(`Koa: ${printPath("[test/framework/koa.test.js]")}`, function () { ); //check the value of the retrieved - assert.deepStrictEqual(response2.body, {}); + assert.deepStrictEqual( + new Set(Object.keys(response2.body)), + new Set([ + "antiCsrfToken", + "exp", + "iat", + "parentRefreshTokenHash1", + "refreshTokenHash1", + "sessionHandle", + "sub", + "iss", + ]) + ); //invalid session handle when updating the jwt payload let invalidSessionResponse = await new Promise((resolve) => request(this.server) @@ -1476,4 +1505,620 @@ describe(`Koa: ${printPath("[test/framework/koa.test.js]")}`, function () { ); assert(response.body.custom); }); + + it("test that authorization header is read correctly in dashboard recipe", async function () { + await startST(); + SuperTokens.init({ + framework: "koa", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + if (authHeader === "Bearer testapikey") { + return true; + } + + return false; + }, + }; + }, + }, + }), + ], + }); + + const app = new Koa(); + app.use(KoaFramework.middleware()); + this.server = app.listen(9999); + + let res = await new Promise((resolve) => + request(this.server) + .get("/auth/dashboard/api/users/count") + .set("Content-Type", "application/json") + .set("Authorization", "Bearer testapikey") + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + + assert(res.statusCode === 200); + }); + + it("test that tags request respond with correct tags", async function () { + await startST(); + SuperTokens.init({ + framework: "koa", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + const app = new Koa(); + app.use(KoaFramework.middleware()); + this.server = app.listen(9999); + + let res = await new Promise((resolve) => + request(this.server) + .get("/auth/dashboard/api/search/tags") + .set("Content-Type", "application/json") + .set("Authorization", "Bearer testapikey") + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + assert(res.statusCode === 200); + const tags = res.body.tags; + assert(tags.length !== 0); + }); + + it("test that search results correct output for 'email: t'", async function () { + await startST(); + SuperTokens.init({ + framework: "koa", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + const app = new Koa(); + app.use(KoaFramework.middleware()); + this.server = app.listen(9999); + + await createUsers(EmailPassword); + + let res = await new Promise((resolve) => + request(this.server) + .get("/auth/dashboard/api/users") + .query({ + email: "t", + limit: 10, + }) + .set("Content-Type", "application/json") + .set("Authorization", "Bearer testapikey") + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + assert(res.statusCode === 200); + assert(res.body.users.length === 5); + }); + + it("test that search results correct output for multiple search items", async function () { + await startST(); + SuperTokens.init({ + framework: "koa", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + const app = new Koa(); + app.use(KoaFramework.middleware()); + this.server = app.listen(9999); + + await createUsers(EmailPassword); + + let res = await new Promise((resolve) => + request(this.server) + .get("/auth/dashboard/api/users") + .query({ + email: "iresh;john", + limit: 10, + }) + .set("Content-Type", "application/json") + .set("Authorization", "Bearer testapikey") + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + assert(res.statusCode === 200); + assert(res.body.users.length === 1); + }); + + it("test that search results correct output for 'email: iresh'", async function () { + await startST(); + SuperTokens.init({ + framework: "koa", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + const app = new Koa(); + app.use(KoaFramework.middleware()); + this.server = app.listen(9999); + + await createUsers(EmailPassword); + + let res = await new Promise((resolve) => + request(this.server) + .get("/auth/dashboard/api/users") + .query({ + email: "iresh", + limit: 10, + }) + .set("Content-Type", "application/json") + .set("Authorization", "Bearer testapikey") + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + assert(res.statusCode === 200); + assert(res.body.users.length === 0); + }); + + it("test that search results correct output for 'phone: +1'", async function () { + await startST(); + SuperTokens.init({ + framework: "koa", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + Passwordless.init({ + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + const app = new Koa(); + app.use(KoaFramework.middleware()); + this.server = app.listen(9999); + + await createUsers(null, Passwordless); + + let res = await new Promise((resolve) => + request(this.server) + .get("/auth/dashboard/api/users") + .query({ + phone: "+1", + limit: 10, + }) + .set("Content-Type", "application/json") + .set("Authorization", "Bearer testapikey") + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + assert(res.statusCode === 200); + assert(res.body.users.length === 3); + }); + + it("test that search results correct output for 'phone: 1('", async function () { + await startST(); + SuperTokens.init({ + framework: "koa", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + Passwordless.init({ + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + const app = new Koa(); + app.use(KoaFramework.middleware()); + this.server = app.listen(9999); + + await createUsers(null, Passwordless); + + let res = await new Promise((resolve) => + request(this.server) + .get("/auth/dashboard/api/users") + .query({ + phone: "1(", + limit: 10, + }) + .set("Content-Type", "application/json") + .set("Authorization", "Bearer testapikey") + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + assert(res.statusCode === 200); + assert(res.body.users.length === 0); + }); + + it("test that search results correct output for 'provider: google'", async function () { + await startST(); + SuperTokens.init({ + framework: "koa", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + ThirdParty.init({ + signInAndUpFeature: { + providers: [ + Google({ + clientId: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + clientSecret: "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", + }), + Github({ + clientId: "467101b197249757c71f", + clientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }), + Apple({ + clientId: "4398792-io.supertokens.example.service", + clientSecret: { + keyId: "7M48Y4RYDL", + privateKey: + "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + teamId: "YWQCXGJRJL", + }, + }), + ], + }, + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + const app = new Koa(); + app.use(KoaFramework.middleware()); + this.server = app.listen(9999); + + await createUsers(null, null, ThirdParty); + + let res = await new Promise((resolve) => + request(this.server) + .get("/auth/dashboard/api/users") + .query({ + provider: "google", + limit: 10, + }) + .set("Content-Type", "application/json") + .set("Authorization", "Bearer testapikey") + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + assert(res.statusCode === 200); + assert(res.body.users.length === 3); + }); + + it("test that search results correct output for 'provider: google, phone: 1'", async function () { + await startST(); + SuperTokens.init({ + framework: "koa", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + ThirdParty.init({ + signInAndUpFeature: { + providers: [ + Google({ + clientId: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + clientSecret: "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", + }), + Github({ + clientId: "467101b197249757c71f", + clientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }), + Apple({ + clientId: "4398792-io.supertokens.example.service", + clientSecret: { + keyId: "7M48Y4RYDL", + privateKey: + "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + teamId: "YWQCXGJRJL", + }, + }), + ], + }, + }), + Passwordless.init({ + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + const app = new Koa(); + app.use(KoaFramework.middleware()); + this.server = app.listen(9999); + + await createUsers(null, Passwordless, ThirdParty); + + let res = await new Promise((resolve) => + request(this.server) + .get("/auth/dashboard/api/users") + .query({ + provider: "google", + phone: "1", + limit: 10, + }) + .set("Content-Type", "application/json") + .set("Authorization", "Bearer testapikey") + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + assert(res.statusCode === 200); + assert(res.body.users.length === 0); + }); }); diff --git a/test/framework/loopback.test.js b/test/framework/loopback.test.js index 784ffa375..33e819ef9 100644 --- a/test/framework/loopback.test.js +++ b/test/framework/loopback.test.js @@ -22,6 +22,13 @@ let EmailPassword = require("../../recipe/emailpassword"); let { verifySession } = require("../../recipe/session/framework/awsLambda"); const request = require("supertest"); const axios = require("axios").default; +let Dashboard = require("../../recipe/dashboard"); +const { createUsers } = require("../utils.js"); +const { Querier } = require("../../lib/build/querier"); +const { maxVersion } = require("../../lib/build/utils"); +const Passwordless = require("../../recipe/passwordless"); +const ThirdParty = require("../../recipe/thirdparty"); +const { Apple, Google, Github } = require("../../recipe/thirdparty"); describe(`Loopback: ${printPath("[test/framework/loopback.test.js]")}`, function () { beforeEach(async function () { @@ -231,4 +238,572 @@ describe(`Loopback: ${printPath("[test/framework/loopback.test.js]")}`, function assert(result.status === 203); assert(result.data.custom); }); + + it("test that authorization header is read correctly in dashboard recipe", async function () { + await startST(); + SuperTokens.init({ + framework: "loopback", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + if (authHeader === "Bearer testapikey") { + return true; + } + + return false; + }, + }; + }, + }, + }), + ], + }); + + await this.app.start(); + + let result = await axios({ + url: "/auth/dashboard/api/users/count", + baseURL: "http://localhost:9876", + method: "get", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + + assert(result.status === 200); + }); + + it("test that tags request respond with correct tags", async function () { + await startST(); + SuperTokens.init({ + framework: "loopback", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.app.start(); + + let result = await axios({ + url: "/auth/dashboard/api/search/tags", + baseURL: "http://localhost:9876", + method: "get", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + }); + + assert(result.status === 200); + assert(result.data.tags.length !== 0); + }); + + it("test that search results correct output for 'email: t'", async function () { + await startST(); + SuperTokens.init({ + framework: "loopback", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.app.start(); + + await createUsers(EmailPassword); + + let result = await axios({ + url: "/auth/dashboard/api/users", + baseURL: "http://localhost:9876", + method: "get", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + params: { + limit: 10, + email: "t", + }, + }); + assert(result.status === 200); + assert(result.data.users.length === 5); + }); + + it("test that search results correct output for multiple search items", async function () { + await startST(); + SuperTokens.init({ + framework: "loopback", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.app.start(); + + await createUsers(EmailPassword); + + let result = await axios({ + url: "/auth/dashboard/api/users", + baseURL: "http://localhost:9876", + method: "get", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + params: { + limit: 10, + email: "iresh;john", + }, + }); + + assert(result.status === 200); + assert(result.data.users.length === 1); + }); + + it("test that search results correct output for 'email: iresh'", async function () { + await startST(); + SuperTokens.init({ + framework: "loopback", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + EmailPassword.init(), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.app.start(); + + await createUsers(EmailPassword); + + let result = await axios({ + url: "/auth/dashboard/api/users", + baseURL: "http://localhost:9876", + method: "get", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + params: { + limit: 10, + email: "iresh;", + }, + }); + + assert(result.status === 200); + assert(result.data.users.length === 0); + }); + + it("test that search results correct output for 'phone: +1'", async function () { + await startST(); + SuperTokens.init({ + framework: "loopback", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + Passwordless.init({ + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.app.start(); + + await createUsers(null, Passwordless); + + let result = await axios({ + url: "/auth/dashboard/api/users", + baseURL: "http://localhost:9876", + method: "get", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + params: { + limit: 10, + phone: "+1", + }, + }); + + assert(result.status === 200); + assert(result.data.users.length === 3); + }); + + it("test that search results correct output for 'phone: 1('", async function () { + await startST(); + SuperTokens.init({ + framework: "loopback", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + Passwordless.init({ + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.app.start(); + + await createUsers(null, Passwordless); + + let result = await axios({ + url: "/auth/dashboard/api/users", + baseURL: "http://localhost:9876", + method: "get", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + params: { + limit: 10, + phone: "1(", + }, + }); + + assert(result.status === 200); + assert(result.data.users.length === 0); + }); + + it("test that search results correct output for 'provider: google', phone: 1", async function () { + await startST(); + SuperTokens.init({ + framework: "loopback", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + ThirdParty.init({ + signInAndUpFeature: { + providers: [ + Google({ + clientId: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + clientSecret: "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", + }), + Github({ + clientId: "467101b197249757c71f", + clientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }), + Apple({ + clientId: "4398792-io.supertokens.example.service", + clientSecret: { + keyId: "7M48Y4RYDL", + privateKey: + "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + teamId: "YWQCXGJRJL", + }, + }), + ], + }, + }), + Passwordless.init({ + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.app.start(); + + await createUsers(null, Passwordless, ThirdParty); + + let result = await axios({ + url: "/auth/dashboard/api/users", + baseURL: "http://localhost:9876", + method: "get", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + params: { + limit: 10, + provider: "google", + phone: "1", + }, + }); + + assert(result.status === 200); + assert(result.data.users.length === 0); + }); + + it("test that search results correct output for 'provider: google'", async function () { + await startST(); + SuperTokens.init({ + framework: "loopback", + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Dashboard.init({ + apiKey: "testapikey", + override: { + functions: (original) => { + return { + ...original, + shouldAllowAccess: async function (input) { + let authHeader = input.req.getHeaderValue("authorization"); + return authHeader === "Bearer testapikey"; + }, + }; + }, + }, + }), + ThirdParty.init({ + signInAndUpFeature: { + providers: [ + Google({ + clientId: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + clientSecret: "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", + }), + Github({ + clientId: "467101b197249757c71f", + clientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }), + Apple({ + clientId: "4398792-io.supertokens.example.service", + clientSecret: { + keyId: "7M48Y4RYDL", + privateKey: + "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + teamId: "YWQCXGJRJL", + }, + }), + ], + }, + }), + ], + }); + + let querier = Querier.getNewInstanceOrThrowError(undefined); + let apiVersion = await querier.getAPIVersion(); + if (maxVersion(apiVersion, "2.19") === "2.19") { + return this.skip(); + } + + await this.app.start(); + + await createUsers(null, null, ThirdParty); + + let result = await axios({ + url: "/auth/dashboard/api/users", + baseURL: "http://localhost:9876", + method: "get", + headers: { + Authorization: "Bearer testapikey", + "Content-Type": "application/json", + }, + params: { + limit: 10, + provider: "google", + }, + }); + + assert(result.status === 200); + assert(result.data.users.length === 3); + }); }); diff --git a/test/frontendIntegration/index.js b/test/frontendIntegration/index.js index f913a2c0c..d4ff0f4dd 100644 --- a/test/frontendIntegration/index.js +++ b/test/frontendIntegration/index.js @@ -16,6 +16,7 @@ let SuperTokens = require("../../"); let Session = require("../../recipe/session"); let SuperTokensRaw = require("../../lib/build/supertokens").default; let SessionRecipeRaw = require("../../lib/build/recipe/session/recipe").default; +let DashboardRecipeRaw = require("../../lib/build/recipe/dashboard/recipe").default; let express = require("express"); let cookieParser = require("cookie-parser"); let bodyParser = require("body-parser"); @@ -25,6 +26,8 @@ let noOfTimesGetSessionCalledDuringTest = 0; let noOfTimesRefreshAttemptedDuringTest = 0; let { verifySession } = require("../../recipe/session/framework/express"); let { middleware, errorHandler } = require("../../framework/express"); +const { Querier } = require("../../lib/build/querier"); +const { default: NormalisedURLPath } = require("../../lib/build/normalisedURLPath"); let supertokens_node_version = require("../../lib/build/version").version; let urlencodedParser = bodyParser.urlencoded({ limit: "20mb", extended: true, parameterLimit: 20000 }); @@ -58,6 +61,53 @@ const maxVersion = function (version1, version2) { }; function getConfig(enableAntiCsrf, enableJWT, jwtPropertyName) { + if (enableJWT && maxVersion(supertokens_node_version, "14.0") === supertokens_node_version) { + return { + appInfo: { + appName: "SuperTokens", + apiDomain: "0.0.0.0:" + (process.env.NODE_PORT === undefined ? 8080 : process.env.NODE_PORT), + websiteDomain: "http://localhost.org:8080", + }, + supertokens: { + connectionURI: "http://localhost:9000", + }, + recipeList: [ + Session.init({ + getTokenTransferMethod: process.env.TRANSFER_METHOD ? () => process.env.TRANSFER_METHOD : undefined, + exposeAccessTokenToFrontendInCookieBasedAuth: true, + errorHandlers: { + onUnauthorised: (err, req, res) => { + res.setStatusCode(401); + res.sendJSONResponse({}); + }, + }, + antiCsrf: enableAntiCsrf ? "VIA_TOKEN" : "NONE", + override: { + apis: (oI) => { + return { + ...oI, + refreshPOST: undefined, + }; + }, + functions: function (oI) { + return { + ...oI, + createNewSession: async function (input) { + input.accessTokenPayload = { + ...input.accessTokenPayload, + customClaim: "customValue", + }; + + return await oI.createNewSession(input); + }, + }; + }, + }, + }), + ], + }; + } + if (maxVersion(supertokens_node_version, "8.3.0") === supertokens_node_version && enableJWT) { return { appInfo: { @@ -92,25 +142,13 @@ function getConfig(enableAntiCsrf, enableJWT, jwtPropertyName) { functions: function (oI) { return { ...oI, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { + createNewSession: async function (input) { + input.accessTokenPayload = { ...accessTokenPayload, customClaim: "customValue", }; - return await oI.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); + return await oI.createNewSession(input); }, }; }, @@ -175,6 +213,7 @@ app.post("/setAntiCsrf", async (req, res) => { if (enableAntiCsrf !== undefined) { SuperTokensRaw.reset(); SessionRecipeRaw.reset(); + DashboardRecipeRaw.reset(); SuperTokens.init(getConfig(enableAntiCsrf)); } res.send("success"); @@ -187,6 +226,7 @@ app.post("/setEnableJWT", async (req, res) => { if (enableJWT !== undefined) { SuperTokensRaw.reset(); SessionRecipeRaw.reset(); + DashboardRecipeRaw.reset(); SuperTokens.init(getConfig(lastSetEnableAntiCSRF, enableJWT)); } res.send("success"); @@ -199,6 +239,7 @@ app.get("/featureFlags", async (req, res) => { sessionJwt: maxVersion(supertokens_node_version, "8.3") === supertokens_node_version && currentEnableJWT === true, sessionClaims: maxVersion(supertokens_node_version, "12.0") === supertokens_node_version, + v3AccessToken: maxVersion(supertokens_node_version, "14.0") === supertokens_node_version, }); }); @@ -208,6 +249,7 @@ app.post("/reinitialiseBackendConfig", async (req, res) => { SuperTokensRaw.reset(); SessionRecipeRaw.reset(); + DashboardRecipeRaw.reset(); SuperTokens.init(getConfig(lastSetEnableAntiCSRF, currentEnableJWT, jwtPropertyName)); res.send(""); @@ -219,6 +261,41 @@ app.post("/login", async (req, res) => { res.send(session.getUserId()); }); +app.post("/login-2.18", async (req, res) => { + // This CDI version is no longer supported by this SDK, but we want to ensure that sessions keep working after the upgrade + // We can hard-code the structure of the request&response, since this is a fixed CDI version and it's not going to change + Querier.apiVersion = "2.18"; + const payload = req.body.payload || {}; + const userId = req.body.userId; + const legacySessionResp = await Querier.getNewInstanceOrThrowError().sendPostRequest( + new NormalisedURLPath("/recipe/session"), + { + userId, + enableAntiCsrf: false, + userDataInJWT: payload, + userDataInDatabase: {}, + } + ); + Querier.apiVersion = undefined; + + const legacyAccessToken = legacySessionResp.accessToken.token; + const legacyRefreshToken = legacySessionResp.refreshToken.token; + + res.set("st-access-token", legacyAccessToken) + .set("st-refresh-token", legacyRefreshToken) + .set( + "front-token", + Buffer.from( + JSON.stringify({ + uid: userId, + ate: Date.now() + 3600000, + up: payload, + }) + ).toString("base64") + ) + .send(); +}); + app.post("/beforeeach", async (req, res) => { noOfTimesRefreshCalledDuringTest = 0; noOfTimesGetSessionCalledDuringTest = 0; @@ -268,7 +345,13 @@ app.post( "/update-jwt", (req, res, next) => verifySession()(req, res, next), async (req, res) => { - await req.session.updateAccessTokenPayload(req.body); + let clearing = {}; + for (const key of Object.keys(req.session.getAccessTokenPayload())) { + if (!isProtectedPropName(key)) { + clearing[key] = null; + } + } + await req.session.mergeIntoAccessTokenPayload({ ...clearing, ...req.body }); res.json(req.session.getAccessTokenPayload()); } ); @@ -392,7 +475,14 @@ app.post( "/update-jwt-with-handle", (req, res, next) => verifySession()(req, res, next), async (req, res) => { - await Session.updateAccessTokenPayload(req.session.getHandle(), req.body); + const info = await Session.getSessionInformation(req.session.getHandle()); + let clearing = {}; + + for (const key of Object.keys(info.customClaimsInAccessTokenPayload)) { + clearing[key] = null; + } + + await Session.mergeIntoAccessTokenPayload(req.session.getHandle(), { ...clearing, ...req.body }); res.json(req.session.getAccessTokenPayload()); } ); @@ -410,3 +500,15 @@ app.use(async (err, req, res, next) => { app.listen(process.env.NODE_PORT === undefined ? 8080 : process.env.NODE_PORT, "0.0.0.0", () => { console.log("app started"); }); + +isProtectedPropName = function (name) { + return [ + "sub", + "iat", + "exp", + "sessionHandle", + "parentRefreshTokenHash1", + "refreshTokenHash1", + "antiCsrfToken", + ].includes(name); +}; diff --git a/test/handshake.test.js b/test/handshake.test.js deleted file mode 100644 index bf9db8e5a..000000000 --- a/test/handshake.test.js +++ /dev/null @@ -1,151 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ -const { printPath, setupST, startST, killAllST, cleanST } = require("./utils"); -let ST = require("../"); -let Session = require("../recipe/session"); -let SessionRecipe = require("../lib/build/recipe/session/recipe").default; -let assert = require("assert"); -let { ProcessState, PROCESS_STATE } = require("../lib/build/processState"); -const { maxVersion } = require("../lib/build/utils"); - -describe(`Handshake: ${printPath("[test/handshake.test.js]")}`, function () { - beforeEach(async function () { - await killAllST(); - await setupST(); - ProcessState.getInstance().reset(); - }); - - after(async function () { - await killAllST(); - await cleanST(); - }); - - // test that once the info is loaded, it doesn't query again - it("test that once the info is loaded, it doesn't querry again", async function () { - await startST(); - ST.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [Session.init({ getTokenTransferMethod: () => "cookie" })], - }); - - let sessionRecipeInstance = SessionRecipe.getInstanceOrThrowError(); - await sessionRecipeInstance.recipeInterfaceImpl.getHandshakeInfo(); - let verifyState = await ProcessState.getInstance().waitForEvent( - PROCESS_STATE.CALLING_SERVICE_IN_GET_HANDSHAKE_INFO, - 2000 - ); - assert(verifyState !== undefined); - - ProcessState.getInstance().reset(); - - await sessionRecipeInstance.recipeInterfaceImpl.getHandshakeInfo(); - verifyState = await ProcessState.getInstance().waitForEvent( - PROCESS_STATE.CALLING_SERVICE_IN_GET_HANDSHAKE_INFO, - 2000 - ); - assert(verifyState === undefined); - }); - - it("core not available", async function () { - ST.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [Session.init({ getTokenTransferMethod: () => "cookie" })], - }); - try { - await Session.revokeSession(""); - throw new Error("should not have come here"); - } catch (err) { - if (err.message !== "No SuperTokens core available to query") { - throw err; - } - } - }); - - it("successful handshake and update JWT without keyList", async function () { - await startST(); - ST.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [Session.init({ getTokenTransferMethod: () => "cookie" })], - }); - let info = await SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.getHandshakeInfo(); - assert(info.getJwtSigningPublicKeyList() instanceof Array); - assert.equal(info.getJwtSigningPublicKeyList().length, 1); - assert.strictEqual(info.antiCsrf, "NONE"); - assert.equal(info.accessTokenBlacklistingEnabled, false); - assert.equal(info.accessTokenValidity, 3600 * 1000); - assert.equal(info.refreshTokenValidity, 144000 * 60 * 1000); - SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.updateJwtSigningPublicKeyInfo( - undefined, - "hello", - Date.now() + 1000 - ); - let info2 = await SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.getHandshakeInfo(); - assert.equal(info2.getJwtSigningPublicKeyList().length, 1); - assert.equal(info2.getJwtSigningPublicKeyList()[0].publicKey, "hello"); - assert(info2.getJwtSigningPublicKeyList()[0].expiryTime <= Date.now() + 1000); - assert(info2.getJwtSigningPublicKeyList()[0].createdAt >= Date.now() - 1000); - }); - - it("successful handshake and update JWT with keyList", async function () { - await startST(); - ST.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [Session.init({ getTokenTransferMethod: () => "cookie" })], - }); - let info = await SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.getHandshakeInfo(); - assert(info.getJwtSigningPublicKeyList() instanceof Array); - assert.equal(info.getJwtSigningPublicKeyList().length, 1); - assert.strictEqual(info.antiCsrf, "NONE"); - assert.equal(info.accessTokenBlacklistingEnabled, false); - assert.equal(info.accessTokenValidity, 3600 * 1000); - assert.equal(info.refreshTokenValidity, 144000 * 60 * 1000); - const expiryTime = Date.now() + 1000; - SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.updateJwtSigningPublicKeyInfo( - [{ publicKey: "hello2", expiryTime }], - "hello2", - expiryTime - ); - let info2 = await SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.getHandshakeInfo(); - assert.deepStrictEqual(info2.getJwtSigningPublicKeyList(), [{ publicKey: "hello2", expiryTime }]); - }); -}); diff --git a/test/import.test.js b/test/import.test.js new file mode 100644 index 000000000..cc1997f92 --- /dev/null +++ b/test/import.test.js @@ -0,0 +1,43 @@ +const { printPath, getAllFilesInDirectory } = require("./utils"); +const { resolve } = require("path"); +const { writeFileSync, rmSync } = require("fs"); +const { existsSync } = require("fs"); +const { execSync } = require("child_process"); + +const testFileName = "importtest.js"; +const testFilePath = resolve(process.cwd(), `./${testFileName}`); + +describe(`importTests: ${printPath("[test/import.test.js]")}`, function () { + after(function () { + // The exists check is just a precaution + if (existsSync(testFilePath)) { + rmSync(testFilePath); + } + }); + + /** + * This test does the following: + * 1. Gets a list of all files in the build folder recursively + * 2. For each build file, creates a simple js file that imports the build file + * 3. Runs the generated js file + * + * The test fails if there is any error thrown when trying to run any of the generated files. + * + * This is to prevent issues arising from circular imports where certain variables from the + * default exports for recipes are not intialised correctly. + * (Refer to: https://github.com/supertokens/supertokens-node/issues/513) + */ + it("Test that importing all build files independently does not cause errors", function () { + const fileNames = getAllFilesInDirectory(resolve(process.cwd(), "./lib/build")).filter( + (i) => !i.endsWith(".d.ts") + ); + + fileNames.forEach((fileName) => { + const relativeFilePath = fileName.replace(process.cwd(), ""); + writeFileSync(testFilePath, `require(".${relativeFilePath}")`); + + // This will throw an error if the command fails + execSync(`node ${resolve(process.cwd(), `./${testFileName}`)}`); + }); + }); +}); diff --git a/test/jwt/override.test.js b/test/jwt/override.test.js index c98279a82..1c00f3c31 100644 --- a/test/jwt/override.test.js +++ b/test/jwt/override.test.js @@ -55,9 +55,7 @@ describe(`overrideTest: ${printPath("[test/jwt/override.test.js]")}`, function ( getJWKS: async () => { let getJWKSResponse = await originalImplementation.getJWKS(); - if (getJWKSResponse.status === "OK") { - jwksKeys = getJWKSResponse.keys; - } + jwksKeys = getJWKSResponse.keys; return getJWKSResponse; }, diff --git a/test/middleware.test.js b/test/middleware.test.js index c85d52491..0a1479b0e 100644 --- a/test/middleware.test.js +++ b/test/middleware.test.js @@ -1372,7 +1372,6 @@ describe(`middleware: ${printPath("[test/middleware.test.js]")}`, function () { // https://github.com/supertokens/supertokens-node/pull/108 // A session exists, is refreshed, then is revoked, and then we try and use the access token (after first refresh), and we see that unauthorised error is called. it("test session verify middleware with old access token and session required false", async function () { - await setKeyValueInConfig("access_token_blacklisting", true); await startST(); SuperTokens.init({ @@ -1427,6 +1426,17 @@ describe(`middleware: ${printPath("[test/middleware.test.js]")}`, function () { } ); + app.get( + "/custom/user/handle-with-blacklisting", + verifySession({ + sessionRequired: false, + checkDatabase: true, + }), + async (req, res) => { + res.status(200).json({ message: req.session !== undefined }); + } + ); + app.post("/custom/logout", verifySession(), async (req, res) => { await req.session.revokeSession(); res.status(200).json({ message: true }); @@ -1559,18 +1569,18 @@ describe(`middleware: ${printPath("[test/middleware.test.js]")}`, function () { let r2 = await new Promise((resolve) => request(app) - .get("/custom/user/handle") + .get("/custom/user/handle-with-blacklisting") .set("Cookie", ["sAccessToken=" + res1.accessToken]) .expect(401) .end((err, res) => { if (err) { - resolve(undefined); + resolve(err); } else { resolve(res.body.message); } }) ); - assert(r2 === "unauthorised"); + assert.strictEqual(r2, "unauthorised"); }); // https://github.com/supertokens/supertokens-node/pull/108 @@ -1639,7 +1649,7 @@ describe(`middleware: ${printPath("[test/middleware.test.js]")}`, function () { }); it("test session verify middleware without error handler added", async function () { - await setKeyValueInConfig("access_token_validity", 2); + await setKeyValueInConfig("access_token_validity", 5); await startST(); SuperTokens.init({ supertokens: { diff --git a/test/nextjs.test.js b/test/nextjs.test.js index de7a885cb..e5188c1e8 100644 --- a/test/nextjs.test.js +++ b/test/nextjs.test.js @@ -15,17 +15,55 @@ const { printPath, setupST, startST, killAllST, cleanST } = require("./utils"); let assert = require("assert"); -const httpMocks = require("node-mocks-http"); let { ProcessState } = require("../lib/build/processState"); let SuperTokens = require("../lib/build/").default; let { middleware } = require("../framework/express"); const Session = require("../lib/build/recipe/session"); const EmailPassword = require("../lib/build/recipe/emailpassword"); const ThirdPartyEmailPassword = require("../lib/build/recipe/thirdpartyemailpassword"); -const superTokensMiddleware = require("../lib/build/nextjs").superTokensMiddleware; const superTokensNextWrapper = require("../lib/build/nextjs").superTokensNextWrapper; -let { verifySession } = require("../recipe/session/framework/express"); -let queryString = require("querystring"); +const { verifySession } = require("../recipe/session/framework/express"); +const { testApiHandler } = require("next-test-api-route-handler"); + +let wrapperErr; + +async function nextApiHandlerWithMiddleware(req, res) { + try { + await superTokensNextWrapper( + async (next) => { + await middleware()(req, res, next); + }, + req, + res + ); + } catch (err) { + wrapperErr = err; + throw err; + } + if (!res.writableEnded) { + res.status(404).send("Not found"); + } +} + +async function nextApiHandlerWithVerifySession(req, res) { + await superTokensNextWrapper( + async (next) => { + await verifySession()(req, res, next); + + if (req.session) { + res.status(200).send({ + status: "OK", + userId: req.session.getUserId(), + }); + } + }, + req, + res + ); + if (!res.writableEnded) { + res.status(404).send("Not found"); + } +} describe(`NextJS Middleware Test: ${printPath("[test/nextjs.test.js]")}`, function () { describe("with superTokensNextWrapper", function () { @@ -48,15 +86,14 @@ describe(`NextJS Middleware Test: ${printPath("[test/nextjs.test.js]")}`, functi recipeList: [ EmailPassword.init(), Session.init({ - getTokenTransferMethod: () => "cookie", override: { functions: (oI) => { return { ...oI, createNewSession: async (input) => { - let response = await oI.createNewSession(input); - process.env.user = response.getUserId(); - return response; + let session = await oI.createNewSession(input); + process.env.user = session.getUserId(); + return session; }, }; }, @@ -71,339 +108,295 @@ describe(`NextJS Middleware Test: ${printPath("[test/nextjs.test.js]")}`, functi await cleanST(); }); - it("Sign Up", function (done) { - const request = httpMocks.createRequest({ - method: "POST", - headers: { - rid: "emailpassword", - }, + it("Sign Up", async function () { + await testApiHandler({ + handler: nextApiHandlerWithMiddleware, url: "/api/auth/signup/", - body: { - formFields: [ - { - id: "email", - value: "john.doe@supertokens.io", - }, - { - id: "password", - value: "P@sSW0rd", + test: async ({ fetch }) => { + const res = await fetch({ + method: "POST", + headers: { + rid: "emailpassword", }, - ], + body: JSON.stringify({ + formFields: [ + { + id: "email", + value: "john.doe@supertokens.io", + }, + { + id: "password", + value: "P@sSW0rd", + }, + ], + }), + }); + const respJson = await res.json(); + assert.deepStrictEqual(respJson.status, "OK"); + assert.deepStrictEqual(respJson.user.email, "john.doe@supertokens.io"); + assert.strictEqual(respJson.user.id, process.env.user); + assert.notStrictEqual(res.headers.get("front-token"), undefined); + const tokens = getSessionTokensFromResponse(res); + assert.notEqual(tokens.access, undefined); + assert.notEqual(tokens.refresh, undefined); }, }); - - const response = httpMocks.createResponse({ - eventEmitter: require("events").EventEmitter, - }); - - response.on("end", () => { - assert.deepStrictEqual(response._getJSONData().status, "OK"); - assert.deepStrictEqual(response._getJSONData().user.email, "john.doe@supertokens.io"); - assert.strictEqual(response._getJSONData().user.id, process.env.user); - assert(response._getHeaders()["front-token"] !== undefined); - assert(response._getHeaders()["set-cookie"][0].startsWith("sAccessToken=")); - assert(response._getHeaders()["set-cookie"][1].startsWith("sRefreshToken=")); - return done(); - }); - - superTokensNextWrapper( - async (next) => { - return middleware()(request, response, next); - }, - request, - response - ); }); - it("Sign In", function (done) { - const loginRequest = httpMocks.createRequest({ - method: "POST", - headers: { - rid: "emailpassword", - }, + it("Sign In", async function () { + let tokens; + await testApiHandler({ + handler: nextApiHandlerWithMiddleware, url: "/api/auth/signin/", - body: { - formFields: [ - { - id: "email", - value: "john.doe@supertokens.io", + test: async ({ fetch }) => { + const res = await fetch({ + method: "POST", + headers: { + rid: "emailpassword", + }, + body: JSON.stringify({ + formFields: [ + { + id: "email", + value: "john.doe@supertokens.io", + }, + { + id: "password", + value: "P@sSW0rd", + }, + ], + }), + }); + const respJson = await res.json(); + + assert.deepStrictEqual(respJson.status, "OK"); + assert.deepStrictEqual(respJson.user.email, "john.doe@supertokens.io"); + assert(res.headers.get("front-token") !== undefined); + tokens = getSessionTokensFromResponse(res); + assert.notEqual(tokens.access, undefined); + assert.notEqual(tokens.refresh, undefined); + }, + }); + // Verify if session exists next middleware tests: + + assert.notStrictEqual(tokens, undefined); + + // Case 1: Successful => add session to request object. + await testApiHandler({ + handler: nextApiHandlerWithVerifySession, + url: "/api/user/", + test: async ({ fetch }) => { + const res = await fetch({ + method: "POST", + headers: { + rid: "emailpassword", }, - { - id: "password", - value: "P@sSW0rd", + headers: { + authorization: `Bearer ${tokens.access}`, }, - ], + body: JSON.stringify({ + formFields: [ + { + id: "email", + value: "john.doe@supertokens.io", + }, + { + id: "password", + value: "P@sSW0rd", + }, + ], + }), + }); + assert.strictEqual(res.status, 200); + const respJson = await res.json(); + assert.strictEqual(respJson.status, "OK"); + assert.strictEqual(respJson.userId, process.env.user); + }, + }); + + // Case 2: Unauthenticated => return 401. + await testApiHandler({ + handler: nextApiHandlerWithVerifySession, + url: "/api/user/", + test: async ({ fetch }) => { + const res = await fetch({ + method: "POST", + headers: { + rid: "emailpassword", + }, + headers: {}, + body: JSON.stringify({ + formFields: [ + { + id: "email", + value: "john.doe@supertokens.io", + }, + { + id: "password", + value: "P@sSW0rd", + }, + ], + }), + }); + assert.strictEqual(res.status, 401); + const respJson = await res.json(); + assert.strictEqual(respJson.message, "unauthorised"); }, }); - - const loginResponse = httpMocks.createResponse({ - eventEmitter: require("events").EventEmitter, - }); - - loginResponse.on("end", async () => { - assert.deepStrictEqual(loginResponse._getJSONData().status, "OK"); - assert.deepStrictEqual(loginResponse._getJSONData().user.email, "john.doe@supertokens.io"); - assert(loginResponse._getHeaders()["front-token"] !== undefined); - assert(loginResponse._getHeaders()["set-cookie"][0].startsWith("sAccessToken=") !== undefined); - assert(loginResponse._getHeaders()["set-cookie"][1].startsWith("sRefreshToken=") !== undefined); - - // Verify if session exists next middleware tests: - - // Case 1: Successful => add session to request object. - const getUserRequestWithSession = httpMocks.createRequest({ - method: "GET", - cookies: getSessionCookiesFromResponse(loginResponse), - url: "/api/user/", - }); - const getUserResponseWithSession = httpMocks.createResponse({}); - - await superTokensNextWrapper( - (next) => { - return verifySession()(getUserRequestWithSession, getUserResponseWithSession, next); - }, - getUserRequestWithSession, - getUserResponseWithSession - ); - - assert(getUserRequestWithSession.session !== undefined); - - // Case 2: Unauthenticated => return 401. - const getUserRequestWithoutSession = httpMocks.createRequest({ - method: "GET", - url: "/api/user/", - }); - - const getUserResponseWithoutSession = httpMocks.createResponse({ - eventEmitter: require("events").EventEmitter, - }); - - getUserResponseWithoutSession.on("end", () => { - assert.strictEqual(getUserResponseWithoutSession.statusCode, 401); - return done(); - }); - - superTokensNextWrapper( - (next) => { - return verifySession()(getUserRequestWithoutSession, getUserResponseWithoutSession, next); - }, - getUserRequestWithoutSession, - getUserResponseWithoutSession - ); - }); - - superTokensNextWrapper( - async (next) => { - return middleware()(loginRequest, loginResponse, next); - }, - loginRequest, - loginResponse - ); }); - it("Reset Password - Send Email", function (done) { - const request = httpMocks.createRequest({ - method: "POST", - headers: { - rid: "emailpassword", - }, + it("Reset Password - Send Email", async function () { + await testApiHandler({ + handler: nextApiHandlerWithMiddleware, url: "/api/auth/user/password/reset/token", - body: { - formFields: [ - { - id: "email", - value: "john.doe@supertokens.io", + test: async ({ fetch }) => { + const res = await fetch({ + method: "POST", + headers: { + rid: "emailpassword", }, - ], - }, - }); - - const response = httpMocks.createResponse({ - eventEmitter: require("events").EventEmitter, - }); + body: JSON.stringify({ + formFields: [ + { + id: "email", + value: "john.doe@supertokens.io", + }, + ], + }), + }); + const respJson = await res.json(); - response.on("end", () => { - assert.deepStrictEqual(response._getJSONData().status, "OK"); - return done(); - }); - - superTokensNextWrapper( - async (next) => { - return middleware()(request, response, next); + assert.deepStrictEqual(respJson.status, "OK"); }, - request, - response - ); + }); }); - it("Reset Password - Create new password", function (done) { - const request = httpMocks.createRequest({ - method: "POST", - headers: { - rid: "emailpassword", - }, + it("Reset Password - Create new password", async function () { + await testApiHandler({ + handler: nextApiHandlerWithMiddleware, url: "/api/auth/user/password/reset/", - body: { - formFields: [ - { - id: "password", - value: "NewP@sSW0rd", + test: async ({ fetch }) => { + const res = await fetch({ + method: "POST", + headers: { + rid: "emailpassword", }, - ], - token: "RandomToken", - }, - }); - - const response = httpMocks.createResponse({ - eventEmitter: require("events").EventEmitter, - }); + body: JSON.stringify({ + formFields: [ + { + id: "password", + value: "NewP@sSW0rd", + }, + ], + token: "RandomToken", + }), + }); + const respJson = await res.json(); - response.on("end", () => { - assert.deepStrictEqual(response._getJSONData().status, "RESET_PASSWORD_INVALID_TOKEN_ERROR"); - return done(); - }); - - superTokensNextWrapper( - async (next) => { - return middleware()(request, response, next); + assert.deepStrictEqual(respJson.status, "RESET_PASSWORD_INVALID_TOKEN_ERROR"); }, - request, - response - ); + }); }); - it("does Email Exist with existing email", function (done) { - const request = httpMocks.createRequest({ - method: "GET", - headers: { - rid: "emailpassword", - }, + it("does Email Exist with existing email", async function () { + await testApiHandler({ + handler: nextApiHandlerWithMiddleware, url: "/api/auth/signup/email/exists", - query: { + params: { email: "john.doe@supertokens.io", }, - }); - - const response = httpMocks.createResponse({ - eventEmitter: require("events").EventEmitter, - }); - - response.on("end", () => { - assert.deepStrictEqual(response._getJSONData(), { status: "OK", exists: true }); - return done(); - }); + test: async ({ fetch }) => { + const res = await fetch({ + method: "GET", + headers: { + rid: "emailpassword", + }, + }); + const respJson = await res.json(); - superTokensNextWrapper( - async (next) => { - return middleware()(request, response, next); + assert.deepStrictEqual(respJson, { status: "OK", exists: true }); }, - request, - response - ); + }); }); - it("does Email Exist with unknown email", function (done) { - const request = httpMocks.createRequest({ - method: "GET", - headers: { - rid: "emailpassword", - }, + it("does Email Exist with unknown email", async function () { + await testApiHandler({ + handler: nextApiHandlerWithMiddleware, url: "/api/auth/signup/email/exists", - query: { + params: { email: "unknown@supertokens.io", }, - }); - - const response = httpMocks.createResponse({ - eventEmitter: require("events").EventEmitter, - }); - - response.on("end", () => { - assert.deepStrictEqual(response._getJSONData().exists, false); - return done(); - }); + test: async ({ fetch }) => { + const res = await fetch({ + method: "GET", + headers: { + rid: "emailpassword", + }, + }); + const respJson = await res.json(); - superTokensNextWrapper( - async (next) => { - return middleware()(request, response, next); + assert.deepStrictEqual(respJson, { status: "OK", exists: false }); }, - request, - response - ); - }); - - it("Verify session successfully when session is present", function (done) { - const request = httpMocks.createRequest({ - method: "GET", - url: "/api/auth/user/info", - }); - - const response = httpMocks.createResponse({ - eventEmitter: require("events").EventEmitter, }); - - response.on("end", () => { - assert.deepStrictEqual(response._getStatusCode(), 401); - return done(); - }); - - superTokensNextWrapper( - async (next) => { - return await verifySession()(request, response, next); - }, - request, - response - ); }); it("Verify session successfully when session is present (check if it continues after)", function (done) { - const request = httpMocks.createRequest({ - method: "GET", + testApiHandler({ + handler: async (request, response) => { + await superTokensNextWrapper( + async (next) => { + await verifySession()(request, response, next); + }, + request, + response + ).then(() => { + return done(new Error("not come here")); + }); + }, url: "/api/auth/user/info", - }); - - const response = httpMocks.createResponse({ - eventEmitter: require("events").EventEmitter, - }); - - response.on("end", () => { - try { - assert.deepStrictEqual(response._getStatusCode(), 401); - return done(); - } catch (err) { - return done(err); - } - }); - - superTokensNextWrapper( - async (next) => { - return await verifySession()(request, response, next); + test: async ({ fetch }) => { + const res = await fetch({ + method: "GET", + headers: { + rid: "emailpassword", + }, + query: { + email: "john.doe@supertokens.io", + }, + }); + assert.strictEqual(res.status, 401); + done(); }, - request, - response - ).then(() => { - return done(new Error("not come here")); }); }); it("Create new session", async function () { - const request = httpMocks.createRequest({ - method: "GET", - url: "/anything", - }); - - const response = httpMocks.createResponse({ - eventEmitter: require("events").EventEmitter, - }); - - const session = await superTokensNextWrapper( - async () => { - return await Session.createNewSession(request, response, "1", {}, {}); + await testApiHandler({ + handler: async (request, response) => { + const session = await superTokensNextWrapper( + async () => { + return await Session.createNewSession(request, response, "1", {}, {}); + }, + request, + response + ); + response.status(200).send({ + status: "OK", + userId: session.getUserId(), + }); }, - request, - response - ); - assert.notDeepStrictEqual(session, undefined); - assert.deepStrictEqual(session.userId, "1"); + url: "/api/auth/user/info", + test: async ({ fetch }) => { + const res = await fetch({ + method: "GET", + }); + assert.strictEqual(res.status, 200); + assert.deepStrictEqual(await res.json(), { + status: "OK", + userId: "1", + }); + }, + }); }); }); @@ -442,26 +435,20 @@ describe(`NextJS Middleware Test: ${printPath("[test/nextjs.test.js]")}`, functi }), ThirdPartyEmailPassword.init({ providers: [ - ThirdPartyEmailPassword.Google({ - clientId: "", - clientSecret: "", + ThirdPartyEmailPassword.Apple({ + isDefault: true, + clientId: "4398792-io.supertokens.example.service", + clientSecret: { + keyId: "7M48Y4RYDL", + privateKey: + "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + teamId: "YWQCXGJRJL", + }, }), ], }), Session.init({ getTokenTransferMethod: () => "cookie", - override: { - functions: (oI) => { - return { - ...oI, - createNewSession: async (input) => { - let response = await oI.createNewSession(input); - process.env.user = response.getUserId(); - return response; - }, - }; - }, - }, }), ], }); @@ -472,74 +459,52 @@ describe(`NextJS Middleware Test: ${printPath("[test/nextjs.test.js]")}`, functi await cleanST(); }); - it("testing __supertokensFromNextJS flag", function (done) { - const request = httpMocks.createRequest({ - method: "POST", - headers: { - rid: "emailpassword", - }, + it("testing __supertokensFromNextJS flag", async function () { + await testApiHandler({ + handler: nextApiHandlerWithMiddleware, url: "/api/auth/user/password/reset", - body: { - token: "hello", - formFields: [ - { - id: "password", - value: "NewP@sSW0rd", + test: async ({ fetch }) => { + const res = await fetch({ + method: "POST", + headers: { + rid: "emailpassword", }, - ], + body: JSON.stringify({ + token: "hello", + formFields: [ + { + id: "password", + value: "NewP@sSW0rd", + }, + ], + }), + }); + const resJson = await res.json(); + + assert.deepStrictEqual(resJson.status, "CUSTOM_RESPONSE"); + assert.deepStrictEqual(resJson.nextJS, true); }, }); - - const response = httpMocks.createResponse({ - eventEmitter: require("events").EventEmitter, - }); - - response.on("end", () => { - assert.deepStrictEqual(response._getJSONData().status, "CUSTOM_RESPONSE"); - assert.deepStrictEqual(response._getJSONData().nextJS, true); - return done(); - }); - - superTokensNextWrapper( - async (next) => { - return middleware()(request, response, next); - }, - request, - response - ); }); - it("testing __supertokensFromNextJS flag, apple redirect", function (done) { - const request = httpMocks.createRequest({ - method: "POST", - headers: { - rid: "thirdpartyemailpassword", - "content-type": "application/x-www-form-urlencoded", - }, + it("testing __supertokensFromNextJS flag, apple redirect", async () => { + await testApiHandler({ + handler: nextApiHandlerWithMiddleware, url: "/api/auth/callback/apple", - body: { - state: "hello", - code: "testing", + test: async ({ fetch }) => { + const res = await fetch({ + method: "POST", + headers: { + rid: "thirdpartyemailpassword", + "content-type": "application/x-www-form-urlencoded", + }, + body: "state=hello&code=testing", + }); + let expected = ``; + const respText = await res.text(); + assert.strictEqual(respText, expected); }, }); - - const response = httpMocks.createResponse({ - eventEmitter: require("events").EventEmitter, - }); - - response.on("end", () => { - let expected = ``; - assert.deepStrictEqual(Buffer.from(response._getData()).toString(), expected); - return done(); - }); - - superTokensNextWrapper( - async (next) => { - return middleware()(request, response, next); - }, - request, - response - ); }); }); @@ -569,8 +534,8 @@ describe(`NextJS Middleware Test: ${printPath("[test/nextjs.test.js]")}`, functi return { ...oI, createNewSession: async (input) => { - let response = await oI.createNewSession(input); - process.env.user = response.getUserId(); + let session = await oI.createNewSession(input); + process.env.user = session.getUserId(); throw { error: "sign up error", }; @@ -589,53 +554,41 @@ describe(`NextJS Middleware Test: ${printPath("[test/nextjs.test.js]")}`, functi }); it("Sign Up", async function () { - const request = httpMocks.createRequest({ - method: "POST", - headers: { - rid: "emailpassword", - }, + await testApiHandler({ + handler: nextApiHandlerWithMiddleware, url: "/api/auth/signup/", - body: { - formFields: [ - { - id: "email", - value: "john.doe@supertokens.io", + test: async ({ fetch }) => { + const res = await fetch({ + method: "POST", + headers: { + rid: "emailpassword", }, - { - id: "password", - value: "P@sSW0rd", - }, - ], - }, - }); - - const response = httpMocks.createResponse({ - eventEmitter: require("events").EventEmitter, - }); - - try { - await superTokensNextWrapper( - async (next) => { - return middleware()(request, response, next); - }, - request, - response - ); - assert(false); - } catch (err) { - assert.deepStrictEqual(err, { error: "sign up error" }); - } + body: JSON.stringify({ + formFields: [ + { + id: "email", + value: "john.doe2@supertokens.io", + }, + { + id: "password", + value: "P@sSW0rd", + }, + ], + }), + }); + const respJson = await res.text(); + assert.strictEqual(res.status, 500); + assert.strictEqual(respJson, "Internal Server Error"); + }, + }); + assert.deepStrictEqual(wrapperErr, { error: "sign up error" }); }); }); }); -function getSessionCookiesFromResponse(response) { +function getSessionTokensFromResponse(response) { return { - sAccessToken: decodeURIComponent( - response._getHeaders()["set-cookie"][0].split("sAccessToken=")[1].split(";")[0] - ), - sRefreshToken: decodeURIComponent( - response._getHeaders()["set-cookie"][1].split("sRefreshToken=")[1].split(";")[0] - ), + access: response.headers.get("st-access-token"), + refresh: response.headers.get("st-refresh-token"), }; } diff --git a/test/session.test.js b/test/session.test.js index dfb504be4..6d79ebfa3 100644 --- a/test/session.test.js +++ b/test/session.test.js @@ -314,15 +314,15 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, response.refreshToken.token, response.antiCsrfToken, - true, - "cookie" + false ); await SessionFunctions.getSession( SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, parseJWTWithoutSignatureVerification(response2.accessToken.token), response2.antiCsrfToken, - true + true, + false ); try { @@ -330,9 +330,7 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, response.refreshToken.token, response.antiCsrfToken, - true, - "cookie", - "cookie" + false ); throw new Error("should not have come here"); } catch (err) { @@ -370,16 +368,15 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, response.refreshToken.token, response.antiCsrfToken, - true, - "cookie", - "cookie" + false ); await SessionFunctions.getSession( SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, parseJWTWithoutSignatureVerification(response2.accessToken.token), response2.antiCsrfToken, - true + true, + false ); try { @@ -387,9 +384,7 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, response.refreshToken.token, response.antiCsrfToken, - true, - "cookie", - "cookie" + false ); throw new Error("should not have come here"); } catch (err) { @@ -445,42 +440,40 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { let s = SessionRecipe.getInstanceOrThrowError(); let response = await SessionFunctions.createNewSession(s.recipeInterfaceImpl.helpers, "", false, {}, {}); - assert(response.session !== undefined); - assert(response.accessToken !== undefined); - assert(response.refreshToken !== undefined); - assert(response.antiCsrfToken !== undefined); - assert(Object.keys(response).length === 5); + assert.notEqual(response.session, undefined); + assert.notEqual(response.accessToken, undefined); + assert.notEqual(response.refreshToken, undefined); + assert.notEqual(response.antiCsrfToken, undefined); + assert.strictEqual(Object.keys(response).length, 4); await SessionFunctions.getSession( s.recipeInterfaceImpl.helpers, parseJWTWithoutSignatureVerification(response.accessToken.token), response.antiCsrfToken, true, - true + false ); let verifyState3 = await ProcessState.getInstance().waitForEvent(PROCESS_STATE.CALLING_SERVICE_IN_VERIFY, 1500); - assert(verifyState3 === undefined); + assert.strictEqual(verifyState3, undefined); let response2 = await SessionFunctions.refreshSession( s.recipeInterfaceImpl.helpers, response.refreshToken.token, response.antiCsrfToken, - true, - "cookie", - "cookie" + false ); assert(response2.session !== undefined); assert(response2.accessToken !== undefined); assert(response2.refreshToken !== undefined); assert(response2.antiCsrfToken !== undefined); - assert(Object.keys(response2).length === 5); + assert(Object.keys(response2).length === 4); let response3 = await SessionFunctions.getSession( s.recipeInterfaceImpl.helpers, parseJWTWithoutSignatureVerification(response2.accessToken.token), response2.antiCsrfToken, true, - true + false ); let verifyState = await ProcessState.getInstance().waitForEvent(PROCESS_STATE.CALLING_SERVICE_IN_VERIFY); assert(verifyState !== undefined); @@ -495,7 +488,7 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { parseJWTWithoutSignatureVerification(response3.accessToken.token), response2.antiCsrfToken, true, - true + false ); let verifyState2 = await ProcessState.getInstance().waitForEvent(PROCESS_STATE.CALLING_SERVICE_IN_VERIFY, 1000); assert(verifyState2 === undefined); @@ -534,7 +527,7 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { true ); assert(response2.session != undefined); - assert(Object.keys(response2.session).length === 3); + assert(Object.keys(response2.session).length === 4); let response3 = await SessionFunctions.getSession( s.recipeInterfaceImpl.helpers, @@ -544,7 +537,7 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { true ); assert(response3.session != undefined); - assert(Object.keys(response3.session).length === 3); + assert(Object.keys(response3.session).length === 4); }); //check session verify for with / without anti-csrf present** @@ -572,10 +565,11 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { parseJWTWithoutSignatureVerification(response.accessToken.token), undefined, false, - true + false ); - assert(response2.session != undefined); - assert(Object.keys(response2.session).length === 3); + + assert.notStrictEqual(response2.session, undefined); + assert.strictEqual(Object.keys(response2.session).length, 4); // TODO check why this changed //passing anti-csrf token as undefined and anti-csrf check as true try { @@ -584,7 +578,7 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { parseJWTWithoutSignatureVerification(response.accessToken.token), undefined, true, - true + false ); throw new Error("should not have come here"); } catch (err) { @@ -658,19 +652,19 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { let s = SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl; //adding session data let res = await SessionFunctions.createNewSession(s.helpers, "", false, {}, {}); - await SessionFunctions.updateSessionData(s.helpers, res.session.handle, { key: "value" }); + await SessionFunctions.updateSessionDataInDatabase(s.helpers, res.session.handle, { key: "value" }); - let res2 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).sessionData; + let res2 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).sessionDataInDatabase; assert.deepStrictEqual(res2, { key: "value" }); //changing the value of session data with the same key - await SessionFunctions.updateSessionData(s.helpers, res.session.handle, { key: "value 2" }); + await SessionFunctions.updateSessionDataInDatabase(s.helpers, res.session.handle, { key: "value 2" }); - let res3 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).sessionData; + let res3 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).sessionDataInDatabase; assert.deepStrictEqual(res3, { key: "value 2" }); //passing invalid session handle when updating session data - assert(!(await SessionFunctions.updateSessionData(s.helpers, "random", { key2: "value2" }))); + assert(!(await SessionFunctions.updateSessionDataInDatabase(s.helpers, "random", { key2: "value2" }))); }); it("test manipulating session data with new get session function", async function () { @@ -698,19 +692,19 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { let s = SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl; //adding session data let res = await SessionFunctions.createNewSession(s.helpers, "", false, {}, {}); - await SessionFunctions.updateSessionData(s.helpers, res.session.handle, { key: "value" }); + await SessionFunctions.updateSessionDataInDatabase(s.helpers, res.session.handle, { key: "value" }); let res2 = await SessionFunctions.getSessionInformation(s.helpers, res.session.handle); - assert.deepStrictEqual(res2.sessionData, { key: "value" }); + assert.deepStrictEqual(res2.sessionDataInDatabase, { key: "value" }); //changing the value of session data with the same key - await SessionFunctions.updateSessionData(s.helpers, res.session.handle, { key: "value 2" }); + await SessionFunctions.updateSessionDataInDatabase(s.helpers, res.session.handle, { key: "value 2" }); let res3 = await SessionFunctions.getSessionInformation(s.helpers, res.session.handle); - assert.deepStrictEqual(res3.sessionData, { key: "value 2" }); + assert.deepStrictEqual(res3.sessionDataInDatabase, { key: "value 2" }); //passing invalid session handle when updating session data - assert(!(await SessionFunctions.updateSessionData(s.helpers, "random", { key2: "value2" }))); + assert(!(await SessionFunctions.updateSessionDataInDatabase(s.helpers, "random", { key2: "value2" }))); }); it("test null and undefined values passed for session data", async function () { @@ -731,27 +725,27 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { //adding session data let res = await SessionFunctions.createNewSession(s.helpers, "", false, {}, null); - let res2 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).sessionData; + let res2 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).sessionDataInDatabase; assert.deepStrictEqual(res2, {}); - await SessionFunctions.updateSessionData(s.helpers, res.session.handle, { key: "value" }); + await SessionFunctions.updateSessionDataInDatabase(s.helpers, res.session.handle, { key: "value" }); - let res3 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).sessionData; + let res3 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).sessionDataInDatabase; assert.deepStrictEqual(res3, { key: "value" }); - await SessionFunctions.updateSessionData(s.helpers, res.session.handle, undefined); + await SessionFunctions.updateSessionDataInDatabase(s.helpers, res.session.handle, undefined); - let res4 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).sessionData; + let res4 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).sessionDataInDatabase; assert.deepStrictEqual(res4, {}); - await SessionFunctions.updateSessionData(s.helpers, res.session.handle, { key: "value 2" }); + await SessionFunctions.updateSessionDataInDatabase(s.helpers, res.session.handle, { key: "value 2" }); - let res5 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).sessionData; + let res5 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).sessionDataInDatabase; assert.deepStrictEqual(res5, { key: "value 2" }); - await SessionFunctions.updateSessionData(s.helpers, res.session.handle, null); + await SessionFunctions.updateSessionDataInDatabase(s.helpers, res.session.handle, null); - let res6 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).sessionData; + let res6 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).sessionDataInDatabase; assert.deepStrictEqual(res6, {}); }); @@ -782,27 +776,27 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { let res = await SessionFunctions.createNewSession(s.helpers, "", false, {}, null); let res2 = await SessionFunctions.getSessionInformation(s.helpers, res.session.handle); - assert.deepStrictEqual(res2.sessionData, {}); + assert.deepStrictEqual(res2.sessionDataInDatabase, {}); - await SessionFunctions.updateSessionData(s.helpers, res.session.handle, { key: "value" }); + await SessionFunctions.updateSessionDataInDatabase(s.helpers, res.session.handle, { key: "value" }); let res3 = await SessionFunctions.getSessionInformation(s.helpers, res.session.handle); - assert.deepStrictEqual(res3.sessionData, { key: "value" }); + assert.deepStrictEqual(res3.sessionDataInDatabase, { key: "value" }); - await SessionFunctions.updateSessionData(s.helpers, res.session.handle, undefined); + await SessionFunctions.updateSessionDataInDatabase(s.helpers, res.session.handle, undefined); let res4 = await SessionFunctions.getSessionInformation(s.helpers, res.session.handle); - assert.deepStrictEqual(res4.sessionData, {}); + assert.deepStrictEqual(res4.sessionDataInDatabase, {}); - await SessionFunctions.updateSessionData(s.helpers, res.session.handle, { key: "value 2" }); + await SessionFunctions.updateSessionDataInDatabase(s.helpers, res.session.handle, { key: "value 2" }); let res5 = await SessionFunctions.getSessionInformation(s.helpers, res.session.handle); - assert.deepStrictEqual(res5.sessionData, { key: "value 2" }); + assert.deepStrictEqual(res5.sessionDataInDatabase, { key: "value 2" }); - await SessionFunctions.updateSessionData(s.helpers, res.session.handle, null); + await SessionFunctions.updateSessionDataInDatabase(s.helpers, res.session.handle, null); let res6 = await SessionFunctions.getSessionInformation(s.helpers, res.session.handle); - assert.deepStrictEqual(res6.sessionData, {}); + assert.deepStrictEqual(res6.sessionDataInDatabase, {}); }); //check manipulating jwt payload @@ -826,13 +820,15 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { await SessionFunctions.updateAccessTokenPayload(s.helpers, res.session.handle, { key: "value" }); - let res2 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).accessTokenPayload; + let res2 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)) + .customClaimsInAccessTokenPayload; assert.deepStrictEqual(res2, { key: "value" }); //changing the value of jwt payload with the same key await SessionFunctions.updateAccessTokenPayload(s.helpers, res.session.handle, { key: "value 2" }); - let res3 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).accessTokenPayload; + let res3 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)) + .customClaimsInAccessTokenPayload; assert.deepStrictEqual(res3, { key: "value 2" }); //passing invalid session handle when updating jwt payload @@ -868,13 +864,13 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { await SessionFunctions.updateAccessTokenPayload(s.helpers, res.session.handle, { key: "value" }); let res2 = await SessionFunctions.getSessionInformation(s.helpers, res.session.handle); - assert.deepStrictEqual(res2.accessTokenPayload, { key: "value" }); + assert.deepStrictEqual(res2.customClaimsInAccessTokenPayload, { key: "value" }); //changing the value of jwt payload with the same key await SessionFunctions.updateAccessTokenPayload(s.helpers, res.session.handle, { key: "value 2" }); let res3 = await SessionFunctions.getSessionInformation(s.helpers, res.session.handle); - assert.deepStrictEqual(res3.accessTokenPayload, { key: "value 2" }); + assert.deepStrictEqual(res3.customClaimsInAccessTokenPayload, { key: "value 2" }); //passing invalid session handle when updating jwt payload assert(!(await SessionFunctions.updateAccessTokenPayload(s.helpers, "random", { key2: "value2" }))); @@ -898,28 +894,32 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { //adding jwt payload let res = await SessionFunctions.createNewSession(s.helpers, "", false, null, {}); - let res2 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).accessTokenPayload; + let res2 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)) + .customClaimsInAccessTokenPayload; assert.deepStrictEqual(res2, {}); await SessionFunctions.updateAccessTokenPayload(s.helpers, res.session.handle, { key: "value" }); - let res3 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).accessTokenPayload; + let res3 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)) + .customClaimsInAccessTokenPayload; assert.deepStrictEqual(res3, { key: "value" }); await SessionFunctions.updateAccessTokenPayload(s.helpers, res.session.handle); let res4 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle, undefined)) - .accessTokenPayload; + .customClaimsInAccessTokenPayload; assert.deepStrictEqual(res4, {}); await SessionFunctions.updateAccessTokenPayload(s.helpers, res.session.handle, { key: "value 2" }); - let res5 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).accessTokenPayload; + let res5 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)) + .customClaimsInAccessTokenPayload; assert.deepStrictEqual(res5, { key: "value 2" }); await SessionFunctions.updateAccessTokenPayload(s.helpers, res.session.handle, null); - let res6 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)).accessTokenPayload; + let res6 = (await SessionFunctions.getSessionInformation(s.helpers, res.session.handle)) + .customClaimsInAccessTokenPayload; assert.deepStrictEqual(res6, {}); }); @@ -950,27 +950,27 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { let res = await SessionFunctions.createNewSession(s.helpers, "", false, null, {}); let res2 = await SessionFunctions.getSessionInformation(s.helpers, res.session.handle); - assert.deepStrictEqual(res2.accessTokenPayload, {}); + assert.deepStrictEqual(res2.customClaimsInAccessTokenPayload, {}); await SessionFunctions.updateAccessTokenPayload(s.helpers, res.session.handle, { key: "value" }); let res3 = await SessionFunctions.getSessionInformation(s.helpers, res.session.handle); - assert.deepStrictEqual(res3.accessTokenPayload, { key: "value" }); + assert.deepStrictEqual(res3.customClaimsInAccessTokenPayload, { key: "value" }); await SessionFunctions.updateAccessTokenPayload(s.helpers, res.session.handle); let res4 = await SessionFunctions.getSessionInformation(s.helpers, res.session.handle, undefined); - assert.deepStrictEqual(res4.accessTokenPayload, {}); + assert.deepStrictEqual(res4.customClaimsInAccessTokenPayload, {}); await SessionFunctions.updateAccessTokenPayload(s.helpers, res.session.handle, { key: "value 2" }); let res5 = await SessionFunctions.getSessionInformation(s.helpers, res.session.handle); - assert.deepStrictEqual(res5.accessTokenPayload, { key: "value 2" }); + assert.deepStrictEqual(res5.customClaimsInAccessTokenPayload, { key: "value 2" }); await SessionFunctions.updateAccessTokenPayload(s.helpers, res.session.handle, null); let res6 = await SessionFunctions.getSessionInformation(s.helpers, res.session.handle); - assert.deepStrictEqual(res6.accessTokenPayload, {}); + assert.deepStrictEqual(res6.customClaimsInAccessTokenPayload, {}); }); //if anti-csrf is disabled from ST core, check that not having that in input to verify session is fine** @@ -989,29 +989,30 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { }); let s = SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl; + s.helpers.config = { antiCsrf: "NONE", useDynamicAccessTokenSigningKey: true }; let response = await SessionFunctions.createNewSession(s.helpers, "", false, {}, {}); //passing anti-csrf token as undefined and anti-csrf check as false let response2 = await SessionFunctions.getSession( - s, + s.helpers, parseJWTWithoutSignatureVerification(response.accessToken.token), undefined, false, true ); assert(response2.session != undefined); - assert(Object.keys(response2.session).length === 3); + assert(Object.keys(response2.session).length === 4); //passing anti-csrf token as undefined and anti-csrf check as true let response3 = await SessionFunctions.getSession( - s, + s.helpers, parseJWTWithoutSignatureVerification(response.accessToken.token), undefined, true, true ); assert(response3.session != undefined); - assert(Object.keys(response3.session).length === 3); + assert(Object.keys(response3.session).length === 4); }); it("test that anti-csrf disabled and sameSite none does not throw an error", async function () { @@ -1133,9 +1134,9 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { assert(typeof res2.status === "string"); assert(res2.status === "OK"); assert(typeof res2.userId === "string"); - assert(typeof res2.sessionData === "object"); + assert(typeof res2.sessionDataInDatabase === "object"); assert(typeof res2.expiry === "number"); - assert(typeof res2.accessTokenPayload === "object"); + assert(typeof res2.customClaimsInAccessTokenPayload === "object"); assert(typeof res2.timeCreated === "number"); }); @@ -1191,7 +1192,7 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { ...oI, getSessionInformation: async (input) => { const info = await oI.getSessionInformation(input); - info.sessionData = { test: 1 }; + info.sessionDataInDatabase = { test: 1 }; return info; }, }), @@ -1202,7 +1203,7 @@ describe(`session: ${printPath("[test/session.test.js]")}`, function () { const session = await Session.createNewSession(mockRequest(), mockResponse(), "testId"); - const data = await session.getSessionData(); + const data = await session.getSessionDataFromDatabase(); assert.equal(data.test, 1); }); diff --git a/test/session/accessTokenVersions.test.js b/test/session/accessTokenVersions.test.js new file mode 100644 index 000000000..d2cdb737c --- /dev/null +++ b/test/session/accessTokenVersions.test.js @@ -0,0 +1,876 @@ +/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * 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. + */ +const { printPath, setupST, startST, killAllST, cleanST, extractInfoFromResponse, resetAll } = require("../utils"); +const assert = require("assert"); +const { Querier } = require("../../lib/build/querier"); +const express = require("express"); +const request = require("supertest"); +const { ProcessState, PROCESS_STATE } = require("../../lib/build/processState"); +const SuperTokens = require("../../"); +const Session = require("../../recipe/session"); +const EmailPassword = require("../../recipe/emailpassword"); +const { parseJWTWithoutSignatureVerification } = require("../../lib/build/recipe/session/jwt"); +const { middleware, errorHandler } = require("../../framework/express"); +const { default: NormalisedURLPath } = require("../../lib/build/normalisedURLPath"); +const { verifySession } = require("../../recipe/session/framework/express"); +const { json } = require("body-parser"); + +describe(`AccessToken versions: ${printPath("[test/session/accessTokenVersions.test.js]")}`, function () { + beforeEach(async function () { + await killAllST(); + await setupST(); + ProcessState.getInstance().reset(); + }); + + after(async function () { + await killAllST(); + await cleanST(); + }); + + describe("createNewSession", () => { + it("should create a V3 token", async function () { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + }); + + const app = getTestExpressApp(); + + let res = await new Promise((resolve) => + request(app) + .post("/create") + .expect(200) + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + + let cookies = extractInfoFromResponse(res); + assert(cookies.accessTokenFromAny !== undefined); + assert(cookies.refreshTokenFromAny !== undefined); + assert(cookies.frontToken !== undefined); + + const parsedToken = parseJWTWithoutSignatureVerification(cookies.accessTokenFromAny); + assert.strictEqual(parsedToken.version, 3); + + const parsedHeader = JSON.parse(Buffer.from(parsedToken.header, "base64").toString()); + assert.strictEqual(typeof parsedHeader.kid, "string"); + assert(parsedHeader.kid.startsWith("d-")); + }); + + it("should create a V3 token signed by a static key if set in session recipe config", async function () { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Session.init({ + useDynamicAccessTokenSigningKey: false, + }), + ], + }); + + const app = getTestExpressApp(); + + let res = await new Promise((resolve) => + request(app) + .post("/create") + .expect(200) + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + + let cookies = extractInfoFromResponse(res); + assert(cookies.accessTokenFromAny !== undefined); + assert(cookies.refreshTokenFromAny !== undefined); + assert(cookies.frontToken !== undefined); + + const parsedToken = parseJWTWithoutSignatureVerification(cookies.accessTokenFromAny); + assert.strictEqual(parsedToken.version, 3); + + const parsedHeader = JSON.parse(Buffer.from(parsedToken.header, "base64").toString()); + assert.strictEqual(typeof parsedHeader.kid, "string"); + assert(parsedHeader.kid.startsWith("s-")); + }); + + it("should throw an error when adding protected props", async function () { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + }); + + const app = getTestExpressApp(); + + let res = await new Promise((res, rej) => + request(app) + .post("/create") + .type("application/json") + .send( + JSON.stringify({ + payload: { + sub: "asdf", + }, + }) + ) + .expect(400) + .end((err, resp) => { + if (err) { + rej(err); + } else { + res(resp); + } + }) + ); + + let cookies = extractInfoFromResponse(res); + assert.strictEqual(cookies.accessTokenFromAny, undefined); + assert.strictEqual(cookies.refreshTokenFromAny, undefined); + assert.strictEqual(cookies.frontToken, undefined); + }); + + it("should make sign in/up return a 500 when adding protected props", async function () { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + EmailPassword.init(), + Session.init({ + override: { + functions: (oI) => ({ + createNewSession: (input) => { + input.accessTokenPayload = { + ...input.accessTokenPayload, + sub: "asdf", + }; + + return oI.createNewSession(input); + }, + }), + }, + }), + ], + }); + + const app = getTestExpressApp(); + + let res = await new Promise((res, rej) => + request(app) + .post("/auth/signup") + .type("application/json") + .send( + JSON.stringify({ + formFields: [ + { id: "email", value: `test-${Date.now()}@supertokens.com` }, + { id: "password", value: "Asdf12.." }, + ], + }) + ) + .expect(500) + .end((err, resp) => { + if (err) { + rej(err); + } else { + res(resp); + } + }) + ); + + let cookies = extractInfoFromResponse(res); + assert.strictEqual(cookies.accessTokenFromAny, undefined); + assert.strictEqual(cookies.refreshTokenFromAny, undefined); + assert.strictEqual(cookies.frontToken, undefined); + + assert(res.text.includes("The user payload contains protected field")); + }); + }); + + describe("mergeIntoAccessTokenPayload", () => { + it("should help migrating a v2 token using protected props", async () => { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + }); + + // This CDI version is no longer supported by this SDK, but we want to ensure that sessions keep working after the upgrade + // We can hard-code the structure of the request&response, since this is a fixed CDI version and it's not going to change + Querier.apiVersion = "2.18"; + const legacySessionResp = await Querier.getNewInstanceOrThrowError().sendPostRequest( + new NormalisedURLPath("/recipe/session"), + { + userId: "test-user-id", + enableAntiCsrf: false, + userDataInJWT: { + sub: "asdf", + }, + userDataInDatabase: {}, + } + ); + Querier.apiVersion = undefined; + + const legacyAccessToken = legacySessionResp.accessToken.token; + const legacyRefreshToken = legacySessionResp.refreshToken.token; + + const app = getTestExpressApp(); + + let mergeRes = await new Promise((res, rej) => + request(app) + .post("/merge-into-payload") + .set("Authorization", `Bearer ${legacyAccessToken}`) + .type("application/json") + .send( + JSON.stringify({ + payload: { + sub: null, + appSub: "asdf", + }, + }) + ) + .expect(200) + .end((err, resp) => { + if (err) { + rej(err); + } else { + res(resp); + } + }) + ); + + let mergeCookies = extractInfoFromResponse(mergeRes); + assert(mergeCookies.accessTokenFromAny !== undefined); + assert(mergeCookies.refreshTokenFromAny === undefined); + assert(mergeCookies.frontToken !== undefined); + + const parsedTokenAfterMerge = parseJWTWithoutSignatureVerification(mergeCookies.accessTokenFromAny); + assert.strictEqual(parsedTokenAfterMerge.version, 2); + + let res = await new Promise((resolve, reject) => + request(app) + .post("/auth/session/refresh") + .set("Authorization", `Bearer ${legacyRefreshToken}`) + .expect(200) + .end((err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }) + ); + + let cookiesAfterRefresh = extractInfoFromResponse(res); + assert(cookiesAfterRefresh.accessTokenFromAny !== undefined); + assert(cookiesAfterRefresh.refreshTokenFromAny !== undefined); + assert(cookiesAfterRefresh.frontToken !== undefined); + + assert.strictEqual(parseJWTWithoutSignatureVerification(cookiesAfterRefresh.accessTokenFromAny).version, 3); + + const parsedTokenAfterRefresh = parseJWTWithoutSignatureVerification( + cookiesAfterRefresh.accessTokenFromAny + ); + assert.strictEqual(parsedTokenAfterRefresh.version, 3); + assert.strictEqual(parsedTokenAfterRefresh.payload.sub, "test-user-id"); + assert.strictEqual(parsedTokenAfterRefresh.payload.appSub, "asdf"); + + const parsedHeaderAfterRefresh = JSON.parse( + Buffer.from(parsedTokenAfterRefresh.header, "base64").toString() + ); + assert.strictEqual(typeof parsedHeaderAfterRefresh.kid, "string"); + assert(parsedHeaderAfterRefresh.kid.startsWith("d-")); + }); + + it("should help migrating a v2 token using protected props when called using session handle", async () => { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + }); + + // This CDI version is no longer supported by this SDK, but we want to ensure that sessions keep working after the upgrade + // We can hard-code the structure of the request&response, since this is a fixed CDI version and it's not going to change + Querier.apiVersion = "2.18"; + const legacySessionResp = await Querier.getNewInstanceOrThrowError().sendPostRequest( + new NormalisedURLPath("/recipe/session"), + { + userId: "test-user-id", + enableAntiCsrf: false, + userDataInJWT: { + sub: "asdf", + }, + userDataInDatabase: {}, + } + ); + Querier.apiVersion = undefined; + + const legacyRefreshToken = legacySessionResp.refreshToken.token; + + const app = getTestExpressApp(); + + await Session.mergeIntoAccessTokenPayload(legacySessionResp.session.handle, { sub: null, appSub: "asdf" }); + let res = await new Promise((resolve, reject) => + request(app) + .post("/auth/session/refresh") + .set("Authorization", `Bearer ${legacyRefreshToken}`) + .expect(200) + .end((err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }) + ); + + let cookies = extractInfoFromResponse(res); + assert(cookies.accessTokenFromAny !== undefined); + assert(cookies.refreshTokenFromAny !== undefined); + assert(cookies.frontToken !== undefined); + + assert.strictEqual(parseJWTWithoutSignatureVerification(cookies.accessTokenFromAny).version, 3); + + const parsedToken = parseJWTWithoutSignatureVerification(cookies.accessTokenFromAny); + assert.strictEqual(parsedToken.version, 3); + assert.strictEqual(parsedToken.payload.sub, "test-user-id"); + assert.strictEqual(parsedToken.payload.appSub, "asdf"); + + const parsedHeader = JSON.parse(Buffer.from(parsedToken.header, "base64").toString()); + assert.strictEqual(typeof parsedHeader.kid, "string"); + assert(parsedHeader.kid.startsWith("d-")); + }); + }); + + describe("verifySession", () => { + it("should validate v2 tokens", async function () { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + }); + + // This CDI version is no longer supported by this SDK, but we want to ensure that sessions keep working after the upgrade + // We can hard-code the structure of the request&response, since this is a fixed CDI version and it's not going to change + Querier.apiVersion = "2.18"; + const legacySessionResp = await Querier.getNewInstanceOrThrowError().sendPostRequest( + new NormalisedURLPath("/recipe/session"), + { + userId: "test-user-id", + enableAntiCsrf: false, + userDataInJWT: {}, + userDataInDatabase: {}, + } + ); + Querier.apiVersion = undefined; + + const legacyToken = legacySessionResp.accessToken.token; + + const app = getTestExpressApp(); + + let res = await new Promise((resolve, reject) => + request(app) + .get("/verify") + .set("Authorization", `Bearer ${legacyToken}`) + .expect(200) + .end((err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }) + ); + assert.notEqual( + await ProcessState.getInstance().waitForEvent(PROCESS_STATE.MULTI_JWKS_VALIDATION, 1500), + undefined + ); + + assert.deepStrictEqual(res.body, { + message: true, + payload: {}, + sessionExists: true, + sessionHandle: legacySessionResp.session.handle, + }); + }); + + it("should validate v2 tokens with check database enabled", async function () { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + }); + + // This CDI version is no longer supported by this SDK, but we want to ensure that sessions keep working after the upgrade + // We can hard-code the structure of the request&response, since this is a fixed CDI version and it's not going to change + Querier.apiVersion = "2.18"; + const legacySessionResp = await Querier.getNewInstanceOrThrowError().sendPostRequest( + new NormalisedURLPath("/recipe/session"), + { + userId: "test-user-id", + enableAntiCsrf: false, + userDataInJWT: {}, + userDataInDatabase: {}, + } + ); + Querier.apiVersion = undefined; + + const legacyToken = legacySessionResp.accessToken.token; + + const app = getTestExpressApp(); + + await new Promise((resolve, reject) => + request(app) + .get("/revoke-session") + .set("Authorization", `Bearer ${legacyToken}`) + .expect(200) + .end((err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }) + ); + + let resDBCheck = await new Promise((resolve, reject) => + request(app) + .get("/verify-checkdb") + .set("Authorization", `Bearer ${legacyToken}`) + .expect(401) + .end((err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }) + ); + + assert.deepStrictEqual(resDBCheck.body, { message: "unauthorised" }); + + let resNoDBCheck = await new Promise((resolve, reject) => + request(app) + .get("/verify") + .set("Authorization", `Bearer ${legacyToken}`) + .expect(200) + .end((err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }) + ); + assert.notEqual( + await ProcessState.getInstance().waitForEvent(PROCESS_STATE.MULTI_JWKS_VALIDATION, 1500), + undefined + ); + + assert.deepStrictEqual(resNoDBCheck.body, { + message: true, + sessionExists: true, + payload: {}, + sessionHandle: legacySessionResp.session.handle, + }); + }); + + it("should validate v3 tokens with check database enabled", async function () { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + }); + + const app = getTestExpressApp(); + + let res = await new Promise((resolve) => + request(app) + .post("/create") + .expect(200) + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + + let cookies = extractInfoFromResponse(res); + + assert(cookies.accessTokenFromAny !== undefined); + assert(cookies.refreshTokenFromAny !== undefined); + assert(cookies.frontToken !== undefined); + + await new Promise((resolve, reject) => + request(app) + .get("/revoke-session") + .set("Authorization", `Bearer ${cookies.accessTokenFromAny}`) + .expect(200) + .end((err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }) + ); + + let resDBCheck = await new Promise((resolve, reject) => + request(app) + .get("/verify-checkdb") + .set("Authorization", `Bearer ${cookies.accessTokenFromAny}`) + .expect(401) + .end((err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }) + ); + + assert.deepStrictEqual(resDBCheck.body, { message: "unauthorised" }); + + let resNoDBCheck = await new Promise((resolve, reject) => + request(app) + .get("/verify") + .set("Authorization", `Bearer ${cookies.accessTokenFromAny}`) + .expect(200) + .end((err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }) + ); + + assert.notDeepStrictEqual(resNoDBCheck.body, { message: "unauthorised" }); + }); + + it("should not validate token signed by a static key if not set in session recipe config", async function () { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Session.init({ + useDynamicAccessTokenSigningKey: false, + }), + ], + }); + + const app = getTestExpressApp(); + + let res = await new Promise((resolve) => + request(app) + .post("/create") + .expect(200) + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + + let cookies = extractInfoFromResponse(res); + assert(cookies.accessTokenFromAny !== undefined); + assert(cookies.refreshTokenFromAny !== undefined); + assert(cookies.frontToken !== undefined); + + resetAll(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Session.init({ + useDynamicAccessTokenSigningKey: true, + }), + ], + }); + + const resDBCheck = await new Promise((resolve, reject) => + request(app) + .get("/verify") + .set("Authorization", `Bearer ${cookies.accessTokenFromAny}`) + .expect(401) + .end((err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }) + ); + + assert.deepStrictEqual(resDBCheck.body, { message: "try refresh token" }); + }); + }); + + describe("refresh session", () => { + it("should refresh legacy sessions to new version", async function () { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + }); + + // This CDI version is no longer supported by this SDK, but we want to ensure that sessions keep working after the upgrade + // We can hard-code the structure of the request&response, since this is a fixed CDI version and it's not going to change + Querier.apiVersion = "2.18"; + const legacySessionResp = await Querier.getNewInstanceOrThrowError().sendPostRequest( + new NormalisedURLPath("/recipe/session"), + { + userId: "test-user-id", + enableAntiCsrf: false, + userDataInJWT: {}, + userDataInDatabase: {}, + } + ); + Querier.apiVersion = undefined; + + const legacyRefreshToken = legacySessionResp.refreshToken.token; + + const app = getTestExpressApp(); + + let res = await new Promise((resolve, reject) => + request(app) + .post("/auth/session/refresh") + .set("Authorization", `Bearer ${legacyRefreshToken}`) + .expect(200) + .end((err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }) + ); + + let cookies = extractInfoFromResponse(res); + assert(cookies.accessTokenFromAny !== undefined); + assert(cookies.refreshTokenFromAny !== undefined); + assert(cookies.frontToken !== undefined); + + assert.strictEqual(parseJWTWithoutSignatureVerification(cookies.accessTokenFromAny).version, 3); + }); + + it("should throw when refreshing legacy session with protected prop in payload", async function () { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + }); + + // This CDI version is no longer supported by this SDK, but we want to ensure that sessions keep working after the upgrade + // We can hard-code the structure of the request&response, since this is a fixed CDI version and it's not going to change + Querier.apiVersion = "2.18"; + const legacySessionResp = await Querier.getNewInstanceOrThrowError().sendPostRequest( + new NormalisedURLPath("/recipe/session"), + { + userId: "test-user-id", + enableAntiCsrf: false, + userDataInJWT: { + sub: "asdf", + }, + userDataInDatabase: {}, + } + ); + Querier.apiVersion = undefined; + + const legacyRefreshToken = legacySessionResp.refreshToken.token; + + const app = getTestExpressApp(); + + let res = await new Promise((resolve, reject) => + request(app) + .post("/auth/session/refresh") + .set("Authorization", `Bearer ${legacyRefreshToken}`) + .expect(401) + .end((err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }) + ); + + let cookies = extractInfoFromResponse(res); + assert.strictEqual(cookies.accessTokenFromAny, ""); + assert.strictEqual(cookies.refreshTokenFromAny, ""); + assert.strictEqual(cookies.frontToken, "remove"); + }); + }); +}); + +function getTestExpressApp() { + const app = express(); + + app.use(middleware()); + app.use(json()); + + app.post("/create", async (req, res) => { + try { + await Session.createNewSession(req, res, "", req.body.payload, {}); + res.status(200).send(""); + } catch (ex) { + res.status(400).json({ message: ex.message }); + } + }); + + app.get("/verify", verifySession(), async (req, res) => { + res.status(200).json({ + message: true, + sessionHandle: req.session.getHandle(), + sessionExists: true, + payload: req.session.getAccessTokenPayload(), + }); + }); + + app.get("/verify-checkdb", verifySession({ checkDatabase: true }), async (req, res) => { + res.status(200).json({ + message: true, + sessionHandle: req.session.getHandle(), + sessionExists: true, + payload: req.session.getAccessTokenPayload(), + }); + }); + + app.get("/verify-optional", verifySession({ sessionRequired: false }), async (req, res) => { + res.status(200).json({ + message: true, + sessionHandle: req.session && req.session.getHandle(), + sessionExists: !!req.session, + }); + }); + + app.post("/merge-into-payload", verifySession(), async (req, res) => { + await req.session.mergeIntoAccessTokenPayload(req.body.payload); + res.status(200).json({ + message: true, + sessionHandle: req.session && req.session.getHandle(), + sessionExists: !!req.session, + newPayload: await req.session.getAccessTokenPayload(), + }); + }); + + app.get("/revoke-session", verifySession(), async (req, res) => { + res.status(200).json({ message: await req.session.revokeSession(), sessionHandle: req.session.getHandle() }); + }); + + app.use(errorHandler()); + return app; +} diff --git a/test/session/claims/assertClaims.test.js b/test/session/claims/assertClaims.test.js index 590bb7cc2..903080051 100644 --- a/test/session/claims/assertClaims.test.js +++ b/test/session/claims/assertClaims.test.js @@ -19,21 +19,16 @@ const sinon = require("sinon"); const { StubClaim } = require("./testClaims"); const { default: getRecipeInterface } = require("../../../lib/build/recipe/session/recipeImplementation"); +const helpers = { getRecipeImpl: () => getRecipeInterface({ getAllCoreUrlsForPath: () => [] }, {}) }; + describe(`sessionClaims/assertClaims: ${printPath("[test/session/claims/assertClaims.test.js]")}`, function () { describe("SessionClass.assertClaims", () => { afterEach(() => { sinon.restore(); }); it("should not throw for empty array", async () => { - const session = new SessionClass( - { getRecipeImpl: () => getRecipeInterface({}, {}) }, - "testToken", - "testHandle", - "testUserId", - {}, - {} - ); - const mock = sinon.mock(session).expects("updateAccessTokenPayload").never(); + const session = new SessionClass(helpers, "testToken", "testHandle", "testUserId", {}, {}); + const mock = sinon.mock(session).expects("mergeIntoAccessTokenPayload").never(); await session.assertClaims([]); mock.verify(); @@ -42,14 +37,17 @@ describe(`sessionClaims/assertClaims: ${printPath("[test/session/claims/assertCl it("should call validate with the same payload object", async () => { const payload = {}; const session = new SessionClass( - { getRecipeImpl: () => getRecipeInterface({}, {}) }, + helpers, + "testToken", "testToken", + undefined, + undefined, "testHandle", "testUserId", payload, {} ); - const mock = sinon.mock(session).expects("updateAccessTokenPayload").never(); + const mock = sinon.mock(session).expects("mergeIntoAccessTokenPayload").never(); const claim = new StubClaim({ key: "st-c1", validateRes: { isValid: true } }); await session.assertClaims([claim.validators.stub]); diff --git a/test/session/claims/createNewSession.test.js b/test/session/claims/createNewSession.test.js index 18917cbd8..79877e738 100644 --- a/test/session/claims/createNewSession.test.js +++ b/test/session/claims/createNewSession.test.js @@ -17,8 +17,6 @@ const assert = require("assert"); const { ProcessState } = require("../../../lib/build/processState"); const SuperTokens = require("../../.."); const Session = require("../../../recipe/session"); -const { Querier } = require("../../../lib/build/querier"); -const { maxVersion } = require("../../../lib/build/utils"); const { TrueClaim, UndefinedClaim } = require("./testClaims"); describe(`sessionClaims/createNewSession: ${printPath("[test/session/claims/createNewSession.test.js]")}`, function () { @@ -64,18 +62,13 @@ describe(`sessionClaims/createNewSession: ${printPath("[test/session/claims/crea }), ], }); - let q = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await q.getAPIVersion(); - // Only run test for >= 2.13 - if (maxVersion(apiVersion, "2.12") === "2.12") { - return; - } const response = mockResponse(); const res = await Session.createNewSession(mockRequest(), response, "someId"); const payload = res.getAccessTokenPayload(); - assert.equal(Object.keys(payload).length, 1); + assert.equal(Object.keys(payload).length, 9); + assert.ok(payload["iss"], "http://api.supertokens.io/auth"); assert.ok(payload["st-true"]); assert.equal(payload["st-true"].v, true); assert(payload["st-true"].t > Date.now() - 1000); @@ -114,17 +107,11 @@ describe(`sessionClaims/createNewSession: ${printPath("[test/session/claims/crea }), ], }); - let q = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await q.getAPIVersion(); - // Only run test for >= 2.13 - if (maxVersion(apiVersion, "2.12") === "2.12") { - return; - } const response = mockResponse(); const res = await Session.createNewSession(mockRequest(), response, "someId"); const payload = res.getAccessTokenPayload(); - assert.equal(Object.keys(payload).length, 0); + assert.equal(Object.keys(payload).length, 8); }); it("should merge claims and the passed access token payload obj", async function () { @@ -164,14 +151,7 @@ describe(`sessionClaims/createNewSession: ${printPath("[test/session/claims/crea }), ], }); - let q = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await q.getAPIVersion(); - // Only run test for >= 2.13 - if (maxVersion(apiVersion, "2.12") === "2.12") { - return; - } - const includesNullInPayload = maxVersion(apiVersion, "2.14") !== "2.14"; const response = mockResponse(); const res = await Session.createNewSession(mockRequest(), response, "someId", payloadParam); @@ -179,7 +159,7 @@ describe(`sessionClaims/createNewSession: ${printPath("[test/session/claims/crea assert.strictEqual(Object.keys(payloadParam).length, 1); const payload = res.getAccessTokenPayload(); - assert.strictEqual(Object.keys(payload).length, includesNullInPayload ? 5 : 4); + assert.strictEqual(Object.keys(payload).length, 13); // 5 + 8 standard // We have the prop from the payload param assert.strictEqual(payload["initial"], true); // We have the boolean claim @@ -189,18 +169,11 @@ describe(`sessionClaims/createNewSession: ${printPath("[test/session/claims/crea // We have the custom claim // The resulting payload is different from the input: it doesn't container undefined assert.deepStrictEqual(payload["user-custom"], "asdf"); - if (includesNullInPayload) { - assert.deepStrictEqual(payload["user-custom2"], { - inner: "asdf", - nullProp: null, - }); - assert.deepStrictEqual(payload["user-custom3"], null); - } else { - assert.deepStrictEqual(payload["user-custom2"], { - inner: "asdf", - }); - assert.deepStrictEqual(payload["user-custom3"], undefined); - } + assert.deepStrictEqual(payload["user-custom2"], { + inner: "asdf", + nullProp: null, + }); + assert.deepStrictEqual(payload["user-custom3"], null); }); }); }); diff --git a/test/session/claims/fetchAndSetClaim.test.js b/test/session/claims/fetchAndSetClaim.test.js index cf4d0864f..4a0476537 100644 --- a/test/session/claims/fetchAndSetClaim.test.js +++ b/test/session/claims/fetchAndSetClaim.test.js @@ -83,8 +83,8 @@ describe(`sessionClaims/fetchAndSetClaim: ${printPath("[test/session/claims/fetc await Session.fetchAndSetClaim(res.getHandle(), TrueClaim); - const payload = (await Session.getSessionInformation(res.getHandle())).accessTokenPayload; - assert.equal(Object.keys(payload).length, 1); + const payload = (await Session.getSessionInformation(res.getHandle())).customClaimsInAccessTokenPayload; + assert.equal(Object.keys(payload).length, 2); assert.ok(payload["st-true"]); assert.equal(payload["st-true"].v, true); assert(payload["st-true"].t > Date.now() - 1000); diff --git a/test/session/claims/removeClaim.test.js b/test/session/claims/removeClaim.test.js index 9dd9e68b6..000cbdac7 100644 --- a/test/session/claims/removeClaim.test.js +++ b/test/session/claims/removeClaim.test.js @@ -83,7 +83,7 @@ describe(`sessionClaims/removeClaim: ${printPath("[test/session/claims/removeCla const res = await Session.createNewSession(mockRequest(), response, "someId"); const payload = res.getAccessTokenPayload(); - assert.equal(Object.keys(payload).length, 1); + assert.equal(Object.keys(payload).length, 9); assert.ok(payload["st-true"]); assert.equal(payload["st-true"].v, true); assert(payload["st-true"].t > Date.now() - 10000); @@ -91,7 +91,7 @@ describe(`sessionClaims/removeClaim: ${printPath("[test/session/claims/removeCla await res.removeClaim(TrueClaim); const payloadAfter = res.getAccessTokenPayload(); - assert.equal(Object.keys(payloadAfter).length, 0); + assert.equal(Object.keys(payloadAfter).length, 8); }); it("should clear previously set claim using a handle", async function () { @@ -129,7 +129,7 @@ describe(`sessionClaims/removeClaim: ${printPath("[test/session/claims/removeCla const session = await Session.createNewSession(mockRequest(), response, "someId"); const payload = session.getAccessTokenPayload(); - assert.equal(Object.keys(payload).length, 1); + assert.equal(Object.keys(payload).length, 9); assert.ok(payload["st-true"]); assert.equal(payload["st-true"].v, true); assert(payload["st-true"].t > Date.now() - 10000); @@ -137,8 +137,9 @@ describe(`sessionClaims/removeClaim: ${printPath("[test/session/claims/removeCla const res = await Session.removeClaim(session.getHandle(), TrueClaim); assert.equal(res, true); - const payloadAfter = (await Session.getSessionInformation(session.getHandle())).accessTokenPayload; - assert.equal(Object.keys(payloadAfter).length, 0); + const payloadAfter = (await Session.getSessionInformation(session.getHandle())) + .customClaimsInAccessTokenPayload; + assert.equal(Object.keys(payloadAfter).length, 1); }); it("should work ok for not existing handle", async function () { diff --git a/test/session/claims/setClaimValue.test.js b/test/session/claims/setClaimValue.test.js index cee0e94e8..5634c100f 100644 --- a/test/session/claims/setClaimValue.test.js +++ b/test/session/claims/setClaimValue.test.js @@ -90,7 +90,7 @@ describe(`sessionClaims/setClaimValue: ${printPath("[test/session/claims/setClai const res = await Session.createNewSession(mockRequest(), response, "someId"); const payload = res.getAccessTokenPayload(); - assert.equal(Object.keys(payload).length, 1); + assert.equal(Object.keys(payload).length, 9); assert.ok(payload["st-true"]); assert.equal(payload["st-true"].v, true); assert(payload["st-true"].t > Date.now() - 2000); @@ -98,7 +98,7 @@ describe(`sessionClaims/setClaimValue: ${printPath("[test/session/claims/setClai await res.setClaimValue(TrueClaim, false); const payloadAfter = res.getAccessTokenPayload(); - assert.equal(Object.keys(payloadAfter).length, 1); + assert.equal(Object.keys(payloadAfter).length, 9); assert.ok(payloadAfter["st-true"]); assert.equal(payloadAfter["st-true"].v, false); assert(payloadAfter["st-true"].t > payload["st-true"].t); @@ -139,15 +139,16 @@ describe(`sessionClaims/setClaimValue: ${printPath("[test/session/claims/setClai const res = await Session.createNewSession(mockRequest(), response, "someId"); const payload = res.getAccessTokenPayload(); - assert.equal(Object.keys(payload).length, 1); + assert.equal(Object.keys(payload).length, 9); assert.ok(payload["st-true"]); assert.equal(payload["st-true"].v, true); assert(payload["st-true"].t > Date.now() - 10000); await Session.setClaimValue(res.getHandle(), TrueClaim, false); - const payloadAfter = (await Session.getSessionInformation(res.getHandle())).accessTokenPayload; - assert.equal(Object.keys(payloadAfter).length, 1); + const payloadAfter = (await Session.getSessionInformation(res.getHandle())) + .customClaimsInAccessTokenPayload; + assert.equal(Object.keys(payloadAfter).length, 2); assert.ok(payloadAfter["st-true"]); assert.equal(payloadAfter["st-true"].v, false); assert(payloadAfter["st-true"].t > payload["st-true"].t); diff --git a/test/session/claims/verifySession.test.js b/test/session/claims/verifySession.test.js index 6a7197cc7..cb7966c15 100644 --- a/test/session/claims/verifySession.test.js +++ b/test/session/claims/verifySession.test.js @@ -269,7 +269,7 @@ describe(`sessionClaims/verifySession: ${printPath("[test/session/claims/verifyS .create("validateClaims") .once() .withArgs({ - accessTokenPayload: {}, + accessTokenPayload: sinon.match.object, userId: "testing-userId", claimValidators: testValidatorArr, userContext: { @@ -328,7 +328,7 @@ describe(`sessionClaims/verifySession: ${printPath("[test/session/claims/verifyS .create("validateClaims") .once() .withArgs({ - accessTokenPayload: {}, + accessTokenPayload: sinon.match.object, userId: "testing-userId", claimValidators: testValidatorArr, userContext: { diff --git a/test/session/claims/withJWT.test.js b/test/session/claims/withJWT.test.js deleted file mode 100644 index b10c9fa02..000000000 --- a/test/session/claims/withJWT.test.js +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ -const JsonWebToken = require("jsonwebtoken"); - -const { printPath, setupST, startST, killAllST, cleanST } = require("../../utils"); -let { Querier } = require("../../../lib/build/querier"); -let { maxVersion } = require("../../../lib/build/utils"); -let assert = require("assert"); -const express = require("express"); -const request = require("supertest"); -let { ProcessState } = require("../../../lib/build/processState"); -let SuperTokens = require("../../../"); -let Session = require("../../../recipe/session"); -let { middleware, errorHandler } = require("../../../framework/express"); -const { TrueClaim, UndefinedClaim } = require("./testClaims"); - -describe(`sessionClaims/withJWT: ${printPath("[test/session/claims/withJWT.test.js]")}`, function () { - beforeEach(async function () { - await killAllST(); - await setupST(); - ProcessState.getInstance().reset(); - }); - - after(async function () { - await killAllST(); - await cleanST(); - }); - - describe("JWT + claims interaction", () => { - it("should create the right access token payload with claims and JWT enabled", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - override: { - functions: (oI) => ({ - ...oI, - createNewSession: async (input) => { - input.accessTokenPayload = { - ...input.accessTokenPayload, - ...(await TrueClaim.build(input.userId, input.userContext)), - }; - return oI.createNewSession(input); - }, - }), - }, - jwt: { enable: true }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", undefined, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - - const sessionInfo = await Session.getSessionInformation(sessionHandle); - let accessTokenPayload = sessionInfo.accessTokenPayload; - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT["sub"], "userId"); - assert.strictEqual(decodedJWT.iss, "https://api.supertokens.io/auth"); - assert.strictEqual(decodedJWT._jwtPName, undefined); - - assert.strictEqual(TrueClaim.getValueFromPayload(accessTokenPayload), true); - assert.strictEqual(TrueClaim.getValueFromPayload(decodedJWT), true); - - const failingValidator = UndefinedClaim.validators.hasValue(true); - assert.deepStrictEqual( - await Session.validateClaimsInJWTPayload(sessionInfo.userId, decodedJWT, () => [ - TrueClaim.validators.hasValue(true, 2), - failingValidator, - ]), - { - status: "OK", - invalidClaims: [ - { - id: failingValidator.id, - reason: { - actualValue: undefined, - expectedValue: true, - message: "value does not exist", - }, - }, - ], - } - ); - }); - }); -}); diff --git a/test/session/exposeAccessTokenToFrontendInCookieBasedAuth.test.js b/test/session/exposeAccessTokenToFrontendInCookieBasedAuth.test.js new file mode 100644 index 000000000..b16595825 --- /dev/null +++ b/test/session/exposeAccessTokenToFrontendInCookieBasedAuth.test.js @@ -0,0 +1,328 @@ +/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * 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. + */ +const { printPath, setupST, startST, killAllST, cleanST, extractInfoFromResponse } = require("../utils"); +const assert = require("assert"); +const express = require("express"); +const request = require("supertest"); +const { ProcessState } = require("../../lib/build/processState"); +const SuperTokens = require("../.."); +const Session = require("../../recipe/session"); +const { middleware, errorHandler } = require("../../framework/express"); +const { verifySession } = require("../../recipe/session/framework/express"); +const { json } = require("body-parser"); +const { default: SessionRecipe } = require("../../lib/build/recipe/session/recipe"); + +describe(`exposeAccessTokenToFrontendInCookieBasedAuth: ${printPath( + "[test/session/exposeAccessTokenToFrontendInCookieBasedAuth.test.js]" +)}`, function () { + beforeEach(async function () { + await killAllST(); + await setupST(); + ProcessState.getInstance().reset(); + }); + + after(async function () { + await killAllST(); + await cleanST(); + }); + + it("should default to false", () => { + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + }); + assert.strictEqual( + SessionRecipe.getInstanceOrThrowError().config.exposeAccessTokenToFrontendInCookieBasedAuth, + false + ); + }); + + getTestCases(true); + getTestCases(false); +}); + +function getTestCases(exposeAccessTokenToFrontendInCookieBasedAuth) { + describe(`with exposeAccessTokenToFrontendInCookieBasedAuth=${exposeAccessTokenToFrontendInCookieBasedAuth}`, () => { + const sessionConfig = { exposeAccessTokenToFrontendInCookieBasedAuth, getTokenTransferMethod: () => "cookie" }; + describe("createNewSession", () => { + it("should attach the appropriate tokens", async function () { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init(sessionConfig)], + }); + + const app = getTestExpressApp(); + + let res = await new Promise((resolve) => + request(app) + .post("/create") + .expect(200) + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + checkResponse(res, exposeAccessTokenToFrontendInCookieBasedAuth); + }); + }); + + describe("mergeIntoAccessTokenPayload", () => { + it("should attach the appropriate tokens", async () => { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init(sessionConfig)], + }); + + const app = getTestExpressApp(); + + let createRes = await new Promise((resolve) => + request(app) + .post("/create") + .expect(200) + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + const info = extractInfoFromResponse(createRes); + + let mergeRes = await new Promise((res, rej) => + request(app) + .post("/merge-into-payload") + .set("Cookie", `sAccessToken=${info.accessTokenFromAny}`) + .type("application/json") + .send( + JSON.stringify({ + payload: { + sub: null, + appSub: "asdf", + }, + }) + ) + .expect(200) + .end((err, resp) => { + if (err) { + rej(err); + } else { + res(resp); + } + }) + ); + + checkResponse(mergeRes, exposeAccessTokenToFrontendInCookieBasedAuth); + }); + }); + + describe("verifySession", () => { + it("should attach the appropriate tokens after refresh", async function () { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init(sessionConfig)], + }); + + const app = getTestExpressApp(); + + let createRes = await new Promise((resolve) => + request(app) + .post("/create") + .expect(200) + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + const info = extractInfoFromResponse(createRes); + let refreshRes = await new Promise((resolve, reject) => + request(app) + .post("/auth/session/refresh") + .set("Cookie", `sRefreshToken=${info.refreshTokenFromAny}`) + .expect(200) + .end((err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }) + ); + const refreshInfo = extractInfoFromResponse(refreshRes); + + let res = await new Promise((resolve, reject) => + request(app) + .get("/verify") + .set("Cookie", `sAccessToken=${refreshInfo.accessTokenFromAny}`) + .expect(200) + .end((err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }) + ); + checkResponse(res, exposeAccessTokenToFrontendInCookieBasedAuth); + }); + }); + + describe("refresh session", () => { + it("should attach the appropriate tokens", async function () { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init(sessionConfig)], + }); + + const app = getTestExpressApp(); + + let createRes = await new Promise((resolve) => + request(app) + .post("/create") + .expect(200) + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + const info = extractInfoFromResponse(createRes); + + let res = await new Promise((resolve, reject) => + request(app) + .post("/auth/session/refresh") + .set("Cookie", `sRefreshToken=${info.refreshTokenFromAny}`) + .expect(200) + .end((err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }) + ); + + checkResponse(res, exposeAccessTokenToFrontendInCookieBasedAuth); + }); + }); + }); +} + +function checkResponse(resp, exposeAccessTokenToFrontendInCookieBasedAuth) { + const info = extractInfoFromResponse(resp); + + if (exposeAccessTokenToFrontendInCookieBasedAuth) { + assert.strictEqual(info.accessToken, info.accessTokenFromHeader); + } else { + assert.notStrictEqual(info.accessToken, undefined); + assert.strictEqual(info.accessTokenFromHeader, undefined); + } +} + +function getTestExpressApp() { + const app = express(); + + app.use(middleware()); + app.use(json()); + + app.post("/create", async (req, res) => { + try { + await Session.createNewSession(req, res, "", req.body.payload, {}); + res.status(200).send(""); + } catch (ex) { + res.status(400).json({ message: ex.message }); + } + }); + + app.get("/verify", verifySession(), async (req, res) => { + res.status(200).json({ message: true, sessionHandle: req.session.getHandle(), sessionExists: true }); + }); + + app.get("/verify-checkdb", verifySession({ checkDatabase: true }), async (req, res) => { + res.status(200).json({ message: true, sessionHandle: req.session.getHandle(), sessionExists: true }); + }); + + app.get("/verify-optional", verifySession({ sessionRequired: false }), async (req, res) => { + res.status(200).json({ + message: true, + sessionHandle: req.session && req.session.getHandle(), + sessionExists: !!req.session, + }); + }); + + app.post("/merge-into-payload", verifySession(), async (req, res) => { + await req.session.mergeIntoAccessTokenPayload(req.body.payload); + res.status(200).json({ + message: true, + sessionHandle: req.session && req.session.getHandle(), + sessionExists: !!req.session, + newPayload: await req.session.getAccessTokenPayload(), + }); + }); + + app.get("/revoke-session", verifySession(), async (req, res) => { + res.status(200).json({ message: await req.session.revokeSession(), sessionHandle: req.session.getHandle() }); + }); + + app.use(errorHandler()); + return app; +} diff --git a/test/session/sessionHandlingFuncsWithoutReq.test.js b/test/session/sessionHandlingFuncsWithoutReq.test.js new file mode 100644 index 000000000..972ac0305 --- /dev/null +++ b/test/session/sessionHandlingFuncsWithoutReq.test.js @@ -0,0 +1,381 @@ +/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * 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. + */ +const { printPath, setupST, startST, killAllST, cleanST, extractInfoFromResponse } = require("../utils"); +const assert = require("assert"); +const SuperTokens = require("../.."); +const Session = require("../../recipe/session"); + +describe(`Session handling functions without modifying response: ${printPath( + "[test/session/sessionHandlingFuncsWithoutReq.test.js]" +)}`, function () { + beforeEach(async function () { + await killAllST(); + await setupST(); + }); + + after(async function () { + await killAllST(); + await cleanST(); + }); + + describe("createNewSessionWithoutRequestResponse", () => { + it("should create a new session", async () => { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + }); + + const res = await Session.createNewSessionWithoutRequestResponse( + "test-user-id", + { tokenProp: true }, + { dbProp: true } + ); + assert.ok(res); + const tokens = res.getAllSessionTokensDangerously(); + assert.strictEqual(tokens.accessAndFrontTokenUpdated, true); + assert.strictEqual(tokens.antiCsrfToken, undefined); + + const payload = res.getAccessTokenPayload(); + assert.strictEqual(payload.sub, "test-user-id"); + assert.strictEqual(payload.tokenProp, true); + assert.strictEqual(payload.iss, "https://api.supertokens.io/auth"); + + assert.deepStrictEqual(await res.getSessionDataFromDatabase(), { dbProp: true }); + }); + + it("should create a new session w/ anti-csrf", async () => { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Session.init({ + antiCsrf: "VIA_TOKEN", + }), + ], + }); + + const session = await Session.createNewSessionWithoutRequestResponse( + "test-user-id", + { tokenProp: true }, + { dbProp: true } + ); + assert.ok(session); + const tokens = session.getAllSessionTokensDangerously(); + assert.strictEqual(tokens.accessAndFrontTokenUpdated, true); + assert.notStrictEqual(tokens.antiCsrfToken, undefined); + + const payload = session.getAccessTokenPayload(); + assert.strictEqual(payload.sub, "test-user-id"); + assert.strictEqual(payload.tokenProp, true); + + assert.deepStrictEqual(await session.getSessionDataFromDatabase(), { dbProp: true }); + }); + }); + + describe("getSessionWithoutRequestResponse", () => { + it("should validate basic access token", async () => { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + }); + + const createRes = await Session.createNewSessionWithoutRequestResponse("test-user-id"); + const tokens = createRes.getAllSessionTokensDangerously(); + const session = await Session.getSessionWithoutRequestResponse(tokens.accessToken, tokens.antiCsrfToken); + assert.ok(session); + /** @type {import("../../recipe/session").SessionContainer} */ + const getSessionTokenInfo = session.getAllSessionTokensDangerously(); + assert.deepStrictEqual(getSessionTokenInfo, { + accessToken: tokens.accessToken, + frontToken: tokens.frontToken, + antiCsrfToken: tokens.antiCsrfToken, + accessAndFrontTokenUpdated: false, + refreshToken: undefined, + }); + }); + + it("should validate basic access token with anti-csrf", async () => { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Session.init({ + antiCsrf: "VIA_TOKEN", + }), + ], + }); + + const createRes = await Session.createNewSessionWithoutRequestResponse("test-user-id"); + const tokens = createRes.getAllSessionTokensDangerously(); + const session = await Session.getSessionWithoutRequestResponse(tokens.accessToken, tokens.antiCsrfToken); + + const getSessionTokenInfo = session.getAllSessionTokensDangerously(); + assert.deepStrictEqual(getSessionTokenInfo, { + accessToken: tokens.accessToken, + frontToken: tokens.frontToken, + antiCsrfToken: tokens.antiCsrfToken, + accessAndFrontTokenUpdated: false, + refreshToken: undefined, + }); + + let caught; + try { + await Session.getSessionWithoutRequestResponse(tokens.accessToken, undefined); + } catch (ex) { + caught = ex; + } + assert.ok(caught); + assert(Session.Error.isErrorFromSuperTokens(caught)); + assert.strictEqual(caught.type, Session.Error.TRY_REFRESH_TOKEN); + + const getSessionWithAntiCSRFDisabled = await Session.getSessionWithoutRequestResponse( + tokens.accessToken, + undefined, + { + antiCsrfCheck: false, + } + ); + assert.ok(getSessionWithAntiCSRFDisabled); + }); + + it("should return error for non-tokens", async () => { + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Session.init({ + antiCsrf: "VIA_TOKEN", + }), + ], + }); + + let caught; + try { + await Session.getSessionWithoutRequestResponse("nope"); + } catch (ex) { + caught = ex; + } + assert.ok(caught); + assert(Session.Error.isErrorFromSuperTokens(caught)); + assert.strictEqual(caught.type, Session.Error.UNAUTHORISED); + }); + + it("should return undefined for non-tokens with requireSession false", async () => { + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Session.init({ + antiCsrf: "VIA_TOKEN", + }), + ], + }); + + const res = await Session.getSessionWithoutRequestResponse("nope", undefined, { sessionRequired: false }); + assert.strictEqual(res, undefined); + }); + + it("should return error for claim validation failures", async () => { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + }); + + const createRes = await Session.createNewSessionWithoutRequestResponse("test-user-id"); + const tokens = createRes.getAllSessionTokensDangerously(); + let caught; + try { + await Session.getSessionWithoutRequestResponse(tokens.accessToken, undefined, { + overrideGlobalClaimValidators: () => [ + { id: "test", validate: () => ({ isValid: false, reason: "test" }) }, + ], + }); + } catch (ex) { + caught = ex; + } + assert.ok(caught); + assert(Session.Error.isErrorFromSuperTokens(caught)); + assert.strictEqual(caught.type, Session.Error.INVALID_CLAIMS); + }); + }); + + describe("refreshSessionWithoutRequestResponse", () => { + it("should refresh session", async () => { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [Session.init()], + }); + + const createRes = await Session.createNewSessionWithoutRequestResponse( + "test-user-id", + { tokenProp: true }, + { dbProp: true } + ); + const tokens = createRes.getAllSessionTokensDangerously(); + const session = await Session.refreshSessionWithoutRequestResponse( + tokens.refreshToken, + false, + tokens.antiCsrfToken + ); + assert.ok(session); + + const tokensAfterRefresh = session.getAllSessionTokensDangerously(); + assert.strictEqual(tokensAfterRefresh.accessAndFrontTokenUpdated, true); + assert.strictEqual(tokensAfterRefresh.antiCsrfToken, undefined); + + const payload = session.getAccessTokenPayload(); + assert.strictEqual(payload.sub, "test-user-id"); + assert.strictEqual(payload.tokenProp, true); + + assert.deepStrictEqual(await session.getSessionDataFromDatabase(), { dbProp: true }); + }); + + it("should work with anti-csrf", async () => { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Session.init({ + antiCsrf: "VIA_TOKEN", + }), + ], + }); + + const createRes = await Session.createNewSessionWithoutRequestResponse("test-user-id"); + const tokens = createRes.getAllSessionTokensDangerously(); + + const session = await Session.refreshSessionWithoutRequestResponse( + tokens.refreshToken, + false, + tokens.antiCsrfToken + ); + + assert.ok(session); + const tokensAfterRefresh = session.getAllSessionTokensDangerously(); + assert.strictEqual(tokensAfterRefresh.accessAndFrontTokenUpdated, true); + + let caught; + try { + await Session.refreshSessionWithoutRequestResponse(tokensAfterRefresh.refreshToken, false); + } catch (ex) { + caught = ex; + } + assert.ok(caught); + assert(Session.Error.isErrorFromSuperTokens(caught)); + assert.strictEqual(caught.type, Session.Error.UNAUTHORISED); + + const sessionAfterRefreshWithDisabledAntiCsrf = await Session.refreshSessionWithoutRequestResponse( + tokensAfterRefresh.refreshToken, + true + ); + const tokensAfterRefreshWithDisable = sessionAfterRefreshWithDisabledAntiCsrf.getAllSessionTokensDangerously(); + assert.strictEqual(tokensAfterRefreshWithDisable.accessAndFrontTokenUpdated, true); + }); + + it("should return error for non-tokens", async () => { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Session.init({ + antiCsrf: "VIA_TOKEN", + }), + ], + }); + + let caught; + try { + await Session.refreshSessionWithoutRequestResponse("nope"); + } catch (ex) { + caught = ex; + } + assert.ok(caught); + assert(Session.Error.isErrorFromSuperTokens(caught)); + assert.strictEqual(caught.type, Session.Error.UNAUTHORISED); + }); + }); +}); diff --git a/test/session/with-jwt/jwt.override.test.js b/test/session/with-jwt/jwt.override.test.js deleted file mode 100644 index 7da217e01..000000000 --- a/test/session/with-jwt/jwt.override.test.js +++ /dev/null @@ -1,214 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ - -const { printPath, setupST, startST, killAllST, cleanST } = require("../../utils"); -let { Querier } = require("../../../lib/build/querier"); -let { maxVersion } = require("../../../lib/build/utils"); -let assert = require("assert"); -const express = require("express"); -const request = require("supertest"); -let { ProcessState } = require("../../../lib/build/processState"); -let SuperTokens = require("../../../"); -let Session = require("../../../recipe/session"); -let { middleware, errorHandler } = require("../../../framework/express"); - -/** - * Test that overriding the jwt recipe functions and apis still work when the JWT feature is enabled - */ -describe(`session-with-jwt: ${printPath("[test/session/with-jwt/jwt.override.test.js]")}`, function () { - beforeEach(async function () { - await killAllST(); - await setupST(); - ProcessState.getInstance().reset(); - }); - - after(async function () { - await killAllST(); - await cleanST(); - }); - - it("Test overriding functions", async function () { - await startST(); - - let jwtCreated = undefined; - let jwksKeys = undefined; - - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - openIdFeature: { - jwtFeature: { - functions: function (originalImplementation) { - return { - ...originalImplementation, - createJWT: async function (input) { - let createJWTResponse = await originalImplementation.createJWT(input); - - if (createJWTResponse.status === "OK") { - jwtCreated = createJWTResponse.jwt; - } - - return createJWTResponse; - }, - getJWKS: async function () { - let getJWKSResponse = await originalImplementation.getJWKS(); - - if (getJWKSResponse.status === "OK") { - jwksKeys = getJWKSResponse.keys; - } - - return getJWKSResponse; - }, - }; - }, - }, - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res.body); - } - }) - ); - - let sessionHandle = createJWTResponse.sessionHandle; - assert.notStrictEqual(jwtCreated, undefined); - - let sessionInformation = await Session.getSessionInformation(sessionHandle); - assert.deepStrictEqual(jwtCreated, sessionInformation.accessTokenPayload.jwt); - - let getJWKSResponse = await new Promise((resolve) => { - request(app) - .get("/auth/jwt/jwks.json") - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res.body); - } - }); - }); - - assert.notStrictEqual(jwksKeys, undefined); - assert.deepStrictEqual(jwksKeys, getJWKSResponse.keys); - }); - - it("Test overriding APIs", async function () { - await startST(); - - let jwksKeys = undefined; - - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - openIdFeature: { - jwtFeature: { - apis: function (originalImplementation) { - return { - ...originalImplementation, - getJWKSGET: async function (input) { - let response = await originalImplementation.getJWKSGET(input); - jwksKeys = response.keys; - return response; - }, - }; - }, - }, - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - - let getJWKSResponse = await new Promise((resolve) => { - request(app) - .get("/auth/jwt/jwks.json") - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res.body); - } - }); - }); - - app.use(errorHandler()); - - assert.notStrictEqual(jwksKeys, undefined); - assert.deepStrictEqual(jwksKeys, getJWKSResponse.keys); - }); -}); diff --git a/test/session/with-jwt/jwtFunctions.test.js b/test/session/with-jwt/jwtFunctions.test.js deleted file mode 100644 index 8a78e92f9..000000000 --- a/test/session/with-jwt/jwtFunctions.test.js +++ /dev/null @@ -1,169 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ -const { printPath, setupST, startST, killAllST, cleanST } = require("../../utils"); -let { ProcessState } = require("../../../lib/build/processState"); -let SuperTokens = require("../../../"); -let Session = require("../../../recipe/session"); -let { Querier } = require("../../../lib/build/querier"); -let { maxVersion } = require("../../../lib/build/utils"); - -describe(`session-jwt-functions: ${printPath("[test/session/with-jwt/jwtFunctions.test.js]")}`, function () { - beforeEach(async function () { - await killAllST(); - await setupST(); - ProcessState.getInstance().reset(); - }); - - after(async function () { - await killAllST(); - await cleanST(); - }); - - it("Test that JWT functions fail if the jwt feature is not enabled", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - try { - await Session.createJWT({}); - throw new Error("createJWT succeeded when it should have failed"); - } catch (e) { - if ( - e.message !== - "createJWT cannot be used without enabling the JWT feature. Please set 'enableJWT: true' when initialising the Session recipe" - ) { - throw e; - } - } - - try { - await Session.getJWKS(); - throw new Error("getJWKS succeeded when it should have failed"); - } catch (e) { - if ( - e.message !== - "getJWKS cannot be used without enabling the JWT feature. Please set 'enableJWT: true' when initialising the Session recipe" - ) { - throw e; - } - } - }); - - it("Test that JWT functions work if the jwt feature is enabled", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - await Session.createJWT({}); - await Session.getJWKS(); - }); -}); diff --git a/test/session/with-jwt/session.override.test.js b/test/session/with-jwt/session.override.test.js deleted file mode 100644 index a414c1724..000000000 --- a/test/session/with-jwt/session.override.test.js +++ /dev/null @@ -1,689 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ - -const { - printPath, - setupST, - startST, - killAllST, - cleanST, - extractInfoFromResponse, - setKeyValueInConfig, -} = require("../../utils"); -let assert = require("assert"); -const express = require("express"); -const request = require("supertest"); -let { ProcessState, PROCESS_STATE } = require("../../../lib/build/processState"); -let SuperTokens = require("../../../"); -let Session = require("../../../recipe/session"); -let { Querier } = require("../../../lib/build/querier"); -let { maxVersion } = require("../../../lib/build/utils"); -const { verifySession } = require("../../../recipe/session/framework/express"); -let { middleware, errorHandler } = require("../../../framework/express"); - -/** - * Test that overriding the session recipe functions and apis still work when the JWT feature is enabled - */ -describe(`session: ${printPath("[test/session/with-jwt/session.override.test.js]")}`, function () { - beforeEach(async function () { - await killAllST(); - await setupST(); - ProcessState.getInstance().reset(); - }); - - after(async function () { - await killAllST(); - await cleanST(); - }); - - it("test overriding of sessions functions", async function () { - await startST(); - - let createNewSessionCalled = false; - let getSessionCalled = false; - let refreshSessionCalled = false; - let session = undefined; - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - apiBasePath: "/", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - antiCsrf: "VIA_TOKEN", - jwt: { enable: true }, - override: { - functions: function (oI) { - return { - ...oI, - createNewSession: async function (input) { - let response = await oI.createNewSession(input); - createNewSessionCalled = true; - session = response; - return response; - }, - getSession: async function (input) { - let response = await oI.getSession(input); - getSessionCalled = true; - session = response; - return response; - }, - refreshSession: async function (input) { - let response = await oI.refreshSession(input); - refreshSessionCalled = true; - session = response; - return response; - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - const app = express(); - - app.use(middleware()); - - app.post("/create", async (req, res) => { - await Session.createNewSession(req, res, "", {}, {}); - res.status(200).send(""); - }); - - app.post("/session/verify", verifySession(), async (req, res) => { - res.status(200).send(""); - }); - - app.post("/session/revoke", verifySession(), async (req, res) => { - let session = req.session; - await session.revokeSession(); - res.status(200).send(""); - }); - - app.use(errorHandler()); - - let res = extractInfoFromResponse( - await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ) - ); - - assert.strictEqual(createNewSessionCalled, true); - assert.notStrictEqual(session, undefined); - assert(res.accessToken !== undefined); - assert.strictEqual(session.getAccessToken(), decodeURIComponent(res.accessToken)); - assert(res.antiCsrf !== undefined); - assert(res.refreshToken !== undefined); - session = undefined; - - await new Promise((resolve) => - request(app) - .post("/session/verify") - .set("Cookie", ["sAccessToken=" + res.accessToken]) - .set("anti-csrf", res.antiCsrf) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let verifyState3 = await ProcessState.getInstance().waitForEvent(PROCESS_STATE.CALLING_SERVICE_IN_VERIFY, 1500); - assert(verifyState3 === undefined); - - let res2 = extractInfoFromResponse( - await new Promise((resolve) => - request(app) - .post("/session/refresh") - .set("Cookie", ["sRefreshToken=" + res.refreshToken]) - .set("anti-csrf", res.antiCsrf) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ) - ); - - assert.strictEqual(refreshSessionCalled, true); - assert.notStrictEqual(session, undefined); - assert(res2.accessToken !== undefined); - assert.strictEqual(session.getAccessToken(), decodeURIComponent(res2.accessToken)); - assert(res2.antiCsrf !== undefined); - assert(res2.refreshToken !== undefined); - session = undefined; - - let res3 = extractInfoFromResponse( - await new Promise((resolve) => - request(app) - .post("/session/verify") - .set("Cookie", ["sAccessToken=" + res2.accessToken]) - .set("anti-csrf", res2.antiCsrf) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ) - ); - let verifyState = await ProcessState.getInstance().waitForEvent(PROCESS_STATE.CALLING_SERVICE_IN_VERIFY); - assert.strictEqual(getSessionCalled, true); - assert.notStrictEqual(session, undefined); - assert(verifyState !== undefined); - assert(res3.accessToken !== undefined); - assert.strictEqual(session.getAccessToken(), decodeURIComponent(res3.accessToken)); - - ProcessState.getInstance().reset(); - - await new Promise((resolve) => - request(app) - .post("/session/verify") - .set("Cookie", ["sAccessToken=" + res3.accessToken]) - .set("anti-csrf", res2.antiCsrf) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - let verifyState2 = await ProcessState.getInstance().waitForEvent(PROCESS_STATE.CALLING_SERVICE_IN_VERIFY, 1000); - assert(verifyState2 === undefined); - - let sessionRevokedResponse = await new Promise((resolve) => - request(app) - .post("/session/revoke") - .set("Cookie", ["sAccessToken=" + res3.accessToken]) - .set("anti-csrf", res2.antiCsrf) - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - let sessionRevokedResponseExtracted = extractInfoFromResponse(sessionRevokedResponse); - assert(sessionRevokedResponseExtracted.accessTokenExpiry === "Thu, 01 Jan 1970 00:00:00 GMT"); - assert(sessionRevokedResponseExtracted.refreshTokenExpiry === "Thu, 01 Jan 1970 00:00:00 GMT"); - assert(sessionRevokedResponseExtracted.accessToken === ""); - assert(sessionRevokedResponseExtracted.refreshToken === ""); - }); - - it("test overriding of sessions functions, error thrown", async function () { - await startST(); - - let createNewSessionCalled = false; - let session = undefined; - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - apiBasePath: "/", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - antiCsrf: "VIA_TOKEN", - jwt: { enable: true }, - override: { - functions: function (oI) { - return { - ...oI, - createNewSession: async function (input) { - let response = await oI.createNewSession(input); - createNewSessionCalled = true; - session = response; - throw { - error: "create new session error", - }; - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - const app = express(); - - app.use(middleware()); - - app.post("/create", async (req, res, next) => { - try { - await Session.createNewSession(req, res, "", {}, {}); - res.status(200).send(""); - } catch (err) { - next(err); - } - }); - - app.use(errorHandler()); - - app.use((err, req, res, next) => { - res.json({ - customError: true, - ...err, - }); - }); - - let res = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res.body); - } - }) - ); - - assert.strictEqual(createNewSessionCalled, true); - assert.notStrictEqual(session, undefined); - assert.deepStrictEqual(res, { customError: true, error: "create new session error" }); - }); - - it("test overriding of sessions apis", async function () { - await startST(); - - let signoutCalled = false; - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - apiBasePath: "/", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - antiCsrf: "VIA_TOKEN", - jwt: { enable: true }, - override: { - apis: function (oI) { - return { - ...oI, - signOutPOST: async function (input) { - let response = await oI.signOutPOST(input); - signoutCalled = true; - return response; - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - const app = express(); - - app.use(middleware()); - - app.post("/create", async (req, res) => { - await Session.createNewSession(req, res, "", {}, {}); - res.status(200).send(""); - }); - - app.post("/session/verify", verifySession(), async (req, res) => { - res.status(200).send(""); - }); - - app.use(errorHandler()); - - let res = extractInfoFromResponse( - await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ) - ); - - assert(res.accessToken !== undefined); - assert(res.antiCsrf !== undefined); - assert(res.refreshToken !== undefined); - - let sessionRevokedResponse = await new Promise((resolve) => - request(app) - .post("/signout") - .set("Cookie", ["sAccessToken=" + res.accessToken]) - .set("anti-csrf", res.antiCsrf) - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - let sessionRevokedResponseExtracted = extractInfoFromResponse(sessionRevokedResponse); - assert.strictEqual(signoutCalled, true); - assert(sessionRevokedResponseExtracted.accessTokenExpiry === "Thu, 01 Jan 1970 00:00:00 GMT"); - assert(sessionRevokedResponseExtracted.refreshTokenExpiry === "Thu, 01 Jan 1970 00:00:00 GMT"); - assert(sessionRevokedResponseExtracted.accessToken === ""); - assert(sessionRevokedResponseExtracted.refreshToken === ""); - }); - - it("test overriding of sessions apis, error thrown", async function () { - await startST(); - - let signoutCalled = false; - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - apiBasePath: "/", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - antiCsrf: "VIA_TOKEN", - jwt: { enable: true }, - override: { - apis: function (oI) { - return { - ...oI, - signOutPOST: async function (input) { - let response = await oI.signOutPOST(input); - signoutCalled = true; - throw { - error: "signout error", - }; - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - const app = express(); - - app.use(middleware()); - - app.post("/create", async (req, res) => { - await Session.createNewSession(req, res, "", {}, {}); - res.status(200).send(""); - }); - - app.post("/session/verify", verifySession(), async (req, res) => { - res.status(200).send(""); - }); - - app.use(errorHandler()); - - app.use((err, req, res, next) => { - res.json({ - customError: true, - ...err, - }); - }); - - let res = extractInfoFromResponse( - await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ) - ); - - assert(res.accessToken !== undefined); - assert(res.antiCsrf !== undefined); - assert(res.refreshToken !== undefined); - - let sessionRevokedResponse = await new Promise((resolve) => - request(app) - .post("/signout") - .set("Cookie", ["sAccessToken=" + res.accessToken]) - .set("anti-csrf", res.antiCsrf) - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res.body); - } - }) - ); - assert.strictEqual(signoutCalled, true); - assert.deepStrictEqual(sessionRevokedResponse, { customError: true, error: "signout error" }); - }); - - it("test that if disabling api, the default refresh API does not work", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - apis: function (oI) { - return { - ...oI, - refreshPOST: undefined, - }; - }, - }, - antiCsrf: "VIA_TOKEN", - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - const app = express(); - app.use(middleware()); - - app.post("/create", async (req, res) => { - await Session.createNewSession(req, res, "", {}, {}); - res.status(200).send(""); - }); - - let res = extractInfoFromResponse( - await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ) - ); - - let res2 = await new Promise((resolve) => - request(app) - .post("/auth/session/refresh") - .set("Cookie", ["sRefreshToken=" + res.refreshToken]) - .set("anti-csrf", res.antiCsrf) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - assert(res2.status === 404); - }); - - it("test that if disabling api, the default sign out API does not work", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - apis: function (oI) { - return { - ...oI, - signOutPOST: undefined, - }; - }, - }, - antiCsrf: "VIA_TOKEN", - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - const app = express(); - app.use(middleware()); - - app.post("/create", async (req, res) => { - await Session.createNewSession(req, res, "", {}, {}); - res.status(200).send(""); - }); - - let res = extractInfoFromResponse( - await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ) - ); - - let res2 = await new Promise((resolve) => - request(app) - .post("/auth/signout") - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - assert(res2.status === 404); - }); -}); diff --git a/test/session/with-jwt/sessionClass.test.js b/test/session/with-jwt/sessionClass.test.js deleted file mode 100644 index 6fb3e2fb6..000000000 --- a/test/session/with-jwt/sessionClass.test.js +++ /dev/null @@ -1,558 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ -const JsonWebToken = require("jsonwebtoken"); - -const { printPath, setupST, startST, killAllST, cleanST, extractInfoFromResponse, resetAll } = require("../../utils"); -let { Querier } = require("../../../lib/build/querier"); -let { maxVersion } = require("../../../lib/build/utils"); -let assert = require("assert"); -const express = require("express"); -const request = require("supertest"); -let { ProcessState } = require("../../../lib/build/processState"); -let SuperTokens = require("../../../"); -let Session = require("../../../recipe/session"); -let { middleware, errorHandler } = require("../../../framework/express"); -const { TrueClaim } = require("../claims/testClaims"); - -describe(`session-jwt-functions: ${printPath("[test/session/with-jwt/sessionClass.test.js]")}`, function () { - beforeEach(async function () { - await killAllST(); - await setupST(); - ProcessState.getInstance().reset(); - }); - - after(async function () { - await killAllST(); - await cleanST(); - }); - - it("Test that updating access token payload works", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - - await session.updateAccessTokenPayload({ newKey: "newValue" }); - - res.status(200).json({ accessTokenPayload: session.getAccessTokenPayload() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let accessTokenPayload = createJWTResponse.body.accessTokenPayload; - assert.strictEqual(accessTokenPayload.sub, undefined); - assert.strictEqual(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload.newKey, "newValue"); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT["sub"], "userId"); - assert.strictEqual(decodedJWT.iss, "https://api.supertokens.io/auth"); - assert.strictEqual(decodedJWT._jwtPName, undefined); - assert.strictEqual(decodedJWT.newKey, "newValue"); - }); - - it("Test that updating access token payload by mergeIntoAccessTokenPayload works", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function (input) { - const accessTokenPayload = { - ...input.accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ ...input, accessTokenPayload }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - - await session.mergeIntoAccessTokenPayload({ newKey: "newValue" }); - - res.status(200).json({ accessTokenPayload: session.getAccessTokenPayload() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let accessTokenPayload = createJWTResponse.body.accessTokenPayload; - assert.strictEqual(accessTokenPayload.sub, undefined); - assert.strictEqual(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload.newKey, "newValue"); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT["sub"], "userId"); - assert.strictEqual(decodedJWT.iss, "https://api.supertokens.io/auth"); - assert.strictEqual(decodedJWT._jwtPName, undefined); - assert.strictEqual(decodedJWT.newKey, "newValue"); - }); - - it("Test that both access token payload and JWT have valid claims when calling update with a undefined payload", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function (input) { - const accessTokenPayload = { - ...input.accessTokenPayload, - customClaim: "customValue", - }; - - return await oi.createNewSession({ ...input, accessTokenPayload }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - - await session.updateAccessTokenPayload(undefined); - - res.status(200).json({ accessTokenPayload: session.getAccessTokenPayload() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let accessTokenPayload = createJWTResponse.body.accessTokenPayload; - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - assert.strictEqual(accessTokenPayload.customClaim, undefined); - - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT["sub"], "userId"); - assert.strictEqual(decodedJWT.iss, "https://api.supertokens.io/auth"); - assert.strictEqual(decodedJWT._jwtPName, undefined); - assert.strictEqual(decodedJWT.customClaim, undefined); - }); - - it("should update JWT when setting claim value by fetchAndSetClaim", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function (input) { - const accessTokenPayload = { - ...input.accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ ...input, accessTokenPayload }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - - await session.fetchAndSetClaim(TrueClaim); - - res.status(200).json({ accessTokenPayload: session.getAccessTokenPayload() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let accessTokenPayload = createJWTResponse.body.accessTokenPayload; - assert.strictEqual(accessTokenPayload.sub, undefined); - assert.strictEqual(accessTokenPayload.iss, undefined); - assert.strictEqual(TrueClaim.getValueFromPayload(accessTokenPayload), true); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT["sub"], "userId"); - assert.strictEqual(decodedJWT.iss, "https://api.supertokens.io/auth"); - assert.strictEqual(decodedJWT._jwtPName, undefined); - assert.strictEqual(TrueClaim.getValueFromPayload(decodedJWT), true); - }); - - it("should update JWT when setting claim value by setClaimValue", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function (input) { - const accessTokenPayload = { - ...input.accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ ...input, accessTokenPayload }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - - await session.setClaimValue(TrueClaim, false); - - res.status(200).json({ accessTokenPayload: session.getAccessTokenPayload() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let accessTokenPayload = createJWTResponse.body.accessTokenPayload; - assert.strictEqual(accessTokenPayload.sub, undefined); - assert.strictEqual(accessTokenPayload.iss, undefined); - assert.strictEqual(TrueClaim.getValueFromPayload(accessTokenPayload), false); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT["sub"], "userId"); - assert.strictEqual(decodedJWT.iss, "https://api.supertokens.io/auth"); - assert.strictEqual(decodedJWT._jwtPName, undefined); - assert.strictEqual(TrueClaim.getValueFromPayload(decodedJWT), false); - }); - - it("should update JWT when removing claim", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function (input) { - const accessTokenPayload = { - ...input.accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ ...input, accessTokenPayload }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - - await session.setClaimValue(TrueClaim, true); - await session.removeClaim(TrueClaim); - - res.status(200).json({ accessTokenPayload: session.getAccessTokenPayload() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let accessTokenPayload = createJWTResponse.body.accessTokenPayload; - assert.strictEqual(accessTokenPayload.sub, undefined); - assert.strictEqual(accessTokenPayload.iss, undefined); - assert.strictEqual(TrueClaim.getValueFromPayload(accessTokenPayload), undefined); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT["sub"], "userId"); - assert.strictEqual(decodedJWT.iss, "https://api.supertokens.io/auth"); - assert.strictEqual(decodedJWT._jwtPName, undefined); - assert.strictEqual(TrueClaim.getValueFromPayload(decodedJWT), undefined); - }); -}); diff --git a/test/session/with-jwt/withjwt.test.js b/test/session/with-jwt/withjwt.test.js deleted file mode 100644 index e7d045e6d..000000000 --- a/test/session/with-jwt/withjwt.test.js +++ /dev/null @@ -1,2334 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * 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. - */ -const JsonWebToken = require("jsonwebtoken"); - -const { - printPath, - setupST, - startST, - killAllST, - cleanST, - extractInfoFromResponse, - resetAll, - setKeyValueInConfig, - delay, -} = require("../../utils"); -let { Querier } = require("../../../lib/build/querier"); -let { maxVersion } = require("../../../lib/build/utils"); -let assert = require("assert"); -const express = require("express"); -const request = require("supertest"); -let { ProcessState } = require("../../../lib/build/processState"); -let SuperTokens = require("../../../"); -let Session = require("../../../recipe/session"); -let { middleware, errorHandler } = require("../../../framework/express"); -let { - setJWTExpiryOffsetSecondsForTesting, -} = require("../../../lib/build/recipe/session/with-jwt/recipeImplementation"); - -describe(`session-with-jwt: ${printPath("[test/session/with-jwt/withjwt.test.js]")}`, function () { - beforeEach(async function () { - await killAllST(); - await setupST(); - ProcessState.getInstance().reset(); - }); - - after(async function () { - await killAllST(); - await cleanST(); - }); - - it("Test that when creating a session with a custom access token payload, the payload has a jwt in it and the jwt has the user defined payload keys", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res.body); - } - }) - ); - - let sessionHandle = createJWTResponse.sessionHandle; - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - let accessTokenPayloadJWT = accessTokenPayload.jwt; - - assert.strictEqual(accessTokenPayload.sub, undefined); - assert.strictEqual(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - assert.notStrictEqual(accessTokenPayloadJWT, undefined); - - let decodedJWTPayload = JsonWebToken.decode(accessTokenPayloadJWT); - - assert(decodedJWTPayload.customKey === "customValue"); - assert(decodedJWTPayload.customKey2 === "customValue2"); - }); - - it("Test that when creating a session the JWT expiry is 30 seconds more than the access token expiry", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let responseInfo = extractInfoFromResponse(createJWTResponse); - - let accessTokenExpiryInSeconds = - JSON.parse( - Buffer.from(decodeURIComponent(responseInfo.accessToken).split(".")[1], "base64").toString("utf-8") - ).expiryTime / 1000; - let sessionHandle = createJWTResponse.body.sessionHandle; - let sessionInformation = await Session.getSessionInformation(sessionHandle); - - let jwtPayload = sessionInformation.accessTokenPayload.jwt.split(".")[1]; - let jwtExpiryInSeconds = JSON.parse(Buffer.from(jwtPayload, "base64").toString("utf-8")).exp; - let expiryDiff = jwtExpiryInSeconds - accessTokenExpiryInSeconds; - - // We check that JWT expiry is 30 seconds more than access token expiry. Accounting for a 5s skew - assert(27 <= expiryDiff); - assert(expiryDiff <= 32); - }); - - it("Test that when a session is refreshed, the JWT expiry is updated correctly", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.get("/getSession", async (req, res) => { - let session = await Session.getSession(req, res); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let responseInfo = extractInfoFromResponse(createJWTResponse); - let sessionHandle = createJWTResponse.body.sessionHandle; - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - - let jwtPayload = accessTokenPayload.jwt.split(".")[1]; - let jwtExpiryInSeconds = JSON.parse(Buffer.from(jwtPayload, "base64").toString("utf-8")).exp; - - let delay = 5; - await new Promise((res) => { - setTimeout(() => { - res(); - }, delay * 1000); - }); - - let refreshResponse = await new Promise((resolve) => - request(app) - .post("/auth/session/refresh") - .set("Cookie", ["sRefreshToken=" + responseInfo.refreshToken]) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - responseInfo = extractInfoFromResponse(refreshResponse); - accessTokenExpiryInSeconds = new Date(responseInfo.accessTokenExpiry).getTime() / 1000; - accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - jwtPayload = accessTokenPayload.jwt.split(".")[1]; - let newJWTExpiryInSeconds = JSON.parse(Buffer.from(jwtPayload, "base64").toString("utf-8")).exp; - - assert.strictEqual(accessTokenPayload.sub, undefined); - assert.strictEqual(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - // Make sure that the new expiry is greater than the old one by the amount of delay before refresh, accounting for a second skew - assert( - newJWTExpiryInSeconds - jwtExpiryInSeconds === delay || - newJWTExpiryInSeconds - jwtExpiryInSeconds === delay + 1 - ); - }); - - it("Test that mergeIntoAccessTokenPayload updates JWT", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function (input) { - const accessTokenPayload = { - ...input.accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ ...input, accessTokenPayload }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - - let jwtPayload = accessTokenPayload.jwt.split(".")[1]; - jwtPayload = accessTokenPayload.jwt.split(".")[1]; - let parsedJWTPayload = JSON.parse(Buffer.from(jwtPayload, "base64").toString("utf-8")); - assert.strictEqual(parsedJWTPayload.newKey, undefined); - let jwtExpiryInSeconds = parsedJWTPayload.exp; - - await Session.mergeIntoAccessTokenPayload(sessionHandle, { newKey: "newValue" }); - - accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - - jwtPayload = accessTokenPayload.jwt.split(".")[1]; - parsedJWTPayload = JSON.parse(Buffer.from(jwtPayload, "base64").toString("utf-8")); - assert.strictEqual(parsedJWTPayload.newKey, "newValue"); - - const newJwtExpiryInSeconds = parsedJWTPayload.exp; - assert.strictEqual(accessTokenPayload.sub, undefined); - assert.strictEqual(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - assert(jwtExpiryInSeconds + 100 >= newJwtExpiryInSeconds && jwtExpiryInSeconds - 100 <= newJwtExpiryInSeconds); - }); - - it("Test that when updating access token payload, jwt expiry does not change", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.get("/getSession", async (req, res) => { - let session = await Session.getSession(req, res); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - - let jwtPayload = accessTokenPayload.jwt.split(".")[1]; - let jwtExpiryInSeconds = JSON.parse(Buffer.from(jwtPayload, "base64").toString("utf-8")).exp; - - await Session.updateAccessTokenPayload(sessionHandle, { newKey: "newValue" }); - - accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - jwtPayload = accessTokenPayload.jwt.split(".")[1]; - let newJwtExpiryInSeconds = JSON.parse(Buffer.from(jwtPayload, "base64").toString("utf-8")).exp; - - assert.strictEqual(accessTokenPayload.sub, undefined); - assert.strictEqual(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - assert(jwtExpiryInSeconds + 100 >= newJwtExpiryInSeconds && jwtExpiryInSeconds - 100 <= newJwtExpiryInSeconds); - }); - - it("Test that for sessions created without jwt enabled, calling updateAccessTokenPayload after enabling jwt does not create a jwt", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.get("/getSession", async (req, res) => { - let session = await Session.getSession(req, res); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - - assert.strictEqual(accessTokenPayload.jwt, undefined); - - resetAll(); - - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - await Session.updateAccessTokenPayload(sessionHandle, { someKey: "someValue" }); - accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, undefined); - assert.strictEqual(accessTokenPayload.jwt, undefined); - assert.equal(accessTokenPayload.someKey, "someValue"); - }); - - it("Test that for sessions created without jwt enabled, refreshing session after enabling jwt adds a JWT to the access token payload", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.get("/getSession", async (req, res) => { - let session = await Session.getSession(req, res); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - let responseInfo = extractInfoFromResponse(createJWTResponse); - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - - assert.strictEqual(accessTokenPayload.jwt, undefined); - - resetAll(); - - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - await new Promise((resolve) => - request(app) - .post("/auth/session/refresh") - .set("Cookie", ["sRefreshToken=" + responseInfo.refreshToken]) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - }); - - it("Test that when creating a session with jwt enabled, the sub claim gets added", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT["sub"], "userId"); - }); - - it("Test that when creating a session with jwt enabled and using a custom sub claim, the custom claim value gets used", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - sub: "customsub", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT["sub"], "customsub"); - assert.strictEqual(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - }); - - it("Test that when creating a session with jwt enabled, the iss claim gets added", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customKey: "customValue", - customKey2: "customValue2", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT["iss"], "https://api.supertokens.io/auth"); - }); - - it("Test that when creating a session with jwt enabled and using a custom iss claim, the custom claim value gets used", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - iss: "customIss", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT["iss"], "customIss"); - }); - - it("Test that sub and iss claims are still present after calling updateAccessTokenPayload", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customClaim: "customValue", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT.customClaim, "customValue"); - assert.strictEqual(decodedJWT["sub"], "userId"); - assert.strictEqual(decodedJWT.iss, "https://api.supertokens.io/auth"); - assert.strictEqual(decodedJWT._jwtPName, undefined); - - await Session.updateAccessTokenPayload(sessionHandle, { newCustomClaim: "newValue" }); - accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - - assert.strictEqual(accessTokenPayload.sub, undefined); - assert.strictEqual(accessTokenPayload.iss, undefined); - - decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT.newCustomClaim, "newValue"); - assert.strictEqual(decodedJWT["sub"], "userId"); - assert.strictEqual(decodedJWT.iss, "https://api.supertokens.io/auth"); - assert.strictEqual(decodedJWT._jwtPName, undefined); - }); - - it("Test that sub and iss claims are still present after refreshing the session", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customClaim: "customValue", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - let responseInfo = extractInfoFromResponse(createJWTResponse); - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT.customClaim, "customValue"); - assert.strictEqual(decodedJWT["sub"], "userId"); - assert.strictEqual(decodedJWT.iss, "https://api.supertokens.io/auth"); - assert.strictEqual(decodedJWT._jwtPName, undefined); - - await new Promise((resolve) => - request(app) - .post("/auth/session/refresh") - .set("Cookie", ["sRefreshToken=" + responseInfo.refreshToken]) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - - assert.strictEqual(accessTokenPayload.sub, undefined); - assert.strictEqual(accessTokenPayload.iss, undefined); - - decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT["sub"], "userId"); - assert.strictEqual(decodedJWT.iss, "https://api.supertokens.io/auth"); - }); - - it("Test that enabling JWT with a custom property name works as expected", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true, propertyNameInAccessTokenPayload: "customPropertyName" }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customClaim: "customValue", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "customPropertyName"); - assert.strictEqual(accessTokenPayload.jwt, undefined); - assert.notStrictEqual(accessTokenPayload.customPropertyName, undefined); - }); - - it("Test that the JWT payload is maintained after updating the access token payload and refreshing the session", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customClaim: "customValue", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.post("/refreshsession", async (req, res) => { - let newSession = await Session.refreshSession(req, res); - res.status(200).json({ accessTokenPayload: newSession.getAccessTokenPayload() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - let responseInfo = extractInfoFromResponse(createJWTResponse); - await Session.updateAccessTokenPayload(sessionHandle, { newClaim: "newValue" }); - - let refreshResponse = await new Promise((resolve) => - request(app) - .post("/refreshsession") - .set("Cookie", ["sRefreshToken=" + responseInfo.refreshToken]) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - assert.equal(refreshResponse.body.accessTokenPayload.sub, undefined); - assert.equal(refreshResponse.body.accessTokenPayload.iss, undefined); - assert.strictEqual(refreshResponse.body.accessTokenPayload._jwtPName, "jwt"); - assert.notStrictEqual(refreshResponse.body.accessTokenPayload, undefined); - assert.strictEqual(refreshResponse.body.accessTokenPayload.newClaim, "newValue"); - }); - - it("Test that access token payload has valid properties when creating, updating and refreshing", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customClaim: "customValue", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - let responseInfo = extractInfoFromResponse(createJWTResponse); - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - - assert.strictEqual(accessTokenPayload.customClaim, "customValue"); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload.sub, undefined); - assert.strictEqual(accessTokenPayload.iss, undefined); - - await Session.updateAccessTokenPayload(sessionHandle, { newKey: "newValue" }); - accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - - assert.strictEqual(accessTokenPayload.customClaim, undefined); - assert.strictEqual(accessTokenPayload.newKey, "newValue"); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload.sub, undefined); - assert.strictEqual(accessTokenPayload.iss, undefined); - - await new Promise((resolve) => - request(app) - .post("/auth/session/refresh") - .set("Cookie", ["sRefreshToken=" + responseInfo.refreshToken]) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - assert.strictEqual(accessTokenPayload.newKey, "newValue"); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload.sub, undefined); - assert.strictEqual(accessTokenPayload.iss, undefined); - }); - - it("Test that after changing the jwt property name, updating access token payload does not change the _jwtPName", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customClaim: "customValue", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - - resetAll(); - - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true, propertyNameInAccessTokenPayload: "jwtProperty" }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customClaim: "customValue", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - await Session.updateAccessTokenPayload(sessionHandle, { newKey: "newValue" }); - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload.newKey, "newValue"); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload.jwtProperty, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - }); - - it("Test that after changing the jwt property name, refreshing the session changes the _jwtPName", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customClaim: "customValue", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - let responseInfo = extractInfoFromResponse(createJWTResponse); - - resetAll(); - - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true, propertyNameInAccessTokenPayload: "jwtProperty" }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customClaim: "customValue", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - await new Promise((resolve) => - request(app) - .post("/auth/session/refresh") - .set("Cookie", ["sRefreshToken=" + responseInfo.refreshToken]) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload.customClaim, "customValue"); - assert.strictEqual(accessTokenPayload.jwt, undefined); - assert.notStrictEqual(accessTokenPayload.jwtProperty, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwtProperty"); - }); - - it("Test that after access token expiry and JWT expiry and refreshing the session, the access token payload and JWT are valid", async function () { - await setKeyValueInConfig("access_token_validity", 2); - await startST(); - setJWTExpiryOffsetSecondsForTesting(2); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customClaim: "customValue", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - let responseInfo = extractInfoFromResponse(createJWTResponse); - - await delay(5); - - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - - let currentTimeInSeconds = Math.ceil(Date.now() / 1000); - // Make sure that the JWT has expired - assert(decodedJWT.exp < currentTimeInSeconds); - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload.customClaim, "customValue"); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - - await new Promise((resolve) => - request(app) - .post("/auth/session/refresh") - .set("Cookie", ["sRefreshToken=" + responseInfo.refreshToken]) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload.customClaim, "customValue"); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - - // Make sure the JWT is not expired after refreshing - decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - currentTimeInSeconds = Math.ceil(Date.now() / 1000); - assert(decodedJWT.exp > currentTimeInSeconds); - }); - - it("Test that both access token payload and JWT have valid claims when calling update with a undefined payload", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Session.init({ - getTokenTransferMethod: () => "cookie", - jwt: { enable: true }, - override: { - functions: function (oi) { - return { - ...oi, - createNewSession: async function ({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }) { - accessTokenPayload = { - ...accessTokenPayload, - customClaim: "customValue", - }; - - return await oi.createNewSession({ - req, - res, - userId, - accessTokenPayload, - sessionData, - }); - }, - }; - }, - }, - }), - ], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", {}, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload.customClaim, "customValue"); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT["sub"], "userId"); - assert.strictEqual(decodedJWT.iss, "https://api.supertokens.io/auth"); - assert.strictEqual(decodedJWT._jwtPName, undefined); - - await Session.updateAccessTokenPayload(sessionHandle, undefined); - - accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.strictEqual(accessTokenPayload.customClaim, undefined); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - - decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT["sub"], "userId"); - assert.strictEqual(decodedJWT.iss, "https://api.supertokens.io/auth"); - assert.strictEqual(decodedJWT._jwtPName, undefined); - }); - - it("Test that both access token payload and JWT have valid claims when creating a session with an undefined payload", async function () { - await startST(); - SuperTokens.init({ - supertokens: { - connectionURI: "http://localhost:8080", - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [Session.init({ getTokenTransferMethod: () => "cookie", jwt: { enable: true } })], - }); - - // Only run for version >= 2.9 - let querier = Querier.getNewInstanceOrThrowError(undefined); - let apiVersion = await querier.getAPIVersion(); - if (maxVersion(apiVersion, "2.8") === "2.8") { - return; - } - - let app = express(); - - app.use(middleware()); - app.use(express.json()); - - app.post("/create", async (req, res) => { - let session = await Session.createNewSession(req, res, "userId", undefined, {}); - res.status(200).json({ sessionHandle: session.getHandle() }); - }); - - app.use(errorHandler()); - - let createJWTResponse = await new Promise((resolve) => - request(app) - .post("/create") - .expect(200) - .end((err, res) => { - if (err) { - resolve(undefined); - } else { - resolve(res); - } - }) - ); - - let sessionHandle = createJWTResponse.body.sessionHandle; - - let accessTokenPayload = (await Session.getSessionInformation(sessionHandle)).accessTokenPayload; - assert.equal(accessTokenPayload.sub, undefined); - assert.equal(accessTokenPayload.iss, undefined); - assert.notStrictEqual(accessTokenPayload.jwt, undefined); - assert.strictEqual(accessTokenPayload._jwtPName, "jwt"); - - let decodedJWT = JsonWebToken.decode(accessTokenPayload.jwt); - assert.notStrictEqual(decodedJWT, null); - assert.strictEqual(decodedJWT["sub"], "userId"); - assert.strictEqual(decodedJWT.iss, "https://api.supertokens.io/auth"); - assert.strictEqual(decodedJWT._jwtPName, undefined); - }); -}); diff --git a/test/sessionAccessTokenSigningKeyUpdate.test.js b/test/sessionAccessTokenSigningKeyUpdate.test.js index 4ac04e95b..7f5cbefb1 100644 --- a/test/sessionAccessTokenSigningKeyUpdate.test.js +++ b/test/sessionAccessTokenSigningKeyUpdate.test.js @@ -12,21 +12,9 @@ * License for the specific language governing permissions and limitations * under the License. */ -const { - printPath, - setupST, - startST, - killAllST, - cleanST, - extractInfoFromResponse, - setKeyValueInConfig, - killAllSTCoresOnly, -} = require("./utils"); +const { printPath, setupST, startST, killAllST, cleanST, setKeyValueInConfig, killAllSTCoresOnly } = require("./utils"); let assert = require("assert"); let { Querier } = require("../lib/build/querier"); -const nock = require("nock"); -const express = require("express"); -const request = require("supertest"); let { ProcessState, PROCESS_STATE } = require("../lib/build/processState"); let SuperTokens = require("../"); let Session = require("../recipe/session"); @@ -35,6 +23,8 @@ let { parseJWTWithoutSignatureVerification } = require("../lib/build/recipe/sess let SessionRecipe = require("../lib/build/recipe/session/recipe").default; const { maxVersion } = require("../lib/build/utils"); const { fail } = require("assert"); +const sinon = require("sinon"); +const request = require("http"); /* TODO: - the opposite of the above (check that if signing key changes, things are still fine) condition @@ -47,19 +37,26 @@ const { fail } = require("assert"); describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( "[test/sessionAccessTokenSigningKeyUpdate.test.js]" )}`, function () { + let requestSpy; beforeEach(async function () { await killAllST(); await setupST(); ProcessState.getInstance().reset(); + requestSpy.resetHistory(); + }); + + before(() => { + requestSpy = sinon.spy(request, "get"); }); after(async function () { + requestSpy.restore(); await killAllST(); await cleanST(); }); it("check that if signing key changes, things are still fine", async function () { - await setKeyValueInConfig("access_token_signing_key_update_interval", "0.001"); // 5 seconds is the update interval + await setKeyValueInConfig("access_token_dynamic_signing_key_update_interval", "0.001"); // 5 seconds is the update interval await startST(); SuperTokens.init({ supertokens: { @@ -73,9 +70,6 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( recipeList: [Session.init({ getTokenTransferMethod: () => "cookie", antiCsrf: "VIA_TOKEN" })], }); - const currCDIVersion = await Querier.getNewInstanceOrThrowError(undefined).getAPIVersion(); - const coreSupportsMultipleSignigKeys = maxVersion(currCDIVersion, "2.8") !== "2.8"; - let response = await SessionFunctions.createNewSession( SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, "", @@ -90,7 +84,7 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( parseJWTWithoutSignatureVerification(response.accessToken.token), response.antiCsrfToken, true, - true + false ); let verifyState = await ProcessState.getInstance().waitForEvent( @@ -108,16 +102,12 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( parseJWTWithoutSignatureVerification(response.accessToken.token), response.antiCsrfToken, true, - true + false ); - // Old core versions should throw here because the signing key was updated - if (!coreSupportsMultipleSignigKeys) { - fail(); - } } catch (err) { if (err.type !== Session.Error.TRY_REFRESH_TOKEN) { throw err; - } else if (coreSupportsMultipleSignigKeys) { + } else { // Cores supporting multiple signig shouldn't throw since the signing key is still valid fail(); } @@ -135,17 +125,16 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, response.refreshToken.token, response.antiCsrfToken, - true, - "cookie", - "cookie" + false ); + assert.strictEqual(requestSpy.callCount, 1); await SessionFunctions.getSession( SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, parseJWTWithoutSignatureVerification(response2.accessToken.token), response2.antiCsrfToken, true, - true + false ); // We call verify, since refresh does not refresh the signing key info @@ -154,10 +143,11 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( 1500 ); assert(verifyState2 !== undefined); + assert.strictEqual(requestSpy.callCount, 2); }); it("check that if signing key changes, after new key is fetched - via token query, old tokens don't query the core", async function () { - await setKeyValueInConfig("access_token_signing_key_update_interval", "0.001"); // 5 seconds is the update interval + await setKeyValueInConfig("access_token_dynamic_signing_key_update_interval", "0.001"); // 5 seconds is the update interval await startST(); SuperTokens.init({ supertokens: { @@ -171,9 +161,6 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( recipeList: [Session.init({ getTokenTransferMethod: () => "cookie", antiCsrf: "VIA_TOKEN" })], }); - const currCDIVersion = await Querier.getNewInstanceOrThrowError(undefined).getAPIVersion(); - const coreSupportsMultipleSignigKeys = maxVersion(currCDIVersion, "2.8") !== "2.8"; - const oldSession = await SessionFunctions.createNewSession( SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, "", @@ -191,9 +178,6 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( ); await new Promise((r) => setTimeout(r, 6000)); - let originalHandShakeInfo = ( - await SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.getHandshakeInfo() - ).clone(); const newSession = await SessionFunctions.createNewSession( SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, @@ -203,15 +187,13 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( {} ); - SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.setHandshakeInfo(originalHandShakeInfo); - { await SessionFunctions.getSession( SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, parseJWTWithoutSignatureVerification(newSession.accessToken.token), newSession.antiCsrfToken, true, - true + false ); let verifyState = await ProcessState.getInstance().waitForEvent( @@ -219,37 +201,21 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( 1500 ); - if (!coreSupportsMultipleSignigKeys) { - assert(verifyState === undefined); - } else { - // We call verify here, since this is a new session we can't verify locally - assert(verifyState !== undefined); - } + assert(verifyState === undefined); + assert.strictEqual(requestSpy.callCount, 1); + assert(requestSpy.getCall(0).args[0].endsWith("/.well-known/jwks.json")); } await ProcessState.getInstance().reset(); { - try { - await SessionFunctions.getSession( - SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, - parseJWTWithoutSignatureVerification(oldSession.accessToken.token), - oldSession.antiCsrfToken, - true, - true - ); - // Old core versions should throw here because the signing key was updated - if (!coreSupportsMultipleSignigKeys) { - fail(); - } - } catch (err) { - if (err.type !== Session.Error.TRY_REFRESH_TOKEN) { - throw err; - } else if (coreSupportsMultipleSignigKeys) { - // Cores supporting multiple signig shouldn't throw since the signing key is still valid - fail(); - } - } + await SessionFunctions.getSession( + SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, + parseJWTWithoutSignatureVerification(oldSession.accessToken.token), + oldSession.antiCsrfToken, + true, + false + ); let verifyState = await ProcessState.getInstance().waitForEvent( PROCESS_STATE.CALLING_SERVICE_IN_VERIFY, @@ -257,10 +223,11 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( ); assert(verifyState === undefined); } + assert.strictEqual(requestSpy.callCount, 1); }); it("check that if signing key changes, after new key is fetched - via creation of new token, old tokens don't query the core", async function () { - await setKeyValueInConfig("access_token_signing_key_update_interval", "0.001"); // 5 seconds is the update interval + await setKeyValueInConfig("access_token_dynamic_signing_key_update_interval", "0.001"); // 5 seconds is the update interval await startST(); SuperTokens.init({ supertokens: { @@ -274,9 +241,6 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( recipeList: [Session.init({ getTokenTransferMethod: () => "cookie", antiCsrf: "VIA_TOKEN" })], }); - const currCDIVersion = await Querier.getNewInstanceOrThrowError(undefined).getAPIVersion(); - const coreSupportsMultipleSignigKeys = maxVersion(currCDIVersion, "2.8") !== "2.8"; - let response2 = await SessionFunctions.createNewSession( SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, "", @@ -301,7 +265,7 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( parseJWTWithoutSignatureVerification(response.accessToken.token), response.antiCsrfToken, true, - true + false ); let verifyState = await ProcessState.getInstance().waitForEvent( @@ -320,16 +284,13 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( parseJWTWithoutSignatureVerification(response2.accessToken.token), response2.antiCsrfToken, true, - true + false ); // Old core versions should throw here because the signing key was updated - if (!coreSupportsMultipleSignigKeys) { - fail(); - } } catch (err) { if (err.type !== Session.Error.TRY_REFRESH_TOKEN) { throw err; - } else if (coreSupportsMultipleSignigKeys) { + } else { // Cores supporting multiple signig shouldn't throw since the signing key is still valid fail(); } @@ -341,10 +302,11 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( ); assert(verifyState === undefined); } + assert.strictEqual(requestSpy.callCount, 1); }); it("check that if signing key changes, after new key is fetched - via verification of old token, old tokens don't query the core", async function () { - await setKeyValueInConfig("access_token_signing_key_update_interval", "0.001"); // 5 seconds is the update interval + await setKeyValueInConfig("access_token_dynamic_signing_key_update_interval", "0.001"); // 5 seconds is the update interval await startST(); SuperTokens.init({ supertokens: { @@ -359,7 +321,6 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( }); const currCDIVersion = await Querier.getNewInstanceOrThrowError(undefined).getAPIVersion(); - const coreSupportsMultipleSignigKeys = maxVersion(currCDIVersion, "2.8") !== "2.8"; let response2 = await SessionFunctions.createNewSession( SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, @@ -371,10 +332,6 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( await new Promise((r) => setTimeout(r, 6000)); - let originalHandShakeInfo = ( - await SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.getHandshakeInfo() - ).clone(); - let response = await SessionFunctions.createNewSession( SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, "", @@ -383,28 +340,22 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( {} ); - // we reset the handshake info to before the session creation so it's - // like the above session was created from another server. - SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.setHandshakeInfo(originalHandShakeInfo); - { await SessionFunctions.getSession( SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, parseJWTWithoutSignatureVerification(response.accessToken.token), response.antiCsrfToken, true, - true + false ); let verifyState = await ProcessState.getInstance().waitForEvent( PROCESS_STATE.CALLING_SERVICE_IN_VERIFY, 1500 ); - if (!coreSupportsMultipleSignigKeys) { - assert(verifyState === undefined); - } else { - assert(verifyState !== undefined); - } + assert(verifyState === undefined); + assert.strictEqual(requestSpy.callCount, 1); + assert(requestSpy.getCall(0).args[0].endsWith("/.well-known/jwks.json")); } await ProcessState.getInstance().reset(); @@ -416,17 +367,12 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( parseJWTWithoutSignatureVerification(response2.accessToken.token), response2.antiCsrfToken, true, - true + false ); - - // Old core versions should throw here because the signing key was updated - if (!coreSupportsMultipleSignigKeys) { - fail(); - } } catch (err) { if (err.type !== Session.Error.TRY_REFRESH_TOKEN) { throw err; - } else if (coreSupportsMultipleSignigKeys) { + } else { // Cores supporting multiple signig shouldn't throw since the signing key is still valid fail(); } @@ -438,10 +384,11 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( ); assert(verifyState === undefined); } + assert.strictEqual(requestSpy.callCount, 1); }); it("test reducing access token signing key update interval time", async function () { - await setKeyValueInConfig("access_token_signing_key_update_interval", "0.0041"); // 10 seconds + await setKeyValueInConfig("access_token_dynamic_signing_key_update_interval", "0.0041"); // 10 seconds await startST(); SuperTokens.init({ supertokens: { @@ -469,7 +416,7 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( parseJWTWithoutSignatureVerification(session.accessToken.token), session.antiCsrfToken, true, - true + false ); let verifyState3 = await ProcessState.getInstance().waitForEvent( @@ -492,7 +439,7 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( parseJWTWithoutSignatureVerification(session.accessToken.token), session.antiCsrfToken, true, - true + false ); let verifyState3 = await ProcessState.getInstance().waitForEvent( @@ -502,12 +449,6 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( assert(verifyState3 === undefined); } - // now we create a new session that will use a new key and we will - // do it in a way that the jwtSigningKey info is not updated (as if another server has created this new session) - let originalHandShakeInfo = ( - await SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.getHandshakeInfo() - ).clone(); - let session2 = await SessionFunctions.createNewSession( SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.helpers, "", @@ -516,10 +457,6 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( {} ); - // we reset the handshake info to before the session creation so it's - // like the above session was created from another server. - SessionRecipe.getInstanceOrThrowError().recipeInterfaceImpl.setHandshakeInfo(originalHandShakeInfo); - // now we will call getSession on session2 and see that the core is called { // jwt signing key has not expired, according to the SDK, so it should succeed @@ -528,14 +465,17 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( parseJWTWithoutSignatureVerification(session2.accessToken.token), session2.antiCsrfToken, true, - true + false ); let verifyState3 = await ProcessState.getInstance().waitForEvent( PROCESS_STATE.CALLING_SERVICE_IN_VERIFY, 1500 ); - assert(verifyState3 !== undefined); + assert(verifyState3 === undefined); + // we have one at the start as well as now + assert.strictEqual(requestSpy.callCount, 2); + assert(requestSpy.getCall(1).args[0].endsWith("/.well-known/jwks.json")); } ProcessState.getInstance().reset(); @@ -548,7 +488,7 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( parseJWTWithoutSignatureVerification(session2.accessToken.token), session2.antiCsrfToken, true, - true + false ); let verifyState3 = await ProcessState.getInstance().waitForEvent( @@ -559,6 +499,8 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( } { + // We should not have called the core jwks endpoint since the last check + assert.strictEqual(requestSpy.callCount, 2); // now we will use the original session again and see that core is not called try { await SessionFunctions.getSession( @@ -566,7 +508,7 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( parseJWTWithoutSignatureVerification(session.accessToken.token), session.antiCsrfToken, true, - true + false ); fail(); } catch (err) { @@ -580,11 +522,13 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( 1500 ); assert(verifyState3 === undefined); + // We call the jwks endpoint since the key is not in the cache anymore, and we double-check + assert.strictEqual(requestSpy.callCount, 3); } }); it("no access token signing key update", async function () { - await setKeyValueInConfig("access_token_signing_key_update_interval", "0.0011"); // 4 seconds + await setKeyValueInConfig("access_token_dynamic_signing_key_update_interval", "0.0011"); // 4 seconds await setKeyValueInConfig("access_token_signing_key_dynamic", "false"); await startST(); SuperTokens.init({ @@ -621,7 +565,7 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( parseJWTWithoutSignatureVerification(session.accessToken.token), session.antiCsrfToken, true, - true + false ); let verifyState3 = await ProcessState.getInstance().waitForEvent( @@ -641,7 +585,7 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( parseJWTWithoutSignatureVerification(session.accessToken.token), session.antiCsrfToken, true, - true + false ); let verifyState3 = await ProcessState.getInstance().waitForEvent( @@ -650,5 +594,6 @@ describe(`sessionAccessTokenSigningKeyUpdate: ${printPath( ); assert(verifyState3 === undefined); } + assert.strictEqual(requestSpy.callCount, 1); }); }); diff --git a/test/sessionExpress.test.js b/test/sessionExpress.test.js index 4a25c75b7..709015f95 100644 --- a/test/sessionExpress.test.js +++ b/test/sessionExpress.test.js @@ -697,6 +697,101 @@ describe(`sessionExpress: ${printPath("[test/sessionExpress.test.js]")}`, functi assert.strictEqual(sessionRevokedResponseExtracted.refreshTokenFromHeader, ""); }); + it("test that if accessTokenPath is set to custom /access, then path of accessToken from session is equal to this", async function () { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Session.init({ + getTokenTransferMethod: () => "cookie", + antiCsrf: "VIA_TOKEN", + accessTokenPath: "/access", + }), + ], + }); + const app = express(); + app.use(middleware()); + + app.post("/create", async (req, res) => { + await Session.createNewSession(req, res, "", {}, {}); + res.status(200).send(""); + }); + const res = await new Promise((resolve) => + request(app) + .post("/create") + .expect(200) + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + let cookies = res.headers["set-cookie"] || res.headers["Set-Cookie"]; + cookies = cookies === undefined ? [] : cookies; + + const paths = cookies.filter((item) => item.startsWith("sAccessToken"))[0].split("; "); + assert.strictEqual( + ["path", "Path"].flatMap((need) => paths.filter((actual) => actual.startsWith(need)))[0].split("=")[1], + "/access" + ); + }); + + it("test that if default accessTokenPath is used, then path of accessToken from session is equal to slash", async function () { + await startST(); + SuperTokens.init({ + supertokens: { + connectionURI: "http://localhost:8080", + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + Session.init({ + getTokenTransferMethod: () => "cookie", + antiCsrf: "VIA_TOKEN", + }), + ], + }); + const app = express(); + app.use(middleware()); + + app.post("/create", async (req, res) => { + await Session.createNewSession(req, res, "", {}, {}); + res.status(200).send(""); + }); + const res = await new Promise((resolve) => + request(app) + .post("/create") + .expect(200) + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(res); + } + }) + ); + let cookies = res.headers["set-cookie"] || res.headers["Set-Cookie"]; + cookies = cookies === undefined ? [] : cookies; + + const paths = cookies.filter((item) => item.startsWith("sAccessToken"))[0].split("; "); + assert.strictEqual( + ["path", "Path"].flatMap((need) => paths.filter((actual) => actual.startsWith(need)))[0].split("=")[1], + "/" + ); + }); + it("test signout API works", async function () { await startST(); SuperTokens.init({ @@ -1280,23 +1375,25 @@ describe(`sessionExpress: ${printPath("[test/sessionExpress.test.js]")}`, functi }); app.post("/updateSessionData", async (req, res) => { let session = await Session.getSession(req, res); - await session.updateSessionData({ key: "value" }); + await session.updateSessionDataInDatabase({ key: "value" }); res.status(200).send(""); }); app.post("/getSessionData", async (req, res) => { let session = await Session.getSession(req, res); - let sessionData = await session.getSessionData(); + let sessionData = await session.getSessionDataFromDatabase(); res.status(200).json(sessionData); }); app.post("/updateSessionData2", async (req, res) => { let session = await Session.getSession(req, res); - await session.updateSessionData(null); + await session.updateSessionDataInDatabase(null); res.status(200).send(""); }); app.post("/updateSessionDataInvalidSessionHandle", async (req, res) => { - res.status(200).json({ success: !(await Session.updateSessionData("InvalidHandle", { key: "value3" })) }); + res.status(200).json({ + success: !(await Session.updateSessionDataInDatabase("InvalidHandle", { key: "value3" })), + }); }); //create a new session @@ -1424,7 +1521,7 @@ describe(`sessionExpress: ${printPath("[test/sessionExpress.test.js]")}`, functi app.post("/updateAccessTokenPayload", async (req, res) => { let session = await Session.getSession(req, res); let accessTokenBefore = session.accessToken; - await session.updateAccessTokenPayload({ key: "value" }); + await session.mergeIntoAccessTokenPayload({ key: "value" }); let accessTokenAfter = session.accessToken; let statusCode = accessTokenBefore !== accessTokenAfter && typeof accessTokenAfter === "string" ? 200 : 500; res.status(statusCode).send(""); @@ -1441,13 +1538,13 @@ describe(`sessionExpress: ${printPath("[test/sessionExpress.test.js]")}`, functi app.post("/updateAccessTokenPayload2", async (req, res) => { let session = await Session.getSession(req, res); - await session.updateAccessTokenPayload(null); + await session.mergeIntoAccessTokenPayload({ key: null }); res.status(200).send(""); }); app.post("/updateAccessTokenPayloadInvalidSessionHandle", async (req, res) => { res.status(200).json({ - success: !(await Session.updateAccessTokenPayload("InvalidHandle", { key: "value3" })), + success: !(await Session.mergeIntoAccessTokenPayload("InvalidHandle", { key: "value3" })), }); }); @@ -1469,7 +1566,9 @@ describe(`sessionExpress: ${printPath("[test/sessionExpress.test.js]")}`, functi let frontendInfo = JSON.parse(new Buffer.from(response.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, {}); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 8); //call the updateAccessTokenPayload api to add jwt payload let updatedResponse = extractInfoFromResponse( @@ -1491,7 +1590,10 @@ describe(`sessionExpress: ${printPath("[test/sessionExpress.test.js]")}`, functi frontendInfo = JSON.parse(new Buffer.from(updatedResponse.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, { key: "value" }); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.key, "value"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 9); //call the getAccessTokenPayload api to get jwt payload let response2 = await new Promise((resolve) => @@ -1531,7 +1633,10 @@ describe(`sessionExpress: ${printPath("[test/sessionExpress.test.js]")}`, functi frontendInfo = JSON.parse(new Buffer.from(response2.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, { key: "value" }); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.key, "value"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 9); // change the value of the inserted jwt payload let updatedResponse2 = extractInfoFromResponse( @@ -1553,7 +1658,9 @@ describe(`sessionExpress: ${printPath("[test/sessionExpress.test.js]")}`, functi frontendInfo = JSON.parse(new Buffer.from(updatedResponse2.frontToken, "base64").toString()); assert(frontendInfo.uid === "user1"); - assert.deepStrictEqual(frontendInfo.up, {}); + assert.strictEqual(frontendInfo.up.sub, "user1"); + assert.strictEqual(frontendInfo.up.exp, Math.floor(frontendInfo.ate / 1000)); + assert.strictEqual(Object.keys(frontendInfo.up).length, 8); //retrieve the changed jwt payload response2 = await new Promise((resolve) => @@ -1572,7 +1679,20 @@ describe(`sessionExpress: ${printPath("[test/sessionExpress.test.js]")}`, functi ); //check the value of the retrieved - assert.deepStrictEqual(response2.body, {}); + assert.deepStrictEqual( + new Set(Object.keys(response2.body)), + new Set([ + "antiCsrfToken", + "exp", + "iat", + "iss", + "parentRefreshTokenHash1", + "refreshTokenHash1", + "sessionHandle", + "sub", + ]) + ); + assert.strictEqual(response2.body.iss, "https://api.supertokens.io/auth"); //invalid session handle when updating the jwt payload let invalidSessionResponse = await new Promise((resolve) => request(app) @@ -1978,14 +2098,14 @@ describe(`sessionExpress: ${printPath("[test/sessionExpress.test.js]")}`, functi } { - let res2 = await new Promise((resolve) => + let res2 = await new Promise((resolve, reject) => request(app) .post("/auth/session/refresh") .set("Cookie", ["sRefreshToken=" + res.refreshToken]) .set("rid", "session") .end((err, res) => { if (err) { - resolve(undefined); + reject(err); } else { resolve(res); } diff --git a/test/thirdpartyemailpassword/signupFeature.test.js b/test/thirdpartyemailpassword/signupFeature.test.js index c8336c228..dbb601294 100644 --- a/test/thirdpartyemailpassword/signupFeature.test.js +++ b/test/thirdpartyemailpassword/signupFeature.test.js @@ -830,6 +830,20 @@ describe(`signupTest: ${printPath("[test/thirdpartyemailpassword/signupFeature.t recipeList: [ ThirdPartyEmailPassword.init({ providers: [this.customProvider1], + signUpFeature: { + formFields: [ + { + id: "email", + }, + { + id: "password", + validate: async (value) => { + if (value.length < 5) return "Password should be greater than 5 characters"; + return undefined; + }, + }, + ], + }, }), Session.init({ getTokenTransferMethod: () => "cookie" }), ], @@ -929,6 +943,15 @@ describe(`signupTest: ${printPath("[test/thirdpartyemailpassword/signupFeature.t }); assert(r2.status === "UNKNOWN_USER_ID_ERROR"); + + let r3 = await ThirdPartyEmailPassword.updateEmailOrPassword({ + userId: signUpUserInfo.id, + email: "test2@example.com", + password: "test", + }); + + assert(r3.status === "PASSWORD_POLICY_VIOLATED_ERROR"); + assert(r3.failureReason === "Password should be greater than 5 characters"); } }); }); diff --git a/test/userContext.test.js b/test/userContext.test.js index 3205e9fb6..9ecad16ff 100644 --- a/test/userContext.test.js +++ b/test/userContext.test.js @@ -180,7 +180,8 @@ describe(`userContext: ${printPath("[test/userContext.test.js]")}`, function () }) ); assert(response.status === 200); - assert(works && signUpContextWorks); + assert(works); + assert(signUpContextWorks); }); it("testing default context across interface and recipe function", async function () { @@ -281,6 +282,8 @@ describe(`userContext: ${printPath("[test/userContext.test.js]")}`, function () }) ); assert(response.status === 200); - assert(signInContextWorks && signInAPIContextWorks && createNewSessionContextWorks); + assert(signInContextWorks); + assert(signInAPIContextWorks); + assert(createNewSessionContextWorks); }); }); diff --git a/test/userroles/claims.test.js b/test/userroles/claims.test.js index 241e92a31..f47b840ab 100644 --- a/test/userroles/claims.test.js +++ b/test/userroles/claims.test.js @@ -1,5 +1,14 @@ const assert = require("assert"); -const { printPath, setupST, startST, killAllST, cleanST, mockResponse, mockRequest } = require("../utils"); +const { + printPath, + setupST, + startST, + killAllST, + cleanST, + mockResponse, + mockRequest, + setKeyValueInConfig, +} = require("../utils"); const { ProcessState } = require("../../lib/build/processState"); const STExpress = require("../.."); const UserRoles = require("../../lib/build/recipe/userroles").default; @@ -139,7 +148,6 @@ describe(`claimsTest: ${printPath("[test/userroles/claims.test.js]")}`, function try { await session.assertClaims([UserRoles.UserRoleClaim.validators.includes("nope")]); } catch (ex) { - console.log(ex); err = ex; } assert.ok(err); @@ -215,7 +223,6 @@ describe(`claimsTest: ${printPath("[test/userroles/claims.test.js]")}`, function try { await session.assertClaims([UserRoles.PermissionClaim.validators.includes("nope")]); } catch (ex) { - console.log(ex); err = ex; } assert.ok(err); diff --git a/test/users.json b/test/users.json new file mode 100644 index 000000000..a58104972 --- /dev/null +++ b/test/users.json @@ -0,0 +1,147 @@ +{ + "users": [ + { + "recipe": "emailpassword", + "email": "test@supertokens.com", + "password": "password" + }, + { + "recipe": "emailpassword", + "email": "test+1@supertokens.com", + "password": "password" + }, + { + "recipe": "emailpassword", + "email": "email+ABC@gmail.com", + "password": "password" + }, + { + "recipe": "emailpassword", + "email": "testing@supertokens.com", + "password": "password" + }, + { + "recipe": "emailpassword", + "email": "test.name@supertokens.com", + "password": "password" + }, + { + "recipe": "emailpassword", + "email": "debugging@supertokens.com", + "password": "password" + }, + { + "recipe": "emailpassword", + "email": "random@supertokens.com", + "password": "password" + }, + { + "recipe": "emailpassword", + "email": "johndoe@testing.weird", + "password": "password" + }, + + { + "recipe": "passwordless", + "email": "test@supertokens.com" + }, + { + "recipe": "passwordless", + "email": "test+1@supertokens.com" + }, + { + "recipe": "passwordless", + "email": "passwordless+ABC@gmail.com" + }, + { + "recipe": "passwordless", + "email": "testing@supertokens.com" + }, + { + "recipe": "passwordless", + "email": "test.name@supertokens.com" + }, + { + "recipe": "passwordless", + "email": "debugging@supertokens.com" + }, + { + "recipe": "passwordless", + "email": "random@supertokens.com" + }, + { + "recipe": "passwordless", + "email": "johndoe@testing.weird" + }, + + { + "recipe": "passwordless", + "phone": "+12029182132" + }, + { + "recipe": "passwordless", + "phone": "+15059842706" + }, + { + "recipe": "passwordless", + "phone": "+3585010760278" + }, + { + "recipe": "passwordless", + "phone": "+918709241809" + }, + { + "recipe": "passwordless", + "phone": "+12642354793" + }, + + { + "recipe": "thirdparty", + "provider": "google", + "email": "test@supertokens.com", + "userId": "774b9318-a91e-4773-80c5-65f0823c5ee7" + }, + { + "recipe": "thirdparty", + "provider": "google", + "email": "test+1@supertokens.com", + "userId": "479d3bb5-371e-4d6b-914b-b6cd8f3787a5" + }, + { + "recipe": "thirdparty", + "provider": "google", + "email": "thirdparty+ABC@gmail.com", + "userId": "648f3b76-4a5e-4f62-a181-ee09b6f3f1bb" + }, + { + "recipe": "thirdparty", + "provider": "github", + "email": "782657849@qq.com", + "userId": "8a479a89-5f0b-465a-9ae0-a0e4f3dd4e6e" + }, + { + "recipe": "thirdparty", + "provider": "github", + "email": "test.name@supertokens.com", + "userId": "cea30444-49fa-485f-a6ca-7e1c98c3836c" + }, + { + "recipe": "thirdparty", + "provider": "apple", + "email": "debugging@supertokens.com", + "userId": "c529222e-1f96-4499-a2ab-103f9612a06b" + }, + { + "recipe": "thirdparty", + "provider": "custom", + "email": "random@supertokens.com", + "userId": "3134f0f1-bb30-455d-a151-12615e1f8f95" + }, + { + "recipe": "thirdparty", + "provider": "kakao", + "email": "johndoe@testing.weird", + "userId": "305773f6-2857-4591-93e9-9ed68c1936c6" + } + ] +} diff --git a/test/utils.js b/test/utils.js index e4fbde65f..876bf51e1 100644 --- a/test/utils.js +++ b/test/utils.js @@ -23,6 +23,7 @@ let ThirPartyPasswordless = require("../lib/build/recipe/thirdpartypasswordless/ let ThirdPartyEmailPasswordRecipe = require("../lib/build/recipe/thirdpartyemailpassword/recipe").default; let ThirdPartyPasswordlessRecipe = require("../lib/build/recipe/thirdpartypasswordless/recipe").default; let EmailPasswordRecipe = require("../lib/build/recipe/emailpassword/recipe").default; +let DashboardRecipe = require("../lib/build/recipe/dashboard/recipe").default; const EmailVerificationRecipe = require("../lib/build/recipe/emailverification/recipe").default; let JWTRecipe = require("..//lib/build/recipe/jwt/recipe").default; const UserMetadataRecipe = require("../lib/build/recipe/usermetadata/recipe").default; @@ -33,6 +34,9 @@ let { Querier } = require("../lib/build/querier"); let { maxVersion } = require("../lib/build/utils"); const { default: OpenIDRecipe } = require("../lib/build/recipe/openid/recipe"); const { wrapRequest } = require("../framework/express"); +const { join } = require("path"); + +const users = require("./users.json"); module.exports.printPath = function (path) { return `${createFormat([consoleOptions.yellow, consoleOptions.italic, consoleOptions.dim])}${path}${createFormat([ @@ -232,6 +236,7 @@ module.exports.resetAll = function () { UserRolesRecipe.reset(); PasswordlessRecipe.reset(); OpenIDRecipe.reset(); + DashboardRecipe.reset(); ProcessState.getInstance().reset(); }; @@ -559,3 +564,52 @@ module.exports.mockRequest = () => { }; return req; }; + +module.exports.getAllFilesInDirectory = (path) => { + return fs + .readdirSync(path, { + withFileTypes: true, + }) + .flatMap((file) => { + if (file.isDirectory()) { + return this.getAllFilesInDirectory(join(path, file.name)); + } else { + return join(path, file.name); + } + }); +}; + +module.exports.createUsers = async (emailpassword = null, passwordless = null, thirdparty = null) => { + const usersArray = users.users; + for (let i = 0; i < usersArray.length; i++) { + const user = usersArray[i]; + if (user.recipe === "emailpassword" && emailpassword !== null) { + await emailpassword.signUp(user.email, user.password); + } + if (user.recipe === "passwordless" && passwordless !== null) { + if (user.email !== undefined) { + const codeResponse = await passwordless.createCode({ + email: user.email, + }); + await passwordless.consumeCode({ + preAuthSessionId: codeResponse.preAuthSessionId, + deviceId: codeResponse.deviceId, + userInputCode: codeResponse.userInputCode, + }); + } else { + const codeResponse = await passwordless.createCode({ + phoneNumber: user.phone, + }); + await passwordless.consumeCode({ + preAuthSessionId: codeResponse.preAuthSessionId, + deviceId: codeResponse.deviceId, + userInputCode: codeResponse.userInputCode, + }); + } + } + + if (user.recipe === "thirdparty" && thirdparty !== null) { + await thirdparty.signInUp(user.provider, user.userId, user.email); + } + } +}; diff --git a/test/utils.test.js b/test/utils.test.js new file mode 100644 index 000000000..0d84bc480 --- /dev/null +++ b/test/utils.test.js @@ -0,0 +1,20 @@ +const assert = require("assert"); +const { getFromObjectCaseInsensitive } = require("../lib/build/utils"); + +describe("SuperTokens utils test", () => { + it("Test getFromObjectCaseInsensitive", () => { + const testObj = { + AuthOriZation: "test", + }; + + assert.equal(getFromObjectCaseInsensitive("test", testObj), undefined); + // Exact + assert.equal(getFromObjectCaseInsensitive("AuthOriZation", testObj), "test"); + // All lower case + assert.equal(getFromObjectCaseInsensitive("authorization", testObj), "test"); + // Traditional case + assert.equal(getFromObjectCaseInsensitive("Authorization", testObj), "test"); + // Weird casing + assert.equal(getFromObjectCaseInsensitive("authoriZation", testObj), "test"); + }); +}); diff --git a/test/with-typescript/index.ts b/test/with-typescript/index.ts index 4762e932d..d7d9bc3f5 100644 --- a/test/with-typescript/index.ts +++ b/test/with-typescript/index.ts @@ -1,6 +1,6 @@ import * as express from "express"; import Supertokens from "../.."; -import Session, { RecipeInterface, SessionClaimValidator } from "../../recipe/session"; +import Session, { RecipeInterface, SessionClaimValidator, VerifySessionOptions } from "../../recipe/session"; import EmailVerification from "../../recipe/emailverification"; import EmailPassword from "../../recipe/emailpassword"; import { verifySession } from "../../recipe/session/framework/express"; @@ -23,7 +23,7 @@ import { SupertokensService as SupertokensServiceP, } from "../../recipe/thirdpartypasswordless/smsdelivery"; import UserMetadata from "../../recipe/usermetadata"; -import { BooleanClaim, PrimitiveClaim, SessionClaim } from "../../recipe/session/claims"; +import { BooleanClaim, PrimitiveClaim } from "../../recipe/session/claims"; import UserRoles from "../../recipe/userroles"; import Dashboard from "../../recipe/dashboard"; import JWT from "../../recipe/jwt"; @@ -821,6 +821,7 @@ ThirdParty.init({ import { TypeInput } from "../../types"; import { TypeInput as SessionTypeInput } from "../../recipe/session/types"; import { TypeInput as EPTypeInput } from "../../recipe/emailpassword/types"; +import SuperTokensError from "../../lib/build/error"; let app = express(); let sessionConfig: SessionTypeInput = { @@ -836,12 +837,11 @@ let sessionConfig: SessionTypeInput = { getAccessToken: session.getAccessToken, getHandle: session.getHandle, getAccessTokenPayload: session.getAccessTokenPayload, - getSessionData: session.getSessionData, + getSessionDataFromDatabase: session.getSessionDataFromDatabase, getUserId: session.getUserId, getRecipeUserId: session.getRecipeUserId, revokeSession: session.revokeSession, - updateAccessTokenPayload: session.updateAccessTokenPayload, - updateSessionData: session.updateSessionData, + updateSessionDataInDatabase: session.updateSessionDataInDatabase, mergeIntoAccessTokenPayload: session.mergeIntoAccessTokenPayload, assertClaims: session.assertClaims, fetchAndSetClaim: session.fetchAndSetClaim, @@ -850,6 +850,8 @@ let sessionConfig: SessionTypeInput = { removeClaim: session.removeClaim, getExpiry: session.getExpiry, getTimeCreated: session.getTimeCreated, + getAllSessionTokensDangerously: session.getAllSessionTokensDangerously, + attachToRequestResponse: session.attachToRequestResponse, }; }, getAllSessionHandlesForUser: originalImpl.getAllSessionHandlesForUser, @@ -857,10 +859,7 @@ let sessionConfig: SessionTypeInput = { revokeAllSessionsForUser: originalImpl.revokeAllSessionsForUser, revokeMultipleSessions: originalImpl.revokeMultipleSessions, revokeSession: originalImpl.revokeSession, - updateAccessTokenPayload: originalImpl.updateAccessTokenPayload, - updateSessionData: originalImpl.updateSessionData, - getAccessTokenLifeTimeMS: originalImpl.getAccessTokenLifeTimeMS, - getRefreshTokenLifeTimeMS: originalImpl.getRefreshTokenLifeTimeMS, + updateSessionDataInDatabase: originalImpl.updateSessionDataInDatabase, getSessionInformation: originalImpl.getSessionInformation, regenerateAccessToken: originalImpl.regenerateAccessToken, mergeIntoAccessTokenPayload: originalImpl.mergeIntoAccessTokenPayload, @@ -1044,8 +1043,8 @@ Supertokens.init({ someKey: "someValue", }; - input.sessionData = { - ...input.sessionData, + input.sessionDataInDatabase = { + ...input.sessionDataInDatabase, someKey: "someValue", }; @@ -1108,10 +1107,8 @@ Supertokens.init({ }); Session.init({ - jwt: { - enable: true, - propertyNameInAccessTokenPayload: "someKey", - }, + exposeAccessTokenToFrontendInCookieBasedAuth: true, + useDynamicAccessTokenSigningKey: false, }); ThirdPartyEmailPassword.init({ @@ -1212,10 +1209,7 @@ Session.init({ refreshSession: async function (input) { let session = await originalImplementation.refreshSession(input); - let currAccessTokenPayload = session.getAccessTokenPayload(); - - await session.updateAccessTokenPayload({ - ...currAccessTokenPayload, + await session.mergeIntoAccessTokenPayload({ lastTokenRefresh: Date.now(), }); @@ -1317,7 +1311,6 @@ Supertokens.init({ }, recipeList: [ Dashboard.init({ - apiKey: "", override: { functions: () => { return { @@ -1341,9 +1334,9 @@ Supertokens.init({ ], }); -Dashboard.init({ - apiKey: "", -}); +Dashboard.init(); +Dashboard.init(undefined); +Dashboard.init({}); Session.init({ getTokenTransferMethod: () => "cookie", @@ -1351,6 +1344,40 @@ Session.init({ Session.init({ getTokenTransferMethod: () => "header", + override: { + functions: (oI) => ({ + ...oI, + getSession: async (input) => { + const session = await oI.getSession(input); + if (session !== undefined) { + const origPayload = session.getAccessTokenPayload(); + if (origPayload.appSub === undefined) { + await session.mergeIntoAccessTokenPayload({ appSub: origPayload.sub, sub: null }); + } + } + return session; + }, + createNewSession: async (input) => { + return oI.createNewSession({ + ...input, + accessTokenPayload: { + ...input.accessTokenPayload, + appSub: input.userId + "!!!", + }, + }); + }, + }), + openIdFeature: { + functions: (oI) => ({ + ...oI, + getOpenIdDiscoveryConfiguration: async (input) => ({ + issuer: "your issuer", + jwks_uri: "https://your.api.domain/auth/jwt/jwks.json", + status: "OK", + }), + }), + }, + }, }); Supertokens.init({ @@ -1409,3 +1436,168 @@ Passwordless.init({ }, }, }); + +async function getSessionWithErrorHandlerMiddleware(req: express.Request, resp: express.Response) { + const session = await Session.getSession(req, resp, { + /* options */ + }); + + // ... +} + +async function getSessionWithoutErrorHandler(req: express.Request, resp: express.Response, next: express.NextFunction) { + try { + const session = await Session.getSession(req, resp, { + /* options */ + }); + /* .... */ + } catch (err) { + if (SuperTokensError.isErrorFromSuperTokens(err)) { + if (err.type === Session.Error.TRY_REFRESH_TOKEN) { + resp.status(401).json({ message: "try again " }); + // This means that the session exists, but the access token + // has expired. + + // You can handle this in a custom way by sending a 401. + // Or you can call the errorHandler middleware as shown below + } else if (err.type === Session.Error.UNAUTHORISED) { + resp.status(401).json({ message: "try again " }); + // This means that the session does not exist anymore. + // You can handle this in a custom way by sending a 401. + // Or you can call the errorHandler middleware as shown below + } else if (err.type === Session.Error.TOKEN_THEFT_DETECTED) { + // Security Alert!! + resp.status(401).json({ message: "try again " }); + // Session hijacking attempted. You should revoke the session + // using Session.revokeSession fucntion and send a 401 + } else if (err.type === Session.Error.INVALID_CLAIMS) { + resp.status(403).json({ status: "CLAIM_VALIDATION_ERROR", claimValidationErrors: err.payload }); + // The user is missing some required claim. + // You can pass the missing claims to the frontend and handle it there + } + + // OR you can use this errorHandler which will + // handle all of the above errors in the default way + errorHandler()(err, req, resp, (err) => { + next(err); + }); + } else { + next(err); + } + } +} + +async function getSessionWithoutRequestOrErrorHandler(req: express.Request, resp: express.Response) { + const accessToken = req.headers.authorization?.replace(/^Bearer /, ""); + + // We only need to split this declaration (and have the else statement) if the session is optional + let session; + if (!accessToken) { + // This means that the user doesn't have an active session + return resp.status(401).json({ message: "try again " }); // Or equivalent... + } else { + try { + const session1 = await Session.getSessionWithoutRequestResponse(accessToken, undefined, { + antiCsrfCheck: false, + }); + const session2 = await Session.getSessionWithoutRequestResponse(accessToken, undefined); + const session3 = await Session.getSessionWithoutRequestResponse(accessToken, undefined, { + sessionRequired: false, + }); + let x: boolean | undefined; + const session4 = await Session.getSessionWithoutRequestResponse(accessToken, undefined, { + sessionRequired: x, + }); + const options: VerifySessionOptions = {}; + session = await Session.getSessionWithoutRequestResponse(accessToken, undefined, { antiCsrfCheck: false }); + session = await Session.getSessionWithoutRequestResponse(accessToken, undefined, { ...options }); + } catch (ex) { + if (Session.Error.isErrorFromSuperTokens(ex)) { + if (ex.type === Session.Error.INVALID_CLAIMS) { + return resp.status(403).json({ + message: "invalid claim", + claimValidationErrors: ex.payload, + }); // Or equivalent... + } else { + resp.status(401); + } + } else { + throw ex; + } + } + } + // API code... +} + +async function getSessionWithoutRequestWithErrorHandler(req: express.Request, resp: express.Response) { + const accessToken = req.headers.authorization?.replace(/^Bearer /, ""); + + // We only need to split this declaration (and have the else statement) if the session is optional + let session; + if (!accessToken) { + // This means that the user doesn't have an active session + return resp.status(401).json({ message: "try again " }); + } else { + session = await Session.getSessionWithoutRequestResponse(accessToken, undefined, { antiCsrfCheck: false }); + } + // API code... + if (session) { + const tokens = session.getAllSessionTokensDangerously(); + if (tokens.accessAndFrontTokenUpdated) { + resp.set("st-access-token", tokens.accessToken); + resp.set("front-token", tokens.frontToken); + } + } +} + +async function createNewSessionWithoutRequestResponse(req: express.Request, resp: express.Response) { + const userId = "user-id"; // This would be fetched from somewhere + + const session = await Session.createNewSessionWithoutRequestResponse(userId); + + const tokens = session.getAllSessionTokensDangerously(); + if (tokens.accessAndFrontTokenUpdated) { + resp.set("st-access-token", tokens.accessToken); + resp.set("front-token", tokens.frontToken); + resp.set("st-refresh-token", tokens.refreshToken); + if (tokens.antiCsrfToken) { + resp.set("anti-csrf", tokens.antiCsrfToken); + } + } +} + +async function refreshSessionWithoutRequestResponse(req: express.Request, resp: express.Response) { + const refreshToken = req.headers.authorization?.replace(/^Bearer /, ""); + + if (!refreshToken) { + // This means that the user doesn't have an active session + return resp.status(401); + } else { + let session; + + try { + session = await Session.refreshSessionWithoutRequestResponse(refreshToken, true); + } catch (ex) { + if (Session.Error.isErrorFromSuperTokens(ex)) { + return resp + .status(401) + .set("st-access-token", "") + .set("set-refresh-token", "") + .set("front-token", "remove"); // Or equivalent... + } else { + throw ex; + } + } + + const tokens = session.getAllSessionTokensDangerously(); + + if (tokens.accessAndFrontTokenUpdated) { + resp.set("st-access-token", tokens.accessToken); + resp.set("front-token", tokens.frontToken); + resp.set("st-refresh-token", tokens.refreshToken); + if (tokens.antiCsrfToken) { + resp.set("anti-csrf", tokens.antiCsrfToken); + } + } + } +}