diff --git a/.github/workflows/test-edge-function.yml b/.github/workflows/test-cf-worker-hono.yml similarity index 57% rename from .github/workflows/test-edge-function.yml rename to .github/workflows/test-cf-worker-hono.yml index a6824b9dc..c4547d077 100644 --- a/.github/workflows/test-edge-function.yml +++ b/.github/workflows/test-cf-worker-hono.yml @@ -1,24 +1,34 @@ -name: "Test edge function compatibility" +name: "Test edge function compatibility for Hono on Cloudflare Workers" on: push jobs: test: runs-on: ubuntu-latest env: - NETLIFY_AUTH_TOKEN: ${{ secrets.netlify_auth_token }} - NETLIFY_SITE_ID: ${{ secrets.netlify_site_id }} + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + APP_URL: "https://hono.rishabh-77b.workers.dev" + CLOUDFLARE_PROJECT_NAME: "hono" TEST_DEPLOYED_VERSION: true defaults: run: - working-directory: examples/next/with-emailpassword + working-directory: examples/cloudflare-workers/with-email-password-hono-be-only steps: - uses: actions/checkout@v2 - run: echo $GITHUB_SHA - run: npm install git+https://github.com:supertokens/supertokens-node.git#$GITHUB_SHA - run: npm install - run: npm install mocha@6.1.4 jsdom-global@3.0.2 puppeteer@^11.0.0 isomorphic-fetch@^3.0.0 - - run: netlify deploy --alias 0 --build --json --auth=$NETLIFY_AUTH_TOKEN > deployInfo.json - - run: cat deployInfo.json - - run: | + + - name: Replace APP_URL with deployed URL value + run: | + sed -i "s|process.env.REACT_APP_API_URL|\"${{ env.APP_URL }}\"|" config.ts + sed -i "s|process.env.REACT_APP_WEBSITE_URL|\"${{ env.APP_URL }}\"|" config.ts + + - name: Deploy the changes + run: npx wrangler deploy --name ${{ env.CLOUDFLARE_PROJECT_NAME }} index.ts + + - name: Run tests + run: | ( \ (echo "=========== Test attempt 1 ===========" && npx mocha --no-config --timeout 80000 test/**/*.test.js) || \ (echo "=========== Test attempt 2 ===========" && npx mocha --no-config --timeout 80000 test/**/*.test.js) || \ diff --git a/.github/workflows/test-cf-worker-next.yml b/.github/workflows/test-cf-worker-next.yml new file mode 100644 index 000000000..83c340fd7 --- /dev/null +++ b/.github/workflows/test-cf-worker-next.yml @@ -0,0 +1,72 @@ +name: "Test edge function compatibility for Next.js on Cloudflare Workers" +on: push +jobs: + test: + runs-on: ubuntu-latest + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + APP_URL: "supertokens-node-b95.pages.dev" + CLOUDFLARE_PROJECT_NAME: "supertokens-node-pr-check-for-edge-function-compat" + TEST_DEPLOYED_VERSION: true + defaults: + run: + working-directory: examples/next/with-emailpassword + steps: + - uses: actions/checkout@v2 + - run: echo $GITHUB_SHA + - run: npm install git+https://github.com:supertokens/supertokens-node.git#$GITHUB_SHA + - run: npm install + - run: npm install mocha@6.1.4 jsdom-global@3.0.2 puppeteer@^11.0.0 isomorphic-fetch@^3.0.0 + + # Step to update the runtime to edge to all files in app/api/ + - name: Add runtime export to API files + run: | + find app/api -type f \( -name "*.js" -o -name "*.ts" \) -exec sed -i '1s/^/export const runtime = "edge";\n/' {} + + echo 'export const runtime = "edge";' >> app/auth/[[...path]]/page.tsx + + # Install next on pages to build the app + - name: Install next-on-pages + run: npm install --save-dev @cloudflare/next-on-pages + + # Setup the compatibility flag to make non edge functions run + - name: Create a wrangler.toml + run: echo "compatibility_flags = [ "nodejs_compat" ]" >> wrangler.toml + + - name: Replace APP_URL with deployed URL value + run: | + sed -i "s|process.env.APP_URL|\"${{ env.APP_URL }}\"|" config/appInfo.ts + - name: Build using next-on-pages + run: npx next-on-pages + + - name: Publish to Cloudflare Pages + id: deploy + uses: cloudflare/pages-action@v1 + with: + apiToken: ${{ env.CLOUDFLARE_API_TOKEN }} + accountId: ${{ env.CLOUDFLARE_ACCOUNT_ID }} + projectName: ${{ env.CLOUDFLARE_PROJECT_NAME }} + directory: "./examples/next/with-emailpassword/.vercel/output/static" + wranglerVersion: "3" + branch: "master" + + - name: Extract deployment info and save to JSON + id: extract_deploy_info + run: | + DEPLOY_ID=${{ steps.deploy.outputs.id }} + DEPLOY_URL=${{ steps.deploy.outputs.url }} + echo "{\"deploy_url\": \"$DEPLOY_URL\", \"deploy_id\": \"$DEPLOY_ID\"}" > deployInfo.json + - name: Run tests + run: | + ( \ + (echo "=========== Test attempt 1 ===========" && npx mocha --no-config --timeout 80000 test/**/*.test.js) || \ + (echo "=========== Test attempt 2 ===========" && npx mocha --no-config --timeout 80000 test/**/*.test.js) || \ + (echo "=========== Test attempt 3 ===========" && npx mocha --no-config --timeout 80000 test/**/*.test.js) \ + ) + - name: The job has failed + if: ${{ failure() }} + uses: actions/upload-artifact@v3 + with: + name: screenshots + path: | + ./**/*screenshot.jpeg diff --git a/CHANGELOG.md b/CHANGELOG.md index f7dfac511..175e36eeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added OAuth2Provider recipe +## [20.1.2] - 2024-09-14 + +- Fixes formFields to accept non string types as well. + +## [20.1.1] - 2024-09-10 + +- Fixes an issue with Okta / Active Directory providers where we check for additional config if `oidcDiscoveryEndpoint` is not defined. It would not be necessary in the cases where other endpoints are already provided. + +## [20.1.0] - 2024-09-09 + +- Add edge compatibility for custom frameworks and Next.JS + +## [20.0.5] - 2024-09-02 + +- Optional form fields are now truly optional, can be omitted from the payload. + +## [20.0.4] - 2024-08-30 + +- Improves thirdParty debug logging to help with debugging issues with JSON parsing. + +## [20.0.3] - 2024-08-22 + +- Fixes issue with dashboard APIs `createOrUpdateThirdPartyConfig` and `deleteThirdPartyConfig` which did not take `includeInNonPublicTenantsByDefault` into account for non-public tenants. +- Updates test server to support dashboard tests. + ## [20.0.2] - 2024-08-08 - Fixes an issue where `shouldDoAutomaticAccountLinking` was called without a primary user when linking in some cases. diff --git a/docs/classes/framework.BaseRequest.html b/docs/classes/framework.BaseRequest.html index 731db467e..69e4a1041 100644 --- a/docs/classes/framework.BaseRequest.html +++ b/docs/classes/framework.BaseRequest.html @@ -1 +1 @@ -BaseRequest | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Class BaseRequest Abstract

Hierarchy

Index

Constructors

Properties

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

Type declaration

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

      • key_: string

      Returns undefined | string

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

Type declaration

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

      • key: string

      Returns undefined | string

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
parsedJSONBody: any
parsedUrlEncodedFormData: any
wrapperUsed: boolean

Methods

  • getFormData(): Promise<any>
  • getFormDataFromRequestBody(): Promise<any>
  • getJSONBody(): Promise<any>
  • getJSONFromRequestBody(): Promise<any>

Generated using TypeDoc

\ No newline at end of file +BaseRequest | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Class BaseRequest Abstract

Hierarchy

Index

Constructors

Properties

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

Type declaration

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

      • key_: string

      Returns undefined | string

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

Type declaration

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

      • key: string

      Returns undefined | string

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
parsedJSONBody: any
parsedUrlEncodedFormData: any
wrapperUsed: boolean

Methods

  • getFormData(): Promise<any>
  • getFormDataFromRequestBody(): Promise<any>
  • getJSONBody(): Promise<any>
  • getJSONFromRequestBody(): Promise<any>

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/framework.BaseResponse.html b/docs/classes/framework.BaseResponse.html index 555ac7ec5..55be2a01e 100644 --- a/docs/classes/framework.BaseResponse.html +++ b/docs/classes/framework.BaseResponse.html @@ -1 +1 @@ -BaseResponse | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Class BaseResponse Abstract

Hierarchy

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

Generated using TypeDoc

\ No newline at end of file +BaseResponse | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Class BaseResponse Abstract

Hierarchy

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

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/framework_custom.CollectingResponse.html b/docs/classes/framework_custom.CollectingResponse.html index 54d8bffe2..6a8c64d4c 100644 --- a/docs/classes/framework_custom.CollectingResponse.html +++ b/docs/classes/framework_custom.CollectingResponse.html @@ -1,2 +1,2 @@ -CollectingResponse | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

Index

Constructors

Properties

body?: string
cookies: CookieInfo[]
headers: Headers
original: any
statusCode: number
wrapperUsed: boolean

Methods

  • removeHeader(key: string): void
  • sendHTMLResponse(html: string): void
  • sendJSONResponse(content: any): void
  • setCookie(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
  • setStatusCode(statusCode: number): void
  • resetPasswordUsingToken(tenantId: string, token: string, newPassword: string, userContext?: Record<string, any>): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "RESET_PASSWORD_INVALID_TOKEN_ERROR" } | { failureReason: string; status: "PASSWORD_POLICY_VIOLATED_ERROR" }>
  • Parameters

    • tenantId: string
    • token: string
    • newPassword: string
    • Optional userContext: Record<string, any>

    Returns Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" | "RESET_PASSWORD_INVALID_TOKEN_ERROR" } | { failureReason: string; status: "PASSWORD_POLICY_VIOLATED_ERROR" }>

  • sendEmail(input: TypeEmailPasswordPasswordResetEmailDeliveryInput & { userContext?: Record<string, any> }): Promise<void>
  • sendResetPasswordEmail(tenantId: string, userId: string, email: string, userContext?: Record<string, any>): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" }>
  • Parameters

    • tenantId: string
    • userId: string
    • email: string
    • Optional userContext: Record<string, any>

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

  • signIn(tenantId: string, email: string, password: string, session?: undefined, userContext?: Record<string, any>): Promise<{ recipeUserId: RecipeUserId; status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>
  • signIn(tenantId: string, email: string, password: string, session: SessionContainer, userContext?: Record<string, any>): Promise<{ recipeUserId: RecipeUserId; status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>
  • Parameters

    • tenantId: string
    • email: string
    • password: string
    • Optional session: undefined
    • Optional userContext: Record<string, any>

    Returns Promise<{ recipeUserId: RecipeUserId; status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" }>

  • Parameters

    • tenantId: string
    • email: string
    • password: string
    • session: SessionContainer
    • Optional userContext: Record<string, any>

    Returns Promise<{ recipeUserId: RecipeUserId; status: "OK"; user: User } | { status: "WRONG_CREDENTIALS_ERROR" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>

  • signUp(tenantId: string, email: string, password: string, session?: undefined, userContext?: Record<string, any>): Promise<{ recipeUserId: RecipeUserId; status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>
  • signUp(tenantId: string, email: string, password: string, session: SessionContainer, userContext?: Record<string, any>): Promise<{ recipeUserId: RecipeUserId; status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>
  • Parameters

    • tenantId: string
    • email: string
    • password: string
    • Optional session: undefined
    • Optional userContext: Record<string, any>

    Returns Promise<{ recipeUserId: RecipeUserId; status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" }>

  • Parameters

    • tenantId: string
    • email: string
    • password: string
    • session: SessionContainer
    • Optional userContext: Record<string, any>

    Returns Promise<{ recipeUserId: RecipeUserId; status: "OK"; user: User } | { status: "EMAIL_ALREADY_EXISTS_ERROR" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>

  • updateEmailOrPassword(input: { applyPasswordPolicy?: boolean; email?: string; password?: string; recipeUserId: RecipeUserId; tenantIdForPasswordPolicy?: string; userContext?: Record<string, any> }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { failureReason: string; status: "PASSWORD_POLICY_VIOLATED_ERROR" }>
  • Parameters

    • input: { applyPasswordPolicy?: boolean; email?: string; password?: string; recipeUserId: RecipeUserId; tenantIdForPasswordPolicy?: string; userContext?: Record<string, any> }
      • Optional applyPasswordPolicy?: boolean
      • Optional email?: string
      • Optional password?: string
      • recipeUserId: RecipeUserId
      • Optional tenantIdForPasswordPolicy?: string
      • Optional userContext?: Record<string, any>

    Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { failureReason: string; status: "PASSWORD_POLICY_VIOLATED_ERROR" }>

  • verifyCredentials(tenantId: string, email: string, password: string, userContext?: Record<string, any>): Promise<{ status: "OK" | "WRONG_CREDENTIALS_ERROR" }>
  • Parameters

    • tenantId: string
    • email: string
    • password: string
    • Optional userContext: Record<string, any>

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

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/recipe_emailverification.default.html b/docs/classes/recipe_emailverification.default.html index 26f506971..5031cb837 100644 --- a/docs/classes/recipe_emailverification.default.html +++ b/docs/classes/recipe_emailverification.default.html @@ -1 +1 @@ -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

  • createEmailVerificationLink(tenantId: string, recipeUserId: RecipeUserId, email?: string, userContext?: Record<string, any>): Promise<{ link: string; status: "OK" } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>
  • createEmailVerificationToken(tenantId: string, recipeUserId: RecipeUserId, email?: string, userContext?: Record<string, any>): Promise<{ status: "OK"; token: string } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>
  • isEmailVerified(recipeUserId: RecipeUserId, email?: string, userContext?: Record<string, any>): Promise<boolean>
  • revokeEmailVerificationTokens(tenantId: string, recipeUserId: RecipeUserId, email?: string, userContext?: Record<string, any>): Promise<{ status: string }>
  • sendEmail(input: TypeEmailVerificationEmailDeliveryInput & { userContext?: Record<string, any> }): Promise<void>
  • sendEmailVerificationEmail(tenantId: string, userId: string, recipeUserId: RecipeUserId, email?: string, userContext?: Record<string, any>): Promise<{ status: "OK" } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>
  • unverifyEmail(recipeUserId: RecipeUserId, email?: string, userContext?: Record<string, any>): Promise<{ status: string }>
  • verifyEmailUsingToken(tenantId: string, token: string, attemptAccountLinking?: boolean, userContext?: Record<string, any>): Promise<{ status: "OK"; user: UserEmailInfo } | { status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR" }>

Generated using TypeDoc

\ No newline at end of file +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

  • createEmailVerificationLink(tenantId: string, recipeUserId: RecipeUserId, email?: string, userContext?: Record<string, any>): Promise<{ link: string; status: "OK" } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>
  • createEmailVerificationToken(tenantId: string, recipeUserId: RecipeUserId, email?: string, userContext?: Record<string, any>): Promise<{ status: "OK"; token: string } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>
  • isEmailVerified(recipeUserId: RecipeUserId, email?: string, userContext?: Record<string, any>): Promise<boolean>
  • revokeEmailVerificationTokens(tenantId: string, recipeUserId: RecipeUserId, email?: string, userContext?: Record<string, any>): Promise<{ status: string }>
  • sendEmail(input: TypeEmailVerificationEmailDeliveryInput & { userContext?: Record<string, any> }): Promise<void>
  • sendEmailVerificationEmail(tenantId: string, userId: string, recipeUserId: RecipeUserId, email?: string, userContext?: Record<string, any>): Promise<{ status: "OK" } | { status: "EMAIL_ALREADY_VERIFIED_ERROR" }>
  • unverifyEmail(recipeUserId: RecipeUserId, email?: string, userContext?: Record<string, any>): Promise<{ status: string }>
  • verifyEmailUsingToken(tenantId: string, token: string, attemptAccountLinking?: boolean, userContext?: Record<string, any>): Promise<{ status: "OK"; user: UserEmailInfo } | { status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR" }>

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/recipe_jwt.default.html b/docs/classes/recipe_jwt.default.html index b36f98416..c1cdd7438 100644 --- a/docs/classes/recipe_jwt.default.html +++ b/docs/classes/recipe_jwt.default.html @@ -1 +1 @@ -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, useStaticSigningKey?: boolean, userContext?: Record<string, any>): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
  • Parameters

    • payload: any
    • Optional validitySeconds: number
    • Optional useStaticSigningKey: boolean
    • Optional userContext: Record<string, any>

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

  • getJWKS(userContext?: Record<string, any>): Promise<{ keys: JsonWebKey[]; validityInSeconds?: number }>

Generated using TypeDoc

\ No newline at end of file +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, useStaticSigningKey?: boolean, userContext?: Record<string, any>): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
  • Parameters

    • payload: any
    • Optional validitySeconds: number
    • Optional useStaticSigningKey: boolean
    • Optional userContext: Record<string, any>

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

  • getJWKS(userContext?: Record<string, any>): Promise<{ keys: JsonWebKey[]; validityInSeconds?: number }>

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/recipe_multifactorauth.default.html b/docs/classes/recipe_multifactorauth.default.html index 95fc4db80..9abedc3c3 100644 --- a/docs/classes/recipe_multifactorauth.default.html +++ b/docs/classes/recipe_multifactorauth.default.html @@ -1 +1 @@ -default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

FactorIds: { EMAILPASSWORD: string; LINK_EMAIL: string; LINK_PHONE: string; OTP_EMAIL: string; OTP_PHONE: string; THIRDPARTY: string; TOTP: string } = FactorIds

Type declaration

  • EMAILPASSWORD: string
  • LINK_EMAIL: string
  • LINK_PHONE: string
  • OTP_EMAIL: string
  • OTP_PHONE: string
  • THIRDPARTY: string
  • TOTP: string
MultiFactorAuthClaim: MultiFactorAuthClaimClass = MultiFactorAuthClaim
init: ((config?: TypeInput) => RecipeListFunction) = Recipe.init

Type declaration

    • (config?: TypeInput): RecipeListFunction
    • Parameters

      • Optional config: TypeInput

      Returns RecipeListFunction

Methods

  • addToRequiredSecondaryFactorsForUser(userId: string, factorId: string, userContext?: Record<string, any>): Promise<void>
  • assertAllowedToSetupFactorElseThrowInvalidClaimError(session: SessionContainer, factorId: string, userContext?: Record<string, any>): Promise<void>
  • getFactorsSetupForUser(userId: string, userContext?: Record<string, any>): Promise<string[]>
  • getMFARequirementsForAuth(session: SessionContainer, userContext?: Record<string, any>): Promise<MFARequirementList>
  • getRequiredSecondaryFactorsForUser(userId: string, userContext?: Record<string, any>): Promise<string[]>
  • markFactorAsCompleteInSession(session: SessionContainer, factorId: string, userContext?: Record<string, any>): Promise<void>
  • removeFromRequiredSecondaryFactorsForUser(userId: string, factorId: string, userContext?: Record<string, any>): Promise<void>

Generated using TypeDoc

\ No newline at end of file +default | supertokens-node
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • default

Index

Constructors

Properties

FactorIds: { EMAILPASSWORD: string; LINK_EMAIL: string; LINK_PHONE: string; OTP_EMAIL: string; OTP_PHONE: string; THIRDPARTY: string; TOTP: string } = FactorIds

Type declaration

  • EMAILPASSWORD: string
  • LINK_EMAIL: string
  • LINK_PHONE: string
  • OTP_EMAIL: string
  • OTP_PHONE: string
  • THIRDPARTY: string
  • TOTP: string
MultiFactorAuthClaim: MultiFactorAuthClaimClass = MultiFactorAuthClaim
init: ((config?: TypeInput) => RecipeListFunction) = Recipe.init

Type declaration

    • (config?: TypeInput): RecipeListFunction
    • Parameters

      • Optional config: TypeInput

      Returns RecipeListFunction

Methods

  • addToRequiredSecondaryFactorsForUser(userId: string, factorId: string, userContext?: Record<string, any>): Promise<void>
  • assertAllowedToSetupFactorElseThrowInvalidClaimError(session: SessionContainer, factorId: string, userContext?: Record<string, any>): Promise<void>
  • getFactorsSetupForUser(userId: string, userContext?: Record<string, any>): Promise<string[]>
  • getMFARequirementsForAuth(session: SessionContainer, userContext?: Record<string, any>): Promise<MFARequirementList>
  • getRequiredSecondaryFactorsForUser(userId: string, userContext?: Record<string, any>): Promise<string[]>
  • markFactorAsCompleteInSession(session: SessionContainer, factorId: string, userContext?: Record<string, any>): Promise<void>
  • removeFromRequiredSecondaryFactorsForUser(userId: string, factorId: string, userContext?: Record<string, any>): Promise<void>

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/recipe_multitenancy.default.html b/docs/classes/recipe_multitenancy.default.html index f594b381b..70d32ae88 100644 --- a/docs/classes/recipe_multitenancy.default.html +++ b/docs/classes/recipe_multitenancy.default.html @@ -1 +1 @@ -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

  • associateUserToTenant(tenantId: string, recipeUserId: RecipeUserId, userContext?: Record<string, any>): Promise<{ status: "OK"; wasAlreadyAssociated: boolean } | { status: "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" | "THIRD_PARTY_USER_ALREADY_EXISTS_ERROR" } | { reason: string; status: "ASSOCIATION_NOT_ALLOWED_ERROR" }>
  • Parameters

    • tenantId: string
    • recipeUserId: RecipeUserId
    • Optional userContext: Record<string, any>

    Returns Promise<{ status: "OK"; wasAlreadyAssociated: boolean } | { status: "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" | "THIRD_PARTY_USER_ALREADY_EXISTS_ERROR" } | { reason: string; status: "ASSOCIATION_NOT_ALLOWED_ERROR" }>

  • createOrUpdateTenant(tenantId: string, config?: { coreConfig?: {}; firstFactors?: null | string[]; requiredSecondaryFactors?: null | string[] }, userContext?: Record<string, any>): Promise<{ createdNew: boolean; status: "OK" }>
  • Parameters

    • tenantId: string
    • Optional config: { coreConfig?: {}; firstFactors?: null | string[]; requiredSecondaryFactors?: null | string[] }
      • Optional coreConfig?: {}
        • [key: string]: any
      • Optional firstFactors?: null | string[]
      • Optional requiredSecondaryFactors?: null | string[]
    • Optional userContext: Record<string, any>

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

  • createOrUpdateThirdPartyConfig(tenantId: string, config: ProviderConfig, skipValidation?: boolean, userContext?: Record<string, any>): Promise<{ createdNew: boolean; status: "OK" }>
  • Parameters

    • tenantId: string
    • config: ProviderConfig
    • Optional skipValidation: boolean
    • Optional userContext: Record<string, any>

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

  • deleteTenant(tenantId: string, userContext?: Record<string, any>): Promise<{ didExist: boolean; status: "OK" }>
  • deleteThirdPartyConfig(tenantId: string, thirdPartyId: string, userContext?: Record<string, any>): Promise<{ didConfigExist: boolean; status: "OK" }>
  • Parameters

    • tenantId: string
    • thirdPartyId: string
    • Optional userContext: Record<string, any>

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

  • disassociateUserFromTenant(tenantId: string, recipeUserId: RecipeUserId, userContext?: Record<string, any>): Promise<{ status: "OK"; wasAssociated: boolean }>
  • getTenant(tenantId: string, userContext?: Record<string, any>): Promise<undefined | { status: "OK" } & TenantConfig>
  • listAllTenants(userContext?: Record<string, any>): Promise<{ status: "OK"; tenants: ({ tenantId: string } & TenantConfig)[] }>

Generated using TypeDoc

\ No newline at end of file +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

  • associateUserToTenant(tenantId: string, recipeUserId: RecipeUserId, userContext?: Record<string, any>): Promise<{ status: "OK"; wasAlreadyAssociated: boolean } | { status: "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" | "THIRD_PARTY_USER_ALREADY_EXISTS_ERROR" } | { reason: string; status: "ASSOCIATION_NOT_ALLOWED_ERROR" }>
  • Parameters

    • tenantId: string
    • recipeUserId: RecipeUserId
    • Optional userContext: Record<string, any>

    Returns Promise<{ status: "OK"; wasAlreadyAssociated: boolean } | { status: "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" | "THIRD_PARTY_USER_ALREADY_EXISTS_ERROR" } | { reason: string; status: "ASSOCIATION_NOT_ALLOWED_ERROR" }>

  • createOrUpdateTenant(tenantId: string, config?: { coreConfig?: {}; firstFactors?: null | string[]; requiredSecondaryFactors?: null | string[] }, userContext?: Record<string, any>): Promise<{ createdNew: boolean; status: "OK" }>
  • Parameters

    • tenantId: string
    • Optional config: { coreConfig?: {}; firstFactors?: null | string[]; requiredSecondaryFactors?: null | string[] }
      • Optional coreConfig?: {}
        • [key: string]: any
      • Optional firstFactors?: null | string[]
      • Optional requiredSecondaryFactors?: null | string[]
    • Optional userContext: Record<string, any>

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

  • createOrUpdateThirdPartyConfig(tenantId: string, config: ProviderConfig, skipValidation?: boolean, userContext?: Record<string, any>): Promise<{ createdNew: boolean; status: "OK" }>
  • Parameters

    • tenantId: string
    • config: ProviderConfig
    • Optional skipValidation: boolean
    • Optional userContext: Record<string, any>

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

  • deleteTenant(tenantId: string, userContext?: Record<string, any>): Promise<{ didExist: boolean; status: "OK" }>
  • deleteThirdPartyConfig(tenantId: string, thirdPartyId: string, userContext?: Record<string, any>): Promise<{ didConfigExist: boolean; status: "OK" }>
  • Parameters

    • tenantId: string
    • thirdPartyId: string
    • Optional userContext: Record<string, any>

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

  • disassociateUserFromTenant(tenantId: string, recipeUserId: RecipeUserId, userContext?: Record<string, any>): Promise<{ status: "OK"; wasAssociated: boolean }>
  • getTenant(tenantId: string, userContext?: Record<string, any>): Promise<undefined | { status: "OK" } & TenantConfig>
  • listAllTenants(userContext?: Record<string, any>): Promise<{ status: "OK"; tenants: ({ tenantId: string } & TenantConfig)[] }>

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/recipe_openid.default.html b/docs/classes/recipe_openid.default.html index 4aab539f7..24461afa6 100644 --- a/docs/classes/recipe_openid.default.html +++ b/docs/classes/recipe_openid.default.html @@ -1 +1 @@ -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, useStaticSigningKey?: boolean, userContext?: Record<string, any>): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
  • Parameters

    • Optional payload: any
    • Optional validitySeconds: number
    • Optional useStaticSigningKey: boolean
    • Optional userContext: Record<string, any>

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

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

    • Optional userContext: Record<string, any>

    Returns Promise<{ issuer: string; jwks_uri: string; status: "OK" }>

Generated using TypeDoc

\ No newline at end of file +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, useStaticSigningKey?: boolean, userContext?: Record<string, any>): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
  • Parameters

    • Optional payload: any
    • Optional validitySeconds: number
    • Optional useStaticSigningKey: boolean
    • Optional userContext: Record<string, any>

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

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

    • Optional userContext: Record<string, any>

    Returns Promise<{ issuer: string; jwks_uri: string; status: "OK" }>

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/recipe_passwordless.default.html b/docs/classes/recipe_passwordless.default.html index b3a464776..417f6324b 100644 --- a/docs/classes/recipe_passwordless.default.html +++ b/docs/classes/recipe_passwordless.default.html @@ -1,14 +1,14 @@ -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

  • checkCode(input: { deviceId: string; preAuthSessionId: string; tenantId: string; userContext?: Record<string, any>; userInputCode: string } | { linkCode: string; preAuthSessionId: string; tenantId: string; userContext?: Record<string, any> }): Promise<{ consumedDevice: { email?: string; failedCodeInputAttemptCount: number; phoneNumber?: string; preAuthSessionId: string }; status: "OK" } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
  • +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

    • checkCode(input: { deviceId: string; preAuthSessionId: string; tenantId: string; userContext?: Record<string, any>; userInputCode: string } | { linkCode: string; preAuthSessionId: string; tenantId: string; userContext?: Record<string, any> }): Promise<{ consumedDevice: { email?: string; failedCodeInputAttemptCount: number; phoneNumber?: string; preAuthSessionId: string }; status: "OK" } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
    • This function will only verify the code (not consume it), and: NOT create a new user if it doesn't exist NOT verify the user email if it exists NOT do any linking NOT delete the code unless it returned RESTART_FLOW_ERROR

      -

      Parameters

      • input: { deviceId: string; preAuthSessionId: string; tenantId: string; userContext?: Record<string, any>; userInputCode: string } | { linkCode: string; preAuthSessionId: string; tenantId: string; userContext?: Record<string, any> }

      Returns Promise<{ consumedDevice: { email?: string; failedCodeInputAttemptCount: number; phoneNumber?: string; preAuthSessionId: string }; status: "OK" } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

    • consumeCode(input: { deviceId: string; preAuthSessionId: string; session?: undefined; tenantId: string; userContext?: Record<string, any>; userInputCode: string } | { linkCode: string; preAuthSessionId: string; session?: undefined; tenantId: string; userContext?: Record<string, any> }): Promise<{ consumedDevice: { email?: string; failedCodeInputAttemptCount: number; phoneNumber?: string; preAuthSessionId: string }; createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
    • consumeCode(input: { deviceId: string; preAuthSessionId: string; session: SessionContainer; tenantId: string; userContext?: Record<string, any>; userInputCode: string } | { linkCode: string; preAuthSessionId: string; session: SessionContainer; tenantId: string; userContext?: Record<string, any> }): Promise<{ consumedDevice: { email?: string; failedCodeInputAttemptCount: number; phoneNumber?: string; preAuthSessionId: string }; createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>
    • +

      Parameters

      • input: { deviceId: string; preAuthSessionId: string; tenantId: string; userContext?: Record<string, any>; userInputCode: string } | { linkCode: string; preAuthSessionId: string; tenantId: string; userContext?: Record<string, any> }

      Returns Promise<{ consumedDevice: { email?: string; failedCodeInputAttemptCount: number; phoneNumber?: string; preAuthSessionId: string }; status: "OK" } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>

    • consumeCode(input: { deviceId: string; preAuthSessionId: string; session?: undefined; tenantId: string; userContext?: Record<string, any>; userInputCode: string } | { linkCode: string; preAuthSessionId: string; session?: undefined; tenantId: string; userContext?: Record<string, any> }): Promise<{ consumedDevice: { email?: string; failedCodeInputAttemptCount: number; phoneNumber?: string; preAuthSessionId: string }; createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" }>
    • consumeCode(input: { deviceId: string; preAuthSessionId: string; session: SessionContainer; tenantId: string; userContext?: Record<string, any>; userInputCode: string } | { linkCode: string; preAuthSessionId: string; session: SessionContainer; tenantId: string; userContext?: Record<string, any> }): Promise<{ consumedDevice: { email?: string; failedCodeInputAttemptCount: number; phoneNumber?: string; preAuthSessionId: string }; createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>
      1. verifies the code
      2. creates the user if it doesn't exist
      3. tries to link it
      4. marks the email as verified
      -

      Parameters

      • input: { deviceId: string; preAuthSessionId: string; session?: undefined; tenantId: string; userContext?: Record<string, any>; userInputCode: string } | { linkCode: string; preAuthSessionId: string; session?: undefined; tenantId: string; userContext?: Record<string, any> }

      Returns Promise<{ consumedDevice: { email?: string; failedCodeInputAttemptCount: number; phoneNumber?: string; preAuthSessionId: string }; createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; 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; session: SessionContainer; tenantId: string; userContext?: Record<string, any>; userInputCode: string } | { linkCode: string; preAuthSessionId: string; session: SessionContainer; tenantId: string; userContext?: Record<string, any> }

      Returns Promise<{ consumedDevice: { email?: string; failedCodeInputAttemptCount: number; phoneNumber?: string; preAuthSessionId: string }; createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>

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

      • input: { email: string } & { session?: SessionContainer; tenantId: string; userContext?: Record<string, any>; userInputCode?: string } & { phoneNumber: string } & { session?: SessionContainer; tenantId: string; userContext?: Record<string, 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; tenantId: string; userContext?: Record<string, any> } | { phoneNumber: string; tenantId: string; userContext?: Record<string, any> }): Promise<string>
    • Parameters

      • input: { email: string; tenantId: string; userContext?: Record<string, any> } | { phoneNumber: string; tenantId: string; userContext?: Record<string, any> }

      Returns Promise<string>

    • createNewCodeForDevice(input: { deviceId: string; tenantId: string; userContext?: Record<string, 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; tenantId: string; userContext?: Record<string, any>; userInputCode?: string }
        • deviceId: string
        • tenantId: string
        • Optional userContext?: Record<string, 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" }>

    • listCodesByDeviceId(input: { deviceId: string; tenantId: string; userContext?: Record<string, any> }): Promise<undefined | DeviceType>
    • Parameters

      • input: { deviceId: string; tenantId: string; userContext?: Record<string, any> }
        • deviceId: string
        • tenantId: string
        • Optional userContext?: Record<string, any>

      Returns Promise<undefined | DeviceType>

    • listCodesByEmail(input: { email: string; tenantId: string; userContext?: Record<string, any> }): Promise<DeviceType[]>
    • Parameters

      • input: { email: string; tenantId: string; userContext?: Record<string, any> }
        • email: string
        • tenantId: string
        • Optional userContext?: Record<string, any>

      Returns Promise<DeviceType[]>

    • listCodesByPhoneNumber(input: { phoneNumber: string; tenantId: string; userContext?: Record<string, any> }): Promise<DeviceType[]>
    • Parameters

      • input: { phoneNumber: string; tenantId: string; userContext?: Record<string, any> }
        • phoneNumber: string
        • tenantId: string
        • Optional userContext?: Record<string, any>

      Returns Promise<DeviceType[]>

    • listCodesByPreAuthSessionId(input: { preAuthSessionId: string; tenantId: string; userContext?: Record<string, any> }): Promise<undefined | DeviceType>
    • Parameters

      • input: { preAuthSessionId: string; tenantId: string; userContext?: Record<string, any> }
        • preAuthSessionId: string
        • tenantId: string
        • Optional userContext?: Record<string, any>

      Returns Promise<undefined | DeviceType>

    • revokeAllCodes(input: { email: string; tenantId: string; userContext?: Record<string, any> } | { phoneNumber: string; tenantId: string; userContext?: Record<string, any> }): Promise<{ status: "OK" }>
    • Parameters

      • input: { email: string; tenantId: string; userContext?: Record<string, any> } | { phoneNumber: string; tenantId: string; userContext?: Record<string, any> }

      Returns Promise<{ status: "OK" }>

    • revokeCode(input: { codeId: string; tenantId: string; userContext?: Record<string, any> } | { preAuthSessionId: string; tenantId: string; userContext?: Record<string, any> }): Promise<{ status: "OK" }>
    • Parameters

      • input: { codeId: string; tenantId: string; userContext?: Record<string, any> } | { preAuthSessionId: string; tenantId: string; userContext?: Record<string, any> }

      Returns Promise<{ status: "OK" }>

    • sendEmail(input: TypePasswordlessEmailDeliveryInput & { userContext?: Record<string, any> }): Promise<void>
    • sendSms(input: TypePasswordlessSmsDeliveryInput & { userContext?: Record<string, any> }): Promise<void>
    • signInUp(input: { email: string; session?: SessionContainer; tenantId: string; userContext?: Record<string, any> } | { phoneNumber: string; session?: SessionContainer; tenantId: string; userContext?: Record<string, any> }): Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: string; user: User }>
    • updateUser(input: { email?: null | string; phoneNumber?: null | string; recipeUserId: RecipeUserId; userContext?: Record<string, any> }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" | "PHONE_NUMBER_CHANGE_NOT_ALLOWED_ERROR" }>
    • Parameters

      • input: { email?: null | string; phoneNumber?: null | string; recipeUserId: RecipeUserId; userContext?: Record<string, any> }
        • Optional email?: null | string
        • Optional phoneNumber?: null | string
        • recipeUserId: RecipeUserId
        • Optional userContext?: Record<string, any>

      Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" | "PHONE_NUMBER_CHANGE_NOT_ALLOWED_ERROR" }>

    Legend

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

    Settings

    Theme

    Generated using TypeDoc

    \ No newline at end of file +

    Parameters

    • input: { deviceId: string; preAuthSessionId: string; session?: undefined; tenantId: string; userContext?: Record<string, any>; userInputCode: string } | { linkCode: string; preAuthSessionId: string; session?: undefined; tenantId: string; userContext?: Record<string, any> }

    Returns Promise<{ consumedDevice: { email?: string; failedCodeInputAttemptCount: number; phoneNumber?: string; preAuthSessionId: string }; createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; 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; session: SessionContainer; tenantId: string; userContext?: Record<string, any>; userInputCode: string } | { linkCode: string; preAuthSessionId: string; session: SessionContainer; tenantId: string; userContext?: Record<string, any> }

    Returns Promise<{ consumedDevice: { email?: string; failedCodeInputAttemptCount: number; phoneNumber?: string; preAuthSessionId: string }; createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { failedCodeInputAttemptCount: number; maximumCodeInputAttempts: number; status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR" } | { status: "RESTART_FLOW_ERROR" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>

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

    • input: { email: string } & { session?: SessionContainer; tenantId: string; userContext?: Record<string, any>; userInputCode?: string } & { phoneNumber: string } & { session?: SessionContainer; tenantId: string; userContext?: Record<string, 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; tenantId: string; userContext?: Record<string, any> } | { phoneNumber: string; tenantId: string; userContext?: Record<string, any> }): Promise<string>
  • Parameters

    • input: { email: string; tenantId: string; userContext?: Record<string, any> } | { phoneNumber: string; tenantId: string; userContext?: Record<string, any> }

    Returns Promise<string>

  • createNewCodeForDevice(input: { deviceId: string; tenantId: string; userContext?: Record<string, 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; tenantId: string; userContext?: Record<string, any>; userInputCode?: string }
      • deviceId: string
      • tenantId: string
      • Optional userContext?: Record<string, 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" }>

  • listCodesByDeviceId(input: { deviceId: string; tenantId: string; userContext?: Record<string, any> }): Promise<undefined | DeviceType>
  • Parameters

    • input: { deviceId: string; tenantId: string; userContext?: Record<string, any> }
      • deviceId: string
      • tenantId: string
      • Optional userContext?: Record<string, any>

    Returns Promise<undefined | DeviceType>

  • listCodesByEmail(input: { email: string; tenantId: string; userContext?: Record<string, any> }): Promise<DeviceType[]>
  • Parameters

    • input: { email: string; tenantId: string; userContext?: Record<string, any> }
      • email: string
      • tenantId: string
      • Optional userContext?: Record<string, any>

    Returns Promise<DeviceType[]>

  • listCodesByPhoneNumber(input: { phoneNumber: string; tenantId: string; userContext?: Record<string, any> }): Promise<DeviceType[]>
  • Parameters

    • input: { phoneNumber: string; tenantId: string; userContext?: Record<string, any> }
      • phoneNumber: string
      • tenantId: string
      • Optional userContext?: Record<string, any>

    Returns Promise<DeviceType[]>

  • listCodesByPreAuthSessionId(input: { preAuthSessionId: string; tenantId: string; userContext?: Record<string, any> }): Promise<undefined | DeviceType>
  • Parameters

    • input: { preAuthSessionId: string; tenantId: string; userContext?: Record<string, any> }
      • preAuthSessionId: string
      • tenantId: string
      • Optional userContext?: Record<string, any>

    Returns Promise<undefined | DeviceType>

  • revokeAllCodes(input: { email: string; tenantId: string; userContext?: Record<string, any> } | { phoneNumber: string; tenantId: string; userContext?: Record<string, any> }): Promise<{ status: "OK" }>
  • Parameters

    • input: { email: string; tenantId: string; userContext?: Record<string, any> } | { phoneNumber: string; tenantId: string; userContext?: Record<string, any> }

    Returns Promise<{ status: "OK" }>

  • revokeCode(input: { codeId: string; tenantId: string; userContext?: Record<string, any> } | { preAuthSessionId: string; tenantId: string; userContext?: Record<string, any> }): Promise<{ status: "OK" }>
  • Parameters

    • input: { codeId: string; tenantId: string; userContext?: Record<string, any> } | { preAuthSessionId: string; tenantId: string; userContext?: Record<string, any> }

    Returns Promise<{ status: "OK" }>

  • sendEmail(input: TypePasswordlessEmailDeliveryInput & { userContext?: Record<string, any> }): Promise<void>
  • sendSms(input: TypePasswordlessSmsDeliveryInput & { userContext?: Record<string, any> }): Promise<void>
  • signInUp(input: { email: string; session?: SessionContainer; tenantId: string; userContext?: Record<string, any> } | { phoneNumber: string; session?: SessionContainer; tenantId: string; userContext?: Record<string, any> }): Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: string; user: User }>
  • updateUser(input: { email?: null | string; phoneNumber?: null | string; recipeUserId: RecipeUserId; userContext?: Record<string, any> }): Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" | "PHONE_NUMBER_CHANGE_NOT_ALLOWED_ERROR" }>
  • Parameters

    • input: { email?: null | string; phoneNumber?: null | string; recipeUserId: RecipeUserId; userContext?: Record<string, any> }
      • Optional email?: null | string
      • Optional phoneNumber?: null | string
      • recipeUserId: RecipeUserId
      • Optional userContext?: Record<string, any>

    Returns Promise<{ status: "OK" | "EMAIL_ALREADY_EXISTS_ERROR" | "UNKNOWN_USER_ID_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" | "PHONE_NUMBER_CHANGE_NOT_ALLOWED_ERROR" }>

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/recipe_session.default.html b/docs/classes/recipe_session.default.html index a51d4bfb3..24d771ff8 100644 --- a/docs/classes/recipe_session.default.html +++ b/docs/classes/recipe_session.default.html @@ -1,4 +1,4 @@ -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, useStaticSigningKey?: boolean, userContext?: Record<string, any>): Promise<{ jwt: string; status: "OK" } | { status: "UNSUPPORTED_ALGORITHM_ERROR" }>
  • Parameters

    • Optional payload: any
    • Optional validitySeconds: number
    • Optional useStaticSigningKey: boolean
    • Optional userContext: Record<string, any>

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

  • createNewSession(req: any, res: any, tenantId: string, recipeUserId: RecipeUserId, accessTokenPayload?: any, sessionDataInDatabase?: any, userContext?: Record<string, any>): Promise<SessionContainer>
  • createNewSessionWithoutRequestResponse(tenantId: string, recipeUserId: RecipeUserId, accessTokenPayload?: any, sessionDataInDatabase?: any, disableAntiCsrf?: boolean, userContext?: Record<string, any>): Promise<SessionContainer>
  • fetchAndSetClaim(sessionHandle: string, claim: SessionClaim<any>, userContext?: Record<string, any>): Promise<boolean>
  • getAllSessionHandlesForUser(userId: string, fetchSessionsForAllLinkedAccounts?: boolean, tenantId?: string, userContext?: Record<string, any>): Promise<string[]>
  • Parameters

    • userId: string
    • fetchSessionsForAllLinkedAccounts: boolean = true
    • Optional tenantId: string
    • Optional userContext: Record<string, any>

    Returns Promise<string[]>

  • getClaimValue<T>(sessionHandle: string, claim: SessionClaim<T>, userContext?: Record<string, any>): Promise<{ status: "SESSION_DOES_NOT_EXIST_ERROR" } | { status: "OK"; value: undefined | T }>
  • Type Parameters

    • T

    Parameters

    • sessionHandle: string
    • claim: SessionClaim<T>
    • Optional userContext: Record<string, any>

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

  • getJWKS(userContext?: Record<string, any>): Promise<{ keys: JsonWebKey[] }>
  • getOpenIdDiscoveryConfiguration(userContext?: Record<string, any>): Promise<{ issuer: string; jwks_uri: string; status: "OK" }>
  • getSessionInformation(sessionHandle: string, userContext?: Record<string, any>): Promise<undefined | SessionInformation>
  • getSessionWithoutRequestResponse(accessToken: string, antiCsrfToken?: string): Promise<SessionContainer>
  • getSessionWithoutRequestResponse(accessToken: string, antiCsrfToken?: string, options?: VerifySessionOptions & { sessionRequired?: true }, userContext?: Record<string, any>): Promise<SessionContainer>
  • getSessionWithoutRequestResponse(accessToken: string, antiCsrfToken?: string, options?: VerifySessionOptions & { sessionRequired: false }, userContext?: Record<string, any>): Promise<undefined | SessionContainer>
  • getSessionWithoutRequestResponse(accessToken: string, antiCsrfToken?: string, options?: VerifySessionOptions, userContext?: Record<string, any>): Promise<undefined | SessionContainer>
  • mergeIntoAccessTokenPayload(sessionHandle: string, accessTokenPayloadUpdate: JSONObject, userContext?: Record<string, any>): Promise<boolean>
  • refreshSession(req: any, res: any, userContext?: Record<string, any>): Promise<SessionContainer>
  • refreshSessionWithoutRequestResponse(refreshToken: string, disableAntiCsrf?: boolean, antiCsrfToken?: string, userContext?: Record<string, any>): Promise<SessionContainer>
  • removeClaim(sessionHandle: string, claim: SessionClaim<any>, userContext?: Record<string, any>): Promise<boolean>
  • revokeAllSessionsForUser(userId: string, revokeSessionsForLinkedAccounts?: boolean, tenantId?: string, userContext?: Record<string, any>): Promise<string[]>
  • Parameters

    • userId: string
    • revokeSessionsForLinkedAccounts: boolean = true
    • Optional tenantId: string
    • Optional userContext: Record<string, any>

    Returns Promise<string[]>

  • revokeMultipleSessions(sessionHandles: string[], userContext?: Record<string, any>): Promise<string[]>
  • revokeSession(sessionHandle: string, userContext?: Record<string, any>): Promise<boolean>
  • setClaimValue<T>(sessionHandle: string, claim: SessionClaim<T>, value: T, userContext?: Record<string, any>): Promise<boolean>
  • Type Parameters

    • T

    Parameters

    • sessionHandle: string
    • claim: SessionClaim<T>
    • value: T
    • Optional userContext: Record<string, any>

    Returns Promise<boolean>

  • updateSessionDataInDatabase(sessionHandle: string, newSessionData: any, userContext?: Record<string, any>): Promise<boolean>

Generated using TypeDoc

\ No newline at end of file +

Returns Promise<SessionContainer>

  • Parameters

    Returns Promise<SessionContainer>

  • Parameters

    Returns Promise<undefined | SessionContainer>

  • Parameters

    Returns Promise<undefined | SessionContainer>

  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/recipe_thirdparty.default.html b/docs/classes/recipe_thirdparty.default.html index bd5c0994a..0fc312769 100644 --- a/docs/classes/recipe_thirdparty.default.html +++ b/docs/classes/recipe_thirdparty.default.html @@ -1 +1 @@ -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

    • getProvider(tenantId: string, thirdPartyId: string, clientType: undefined | string, userContext?: Record<string, any>): Promise<undefined | TypeProvider>
    • manuallyCreateOrUpdateUser(tenantId: string, thirdPartyId: string, thirdPartyUserId: string, email: string, isVerified: boolean, session?: undefined, userContext?: Record<string, any>): Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" }>
    • manuallyCreateOrUpdateUser(tenantId: string, thirdPartyId: string, thirdPartyUserId: string, email: string, isVerified: boolean, session: SessionContainer, userContext?: Record<string, any>): Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>
    • Parameters

      • tenantId: string
      • thirdPartyId: string
      • thirdPartyUserId: string
      • email: string
      • isVerified: boolean
      • Optional session: undefined
      • Optional userContext: Record<string, any>

      Returns Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" }>

    • Parameters

      • tenantId: string
      • thirdPartyId: string
      • thirdPartyUserId: string
      • email: string
      • isVerified: boolean
      • session: SessionContainer
      • Optional userContext: Record<string, any>

      Returns Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>

    Generated using TypeDoc

    \ No newline at end of file +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

    • getProvider(tenantId: string, thirdPartyId: string, clientType: undefined | string, userContext?: Record<string, any>): Promise<undefined | TypeProvider>
    • manuallyCreateOrUpdateUser(tenantId: string, thirdPartyId: string, thirdPartyUserId: string, email: string, isVerified: boolean, session?: undefined, userContext?: Record<string, any>): Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" }>
    • manuallyCreateOrUpdateUser(tenantId: string, thirdPartyId: string, thirdPartyUserId: string, email: string, isVerified: boolean, session: SessionContainer, userContext?: Record<string, any>): Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>
    • Parameters

      • tenantId: string
      • thirdPartyId: string
      • thirdPartyUserId: string
      • email: string
      • isVerified: boolean
      • Optional session: undefined
      • Optional userContext: Record<string, any>

      Returns Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" }>

    • Parameters

      • tenantId: string
      • thirdPartyId: string
      • thirdPartyUserId: string
      • email: string
      • isVerified: boolean
      • session: SessionContainer
      • Optional userContext: Record<string, any>

      Returns Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/recipe_totp.default.html b/docs/classes/recipe_totp.default.html index 5b8523ffe..81561808c 100644 --- a/docs/classes/recipe_totp.default.html +++ b/docs/classes/recipe_totp.default.html @@ -1 +1 @@ -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

    • createDevice(userId: string, userIdentifierInfo?: string, deviceName?: string, skew?: number, period?: number, userContext?: Record<string, any>): Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | { status: "UNKNOWN_USER_ID_ERROR" }>
    • Parameters

      • userId: string
      • Optional userIdentifierInfo: string
      • Optional deviceName: string
      • Optional skew: number
      • Optional period: number
      • Optional userContext: Record<string, any>

      Returns Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | { status: "UNKNOWN_USER_ID_ERROR" }>

    • listDevices(userId: string, userContext?: Record<string, any>): Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" }>
    • Parameters

      • userId: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" }>

    • removeDevice(userId: string, deviceName: string, userContext?: Record<string, any>): Promise<{ didDeviceExist: boolean; status: "OK" }>
    • Parameters

      • userId: string
      • deviceName: string
      • Optional userContext: Record<string, any>

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

    • updateDevice(userId: string, existingDeviceName: string, newDeviceName: string, userContext?: Record<string, any>): Promise<{ status: "OK" | "DEVICE_ALREADY_EXISTS_ERROR" | "UNKNOWN_DEVICE_ERROR" }>
    • Parameters

      • userId: string
      • existingDeviceName: string
      • newDeviceName: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ status: "OK" | "DEVICE_ALREADY_EXISTS_ERROR" | "UNKNOWN_DEVICE_ERROR" }>

    • verifyDevice(tenantId: string, userId: string, deviceName: string, totp: string, userContext?: Record<string, any>): Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>
    • Parameters

      • tenantId: string
      • userId: string
      • deviceName: string
      • totp: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>

    • verifyTOTP(tenantId: string, userId: string, totp: string, userContext?: Record<string, any>): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>
    • Parameters

      • tenantId: string
      • userId: string
      • totp: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>

    Generated using TypeDoc

    \ No newline at end of file +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

    • createDevice(userId: string, userIdentifierInfo?: string, deviceName?: string, skew?: number, period?: number, userContext?: Record<string, any>): Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | { status: "UNKNOWN_USER_ID_ERROR" }>
    • Parameters

      • userId: string
      • Optional userIdentifierInfo: string
      • Optional deviceName: string
      • Optional skew: number
      • Optional period: number
      • Optional userContext: Record<string, any>

      Returns Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | { status: "UNKNOWN_USER_ID_ERROR" }>

    • listDevices(userId: string, userContext?: Record<string, any>): Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" }>
    • Parameters

      • userId: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" }>

    • removeDevice(userId: string, deviceName: string, userContext?: Record<string, any>): Promise<{ didDeviceExist: boolean; status: "OK" }>
    • Parameters

      • userId: string
      • deviceName: string
      • Optional userContext: Record<string, any>

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

    • updateDevice(userId: string, existingDeviceName: string, newDeviceName: string, userContext?: Record<string, any>): Promise<{ status: "OK" | "DEVICE_ALREADY_EXISTS_ERROR" | "UNKNOWN_DEVICE_ERROR" }>
    • Parameters

      • userId: string
      • existingDeviceName: string
      • newDeviceName: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ status: "OK" | "DEVICE_ALREADY_EXISTS_ERROR" | "UNKNOWN_DEVICE_ERROR" }>

    • verifyDevice(tenantId: string, userId: string, deviceName: string, totp: string, userContext?: Record<string, any>): Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>
    • Parameters

      • tenantId: string
      • userId: string
      • deviceName: string
      • totp: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>

    • verifyTOTP(tenantId: string, userId: string, totp: string, userContext?: Record<string, any>): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>
    • Parameters

      • tenantId: string
      • userId: string
      • totp: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/recipe_usermetadata.default.html b/docs/classes/recipe_usermetadata.default.html index f874813af..49c275323 100644 --- a/docs/classes/recipe_usermetadata.default.html +++ b/docs/classes/recipe_usermetadata.default.html @@ -1 +1 @@ -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?: Record<string, any>): Promise<{ status: "OK" }>
    • getUserMetadata(userId: string, userContext?: Record<string, any>): Promise<{ metadata: any; status: "OK" }>
    • updateUserMetadata(userId: string, metadataUpdate: JSONObject, userContext?: Record<string, any>): Promise<{ metadata: JSONObject; status: "OK" }>

    Generated using TypeDoc

    \ No newline at end of file +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?: Record<string, any>): Promise<{ status: "OK" }>
    • getUserMetadata(userId: string, userContext?: Record<string, any>): Promise<{ metadata: any; status: "OK" }>
    • updateUserMetadata(userId: string, metadataUpdate: JSONObject, userContext?: Record<string, any>): Promise<{ metadata: JSONObject; status: "OK" }>

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/recipe_userroles.default.html b/docs/classes/recipe_userroles.default.html index eb27b0dd8..c3e52f425 100644 --- a/docs/classes/recipe_userroles.default.html +++ b/docs/classes/recipe_userroles.default.html @@ -1 +1 @@ -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(tenantId: string, userId: string, role: string, userContext?: Record<string, any>): Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
    • Parameters

      • tenantId: string
      • userId: string
      • role: string
      • Optional userContext: Record<string, any>

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

    • createNewRoleOrAddPermissions(role: string, permissions: string[], userContext?: Record<string, any>): Promise<{ createdNewRole: boolean; status: "OK" }>
    • Parameters

      • role: string
      • permissions: string[]
      • Optional userContext: Record<string, any>

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

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

      • role: string
      • Optional userContext: Record<string, any>

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

    • getRolesForUser(tenantId: string, userId: string, userContext?: Record<string, any>): Promise<{ roles: string[]; status: "OK" }>
    • Parameters

      • tenantId: string
      • userId: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ roles: string[]; status: "OK" }>

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

      • tenantId: string
      • role: string
      • Optional userContext: Record<string, any>

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

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

      • role: string
      • permissions: string[]
      • Optional userContext: Record<string, any>

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

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

      • tenantId: string
      • userId: string
      • role: string
      • Optional userContext: Record<string, any>

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

    Generated using TypeDoc

    \ No newline at end of file +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(tenantId: string, userId: string, role: string, userContext?: Record<string, any>): Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
    • Parameters

      • tenantId: string
      • userId: string
      • role: string
      • Optional userContext: Record<string, any>

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

    • createNewRoleOrAddPermissions(role: string, permissions: string[], userContext?: Record<string, any>): Promise<{ createdNewRole: boolean; status: "OK" }>
    • Parameters

      • role: string
      • permissions: string[]
      • Optional userContext: Record<string, any>

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

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

      • role: string
      • Optional userContext: Record<string, any>

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

    • getRolesForUser(tenantId: string, userId: string, userContext?: Record<string, any>): Promise<{ roles: string[]; status: "OK" }>
    • Parameters

      • tenantId: string
      • userId: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ roles: string[]; status: "OK" }>

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

      • tenantId: string
      • role: string
      • Optional userContext: Record<string, any>

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

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

      • role: string
      • permissions: string[]
      • Optional userContext: Record<string, any>

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

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

      • tenantId: string
      • userId: string
      • role: string
      • Optional userContext: Record<string, any>

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

    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 index 25befe559..6df24a799 100644 --- a/docs/interfaces/framework_awsLambda.SessionEvent.html +++ b/docs/interfaces/framework_awsLambda.SessionEvent.html @@ -1 +1 @@ -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 }[]

    Generated using TypeDoc

    \ No newline at end of file +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 }[]

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/framework_awsLambda.SessionEventV2.html b/docs/interfaces/framework_awsLambda.SessionEventV2.html index 0fa6a3ca4..eb0630862 100644 --- a/docs/interfaces/framework_awsLambda.SessionEventV2.html +++ b/docs/interfaces/framework_awsLambda.SessionEventV2.html @@ -1 +1 @@ -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

    Generated using TypeDoc

    \ No newline at end of file +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

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/framework_express.SessionRequest.html b/docs/interfaces/framework_express.SessionRequest.html index 06aa48d56..abffa7d9f 100644 --- a/docs/interfaces/framework_express.SessionRequest.html +++ b/docs/interfaces/framework_express.SessionRequest.html @@ -135,7 +135,7 @@
    route: any
    secure: boolean

    Short-hand for:

    req.protocol == 'https'

    -
    session?: SessionContainer
    signedCookies: any
    socket: Socket
    +
    session?: SessionContainer
    signedCookies: any
    socket: Socket

    The net.Socket object associated with the connection.

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

    @@ -176,10 +176,10 @@

    Methods

    server: Server

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

    -
    state: Dictionary<any>
    +
    state: Dictionary<any>

    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.

    diff --git a/docs/interfaces/framework_koa.SessionContext.html b/docs/interfaces/framework_koa.SessionContext.html index 9266c8230..5d0bfa440 100644 --- a/docs/interfaces/framework_koa.SessionContext.html +++ b/docs/interfaces/framework_koa.SessionContext.html @@ -81,7 +81,7 @@
    secure: boolean

    Short-hand for:

    this.protocol == 'https'

    -
    socket: Socket
    +
    socket: Socket

    Return the request socket.

    stale: boolean

    Check if the request is stale, aka diff --git a/docs/interfaces/framework_loopback.SessionContext.html b/docs/interfaces/framework_loopback.SessionContext.html index e1e17acc9..cdd6a86f5 100644 --- a/docs/interfaces/framework_loopback.SessionContext.html +++ b/docs/interfaces/framework_loopback.SessionContext.html @@ -14,12 +14,12 @@

    A flag to tell if the response is finished.

    scope: BindingScope

    Scope for binding resolution

    -
    subscriptionManager: ContextSubscriptionManager
    +
    subscriptionManager: ContextSubscriptionManager

    Manager for observer subscriptions

    tagIndexer: ContextTagIndexer

    Indexer for bindings by tag

    Accessors

    Methods

    Methods

    SessionClaimValidator: ({ claim: SessionClaim<any>; shouldRefetch: any } | {}) & { id: string; validate: any }
    SessionInformation: { customClaimsInAccessTokenPayload: any; expiry: number; recipeUserId: RecipeUserId; sessionDataInDatabase: any; sessionHandle: string; tenantId: string; timeCreated: number; userId: string }

    Type declaration

    • customClaimsInAccessTokenPayload: any
    • expiry: number
    • recipeUserId: RecipeUserId
    • sessionDataInDatabase: any
    • sessionHandle: string
    • tenantId: string
    • timeCreated: number
    • userId: string

    Variables

    Error: typeof default = SessionWrapper.Error

    Functions

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules/recipe_thirdparty.html b/docs/modules/recipe_thirdparty.html index b49958d51..ea3b0a14b 100644 --- a/docs/modules/recipe_thirdparty.html +++ b/docs/modules/recipe_thirdparty.html @@ -1 +1 @@ -recipe/thirdparty | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/thirdparty

    Index

    Type Aliases

    APIInterface: { appleRedirectHandlerPOST: undefined | ((input: { formPostInfoFromProvider: {}; options: APIOptions; userContext: UserContext }) => Promise<void>); authorisationUrlGET: undefined | ((input: { options: APIOptions; provider: TypeProvider; redirectURIOnProviderDashboard: string; tenantId: string; userContext: UserContext }) => Promise<{ pkceCodeVerifier?: string; status: "OK"; urlWithQueryParams: string } | GeneralErrorResponse>); signInUpPOST: undefined | ((input: { options: APIOptions; provider: TypeProvider; session: SessionContainer | undefined; tenantId: string; userContext: UserContext } & ({ redirectURIInfo: { pkceCodeVerifier?: string; redirectURIOnProviderDashboard: string; redirectURIQueryParams: any } } | { oAuthTokens: {} })) => Promise<{ createdNewRecipeUser: boolean; oAuthTokens: {}; rawUserInfoFromProvider: { fromIdTokenPayload?: {}; fromUserInfoAPI?: {} }; session: SessionContainer; status: "OK"; user: User } | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | GeneralErrorResponse>) }

    Type declaration

    • appleRedirectHandlerPOST: undefined | ((input: { formPostInfoFromProvider: {}; options: APIOptions; userContext: UserContext }) => Promise<void>)
    • authorisationUrlGET: undefined | ((input: { options: APIOptions; provider: TypeProvider; redirectURIOnProviderDashboard: string; tenantId: string; userContext: UserContext }) => Promise<{ pkceCodeVerifier?: string; status: "OK"; urlWithQueryParams: string } | GeneralErrorResponse>)
    • signInUpPOST: undefined | ((input: { options: APIOptions; provider: TypeProvider; session: SessionContainer | undefined; tenantId: string; userContext: UserContext } & ({ redirectURIInfo: { pkceCodeVerifier?: string; redirectURIOnProviderDashboard: string; redirectURIQueryParams: any } } | { oAuthTokens: {} })) => Promise<{ createdNewRecipeUser: boolean; oAuthTokens: {}; rawUserInfoFromProvider: { fromIdTokenPayload?: {}; fromUserInfoAPI?: {} }; session: SessionContainer; status: "OK"; user: User } | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | GeneralErrorResponse>)
    APIOptions: { appInfo: NormalisedAppinfo; config: TypeNormalisedInput; isInServerlessEnv: boolean; providers: ProviderInput[]; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse }

    Type declaration

    • appInfo: NormalisedAppinfo
    • config: TypeNormalisedInput
    • isInServerlessEnv: boolean
    • providers: ProviderInput[]
    • recipeId: string
    • recipeImplementation: RecipeInterface
    • req: BaseRequest
    • res: BaseResponse
    RecipeInterface: { getProvider: any; manuallyCreateOrUpdateUser: any; signInUp: any }

    Type declaration

    • getProvider:function
      • getProvider(input: { clientType?: string; tenantId: string; thirdPartyId: string; userContext: UserContext }): Promise<undefined | TypeProvider>
      • Parameters

        • input: { clientType?: string; tenantId: string; thirdPartyId: string; userContext: UserContext }
          • Optional clientType?: string
          • tenantId: string
          • thirdPartyId: string
          • userContext: UserContext

        Returns Promise<undefined | TypeProvider>

    • manuallyCreateOrUpdateUser:function
      • manuallyCreateOrUpdateUser(input: { email: string; isVerified: boolean; session: SessionContainer | undefined; tenantId: string; thirdPartyId: string; thirdPartyUserId: string; userContext: UserContext }): Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>
      • Parameters

        • input: { email: string; isVerified: boolean; session: SessionContainer | undefined; tenantId: string; thirdPartyId: string; thirdPartyUserId: string; userContext: UserContext }
          • email: string
          • isVerified: boolean
          • session: SessionContainer | undefined
          • tenantId: string
          • thirdPartyId: string
          • thirdPartyUserId: string
          • userContext: UserContext

        Returns Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>

    • signInUp:function
      • signInUp(input: { email: string; isVerified: boolean; oAuthTokens: {}; rawUserInfoFromProvider: { fromIdTokenPayload?: {}; fromUserInfoAPI?: {} }; session: SessionContainer | undefined; tenantId: string; thirdPartyId: string; thirdPartyUserId: string; userContext: UserContext }): Promise<{ createdNewRecipeUser: boolean; oAuthTokens: {}; rawUserInfoFromProvider: { fromIdTokenPayload?: {}; fromUserInfoAPI?: {} }; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>
      • Parameters

        • input: { email: string; isVerified: boolean; oAuthTokens: {}; rawUserInfoFromProvider: { fromIdTokenPayload?: {}; fromUserInfoAPI?: {} }; session: SessionContainer | undefined; tenantId: string; thirdPartyId: string; thirdPartyUserId: string; userContext: UserContext }
          • email: string
          • isVerified: boolean
          • oAuthTokens: {}
            • [key: string]: any
          • rawUserInfoFromProvider: { fromIdTokenPayload?: {}; fromUserInfoAPI?: {} }
            • Optional fromIdTokenPayload?: {}
              • [key: string]: any
            • Optional fromUserInfoAPI?: {}
              • [key: string]: any
          • session: SessionContainer | undefined
          • tenantId: string
          • thirdPartyId: string
          • thirdPartyUserId: string
          • userContext: UserContext

        Returns Promise<{ createdNewRecipeUser: boolean; oAuthTokens: {}; rawUserInfoFromProvider: { fromIdTokenPayload?: {}; fromUserInfoAPI?: {} }; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>

    TypeProvider: { config: ProviderConfigForClientType; id: string; exchangeAuthCodeForOAuthTokens: any; getAuthorisationRedirectURL: any; getConfigForClientType: any; getUserInfo: any }

    Type declaration

    • config: ProviderConfigForClientType
    • id: string
    • exchangeAuthCodeForOAuthTokens:function
      • exchangeAuthCodeForOAuthTokens(input: { redirectURIInfo: { pkceCodeVerifier?: string; redirectURIOnProviderDashboard: string; redirectURIQueryParams: any }; userContext: UserContext }): Promise<any>
      • Parameters

        • input: { redirectURIInfo: { pkceCodeVerifier?: string; redirectURIOnProviderDashboard: string; redirectURIQueryParams: any }; userContext: UserContext }
          • redirectURIInfo: { pkceCodeVerifier?: string; redirectURIOnProviderDashboard: string; redirectURIQueryParams: any }
            • Optional pkceCodeVerifier?: string
            • redirectURIOnProviderDashboard: string
            • redirectURIQueryParams: any
          • userContext: UserContext

        Returns Promise<any>

    • getAuthorisationRedirectURL:function
      • getAuthorisationRedirectURL(input: { redirectURIOnProviderDashboard: string; userContext: UserContext }): Promise<{ pkceCodeVerifier?: string; urlWithQueryParams: string }>
      • Parameters

        • input: { redirectURIOnProviderDashboard: string; userContext: UserContext }
          • redirectURIOnProviderDashboard: string
          • userContext: UserContext

        Returns Promise<{ pkceCodeVerifier?: string; urlWithQueryParams: string }>

    • getConfigForClientType:function
      • getConfigForClientType(input: { clientType?: string; userContext: UserContext }): Promise<ProviderConfigForClientType>
      • Parameters

        • input: { clientType?: string; userContext: UserContext }
          • Optional clientType?: string
          • userContext: UserContext

        Returns Promise<ProviderConfigForClientType>

    • getUserInfo:function
      • getUserInfo(input: { oAuthTokens: any; userContext: UserContext }): Promise<UserInfo>

    Variables

    Error: typeof default = Wrapper.Error

    Functions

    • getProvider(tenantId: string, thirdPartyId: string, clientType: undefined | string, userContext?: Record<string, any>): Promise<undefined | TypeProvider>
    • init(config?: TypeInput): RecipeListFunction
    • manuallyCreateOrUpdateUser(tenantId: string, thirdPartyId: string, thirdPartyUserId: string, email: string, isVerified: boolean, session?: undefined, userContext?: Record<string, any>): Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" }>
    • manuallyCreateOrUpdateUser(tenantId: string, thirdPartyId: string, thirdPartyUserId: string, email: string, isVerified: boolean, session: SessionContainer, userContext?: Record<string, any>): Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>
    • Parameters

      • tenantId: string
      • thirdPartyId: string
      • thirdPartyUserId: string
      • email: string
      • isVerified: boolean
      • Optional session: undefined
      • Optional userContext: Record<string, any>

      Returns Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" }>

    • Parameters

      • tenantId: string
      • thirdPartyId: string
      • thirdPartyUserId: string
      • email: string
      • isVerified: boolean
      • session: SessionContainer
      • Optional userContext: Record<string, any>

      Returns Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>

    Generated using TypeDoc

    \ No newline at end of file +recipe/thirdparty | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/thirdparty

    Index

    Type Aliases

    APIInterface: { appleRedirectHandlerPOST: undefined | ((input: { formPostInfoFromProvider: {}; options: APIOptions; userContext: UserContext }) => Promise<void>); authorisationUrlGET: undefined | ((input: { options: APIOptions; provider: TypeProvider; redirectURIOnProviderDashboard: string; tenantId: string; userContext: UserContext }) => Promise<{ pkceCodeVerifier?: string; status: "OK"; urlWithQueryParams: string } | GeneralErrorResponse>); signInUpPOST: undefined | ((input: { options: APIOptions; provider: TypeProvider; session: SessionContainer | undefined; tenantId: string; userContext: UserContext } & ({ redirectURIInfo: { pkceCodeVerifier?: string; redirectURIOnProviderDashboard: string; redirectURIQueryParams: any } } | { oAuthTokens: {} })) => Promise<{ createdNewRecipeUser: boolean; oAuthTokens: {}; rawUserInfoFromProvider: { fromIdTokenPayload?: {}; fromUserInfoAPI?: {} }; session: SessionContainer; status: "OK"; user: User } | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | GeneralErrorResponse>) }

    Type declaration

    • appleRedirectHandlerPOST: undefined | ((input: { formPostInfoFromProvider: {}; options: APIOptions; userContext: UserContext }) => Promise<void>)
    • authorisationUrlGET: undefined | ((input: { options: APIOptions; provider: TypeProvider; redirectURIOnProviderDashboard: string; tenantId: string; userContext: UserContext }) => Promise<{ pkceCodeVerifier?: string; status: "OK"; urlWithQueryParams: string } | GeneralErrorResponse>)
    • signInUpPOST: undefined | ((input: { options: APIOptions; provider: TypeProvider; session: SessionContainer | undefined; tenantId: string; userContext: UserContext } & ({ redirectURIInfo: { pkceCodeVerifier?: string; redirectURIOnProviderDashboard: string; redirectURIQueryParams: any } } | { oAuthTokens: {} })) => Promise<{ createdNewRecipeUser: boolean; oAuthTokens: {}; rawUserInfoFromProvider: { fromIdTokenPayload?: {}; fromUserInfoAPI?: {} }; session: SessionContainer; status: "OK"; user: User } | { status: "NO_EMAIL_GIVEN_BY_PROVIDER" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | GeneralErrorResponse>)
    APIOptions: { appInfo: NormalisedAppinfo; config: TypeNormalisedInput; isInServerlessEnv: boolean; providers: ProviderInput[]; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse }

    Type declaration

    • appInfo: NormalisedAppinfo
    • config: TypeNormalisedInput
    • isInServerlessEnv: boolean
    • providers: ProviderInput[]
    • recipeId: string
    • recipeImplementation: RecipeInterface
    • req: BaseRequest
    • res: BaseResponse
    RecipeInterface: { getProvider: any; manuallyCreateOrUpdateUser: any; signInUp: any }

    Type declaration

    • getProvider:function
      • getProvider(input: { clientType?: string; tenantId: string; thirdPartyId: string; userContext: UserContext }): Promise<undefined | TypeProvider>
      • Parameters

        • input: { clientType?: string; tenantId: string; thirdPartyId: string; userContext: UserContext }
          • Optional clientType?: string
          • tenantId: string
          • thirdPartyId: string
          • userContext: UserContext

        Returns Promise<undefined | TypeProvider>

    • manuallyCreateOrUpdateUser:function
      • manuallyCreateOrUpdateUser(input: { email: string; isVerified: boolean; session: SessionContainer | undefined; tenantId: string; thirdPartyId: string; thirdPartyUserId: string; userContext: UserContext }): Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>
      • Parameters

        • input: { email: string; isVerified: boolean; session: SessionContainer | undefined; tenantId: string; thirdPartyId: string; thirdPartyUserId: string; userContext: UserContext }
          • email: string
          • isVerified: boolean
          • session: SessionContainer | undefined
          • tenantId: string
          • thirdPartyId: string
          • thirdPartyUserId: string
          • userContext: UserContext

        Returns Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>

    • signInUp:function
      • signInUp(input: { email: string; isVerified: boolean; oAuthTokens: {}; rawUserInfoFromProvider: { fromIdTokenPayload?: {}; fromUserInfoAPI?: {} }; session: SessionContainer | undefined; tenantId: string; thirdPartyId: string; thirdPartyUserId: string; userContext: UserContext }): Promise<{ createdNewRecipeUser: boolean; oAuthTokens: {}; rawUserInfoFromProvider: { fromIdTokenPayload?: {}; fromUserInfoAPI?: {} }; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>
      • Parameters

        • input: { email: string; isVerified: boolean; oAuthTokens: {}; rawUserInfoFromProvider: { fromIdTokenPayload?: {}; fromUserInfoAPI?: {} }; session: SessionContainer | undefined; tenantId: string; thirdPartyId: string; thirdPartyUserId: string; userContext: UserContext }
          • email: string
          • isVerified: boolean
          • oAuthTokens: {}
            • [key: string]: any
          • rawUserInfoFromProvider: { fromIdTokenPayload?: {}; fromUserInfoAPI?: {} }
            • Optional fromIdTokenPayload?: {}
              • [key: string]: any
            • Optional fromUserInfoAPI?: {}
              • [key: string]: any
          • session: SessionContainer | undefined
          • tenantId: string
          • thirdPartyId: string
          • thirdPartyUserId: string
          • userContext: UserContext

        Returns Promise<{ createdNewRecipeUser: boolean; oAuthTokens: {}; rawUserInfoFromProvider: { fromIdTokenPayload?: {}; fromUserInfoAPI?: {} }; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>

    TypeProvider: { config: ProviderConfigForClientType; id: string; exchangeAuthCodeForOAuthTokens: any; getAuthorisationRedirectURL: any; getConfigForClientType: any; getUserInfo: any }

    Type declaration

    • config: ProviderConfigForClientType
    • id: string
    • exchangeAuthCodeForOAuthTokens:function
      • exchangeAuthCodeForOAuthTokens(input: { redirectURIInfo: { pkceCodeVerifier?: string; redirectURIOnProviderDashboard: string; redirectURIQueryParams: any }; userContext: UserContext }): Promise<any>
      • Parameters

        • input: { redirectURIInfo: { pkceCodeVerifier?: string; redirectURIOnProviderDashboard: string; redirectURIQueryParams: any }; userContext: UserContext }
          • redirectURIInfo: { pkceCodeVerifier?: string; redirectURIOnProviderDashboard: string; redirectURIQueryParams: any }
            • Optional pkceCodeVerifier?: string
            • redirectURIOnProviderDashboard: string
            • redirectURIQueryParams: any
          • userContext: UserContext

        Returns Promise<any>

    • getAuthorisationRedirectURL:function
      • getAuthorisationRedirectURL(input: { redirectURIOnProviderDashboard: string; userContext: UserContext }): Promise<{ pkceCodeVerifier?: string; urlWithQueryParams: string }>
      • Parameters

        • input: { redirectURIOnProviderDashboard: string; userContext: UserContext }
          • redirectURIOnProviderDashboard: string
          • userContext: UserContext

        Returns Promise<{ pkceCodeVerifier?: string; urlWithQueryParams: string }>

    • getConfigForClientType:function
      • getConfigForClientType(input: { clientType?: string; userContext: UserContext }): Promise<ProviderConfigForClientType>
      • Parameters

        • input: { clientType?: string; userContext: UserContext }
          • Optional clientType?: string
          • userContext: UserContext

        Returns Promise<ProviderConfigForClientType>

    • getUserInfo:function
      • getUserInfo(input: { oAuthTokens: any; userContext: UserContext }): Promise<UserInfo>

    Variables

    Error: typeof default = Wrapper.Error

    Functions

    • getProvider(tenantId: string, thirdPartyId: string, clientType: undefined | string, userContext?: Record<string, any>): Promise<undefined | TypeProvider>
    • init(config?: TypeInput): RecipeListFunction
    • manuallyCreateOrUpdateUser(tenantId: string, thirdPartyId: string, thirdPartyUserId: string, email: string, isVerified: boolean, session?: undefined, userContext?: Record<string, any>): Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" }>
    • manuallyCreateOrUpdateUser(tenantId: string, thirdPartyId: string, thirdPartyUserId: string, email: string, isVerified: boolean, session: SessionContainer, userContext?: Record<string, any>): Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>
    • Parameters

      • tenantId: string
      • thirdPartyId: string
      • thirdPartyUserId: string
      • email: string
      • isVerified: boolean
      • Optional session: undefined
      • Optional userContext: Record<string, any>

      Returns Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" }>

    • Parameters

      • tenantId: string
      • thirdPartyId: string
      • thirdPartyUserId: string
      • email: string
      • isVerified: boolean
      • session: SessionContainer
      • Optional userContext: Record<string, any>

      Returns Promise<{ createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; status: "OK"; user: User } | { reason: string; status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" } | { reason: string; status: "SIGN_IN_UP_NOT_ALLOWED" } | { reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "EMAIL_VERIFICATION_REQUIRED" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; status: "LINKING_TO_SESSION_USER_FAILED" }>

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules/recipe_totp.html b/docs/modules/recipe_totp.html index a4448fbe8..1863ef2ca 100644 --- a/docs/modules/recipe_totp.html +++ b/docs/modules/recipe_totp.html @@ -1 +1 @@ -recipe/totp | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/totp

    Index

    Type Aliases

    APIInterface: { createDevicePOST: undefined | ((input: { deviceName?: string; options: APIOptions; session: SessionContainer; userContext: UserContext }) => Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | GeneralErrorResponse>); listDevicesGET: undefined | ((input: { options: APIOptions; session: SessionContainer; userContext: UserContext }) => Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" } | GeneralErrorResponse>); removeDevicePOST: undefined | ((input: { deviceName: string; options: APIOptions; session: SessionContainer; userContext: UserContext }) => Promise<{ didDeviceExist: boolean; status: "OK" } | GeneralErrorResponse>); verifyDevicePOST: undefined | ((input: { deviceName: string; options: APIOptions; session: SessionContainer; totp: string; userContext: UserContext }) => Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" } | GeneralErrorResponse>); verifyTOTPPOST: undefined | ((input: { options: APIOptions; session: SessionContainer; totp: string; userContext: UserContext }) => Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" } | GeneralErrorResponse>) }

    Type declaration

    • createDevicePOST: undefined | ((input: { deviceName?: string; options: APIOptions; session: SessionContainer; userContext: UserContext }) => Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | GeneralErrorResponse>)
    • listDevicesGET: undefined | ((input: { options: APIOptions; session: SessionContainer; userContext: UserContext }) => Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" } | GeneralErrorResponse>)
    • removeDevicePOST: undefined | ((input: { deviceName: string; options: APIOptions; session: SessionContainer; userContext: UserContext }) => Promise<{ didDeviceExist: boolean; status: "OK" } | GeneralErrorResponse>)
    • verifyDevicePOST: undefined | ((input: { deviceName: string; options: APIOptions; session: SessionContainer; totp: string; userContext: UserContext }) => Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" } | GeneralErrorResponse>)
    • verifyTOTPPOST: undefined | ((input: { options: APIOptions; session: SessionContainer; totp: string; userContext: UserContext }) => Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" } | GeneralErrorResponse>)
    APIOptions: { config: TypeNormalisedInput; isInServerlessEnv: boolean; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse }

    Type declaration

    RecipeInterface: { createDevice: any; getUserIdentifierInfoForUserId: any; listDevices: any; removeDevice: any; updateDevice: any; verifyDevice: any; verifyTOTP: any }

    Type declaration

    • createDevice:function
      • createDevice(input: { deviceName?: string; period?: number; skew?: number; userContext: UserContext; userId: string; userIdentifierInfo?: string }): Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | { status: "UNKNOWN_USER_ID_ERROR" }>
      • Parameters

        • input: { deviceName?: string; period?: number; skew?: number; userContext: UserContext; userId: string; userIdentifierInfo?: string }
          • Optional deviceName?: string
          • Optional period?: number
          • Optional skew?: number
          • userContext: UserContext
          • userId: string
          • Optional userIdentifierInfo?: string

        Returns Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | { status: "UNKNOWN_USER_ID_ERROR" }>

    • getUserIdentifierInfoForUserId:function
      • getUserIdentifierInfoForUserId(input: { userContext: UserContext; userId: string }): Promise<{ info: string; status: "OK" } | { status: "UNKNOWN_USER_ID_ERROR" | "USER_IDENTIFIER_INFO_DOES_NOT_EXIST_ERROR" }>
      • Parameters

        • input: { userContext: UserContext; userId: string }
          • userContext: UserContext
          • userId: string

        Returns Promise<{ info: string; status: "OK" } | { status: "UNKNOWN_USER_ID_ERROR" | "USER_IDENTIFIER_INFO_DOES_NOT_EXIST_ERROR" }>

    • listDevices:function
      • listDevices(input: { userContext: UserContext; userId: string }): Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" }>
      • Parameters

        • input: { userContext: UserContext; userId: string }
          • userContext: UserContext
          • userId: string

        Returns Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" }>

    • removeDevice:function
      • removeDevice(input: { deviceName: string; userContext: UserContext; userId: string }): Promise<{ didDeviceExist: boolean; status: "OK" }>
      • Parameters

        • input: { deviceName: string; userContext: UserContext; userId: string }
          • deviceName: string
          • userContext: UserContext
          • userId: string

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

    • updateDevice:function
      • updateDevice(input: { existingDeviceName: string; newDeviceName: string; userContext: UserContext; userId: string }): Promise<{ status: "OK" | "UNKNOWN_DEVICE_ERROR" | "DEVICE_ALREADY_EXISTS_ERROR" }>
      • Parameters

        • input: { existingDeviceName: string; newDeviceName: string; userContext: UserContext; userId: string }
          • existingDeviceName: string
          • newDeviceName: string
          • userContext: UserContext
          • userId: string

        Returns Promise<{ status: "OK" | "UNKNOWN_DEVICE_ERROR" | "DEVICE_ALREADY_EXISTS_ERROR" }>

    • verifyDevice:function
      • verifyDevice(input: { deviceName: string; tenantId: string; totp: string; userContext: UserContext; userId: string }): Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>
      • Parameters

        • input: { deviceName: string; tenantId: string; totp: string; userContext: UserContext; userId: string }
          • deviceName: string
          • tenantId: string
          • totp: string
          • userContext: UserContext
          • userId: string

        Returns Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>

    • verifyTOTP:function
      • verifyTOTP(input: { tenantId: string; totp: string; userContext: UserContext; userId: string }): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>
      • Parameters

        • input: { tenantId: string; totp: string; userContext: UserContext; userId: string }
          • tenantId: string
          • totp: string
          • userContext: UserContext
          • userId: string

        Returns Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>

    Functions

    • createDevice(userId: string, userIdentifierInfo?: string, deviceName?: string, skew?: number, period?: number, userContext?: Record<string, any>): Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | { status: "UNKNOWN_USER_ID_ERROR" }>
    • Parameters

      • userId: string
      • Optional userIdentifierInfo: string
      • Optional deviceName: string
      • Optional skew: number
      • Optional period: number
      • Optional userContext: Record<string, any>

      Returns Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | { status: "UNKNOWN_USER_ID_ERROR" }>

    • init(config?: TypeInput): RecipeListFunction
    • listDevices(userId: string, userContext?: Record<string, any>): Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" }>
    • Parameters

      • userId: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" }>

    • removeDevice(userId: string, deviceName: string, userContext?: Record<string, any>): Promise<{ didDeviceExist: boolean; status: "OK" }>
    • Parameters

      • userId: string
      • deviceName: string
      • Optional userContext: Record<string, any>

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

    • updateDevice(userId: string, existingDeviceName: string, newDeviceName: string, userContext?: Record<string, any>): Promise<{ status: "OK" | "DEVICE_ALREADY_EXISTS_ERROR" | "UNKNOWN_DEVICE_ERROR" }>
    • Parameters

      • userId: string
      • existingDeviceName: string
      • newDeviceName: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ status: "OK" | "DEVICE_ALREADY_EXISTS_ERROR" | "UNKNOWN_DEVICE_ERROR" }>

    • verifyDevice(tenantId: string, userId: string, deviceName: string, totp: string, userContext?: Record<string, any>): Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>
    • Parameters

      • tenantId: string
      • userId: string
      • deviceName: string
      • totp: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>

    • verifyTOTP(tenantId: string, userId: string, totp: string, userContext?: Record<string, any>): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>
    • Parameters

      • tenantId: string
      • userId: string
      • totp: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>

    Generated using TypeDoc

    \ No newline at end of file +recipe/totp | supertokens-node
    Options
    All
    • Public
    • Public/Protected
    • All
    Menu

    Module recipe/totp

    Index

    Type Aliases

    APIInterface: { createDevicePOST: undefined | ((input: { deviceName?: string; options: APIOptions; session: SessionContainer; userContext: UserContext }) => Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | GeneralErrorResponse>); listDevicesGET: undefined | ((input: { options: APIOptions; session: SessionContainer; userContext: UserContext }) => Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" } | GeneralErrorResponse>); removeDevicePOST: undefined | ((input: { deviceName: string; options: APIOptions; session: SessionContainer; userContext: UserContext }) => Promise<{ didDeviceExist: boolean; status: "OK" } | GeneralErrorResponse>); verifyDevicePOST: undefined | ((input: { deviceName: string; options: APIOptions; session: SessionContainer; totp: string; userContext: UserContext }) => Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" } | GeneralErrorResponse>); verifyTOTPPOST: undefined | ((input: { options: APIOptions; session: SessionContainer; totp: string; userContext: UserContext }) => Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" } | GeneralErrorResponse>) }

    Type declaration

    • createDevicePOST: undefined | ((input: { deviceName?: string; options: APIOptions; session: SessionContainer; userContext: UserContext }) => Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | GeneralErrorResponse>)
    • listDevicesGET: undefined | ((input: { options: APIOptions; session: SessionContainer; userContext: UserContext }) => Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" } | GeneralErrorResponse>)
    • removeDevicePOST: undefined | ((input: { deviceName: string; options: APIOptions; session: SessionContainer; userContext: UserContext }) => Promise<{ didDeviceExist: boolean; status: "OK" } | GeneralErrorResponse>)
    • verifyDevicePOST: undefined | ((input: { deviceName: string; options: APIOptions; session: SessionContainer; totp: string; userContext: UserContext }) => Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" } | GeneralErrorResponse>)
    • verifyTOTPPOST: undefined | ((input: { options: APIOptions; session: SessionContainer; totp: string; userContext: UserContext }) => Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" } | GeneralErrorResponse>)
    APIOptions: { config: TypeNormalisedInput; isInServerlessEnv: boolean; recipeId: string; recipeImplementation: RecipeInterface; req: BaseRequest; res: BaseResponse }

    Type declaration

    RecipeInterface: { createDevice: any; getUserIdentifierInfoForUserId: any; listDevices: any; removeDevice: any; updateDevice: any; verifyDevice: any; verifyTOTP: any }

    Type declaration

    • createDevice:function
      • createDevice(input: { deviceName?: string; period?: number; skew?: number; userContext: UserContext; userId: string; userIdentifierInfo?: string }): Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | { status: "UNKNOWN_USER_ID_ERROR" }>
      • Parameters

        • input: { deviceName?: string; period?: number; skew?: number; userContext: UserContext; userId: string; userIdentifierInfo?: string }
          • Optional deviceName?: string
          • Optional period?: number
          • Optional skew?: number
          • userContext: UserContext
          • userId: string
          • Optional userIdentifierInfo?: string

        Returns Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | { status: "UNKNOWN_USER_ID_ERROR" }>

    • getUserIdentifierInfoForUserId:function
      • getUserIdentifierInfoForUserId(input: { userContext: UserContext; userId: string }): Promise<{ info: string; status: "OK" } | { status: "UNKNOWN_USER_ID_ERROR" | "USER_IDENTIFIER_INFO_DOES_NOT_EXIST_ERROR" }>
      • Parameters

        • input: { userContext: UserContext; userId: string }
          • userContext: UserContext
          • userId: string

        Returns Promise<{ info: string; status: "OK" } | { status: "UNKNOWN_USER_ID_ERROR" | "USER_IDENTIFIER_INFO_DOES_NOT_EXIST_ERROR" }>

    • listDevices:function
      • listDevices(input: { userContext: UserContext; userId: string }): Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" }>
      • Parameters

        • input: { userContext: UserContext; userId: string }
          • userContext: UserContext
          • userId: string

        Returns Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" }>

    • removeDevice:function
      • removeDevice(input: { deviceName: string; userContext: UserContext; userId: string }): Promise<{ didDeviceExist: boolean; status: "OK" }>
      • Parameters

        • input: { deviceName: string; userContext: UserContext; userId: string }
          • deviceName: string
          • userContext: UserContext
          • userId: string

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

    • updateDevice:function
      • updateDevice(input: { existingDeviceName: string; newDeviceName: string; userContext: UserContext; userId: string }): Promise<{ status: "OK" | "UNKNOWN_DEVICE_ERROR" | "DEVICE_ALREADY_EXISTS_ERROR" }>
      • Parameters

        • input: { existingDeviceName: string; newDeviceName: string; userContext: UserContext; userId: string }
          • existingDeviceName: string
          • newDeviceName: string
          • userContext: UserContext
          • userId: string

        Returns Promise<{ status: "OK" | "UNKNOWN_DEVICE_ERROR" | "DEVICE_ALREADY_EXISTS_ERROR" }>

    • verifyDevice:function
      • verifyDevice(input: { deviceName: string; tenantId: string; totp: string; userContext: UserContext; userId: string }): Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>
      • Parameters

        • input: { deviceName: string; tenantId: string; totp: string; userContext: UserContext; userId: string }
          • deviceName: string
          • tenantId: string
          • totp: string
          • userContext: UserContext
          • userId: string

        Returns Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>

    • verifyTOTP:function
      • verifyTOTP(input: { tenantId: string; totp: string; userContext: UserContext; userId: string }): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>
      • Parameters

        • input: { tenantId: string; totp: string; userContext: UserContext; userId: string }
          • tenantId: string
          • totp: string
          • userContext: UserContext
          • userId: string

        Returns Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>

    Functions

    • createDevice(userId: string, userIdentifierInfo?: string, deviceName?: string, skew?: number, period?: number, userContext?: Record<string, any>): Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | { status: "UNKNOWN_USER_ID_ERROR" }>
    • Parameters

      • userId: string
      • Optional userIdentifierInfo: string
      • Optional deviceName: string
      • Optional skew: number
      • Optional period: number
      • Optional userContext: Record<string, any>

      Returns Promise<{ deviceName: string; qrCodeString: string; secret: string; status: "OK" } | { status: "DEVICE_ALREADY_EXISTS_ERROR" } | { status: "UNKNOWN_USER_ID_ERROR" }>

    • init(config?: TypeInput): RecipeListFunction
    • listDevices(userId: string, userContext?: Record<string, any>): Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" }>
    • Parameters

      • userId: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ devices: { name: string; period: number; skew: number; verified: boolean }[]; status: "OK" }>

    • removeDevice(userId: string, deviceName: string, userContext?: Record<string, any>): Promise<{ didDeviceExist: boolean; status: "OK" }>
    • Parameters

      • userId: string
      • deviceName: string
      • Optional userContext: Record<string, any>

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

    • updateDevice(userId: string, existingDeviceName: string, newDeviceName: string, userContext?: Record<string, any>): Promise<{ status: "OK" | "DEVICE_ALREADY_EXISTS_ERROR" | "UNKNOWN_DEVICE_ERROR" }>
    • Parameters

      • userId: string
      • existingDeviceName: string
      • newDeviceName: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ status: "OK" | "DEVICE_ALREADY_EXISTS_ERROR" | "UNKNOWN_DEVICE_ERROR" }>

    • verifyDevice(tenantId: string, userId: string, deviceName: string, totp: string, userContext?: Record<string, any>): Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>
    • Parameters

      • tenantId: string
      • userId: string
      • deviceName: string
      • totp: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ status: "OK"; wasAlreadyVerified: boolean } | { status: "UNKNOWN_DEVICE_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>

    • verifyTOTP(tenantId: string, userId: string, totp: string, userContext?: Record<string, any>): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>
    • Parameters

      • tenantId: string
      • userId: string
      • totp: string
      • Optional userContext: Record<string, any>

      Returns Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR" } | { currentNumberOfFailedAttempts: number; maxNumberOfFailedAttempts: number; status: "INVALID_TOTP_ERROR" } | { retryAfterMs: number; status: "LIMIT_REACHED_ERROR" }>

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules/recipe_usermetadata.html b/docs/modules/recipe_usermetadata.html index 47d66b7d6..01f6c1584 100644 --- a/docs/modules/recipe_usermetadata.html +++ b/docs/modules/recipe_usermetadata.html @@ -1,4 +1,4 @@ -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

    • clearUserMetadata:function
      • clearUserMetadata(input: { userContext: UserContext; userId: string }): Promise<{ status: "OK" }>
    • getUserMetadata:function
      • getUserMetadata(input: { userContext: UserContext; userId: string }): Promise<{ metadata: any; status: "OK" }>
      • Parameters

        • input: { userContext: UserContext; userId: string }
          • userContext: UserContext
          • userId: string

        Returns Promise<{ metadata: any; status: "OK" }>

    • updateUserMetadata:function
      • updateUserMetadata(input: { metadataUpdate: JSONObject; userContext: UserContext; userId: string }): Promise<{ metadata: JSONObject; status: "OK" }>
      • +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

        • clearUserMetadata:function
          • clearUserMetadata(input: { userContext: UserContext; userId: string }): Promise<{ status: "OK" }>
        • getUserMetadata:function
          • getUserMetadata(input: { userContext: UserContext; userId: string }): Promise<{ metadata: any; status: "OK" }>
          • Parameters

            • input: { userContext: UserContext; userId: string }
              • userContext: UserContext
              • userId: string

            Returns Promise<{ metadata: any; status: "OK" }>

        • updateUserMetadata:function
          • updateUserMetadata(input: { metadataUpdate: JSONObject; userContext: UserContext; userId: string }): Promise<{ metadata: JSONObject; status: "OK" }>
          • Updates the metadata object of the user by doing a shallow merge of the stored and the update JSONs and removing properties set to null on the root level of the update object. e.g.:

            @@ -7,4 +7,4 @@
          • update: { "notifications": { "sms": true }, "todos": null }
          • result: { "preferences": { "theme":"dark" }, "notifications": { "sms": true } }
          -

        Parameters

        • input: { metadataUpdate: JSONObject; userContext: UserContext; userId: string }
          • metadataUpdate: JSONObject
          • userContext: UserContext
          • userId: string

        Returns Promise<{ metadata: JSONObject; status: "OK" }>

    Functions

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

    Generated using TypeDoc

    \ No newline at end of file +

    Parameters

    Returns Promise<{ metadata: JSONObject; status: "OK" }>

    Functions

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules/recipe_userroles.html b/docs/modules/recipe_userroles.html index cbb8597a1..59142e527 100644 --- a/docs/modules/recipe_userroles.html +++ b/docs/modules/recipe_userroles.html @@ -1 +1 @@ -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; tenantId: string; userContext: UserContext; userId: string }): Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; tenantId: string; userContext: UserContext; userId: string }
          • role: string
          • tenantId: string
          • userContext: UserContext
          • userId: string

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

    • createNewRoleOrAddPermissions:function
      • createNewRoleOrAddPermissions(input: { permissions: string[]; role: string; userContext: UserContext }): Promise<{ createdNewRole: boolean; status: "OK" }>
      • Parameters

        • input: { permissions: string[]; role: string; userContext: UserContext }
          • permissions: string[]
          • role: string
          • userContext: UserContext

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

    • deleteRole:function
      • deleteRole(input: { role: string; userContext: UserContext }): Promise<{ didRoleExist: boolean; status: "OK" }>
      • Parameters

        • input: { role: string; userContext: UserContext }
          • role: string
          • userContext: UserContext

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

    • getAllRoles:function
      • getAllRoles(input: { userContext: UserContext }): Promise<{ roles: string[]; status: "OK" }>
    • getPermissionsForRole:function
      • getPermissionsForRole(input: { role: string; userContext: UserContext }): Promise<{ permissions: string[]; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; userContext: UserContext }
          • role: string
          • userContext: UserContext

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

    • getRolesForUser:function
      • getRolesForUser(input: { tenantId: string; userContext: UserContext; userId: string }): Promise<{ roles: string[]; status: "OK" }>
      • Parameters

        • input: { tenantId: string; userContext: UserContext; userId: string }
          • tenantId: string
          • userContext: UserContext
          • userId: string

        Returns Promise<{ roles: string[]; status: "OK" }>

    • getRolesThatHavePermission:function
      • getRolesThatHavePermission(input: { permission: string; userContext: UserContext }): Promise<{ roles: string[]; status: "OK" }>
      • Parameters

        • input: { permission: string; userContext: UserContext }
          • permission: string
          • userContext: UserContext

        Returns Promise<{ roles: string[]; status: "OK" }>

    • getUsersThatHaveRole:function
      • getUsersThatHaveRole(input: { role: string; tenantId: string; userContext: UserContext }): Promise<{ status: "OK"; users: string[] } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; tenantId: string; userContext: UserContext }
          • role: string
          • tenantId: string
          • userContext: UserContext

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

    • removePermissionsFromRole:function
      • removePermissionsFromRole(input: { permissions: string[]; role: string; userContext: UserContext }): Promise<{ status: "OK" | "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { permissions: string[]; role: string; userContext: UserContext }
          • permissions: string[]
          • role: string
          • userContext: UserContext

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

    • removeUserRole:function
      • removeUserRole(input: { role: string; tenantId: string; userContext: UserContext; userId: string }): Promise<{ didUserHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; tenantId: string; userContext: UserContext; userId: string }
          • role: string
          • tenantId: string
          • userContext: UserContext
          • userId: string

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

    Variables

    PermissionClaim: PermissionClaimClass = ...
    UserRoleClaim: UserRoleClaimClass = ...

    Functions

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

      • tenantId: string
      • userId: string
      • role: string
      • Optional userContext: Record<string, any>

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

    • createNewRoleOrAddPermissions(role: string, permissions: string[], userContext?: Record<string, any>): Promise<{ createdNewRole: boolean; status: "OK" }>
    • Parameters

      • role: string
      • permissions: string[]
      • Optional userContext: Record<string, any>

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

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

      • role: string
      • Optional userContext: Record<string, any>

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

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

      • tenantId: string
      • role: string
      • Optional userContext: Record<string, any>

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

    • init(config?: TypeInput): RecipeListFunction
    • removePermissionsFromRole(role: string, permissions: string[], userContext?: Record<string, any>): Promise<{ status: "OK" | "UNKNOWN_ROLE_ERROR" }>
    • Parameters

      • role: string
      • permissions: string[]
      • Optional userContext: Record<string, any>

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

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

      • tenantId: string
      • userId: string
      • role: string
      • Optional userContext: Record<string, any>

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

    Generated using TypeDoc

    \ No newline at end of file +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; tenantId: string; userContext: UserContext; userId: string }): Promise<{ didUserAlreadyHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; tenantId: string; userContext: UserContext; userId: string }
          • role: string
          • tenantId: string
          • userContext: UserContext
          • userId: string

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

    • createNewRoleOrAddPermissions:function
      • createNewRoleOrAddPermissions(input: { permissions: string[]; role: string; userContext: UserContext }): Promise<{ createdNewRole: boolean; status: "OK" }>
      • Parameters

        • input: { permissions: string[]; role: string; userContext: UserContext }
          • permissions: string[]
          • role: string
          • userContext: UserContext

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

    • deleteRole:function
      • deleteRole(input: { role: string; userContext: UserContext }): Promise<{ didRoleExist: boolean; status: "OK" }>
      • Parameters

        • input: { role: string; userContext: UserContext }
          • role: string
          • userContext: UserContext

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

    • getAllRoles:function
      • getAllRoles(input: { userContext: UserContext }): Promise<{ roles: string[]; status: "OK" }>
    • getPermissionsForRole:function
      • getPermissionsForRole(input: { role: string; userContext: UserContext }): Promise<{ permissions: string[]; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; userContext: UserContext }
          • role: string
          • userContext: UserContext

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

    • getRolesForUser:function
      • getRolesForUser(input: { tenantId: string; userContext: UserContext; userId: string }): Promise<{ roles: string[]; status: "OK" }>
      • Parameters

        • input: { tenantId: string; userContext: UserContext; userId: string }
          • tenantId: string
          • userContext: UserContext
          • userId: string

        Returns Promise<{ roles: string[]; status: "OK" }>

    • getRolesThatHavePermission:function
      • getRolesThatHavePermission(input: { permission: string; userContext: UserContext }): Promise<{ roles: string[]; status: "OK" }>
      • Parameters

        • input: { permission: string; userContext: UserContext }
          • permission: string
          • userContext: UserContext

        Returns Promise<{ roles: string[]; status: "OK" }>

    • getUsersThatHaveRole:function
      • getUsersThatHaveRole(input: { role: string; tenantId: string; userContext: UserContext }): Promise<{ status: "OK"; users: string[] } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; tenantId: string; userContext: UserContext }
          • role: string
          • tenantId: string
          • userContext: UserContext

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

    • removePermissionsFromRole:function
      • removePermissionsFromRole(input: { permissions: string[]; role: string; userContext: UserContext }): Promise<{ status: "OK" | "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { permissions: string[]; role: string; userContext: UserContext }
          • permissions: string[]
          • role: string
          • userContext: UserContext

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

    • removeUserRole:function
      • removeUserRole(input: { role: string; tenantId: string; userContext: UserContext; userId: string }): Promise<{ didUserHaveRole: boolean; status: "OK" } | { status: "UNKNOWN_ROLE_ERROR" }>
      • Parameters

        • input: { role: string; tenantId: string; userContext: UserContext; userId: string }
          • role: string
          • tenantId: string
          • userContext: UserContext
          • userId: string

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

    Variables

    PermissionClaim: PermissionClaimClass = ...
    UserRoleClaim: UserRoleClaimClass = ...

    Functions

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

      • tenantId: string
      • userId: string
      • role: string
      • Optional userContext: Record<string, any>

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

    • createNewRoleOrAddPermissions(role: string, permissions: string[], userContext?: Record<string, any>): Promise<{ createdNewRole: boolean; status: "OK" }>
    • Parameters

      • role: string
      • permissions: string[]
      • Optional userContext: Record<string, any>

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

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

      • role: string
      • Optional userContext: Record<string, any>

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

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

      • tenantId: string
      • role: string
      • Optional userContext: Record<string, any>

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

    • init(config?: TypeInput): RecipeListFunction
    • removePermissionsFromRole(role: string, permissions: string[], userContext?: Record<string, any>): Promise<{ status: "OK" | "UNKNOWN_ROLE_ERROR" }>
    • Parameters

      • role: string
      • permissions: string[]
      • Optional userContext: Record<string, any>

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

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

      • tenantId: string
      • userId: string
      • role: string
      • Optional userContext: Record<string, any>

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

    Generated using TypeDoc

    \ No newline at end of file diff --git a/examples/aws/with-emailpassword/backend/config.mjs b/examples/aws/with-emailpassword/backend/config.mjs index f7c98e499..c9bfefad8 100644 --- a/examples/aws/with-emailpassword/backend/config.mjs +++ b/examples/aws/with-emailpassword/backend/config.mjs @@ -3,13 +3,14 @@ import EmailPassword from "supertokens-node/recipe/emailpassword"; export const getBackendConfig = () => { return { + debug: true, framework: "awsLambda", supertokens: { connectionURI: "https://try.supertokens.com", }, appInfo: { appName: "SuperTokens Demo", - apiDomain: "https://0ez3j5libc.execute-api.ap-south-1.amazonaws.com", + apiDomain: "https://zcbgp7k8ti.execute-api.ap-south-1.amazonaws.com", websiteDomain: "http://localhost:3000", apiBasePath: "/auth", apiGatewayPath: "/prod", diff --git a/examples/aws/with-emailpassword/frontend/src/config.tsx b/examples/aws/with-emailpassword/frontend/src/config.tsx index 9fe60198d..6ebb16855 100644 --- a/examples/aws/with-emailpassword/frontend/src/config.tsx +++ b/examples/aws/with-emailpassword/frontend/src/config.tsx @@ -5,7 +5,7 @@ import Session from "supertokens-auth-react/recipe/session"; export function getApiDomain() { // const apiPort = process.env.REACT_APP_API_PORT || 3001; // const apiUrl = process.env.REACT_APP_API_URL || `http://localhost:${apiPort}`; - return "https://0ez3j5libc.execute-api.ap-south-1.amazonaws.com"; + return "https://zcbgp7k8ti.execute-api.ap-south-1.amazonaws.com"; } export function getWebsiteDomain() { diff --git a/examples/cloudflare-workers/with-email-password-hono-be-only/README.md b/examples/cloudflare-workers/with-email-password-hono-be-only/README.md new file mode 100644 index 000000000..f38212857 --- /dev/null +++ b/examples/cloudflare-workers/with-email-password-hono-be-only/README.md @@ -0,0 +1,25 @@ +![SuperTokens banner](https://raw.githubusercontent.com/supertokens/supertokens-logo/master/images/Artboard%20%E2%80%93%2027%402x.png) + +# SuperTokens EmailPassword with Cloudflare Workers (HonoJS) on Edge Runtime + +This demo app uses HonoJS with Cloudflare Workers for the backend server. We use [Wrangler](https://developers.cloudflare.com/workers/wrangler/) in the backend server to simulate the Cloudflare Worker runtime. This is a pure Edge runtime implementation (works without `nodejs_compat` flag). + +## Project setup + +Clone the repo, enter the directory, and use `npm` to install the project dependencies: + +```bash +git clone https://github.com/supertokens/supertokens-node +cd supertokens-node/examples/cloudflare-workers/with-be-emailpassword +npm install +``` + +## Run the demo app + +This compiles and serves the React app and starts the backend API server on port 3001. + +```bash +npm run start +``` + +The app will start on `http://localhost:3000` diff --git a/examples/cloudflare-workers/with-email-password-hono-be-only/config.ts b/examples/cloudflare-workers/with-email-password-hono-be-only/config.ts new file mode 100644 index 000000000..30fbc08bb --- /dev/null +++ b/examples/cloudflare-workers/with-email-password-hono-be-only/config.ts @@ -0,0 +1,33 @@ +import EmailPassword from "supertokens-node/recipe/emailpassword"; +import Session from "supertokens-node/recipe/session"; +import { TypeInput } from "supertokens-node/types"; +import process from "process"; + +export const runtime = "edge"; + +export function getApiDomain() { + const apiPort = process.env.REACT_APP_API_PORT || 3001; + const apiUrl = process.env.REACT_APP_API_URL || `http://localhost:${apiPort}`; + return apiUrl; +} + +export function getWebsiteDomain() { + const websitePort = process.env.REACT_APP_WEBSITE_PORT || 3000; + const websiteUrl = process.env.REACT_APP_WEBSITE_URL || `http://localhost:${websitePort}`; + return websiteUrl; +} + +export const SuperTokensConfig: TypeInput = { + supertokens: { + // this is the location of the SuperTokens core. + connectionURI: "https://try.supertokens.com", + }, + appInfo: { + appName: "SuperTokens Demo App", + apiDomain: getApiDomain(), + websiteDomain: getWebsiteDomain(), + }, + // recipeList contains all the modules that you want to + // use from SuperTokens. See the full list here: https://supertokens.com/docs/guides + recipeList: [EmailPassword.init(), Session.init()], +}; diff --git a/examples/cloudflare-workers/with-email-password-hono-be-only/hono.d.ts b/examples/cloudflare-workers/with-email-password-hono-be-only/hono.d.ts new file mode 100644 index 000000000..bc752f28c --- /dev/null +++ b/examples/cloudflare-workers/with-email-password-hono-be-only/hono.d.ts @@ -0,0 +1,7 @@ +import { SessionContainer } from "supertokens-node/recipe/session"; + +declare module "hono" { + interface HonoRequest { + session?: SessionContainer; + } +} diff --git a/examples/cloudflare-workers/with-email-password-hono-be-only/index.ts b/examples/cloudflare-workers/with-email-password-hono-be-only/index.ts new file mode 100644 index 000000000..1c5ad844f --- /dev/null +++ b/examples/cloudflare-workers/with-email-password-hono-be-only/index.ts @@ -0,0 +1,48 @@ +import { Hono } from "hono"; +import { cors } from "hono/cors"; +import supertokens from "supertokens-node"; +import { middleware } from "./middleware"; +import { getWebsiteDomain, SuperTokensConfig } from "./config"; +import type { PageConfig } from "next"; + +export const config: PageConfig = { + runtime: "edge", +}; + +supertokens.init(SuperTokensConfig); + +const app = new Hono(); + +app.use("*", async (c, next) => { + return await cors({ + origin: getWebsiteDomain(), + credentials: true, + allowHeaders: ["Content-Type", ...supertokens.getAllCORSHeaders()], + allowMethods: ["GET", "POST", "PUT", "PATCH", "DELETE"], + })(c, next); +}); + +// This exposes all the APIs from SuperTokens to the client. +// and adds the session to the request object if one exists. +app.use("*", middleware()); + +// An example API that requires session verification +app.get("/sessioninfo", (c) => { + let session = c.req.session; + if (!session) { + return c.text("Unauthorized", 401); + } + return c.json({ + sessionHandle: session!.getHandle(), + userId: session!.getUserId(), + accessTokenPayload: session!.getAccessTokenPayload(), + }); +}); + +app.get("/", (c) => { + return c.json({ + message: "Hello from Supertokens", + }); +}); + +export default app; diff --git a/examples/cloudflare-workers/with-email-password-hono-be-only/middleware.ts b/examples/cloudflare-workers/with-email-password-hono-be-only/middleware.ts new file mode 100644 index 000000000..f96d0c98f --- /dev/null +++ b/examples/cloudflare-workers/with-email-password-hono-be-only/middleware.ts @@ -0,0 +1,88 @@ +import { Context, Next } from "hono"; +import { getCookie } from "hono/cookie"; +import { + CollectingResponse, + PreParsedRequest, + middleware as customMiddleware, +} from "supertokens-node/framework/custom"; +import Session from "supertokens-node/recipe/session"; +import { HTTPMethod } from "supertokens-node/types"; +import { serialize } from "cookie"; + +export const runtime = "edge"; + +function setCookiesInHeaders(headers: Headers, cookies: CollectingResponse["cookies"]) { + for (const cookie of cookies) { + headers.append( + "Set-Cookie", + serialize(cookie.key, cookie.value, { + domain: cookie.domain, + expires: new Date(cookie.expires), + httpOnly: cookie.httpOnly, + path: cookie.path, + sameSite: cookie.sameSite, + secure: cookie.secure, + }) + ); + } +} + +function copyHeaders(source: Headers, destination: Headers): void { + for (const [key, value] of source.entries()) { + destination.append(key, value); + } +} + +export const middleware = () => { + return async function (c: Context, next: Next) { + const request = new PreParsedRequest({ + method: c.req.method as HTTPMethod, + url: c.req.url, + query: Object.fromEntries(new URL(c.req.url).searchParams.entries()), + cookies: getCookie(c), + headers: c.req.raw.headers as Headers, + getFormBody: () => c.req.formData(), + getJSONBody: () => c.req.json(), + }); + const baseResponse = new CollectingResponse(); + + const stMiddleware = customMiddleware(() => request); + + const { handled, error } = await stMiddleware(request, baseResponse); + + if (error) { + throw error; + } + + if (handled) { + setCookiesInHeaders(baseResponse.headers, baseResponse.cookies); + return new Response(baseResponse.body, { + status: baseResponse.statusCode, + headers: baseResponse.headers, + }); + } + + // Add session to c.req if it exists + try { + c.req.session = await Session.getSession(request, baseResponse, { + sessionRequired: false, + }); + + await next(); + + // Add cookies that were set by `getSession` to response + setCookiesInHeaders(c.res.headers, baseResponse.cookies); + // Copy headers that were set by `getSession` to response + copyHeaders(baseResponse.headers, c.res.headers); + return c.res; + } catch (err) { + if (Session.Error.isErrorFromSuperTokens(err)) { + if (err.type === Session.Error.TRY_REFRESH_TOKEN || err.type === Session.Error.INVALID_CLAIMS) { + return new Response("Unauthorized", { + status: err.type === Session.Error.INVALID_CLAIMS ? 403 : 401, + }); + } + } + } + }; +}; diff --git a/examples/cloudflare-workers/with-email-password-hono-be-only/package-lock.json b/examples/cloudflare-workers/with-email-password-hono-be-only/package-lock.json new file mode 100644 index 000000000..ed96d38c3 --- /dev/null +++ b/examples/cloudflare-workers/with-email-password-hono-be-only/package-lock.json @@ -0,0 +1,3221 @@ +{ + "name": "with-email-password-hono-be-only", + "version": "0.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "with-email-password-hono-be-only", + "version": "0.0.1", + "license": "ISC", + "dependencies": { + "hono": "^4.3.9", + "process": "^0.11.10", + "supertokens-node": "file:../../../lib/build" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20240403.0", + "@types/node": "^18.0.0", + "jsdom-global": "^3.0.2", + "wrangler": "^3.57.0" + } + }, + "../../../lib/build": {}, + "node_modules/@cloudflare/kv-asset-handler": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.4.tgz", + "integrity": "sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==", + "dev": true, + "dependencies": { + "mime": "^3.0.0" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@cloudflare/kv-asset-handler/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20240821.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20240821.1.tgz", + "integrity": "sha512-CDBpfZKrSy4YrIdqS84z67r3Tzal2pOhjCsIb63IuCnvVes59/ft1qhczBzk9EffeOE2iTCrA4YBT7Sbn7USew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20240821.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20240821.1.tgz", + "integrity": "sha512-Q+9RedvNbPcEt/dKni1oN94OxbvuNAeJkgHmrLFTGF8zu21wzOhVkQeRNxcYxrMa9mfStc457NAg13OVCj2kHQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20240821.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20240821.1.tgz", + "integrity": "sha512-j6z3KsPtawrscoLuP985LbqFrmsJL6q1mvSXOXTqXGODAHIzGBipHARdOjms3UQqovzvqB2lQaQsZtLBwCZxtA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20240821.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20240821.1.tgz", + "integrity": "sha512-I9bHgZOxJQW0CV5gTdilyxzTG7ILzbTirehQWgfPx9X77E/7eIbR9sboOMgyeC69W4he0SKtpx0sYZuTJu4ERw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20240821.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20240821.1.tgz", + "integrity": "sha512-keC97QPArs6LWbPejQM7/Y8Jy8QqyaZow4/ZdsGo+QjlOLiZRDpAenfZx3CBUoWwEeFwQTl2FLO+8hV1SWFFYw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workers-shared": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-shared/-/workers-shared-0.4.1.tgz", + "integrity": "sha512-nYh4r8JwOOjYIdH2zub++CmIKlkYFlpxI1nBHimoiHcytJXD/b7ldJ21TtfzUZMCgI78mxVlymMHA/ReaOxKlA==", + "dev": true, + "engines": { + "node": ">=16.7.0" + } + }, + "node_modules/@cloudflare/workers-types": { + "version": "4.20240903.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20240903.0.tgz", + "integrity": "sha512-a4mqgtVsPWg3JNNlQdLRE0Z6/mHr/uXa1ANDw6Zd7in438UCbeb+j7Z954Sf93G24jExpAn9VZ8kUUml0RwZbQ==", + "dev": true + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-plugins/node-globals-polyfill": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.2.3.tgz", + "integrity": "sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==", + "dev": true, + "peerDependencies": { + "esbuild": "*" + } + }, + "node_modules/@esbuild-plugins/node-modules-polyfill": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.2.2.tgz", + "integrity": "sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^4.0.0", + "rollup-plugin-node-polyfills": "^0.2.1" + }, + "peerDependencies": { + "esbuild": "*" + } + }, + "node_modules/@esbuild-plugins/node-modules-polyfill/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", + "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", + "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", + "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", + "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", + "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", + "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", + "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", + "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", + "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", + "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", + "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", + "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", + "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", + "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", + "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", + "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", + "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", + "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", + "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", + "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", + "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", + "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@types/node": { + "version": "18.19.49", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.49.tgz", + "integrity": "sha512-ALCeIR6n0nQ7j0FUF1ycOhrp6+XutJWqEu/vtdEqXFUQwkBfgUA5cEg3ZNmjWGF/ZYA/FcF9QMkL55Ar0O6UrA==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/acorn": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", + "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "peer": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "peer": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/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==", + "dev": true, + "peer": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/as-table": { + "version": "1.0.55", + "resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz", + "integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==", + "dev": true, + "dependencies": { + "printable-characters": "^1.0.42" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "peer": true + }, + "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/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true + }, + "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/capnp-ts": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/capnp-ts/-/capnp-ts-0.7.0.tgz", + "integrity": "sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==", + "dev": true, + "dependencies": { + "debug": "^4.3.1", + "tslib": "^2.2.0" + } + }, + "node_modules/capnp-ts/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/capnp-ts/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==", + "dev": true + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "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, + "peer": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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/cssstyle": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", + "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", + "dev": true, + "peer": true, + "dependencies": { + "rrweb-cssom": "^0.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cssstyle/node_modules/rrweb-cssom": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", + "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", + "dev": true, + "peer": true + }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "peer": true, + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true, + "peer": true + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", + "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.17.19", + "@esbuild/android-arm64": "0.17.19", + "@esbuild/android-x64": "0.17.19", + "@esbuild/darwin-arm64": "0.17.19", + "@esbuild/darwin-x64": "0.17.19", + "@esbuild/freebsd-arm64": "0.17.19", + "@esbuild/freebsd-x64": "0.17.19", + "@esbuild/linux-arm": "0.17.19", + "@esbuild/linux-arm64": "0.17.19", + "@esbuild/linux-ia32": "0.17.19", + "@esbuild/linux-loong64": "0.17.19", + "@esbuild/linux-mips64el": "0.17.19", + "@esbuild/linux-ppc64": "0.17.19", + "@esbuild/linux-riscv64": "0.17.19", + "@esbuild/linux-s390x": "0.17.19", + "@esbuild/linux-x64": "0.17.19", + "@esbuild/netbsd-x64": "0.17.19", + "@esbuild/openbsd-x64": "0.17.19", + "@esbuild/sunos-x64": "0.17.19", + "@esbuild/win32-arm64": "0.17.19", + "@esbuild/win32-ia32": "0.17.19", + "@esbuild/win32-x64": "0.17.19" + } + }, + "node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "node_modules/exit-hook": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", + "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "peer": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "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.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-source": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz", + "integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==", + "dev": true, + "dependencies": { + "data-uri-to-buffer": "^2.0.0", + "source-map": "^0.6.1" + } + }, + "node_modules/get-source/node_modules/data-uri-to-buffer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", + "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==", + "dev": true + }, + "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/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hono": { + "version": "4.5.11", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.5.11.tgz", + "integrity": "sha512-62FcjLPtjAFwISVBUshryl+vbHOjg8rE4uIK/dxyR8GpLztunZpwFmfEvmJCUI7xoGh/Sr3CGCDPCmYxVw7wUQ==", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "peer": true, + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "peer": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "peer": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-agent/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==", + "dev": true, + "peer": true + }, + "node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "peer": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "peer": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/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==", + "dev": true, + "peer": true + }, + "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-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "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": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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-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-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "peer": true + }, + "node_modules/jsdom": { + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.0.tgz", + "integrity": "sha512-OhoFVT59T7aEq75TVw9xxEfkXgacpqAhQaYgP9y/fDqWQCMB/b1H66RfmPm/MaeaAIU9nDwMOVTlPN51+ao6CQ==", + "dev": true, + "peer": true, + "dependencies": { + "cssstyle": "^4.0.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.4", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom-global": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsdom-global/-/jsdom-global-3.0.2.tgz", + "integrity": "sha512-t1KMcBkz/pT5JrvcJbpUR2u/w1kO9jXctaaGJ0vZDzwFnIvGWw9IDSRciT83kIs8Bnw4qpOl8bQK08V01YgMPg==", + "dev": true, + "peerDependencies": { + "jsdom": ">=10.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "peer": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/miniflare": { + "version": "3.20240821.1", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20240821.1.tgz", + "integrity": "sha512-81qdiryDG7VXzZuoa0EwhkaIYYrn7+StRIrd/2i7SPqPUNICUBjbhFFKqTnvE1+fqIPPB6l8ShKFaFvmnZOASg==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "0.8.1", + "acorn": "^8.8.0", + "acorn-walk": "^8.2.0", + "capnp-ts": "^0.7.0", + "exit-hook": "^2.2.1", + "glob-to-regexp": "^0.4.1", + "stoppable": "^1.1.0", + "undici": "^5.28.4", + "workerd": "1.20240821.1", + "ws": "^8.17.1", + "youch": "^3.2.2", + "zod": "^3.22.3" + }, + "bin": { + "miniflare": "bootstrap.js" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "dev": true, + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.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/nwsapi": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", + "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", + "dev": true, + "peer": true + }, + "node_modules/ohash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz", + "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==", + "dev": true + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "peer": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": 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/printable-characters": { + "version": "1.0.42", + "resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz", + "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==", + "dev": true + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true, + "peer": true + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true, + "peer": true + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true, + "peer": true + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/rollup-plugin-inject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", + "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==", + "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.", + "dev": true, + "dependencies": { + "estree-walker": "^0.6.1", + "magic-string": "^0.25.3", + "rollup-pluginutils": "^2.8.1" + } + }, + "node_modules/rollup-plugin-node-polyfills": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz", + "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==", + "dev": true, + "dependencies": { + "rollup-plugin-inject": "^3.0.0" + } + }, + "node_modules/rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "dependencies": { + "estree-walker": "^0.6.1" + } + }, + "node_modules/rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true, + "peer": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "peer": true + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "peer": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "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/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", + "dev": true + }, + "node_modules/stacktracey": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz", + "integrity": "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==", + "dev": true, + "dependencies": { + "as-table": "^1.0.36", + "get-source": "^2.0.12" + } + }, + "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/supertokens-node": { + "resolved": "../../../lib/build", + "link": true + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "peer": true + }, + "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/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "peer": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "peer": true, + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "node_modules/ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "dev": true + }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dev": true, + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unenv": { + "name": "unenv-nightly", + "version": "2.0.0-1724863496.70db6f1", + "resolved": "https://registry.npmjs.org/unenv-nightly/-/unenv-nightly-2.0.0-1724863496.70db6f1.tgz", + "integrity": "sha512-r+VIl1gnsI4WQxluruSQhy8alpAf1AsLRLm4sEKp3otCyTIVD6I6wHEYzeQnwsyWgaD4+3BD4A/eqrgOpdTzhw==", + "dev": true, + "dependencies": { + "defu": "^6.1.4", + "ohash": "^1.1.3", + "pathe": "^1.1.2", + "ufo": "^1.5.4" + } + }, + "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==", + "dev": true, + "peer": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "peer": true, + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "peer": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-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, + "peer": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, + "peer": true, + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/workerd": { + "version": "1.20240821.1", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20240821.1.tgz", + "integrity": "sha512-y4phjCnEG96u8ZkgkkHB+gSw0i6uMNo23rBmixylWpjxDklB+LWD8dztasvsu7xGaZbLoTxQESdEw956F7VJDA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20240821.1", + "@cloudflare/workerd-darwin-arm64": "1.20240821.1", + "@cloudflare/workerd-linux-64": "1.20240821.1", + "@cloudflare/workerd-linux-arm64": "1.20240821.1", + "@cloudflare/workerd-windows-64": "1.20240821.1" + } + }, + "node_modules/wrangler": { + "version": "3.74.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.74.0.tgz", + "integrity": "sha512-wmtb+tQrgb61yN+Wa2JM98G1Gt4tKFRYPw6xwuyzUcA74L+Dum1A13w22/manl9Gq1jA3dPn+7UzT5sYEVHRog==", + "dev": true, + "dependencies": { + "@cloudflare/kv-asset-handler": "0.3.4", + "@cloudflare/workers-shared": "0.4.1", + "@esbuild-plugins/node-globals-polyfill": "^0.2.3", + "@esbuild-plugins/node-modules-polyfill": "^0.2.2", + "blake3-wasm": "^2.1.5", + "chokidar": "^3.5.3", + "date-fns": "^3.6.0", + "esbuild": "0.17.19", + "miniflare": "3.20240821.1", + "nanoid": "^3.3.3", + "path-to-regexp": "^6.2.0", + "resolve": "^1.22.8", + "resolve.exports": "^2.0.2", + "selfsigned": "^2.0.1", + "source-map": "^0.6.1", + "unenv": "npm:unenv-nightly@2.0.0-1724863496.70db6f1", + "workerd": "1.20240821.1", + "xxhash-wasm": "^1.0.1" + }, + "bin": { + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" + }, + "engines": { + "node": ">=16.17.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@cloudflare/workers-types": "^4.20240821.1" + }, + "peerDependenciesMeta": { + "@cloudflare/workers-types": { + "optional": true + } + } + }, + "node_modules/wrangler/node_modules/path-to-regexp": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", + "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", + "dev": true + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "peer": true + }, + "node_modules/xxhash-wasm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz", + "integrity": "sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==", + "dev": true + }, + "node_modules/youch": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/youch/-/youch-3.3.3.tgz", + "integrity": "sha512-qSFXUk3UZBLfggAW3dJKg0BMblG5biqSF8M34E06o5CSsZtH92u9Hqmj2RzGiHDi64fhe83+4tENFP2DB6t6ZA==", + "dev": true, + "dependencies": { + "cookie": "^0.5.0", + "mustache": "^4.2.0", + "stacktracey": "^2.1.8" + } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + }, + "dependencies": { + "@cloudflare/kv-asset-handler": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.4.tgz", + "integrity": "sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==", + "dev": true, + "requires": { + "mime": "^3.0.0" + }, + "dependencies": { + "mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true + } + } + }, + "@cloudflare/workerd-darwin-64": { + "version": "1.20240821.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20240821.1.tgz", + "integrity": "sha512-CDBpfZKrSy4YrIdqS84z67r3Tzal2pOhjCsIb63IuCnvVes59/ft1qhczBzk9EffeOE2iTCrA4YBT7Sbn7USew==", + "dev": true, + "optional": true + }, + "@cloudflare/workerd-darwin-arm64": { + "version": "1.20240821.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20240821.1.tgz", + "integrity": "sha512-Q+9RedvNbPcEt/dKni1oN94OxbvuNAeJkgHmrLFTGF8zu21wzOhVkQeRNxcYxrMa9mfStc457NAg13OVCj2kHQ==", + "dev": true, + "optional": true + }, + "@cloudflare/workerd-linux-64": { + "version": "1.20240821.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20240821.1.tgz", + "integrity": "sha512-j6z3KsPtawrscoLuP985LbqFrmsJL6q1mvSXOXTqXGODAHIzGBipHARdOjms3UQqovzvqB2lQaQsZtLBwCZxtA==", + "dev": true, + "optional": true + }, + "@cloudflare/workerd-linux-arm64": { + "version": "1.20240821.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20240821.1.tgz", + "integrity": "sha512-I9bHgZOxJQW0CV5gTdilyxzTG7ILzbTirehQWgfPx9X77E/7eIbR9sboOMgyeC69W4he0SKtpx0sYZuTJu4ERw==", + "dev": true, + "optional": true + }, + "@cloudflare/workerd-windows-64": { + "version": "1.20240821.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20240821.1.tgz", + "integrity": "sha512-keC97QPArs6LWbPejQM7/Y8Jy8QqyaZow4/ZdsGo+QjlOLiZRDpAenfZx3CBUoWwEeFwQTl2FLO+8hV1SWFFYw==", + "dev": true, + "optional": true + }, + "@cloudflare/workers-shared": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-shared/-/workers-shared-0.4.1.tgz", + "integrity": "sha512-nYh4r8JwOOjYIdH2zub++CmIKlkYFlpxI1nBHimoiHcytJXD/b7ldJ21TtfzUZMCgI78mxVlymMHA/ReaOxKlA==", + "dev": true + }, + "@cloudflare/workers-types": { + "version": "4.20240903.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20240903.0.tgz", + "integrity": "sha512-a4mqgtVsPWg3JNNlQdLRE0Z6/mHr/uXa1ANDw6Zd7in438UCbeb+j7Z954Sf93G24jExpAn9VZ8kUUml0RwZbQ==", + "dev": true + }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + } + }, + "@esbuild-plugins/node-globals-polyfill": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.2.3.tgz", + "integrity": "sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==", + "dev": true, + "requires": {} + }, + "@esbuild-plugins/node-modules-polyfill": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.2.2.tgz", + "integrity": "sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==", + "dev": true, + "requires": { + "escape-string-regexp": "^4.0.0", + "rollup-plugin-node-polyfills": "^0.2.1" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + } + } + }, + "@esbuild/android-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", + "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", + "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", + "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", + "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", + "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", + "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", + "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", + "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", + "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", + "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", + "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", + "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", + "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", + "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", + "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", + "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", + "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", + "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", + "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", + "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", + "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", + "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "dev": true, + "optional": true + }, + "@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true + }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@types/node": { + "version": "18.19.49", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.49.tgz", + "integrity": "sha512-ALCeIR6n0nQ7j0FUF1ycOhrp6+XutJWqEu/vtdEqXFUQwkBfgUA5cEg3ZNmjWGF/ZYA/FcF9QMkL55Ar0O6UrA==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } + }, + "@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", + "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", + "dev": true + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "peer": true, + "requires": { + "debug": "^4.3.4" + }, + "dependencies": { + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "peer": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true, + "peer": true + } + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "as-table": { + "version": "1.0.55", + "resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz", + "integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==", + "dev": true, + "requires": { + "printable-characters": "^1.0.42" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "peer": 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 + }, + "blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true + }, + "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" + } + }, + "capnp-ts": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/capnp-ts/-/capnp-ts-0.7.0.tgz", + "integrity": "sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==", + "dev": true, + "requires": { + "debug": "^4.3.1", + "tslib": "^2.2.0" + }, + "dependencies": { + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "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, + "peer": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true + }, + "cssstyle": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", + "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", + "dev": true, + "peer": true, + "requires": { + "rrweb-cssom": "^0.6.0" + }, + "dependencies": { + "rrweb-cssom": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", + "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", + "dev": true, + "peer": true + } + } + }, + "data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "peer": true, + "requires": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + } + }, + "date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "dev": true + }, + "decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true, + "peer": true + }, + "defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "peer": true + }, + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "peer": true + }, + "esbuild": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", + "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.17.19", + "@esbuild/android-arm64": "0.17.19", + "@esbuild/android-x64": "0.17.19", + "@esbuild/darwin-arm64": "0.17.19", + "@esbuild/darwin-x64": "0.17.19", + "@esbuild/freebsd-arm64": "0.17.19", + "@esbuild/freebsd-x64": "0.17.19", + "@esbuild/linux-arm": "0.17.19", + "@esbuild/linux-arm64": "0.17.19", + "@esbuild/linux-ia32": "0.17.19", + "@esbuild/linux-loong64": "0.17.19", + "@esbuild/linux-mips64el": "0.17.19", + "@esbuild/linux-ppc64": "0.17.19", + "@esbuild/linux-riscv64": "0.17.19", + "@esbuild/linux-s390x": "0.17.19", + "@esbuild/linux-x64": "0.17.19", + "@esbuild/netbsd-x64": "0.17.19", + "@esbuild/openbsd-x64": "0.17.19", + "@esbuild/sunos-x64": "0.17.19", + "@esbuild/win32-arm64": "0.17.19", + "@esbuild/win32-ia32": "0.17.19", + "@esbuild/win32-x64": "0.17.19" + } + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "exit-hook": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", + "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", + "dev": true + }, + "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" + } + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "peer": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "get-source": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz", + "integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==", + "dev": true, + "requires": { + "data-uri-to-buffer": "^2.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "data-uri-to-buffer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", + "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==", + "dev": true + } + } + }, + "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 + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, + "hono": { + "version": "4.5.11", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.5.11.tgz", + "integrity": "sha512-62FcjLPtjAFwISVBUshryl+vbHOjg8rE4uIK/dxyR8GpLztunZpwFmfEvmJCUI7xoGh/Sr3CGCDPCmYxVw7wUQ==" + }, + "html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "peer": true, + "requires": { + "whatwg-encoding": "^3.1.1" + } + }, + "http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "peer": true, + "requires": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "dependencies": { + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "peer": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true, + "peer": true + } + } + }, + "https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "peer": true, + "requires": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "peer": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true, + "peer": true + } + } + }, + "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-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "requires": { + "hasown": "^2.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "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-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-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "peer": true + }, + "jsdom": { + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.0.tgz", + "integrity": "sha512-OhoFVT59T7aEq75TVw9xxEfkXgacpqAhQaYgP9y/fDqWQCMB/b1H66RfmPm/MaeaAIU9nDwMOVTlPN51+ao6CQ==", + "dev": true, + "peer": true, + "requires": { + "cssstyle": "^4.0.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.4", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + } + }, + "jsdom-global": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsdom-global/-/jsdom-global-3.0.2.tgz", + "integrity": "sha512-t1KMcBkz/pT5JrvcJbpUR2u/w1kO9jXctaaGJ0vZDzwFnIvGWw9IDSRciT83kIs8Bnw4qpOl8bQK08V01YgMPg==", + "dev": true, + "requires": {} + }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "peer": true + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "peer": true, + "requires": { + "mime-db": "1.52.0" + } + }, + "miniflare": { + "version": "3.20240821.1", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20240821.1.tgz", + "integrity": "sha512-81qdiryDG7VXzZuoa0EwhkaIYYrn7+StRIrd/2i7SPqPUNICUBjbhFFKqTnvE1+fqIPPB6l8ShKFaFvmnZOASg==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "0.8.1", + "acorn": "^8.8.0", + "acorn-walk": "^8.2.0", + "capnp-ts": "^0.7.0", + "exit-hook": "^2.2.1", + "glob-to-regexp": "^0.4.1", + "stoppable": "^1.1.0", + "undici": "^5.28.4", + "workerd": "1.20240821.1", + "ws": "^8.17.1", + "youch": "^3.2.2", + "zod": "^3.22.3" + } + }, + "mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "dev": true + }, + "nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true + }, + "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 + }, + "nwsapi": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", + "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", + "dev": true, + "peer": true + }, + "ohash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz", + "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==", + "dev": true + }, + "parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "peer": true, + "requires": { + "entities": "^4.4.0" + } + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "printable-characters": { + "version": "1.0.42", + "resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz", + "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" + }, + "psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true, + "peer": true + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "peer": true + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true, + "peer": true + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true, + "peer": true + }, + "resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true + }, + "rollup-plugin-inject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", + "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1", + "magic-string": "^0.25.3", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-node-polyfills": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz", + "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==", + "dev": true, + "requires": { + "rollup-plugin-inject": "^3.0.0" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + }, + "rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true, + "peer": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "peer": true + }, + "saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "peer": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, + "selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "requires": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + } + }, + "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 + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "stacktracey": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz", + "integrity": "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==", + "dev": true, + "requires": { + "as-table": "^1.0.36", + "get-source": "^2.0.12" + } + }, + "stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", + "dev": true + }, + "supertokens-node": { + "version": "file:../../../lib/build" + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "peer": 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" + } + }, + "tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "peer": true, + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "dependencies": { + "universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "peer": true + } + } + }, + "tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "peer": true, + "requires": { + "punycode": "^2.3.1" + } + }, + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "dev": true + }, + "undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dev": true, + "requires": { + "@fastify/busboy": "^2.0.0" + } + }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "unenv": { + "version": "npm:unenv-nightly@2.0.0-1724863496.70db6f1", + "resolved": "https://registry.npmjs.org/unenv-nightly/-/unenv-nightly-2.0.0-1724863496.70db6f1.tgz", + "integrity": "sha512-r+VIl1gnsI4WQxluruSQhy8alpAf1AsLRLm4sEKp3otCyTIVD6I6wHEYzeQnwsyWgaD4+3BD4A/eqrgOpdTzhw==", + "dev": true, + "requires": { + "defu": "^6.1.4", + "ohash": "^1.1.3", + "pathe": "^1.1.2", + "ufo": "^1.5.4" + } + }, + "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==", + "dev": true, + "peer": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "peer": true, + "requires": { + "xml-name-validator": "^5.0.0" + } + }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "peer": true + }, + "whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "peer": true, + "requires": { + "iconv-lite": "0.6.3" + }, + "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, + "peer": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "peer": true + }, + "whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, + "peer": true, + "requires": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + } + }, + "workerd": { + "version": "1.20240821.1", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20240821.1.tgz", + "integrity": "sha512-y4phjCnEG96u8ZkgkkHB+gSw0i6uMNo23rBmixylWpjxDklB+LWD8dztasvsu7xGaZbLoTxQESdEw956F7VJDA==", + "dev": true, + "requires": { + "@cloudflare/workerd-darwin-64": "1.20240821.1", + "@cloudflare/workerd-darwin-arm64": "1.20240821.1", + "@cloudflare/workerd-linux-64": "1.20240821.1", + "@cloudflare/workerd-linux-arm64": "1.20240821.1", + "@cloudflare/workerd-windows-64": "1.20240821.1" + } + }, + "wrangler": { + "version": "3.74.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.74.0.tgz", + "integrity": "sha512-wmtb+tQrgb61yN+Wa2JM98G1Gt4tKFRYPw6xwuyzUcA74L+Dum1A13w22/manl9Gq1jA3dPn+7UzT5sYEVHRog==", + "dev": true, + "requires": { + "@cloudflare/kv-asset-handler": "0.3.4", + "@cloudflare/workers-shared": "0.4.1", + "@esbuild-plugins/node-globals-polyfill": "^0.2.3", + "@esbuild-plugins/node-modules-polyfill": "^0.2.2", + "blake3-wasm": "^2.1.5", + "chokidar": "^3.5.3", + "date-fns": "^3.6.0", + "esbuild": "0.17.19", + "fsevents": "~2.3.2", + "miniflare": "3.20240821.1", + "nanoid": "^3.3.3", + "path-to-regexp": "^6.2.0", + "resolve": "^1.22.8", + "resolve.exports": "^2.0.2", + "selfsigned": "^2.0.1", + "source-map": "^0.6.1", + "unenv": "npm:unenv-nightly@2.0.0-1724863496.70db6f1", + "workerd": "1.20240821.1", + "xxhash-wasm": "^1.0.1" + }, + "dependencies": { + "path-to-regexp": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", + "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", + "dev": true + } + } + }, + "ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "requires": {} + }, + "xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "peer": true + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "peer": true + }, + "xxhash-wasm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz", + "integrity": "sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==", + "dev": true + }, + "youch": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/youch/-/youch-3.3.3.tgz", + "integrity": "sha512-qSFXUk3UZBLfggAW3dJKg0BMblG5biqSF8M34E06o5CSsZtH92u9Hqmj2RzGiHDi64fhe83+4tENFP2DB6t6ZA==", + "dev": true, + "requires": { + "cookie": "^0.5.0", + "mustache": "^4.2.0", + "stacktracey": "^2.1.8" + } + }, + "zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "dev": true + } + } +} diff --git a/examples/cloudflare-workers/with-email-password-hono-be-only/package.json b/examples/cloudflare-workers/with-email-password-hono-be-only/package.json new file mode 100644 index 000000000..4c242a13f --- /dev/null +++ b/examples/cloudflare-workers/with-email-password-hono-be-only/package.json @@ -0,0 +1,24 @@ +{ + "name": "with-email-password-hono-be-only", + "version": "0.0.1", + "private": true, + "description": "", + "main": "index.js", + "scripts": { + "start": "wrangler dev index.ts --port 3000" + }, + "dependencies": { + "hono": "^4.3.9", + "process": "^0.11.10", + "supertokens-node": "file:../../../lib/build" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20240403.0", + "@types/node": "^18.0.0", + "jsdom-global": "^3.0.2", + "wrangler": "^3.57.0" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/examples/cloudflare-workers/with-email-password-hono-be-only/test/basic.test.js b/examples/cloudflare-workers/with-email-password-hono-be-only/test/basic.test.js new file mode 100644 index 000000000..9d60cb99f --- /dev/null +++ b/examples/cloudflare-workers/with-email-password-hono-be-only/test/basic.test.js @@ -0,0 +1,90 @@ +/* Copyright (c) 2024, 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. + */ + +/* + * Imports + */ + +const assert = require("assert"); + +// Run the tests in a DOM environment. +require("jsdom-global")(); + +const APP_URL = process.env.APP_URL || "http://localhost:3000"; + +describe("Auth API Tests", () => { + const signupBody = { + formFields: [ + { + id: "email", + value: "test@test.com", + }, + { + id: "password", + value: "testpw1234", + }, + ], + }; + + it("should sign up successfully and return status 200 with OK status", async () => { + const response = await fetch(`${APP_URL}/auth/signup`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(signupBody), + }); + + const data = await response.json(); + + assert.strictEqual(response.status, 200, "Expected status code to be 200"); + assert.strictEqual(data.status, "FIELD_ERROR", "Expected status to be FIELD_ERROR"); + assert.strictEqual(data.formFields.length, 1, "Expected formFields length to be 1"); + }); + + it("should sign in successfully and return status 200 with OK status", async () => { + const response = await fetch(`${APP_URL}/auth/signin`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(signupBody), + }); + + const data = await response.json(); + + assert.strictEqual(response.status, 200, "Expected status code to be 200"); + assert.strictEqual(data.status, "OK", "Expected status to be OK"); + + // Assert that session is working by getting the sessioninfo + const accessToken = response.headers.get("St-Access-Token"); + assert(accessToken, "Expected access token to be present in headers"); + + // Use the access token to get session info + const sessionResponse = await fetch(`${APP_URL}/sessioninfo`, { + method: "GET", + headers: { + Authorization: `Bearer ${accessToken}`, + "Content-Type": "application/json", + }, + }); + + const sessionData = await sessionResponse.json(); + + // Check that session info is retrieved successfully + assert.strictEqual(sessionResponse.status, 200, "Expected session info status code to be 200"); + assert(sessionData, "Expected session data to be present"); + }); +}); diff --git a/examples/cloudflare-workers/with-email-password-hono-be-only/tsconfig.json b/examples/cloudflare-workers/with-email-password-hono-be-only/tsconfig.json new file mode 100644 index 000000000..06ac0c543 --- /dev/null +++ b/examples/cloudflare-workers/with-email-password-hono-be-only/tsconfig.json @@ -0,0 +1,63 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "ES6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + // "lib": [], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + // "outDir": "./", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */, + "types": ["@cloudflare/workers-types"] + } +} diff --git a/examples/cloudflare-workers/with-email-password-hono-be-only/wrangler.toml b/examples/cloudflare-workers/with-email-password-hono-be-only/wrangler.toml new file mode 100644 index 000000000..998e65947 --- /dev/null +++ b/examples/cloudflare-workers/with-email-password-hono-be-only/wrangler.toml @@ -0,0 +1,2 @@ +name = "hono" +compatibility_date = "2023-12-01" diff --git a/examples/express/with-emailpassword/test/basic.test.js b/examples/express/with-emailpassword/test/basic.test.js index bc33830fb..86527e3fa 100644 --- a/examples/express/with-emailpassword/test/basic.test.js +++ b/examples/express/with-emailpassword/test/basic.test.js @@ -79,9 +79,9 @@ describe("SuperTokens Example Basic tests", function () { { name: "password", value: testPW }, ]); await submitForm(page); + const callApiBtn = await page.waitForSelector(".sessionButton"); const userList = await SuperTokensNode.listUsersByAccountInfo("public", { email }); const user = userList[0]; - const callApiBtn = await page.waitForSelector(".sessionButton"); let setAlertContent; let alertContent = new Promise((res) => (setAlertContent = res)); page.on("dialog", async (dialog) => { diff --git a/examples/fastify/with-emailpassword/test/basic.test.js b/examples/fastify/with-emailpassword/test/basic.test.js index bc33830fb..86527e3fa 100644 --- a/examples/fastify/with-emailpassword/test/basic.test.js +++ b/examples/fastify/with-emailpassword/test/basic.test.js @@ -79,9 +79,9 @@ describe("SuperTokens Example Basic tests", function () { { name: "password", value: testPW }, ]); await submitForm(page); + const callApiBtn = await page.waitForSelector(".sessionButton"); const userList = await SuperTokensNode.listUsersByAccountInfo("public", { email }); const user = userList[0]; - const callApiBtn = await page.waitForSelector(".sessionButton"); let setAlertContent; let alertContent = new Promise((res) => (setAlertContent = res)); page.on("dialog", async (dialog) => { diff --git a/examples/koa/with-emailpassword/test/basic.test.js b/examples/koa/with-emailpassword/test/basic.test.js index bc33830fb..86527e3fa 100644 --- a/examples/koa/with-emailpassword/test/basic.test.js +++ b/examples/koa/with-emailpassword/test/basic.test.js @@ -79,9 +79,9 @@ describe("SuperTokens Example Basic tests", function () { { name: "password", value: testPW }, ]); await submitForm(page); + const callApiBtn = await page.waitForSelector(".sessionButton"); const userList = await SuperTokensNode.listUsersByAccountInfo("public", { email }); const user = userList[0]; - const callApiBtn = await page.waitForSelector(".sessionButton"); let setAlertContent; let alertContent = new Promise((res) => (setAlertContent = res)); page.on("dialog", async (dialog) => { diff --git a/examples/next/with-emailpassword/app/api/auth/[...path]/route.ts b/examples/next/with-emailpassword/app/api/auth/[...path]/route.ts new file mode 100644 index 000000000..4385f250f --- /dev/null +++ b/examples/next/with-emailpassword/app/api/auth/[...path]/route.ts @@ -0,0 +1,37 @@ +import { getAppDirRequestHandler } from "supertokens-node/nextjs"; +import { NextRequest, NextResponse } from "next/server"; +import supertokens from "supertokens-node"; +import { backendConfig } from "../../../../config/backendConfig"; + +supertokens.init(backendConfig()); + +const handleCall = getAppDirRequestHandler(NextResponse); + +export async function GET(request: NextRequest) { + const res = await handleCall(request); + if (!res.headers.has("Cache-Control")) { + // This is needed for production deployments with Vercel + res.headers.set("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate"); + } + return res; +} + +export async function POST(request: NextRequest) { + return handleCall(request); +} + +export async function DELETE(request: NextRequest) { + return handleCall(request); +} + +export async function PUT(request: NextRequest) { + return handleCall(request); +} + +export async function PATCH(request: NextRequest) { + return handleCall(request); +} + +export async function HEAD(request: NextRequest) { + return handleCall(request); +} diff --git a/examples/next/with-emailpassword/pages/api/auth/[[...path]].tsx b/examples/next/with-emailpassword/pages/api/auth/[[...path]].tsx deleted file mode 100644 index a4f5028b3..000000000 --- a/examples/next/with-emailpassword/pages/api/auth/[[...path]].tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { superTokensNextWrapper } from "supertokens-node/nextjs"; -import { middleware } from "supertokens-node/framework/express"; -import { NextApiRequest, NextApiResponse } from "next"; -import supertokens from "supertokens-node"; -import { backendConfig } from "../../../config/backendConfig"; - -supertokens.init(backendConfig()); - -export default async function superTokens(req: NextApiRequest, res: NextApiResponse) { - await superTokensNextWrapper( - async (next) => { - // This is needed for production deployments with Vercel - // It'll be overwritten by the middleware in some cases (the jwks.json endpoint) - res.setHeader("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate"); - - await middleware()(req as any, res as any, next); - }, - req, - res - ); - if (!res.writableEnded) { - res.status(404).send("Not found"); - } -} diff --git a/lib/build/framework/awsLambda/framework.js b/lib/build/framework/awsLambda/framework.js index 45b93076a..9ad56d91b 100644 --- a/lib/build/framework/awsLambda/framework.js +++ b/lib/build/framework/awsLambda/framework.js @@ -12,7 +12,7 @@ const response_1 = require("../response"); const utils_2 = require("../utils"); const constants_1 = require("../constants"); const supertokens_1 = __importDefault(require("../../supertokens")); -const querystring_1 = require("querystring"); +const error_1 = __importDefault(require("../../error")); class AWSRequest extends request_1.BaseRequest { constructor(event) { super(); @@ -20,8 +20,15 @@ class AWSRequest extends request_1.BaseRequest { if (this.event.body === null || this.event.body === undefined) { return {}; } else { - const parsedUrlEncodedFormData = querystring_1.parse(this.event.body); - return parsedUrlEncodedFormData === undefined ? {} : parsedUrlEncodedFormData; + try { + const parsedUrlEncodedFormData = Object.fromEntries(new URLSearchParams(this.event.body).entries()); + return parsedUrlEncodedFormData === undefined ? {} : parsedUrlEncodedFormData; + } catch (err) { + throw new error_1.default({ + type: error_1.default.BAD_INPUT_ERROR, + message: "API input error: Please make sure to pass valid url encoded form in the request body", + }); + } } }; this.getJSONFromRequestBody = async () => { diff --git a/lib/build/framework/constants.d.ts b/lib/build/framework/constants.d.ts index eb751247f..79db4b944 100644 --- a/lib/build/framework/constants.d.ts +++ b/lib/build/framework/constants.d.ts @@ -1,2 +1,4 @@ // @ts-nocheck export declare const COOKIE_HEADER = "Set-Cookie"; +export declare const BROTLI_DECOMPRESSION_ERROR_MESSAGE = + "Brotli decompression not implement, Please add a middleware that handles decompression before the SuperTokens middleware."; diff --git a/lib/build/framework/constants.js b/lib/build/framework/constants.js index 8a7a8ea6c..1038b6933 100644 --- a/lib/build/framework/constants.js +++ b/lib/build/framework/constants.js @@ -1,6 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.COOKIE_HEADER = void 0; +exports.BROTLI_DECOMPRESSION_ERROR_MESSAGE = exports.COOKIE_HEADER = 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,3 +16,6 @@ exports.COOKIE_HEADER = void 0; * under the License. */ exports.COOKIE_HEADER = "Set-Cookie"; +// Define error message for brotli decompression not being supported +exports.BROTLI_DECOMPRESSION_ERROR_MESSAGE = + "Brotli decompression not implement, Please add a middleware that handles decompression before the SuperTokens middleware."; diff --git a/lib/build/framework/custom/nodeHeaders.js b/lib/build/framework/custom/nodeHeaders.js index 9fa0cfa08..88f417cd1 100644 --- a/lib/build/framework/custom/nodeHeaders.js +++ b/lib/build/framework/custom/nodeHeaders.js @@ -15,7 +15,7 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -const util_1 = require("util"); +const utils_1 = require("../utils"); const validateHeaderName = (name) => { if (!/^[\^`\-\w!#$%&'*+.|~]+$/.test(name)) { const err = new TypeError(`Header name must be a valid HTTP token [${name}]`); @@ -60,7 +60,7 @@ class Headers extends URLSearchParams { } else if (init == null) { // eslint-disable-line no-eq-null, eqeqeq // No op - } else if (typeof init === "object" && !util_1.types.isBoxedPrimitive(init)) { + } else if (typeof init === "object" && !utils_1.isBoxedPrimitive(init)) { const method = init[Symbol.iterator]; // eslint-disable-next-line no-eq-null, eqeqeq if (method == null) { @@ -74,7 +74,7 @@ class Headers extends URLSearchParams { // Note: per spec we have to first exhaust the lists then process them result = [...init] .map((pair) => { - if (typeof pair !== "object" || util_1.types.isBoxedPrimitive(pair)) { + if (typeof pair !== "object" || utils_1.isBoxedPrimitive(pair)) { throw new TypeError("Each header pair must be an iterable object"); } return [...pair]; diff --git a/lib/build/framework/express/framework.js b/lib/build/framework/express/framework.js index 091cc96df..d8a58729b 100644 --- a/lib/build/framework/express/framework.js +++ b/lib/build/framework/express/framework.js @@ -76,7 +76,7 @@ class ExpressResponse extends response_1.BaseResponse { * like response as well as nextjs like response */ this.response.setHeader("Content-Type", "text/html"); - this.response.status(this.statusCode).send(Buffer.from(html)); + this.response.status(this.statusCode).send(html); } }; this.setHeader = (key, value, allowDuplicateKey) => { diff --git a/lib/build/framework/loopback/framework.js b/lib/build/framework/loopback/framework.js index 610a00fa0..fc4097b3f 100644 --- a/lib/build/framework/loopback/framework.js +++ b/lib/build/framework/loopback/framework.js @@ -69,7 +69,7 @@ class LoopbackResponse extends response_1.BaseResponse { this.sendHTMLResponse = (html) => { if (!this.response.writableEnded) { this.response.set("Content-Type", "text/html"); - this.response.status(this.statusCode).send(Buffer.from(html)); + this.response.status(this.statusCode).send(html); } }; this.setHeader = (key, value, allowDuplicateKey) => { diff --git a/lib/build/framework/utils.d.ts b/lib/build/framework/utils.d.ts index 9350de8b2..4ef5fc0f5 100644 --- a/lib/build/framework/utils.d.ts +++ b/lib/build/framework/utils.d.ts @@ -58,3 +58,4 @@ export declare function serializeCookieValue( path: string, sameSite: "strict" | "lax" | "none" ): string; +export declare function isBoxedPrimitive(value: any): boolean; diff --git a/lib/build/framework/utils.js b/lib/build/framework/utils.js index 6607ae65f..eb78c07df 100644 --- a/lib/build/framework/utils.js +++ b/lib/build/framework/utils.js @@ -13,19 +13,109 @@ * License for the specific language governing permissions and limitations * under the License. */ +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) { return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.serializeCookieValue = exports.getCookieValueToSetInHeader = exports.setCookieForServerResponse = exports.setHeaderForExpressLikeResponse = exports.assertFormDataBodyParserHasBeenUsedForExpressLikeRequest = exports.assertThatBodyParserHasBeenUsedForExpressLikeRequest = exports.parseURLEncodedFormData = exports.parseJSONBodyFromRequest = exports.normalizeHeaderValue = exports.getHeaderValueFromIncomingMessage = exports.getCookieValueFromIncomingMessage = exports.getCookieValueFromHeaders = void 0; +exports.isBoxedPrimitive = exports.serializeCookieValue = exports.getCookieValueToSetInHeader = exports.setCookieForServerResponse = exports.setHeaderForExpressLikeResponse = exports.assertFormDataBodyParserHasBeenUsedForExpressLikeRequest = exports.assertThatBodyParserHasBeenUsedForExpressLikeRequest = exports.parseURLEncodedFormData = exports.parseJSONBodyFromRequest = exports.normalizeHeaderValue = exports.getHeaderValueFromIncomingMessage = exports.getCookieValueFromIncomingMessage = exports.getCookieValueFromHeaders = void 0; const cookie_1 = require("cookie"); const error_1 = __importDefault(require("../error")); const constants_1 = require("./constants"); const utils_1 = require("../utils"); const content_type_1 = __importDefault(require("content-type")); -const inflation_1 = __importDefault(require("inflation")); +const pako_1 = __importDefault(require("pako")); +async function inflate(stream) { + var e_1, _a, e_2, _b; + if (!stream) { + throw new TypeError("argument stream is required"); + } + const encoding = (stream.headers && stream.headers["content-encoding"]) || "identity"; + let decompressedData; + if (encoding === "gzip" || encoding === "deflate") { + const inflator = new pako_1.default.Inflate(); + try { + for ( + var stream_1 = __asyncValues(stream), stream_1_1; + (stream_1_1 = await stream_1.next()), !stream_1_1.done; + + ) { + const chunk = stream_1_1.value; + inflator.push(chunk, false); + } + } catch (e_1_1) { + e_1 = { error: e_1_1 }; + } finally { + try { + if (stream_1_1 && !stream_1_1.done && (_a = stream_1.return)) await _a.call(stream_1); + } finally { + if (e_1) throw e_1.error; + } + } + if (inflator.err) { + throw new Error(`Decompression error: ${inflator.msg}`); + } + decompressedData = inflator.result; + } else if (encoding === "br") { + throw new Error(constants_1.BROTLI_DECOMPRESSION_ERROR_MESSAGE); + } else { + // Handle identity or unsupported encoding + decompressedData = utils_1.getBuffer().concat([]); + try { + for ( + var stream_2 = __asyncValues(stream), stream_2_1; + (stream_2_1 = await stream_2.next()), !stream_2_1.done; + + ) { + const chunk = stream_2_1.value; + decompressedData = utils_1.getBuffer().concat([decompressedData, chunk]); + } + } catch (e_2_1) { + e_2 = { error: e_2_1 }; + } finally { + try { + if (stream_2_1 && !stream_2_1.done && (_b = stream_2.return)) await _b.call(stream_2); + } finally { + if (e_2) throw e_2.error; + } + } + } + if (typeof decompressedData === "string") return decompressedData; + return new TextDecoder().decode(decompressedData); +} function getCookieValueFromHeaders(headers, key) { if (headers === undefined || headers === null) { return undefined; @@ -110,8 +200,7 @@ async function parseJSONBodyFromRequest(req) { if (!encoding.startsWith("utf-")) { throw new Error(`unsupported charset ${encoding.toUpperCase()}`); } - const buffer = await getBody(inflation_1.default(req)); - const str = buffer.toString(encoding); + const str = await inflate(req); if (str.length === 0) { return {}; } @@ -123,8 +212,7 @@ async function parseURLEncodedFormData(req) { if (!encoding.startsWith("utf-")) { throw new Error(`unsupported charset ${encoding.toUpperCase()}`); } - const buffer = await getBody(inflation_1.default(req)); - const str = buffer.toString(encoding); + const str = await inflate(req); let body = {}; for (const [key, val] of new URLSearchParams(str).entries()) { if (key in body) { @@ -158,13 +246,21 @@ async function assertThatBodyParserHasBeenUsedForExpressLikeRequest(method, requ } } else if ( request.body === undefined || - Buffer.isBuffer(request.body) || + utils_1.isBuffer(request.body) || (Object.keys(request.body).length === 0 && request.readable) ) { try { // parsing it again to make sure that the request is parsed atleast once by a json parser request.body = await parseJSONBodyFromRequest(request); - } catch (_a) { + } catch (err) { + // If the error message matches the brotli decompression + // related error, then throw that error. + if (err.message === constants_1.BROTLI_DECOMPRESSION_ERROR_MESSAGE) { + throw new error_1.default({ + type: error_1.default.BAD_INPUT_ERROR, + message: `API input error: ${constants_1.BROTLI_DECOMPRESSION_ERROR_MESSAGE}`, + }); + } throw new error_1.default({ type: error_1.default.BAD_INPUT_ERROR, message: "API input error: Please make sure to pass a valid JSON input in the request body", @@ -190,7 +286,7 @@ async function assertFormDataBodyParserHasBeenUsedForExpressLikeRequest(request) } } else if ( request.body === undefined || - Buffer.isBuffer(request.body) || + utils_1.isBuffer(request.body) || (Object.keys(request.body).length === 0 && request.readable) ) { try { @@ -324,16 +420,8 @@ function serializeCookieValue(key, value, domain, secure, httpOnly, expires, pat return cookie_1.serialize(key, value, opts); } exports.serializeCookieValue = serializeCookieValue; -// based on https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction -function getBody(request) { - return new Promise((resolve) => { - const bodyParts = []; - request - .on("data", (chunk) => { - bodyParts.push(chunk); - }) - .on("end", () => { - resolve(Buffer.concat(bodyParts)); - }); - }); +function isBoxedPrimitive(value) { + const boxedTypes = [Boolean, Number, String, Symbol, BigInt]; + return boxedTypes.some((type) => value instanceof type); } +exports.isBoxedPrimitive = isBoxedPrimitive; diff --git a/lib/build/nextjs.js b/lib/build/nextjs.js index 1435b2cdd..28c1a63d6 100644 --- a/lib/build/nextjs.js +++ b/lib/build/nextjs.js @@ -1,4 +1,18 @@ "use strict"; +/* 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. + */ var __rest = (this && this.__rest) || function (s, e) { @@ -17,20 +31,6 @@ var __importDefault = }; Object.defineProperty(exports, "__esModule", { value: true }); exports.withPreParsedRequestResponse = exports.withSession = exports.getSSRSession = exports.getAppDirRequestHandler = exports.superTokensNextWrapper = 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 cookie_1 = require("cookie"); const express_1 = require("./framework/express"); const utils_1 = require("./utils"); diff --git a/lib/build/processState.js b/lib/build/processState.js index 45d1bcd92..9dd483422 100644 --- a/lib/build/processState.js +++ b/lib/build/processState.js @@ -15,6 +15,7 @@ */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ProcessState = exports.PROCESS_STATE = void 0; +const utils_1 = require("./utils"); var PROCESS_STATE; (function (PROCESS_STATE) { PROCESS_STATE[(PROCESS_STATE["CALLING_SERVICE_IN_VERIFY"] = 0)] = "CALLING_SERVICE_IN_VERIFY"; @@ -32,7 +33,7 @@ class ProcessState { constructor() { this.history = []; this.addState = (state) => { - if (process.env.TEST_MODE === "testing") { + if (utils_1.isTestEnv()) { this.history.push(state); } }; diff --git a/lib/build/querier.js b/lib/build/querier.js index 67345b3d9..9ee1f364f 100644 --- a/lib/build/querier.js +++ b/lib/build/querier.js @@ -92,7 +92,7 @@ class Querier { return Querier.apiVersion; }; this.getHostsAliveForTesting = () => { - if (process.env.TEST_MODE !== "testing") { + if (!utils_1.isTestEnv()) { throw Error("calling testing function in non testing env"); } return Querier.hostsAliveForTesting; @@ -464,7 +464,7 @@ class Querier { ); logger_1.logDebugMessage(`core-call: ${method} ${url}`); let response = await requestFunc(url); - if (process.env.TEST_MODE === "testing") { + if (utils_1.isTestEnv()) { Querier.hostsAliveForTesting.add(currentDomain + currentBasePath); } if (response.status !== 200) { @@ -517,7 +517,7 @@ class Querier { this.rIdToCore = rIdToCore; } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_1.isTestEnv()) { throw Error("calling testing function in non testing env"); } Querier.initCalled = false; diff --git a/lib/build/recipe/accountlinking/recipe.js b/lib/build/recipe/accountlinking/recipe.js index e9eeeb363..a5faf204f 100644 --- a/lib/build/recipe/accountlinking/recipe.js +++ b/lib/build/recipe/accountlinking/recipe.js @@ -29,6 +29,7 @@ const supertokens_1 = __importDefault(require("../../supertokens")); const processState_1 = require("../../processState"); const logger_1 = require("../../logger"); const recipe_1 = __importDefault(require("../emailverification/recipe")); +const utils_2 = require("../../utils"); class Recipe extends recipeModule_1.default { constructor(recipeId, appInfo, config, _recipes, _ingredients) { super(recipeId, appInfo); @@ -623,7 +624,7 @@ class Recipe extends recipeModule_1.default { return error_1.default.isErrorFromSuperTokens(err) && err.fromRecipe === Recipe.RECIPE_ID; } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_2.isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/build/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.js b/lib/build/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.js index 7586e9f9b..e4f151e0d 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.js +++ b/lib/build/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.js @@ -10,6 +10,8 @@ const recipe_1 = __importDefault(require("../../../multitenancy/recipe")); const normalisedURLDomain_1 = __importDefault(require("../../../../normalisedURLDomain")); const normalisedURLPath_1 = __importDefault(require("../../../../normalisedURLPath")); const thirdpartyUtils_1 = require("../../../../thirdpartyUtils"); +const constants_1 = require("../../../multitenancy/constants"); +const utils_1 = require("../../../../utils"); async function createOrUpdateThirdPartyConfig(_, tenantId, options, userContext) { var _a; const requestBody = await options.req.getJSONBody(); @@ -29,7 +31,8 @@ async function createOrUpdateThirdPartyConfig(_, tenantId, options, userContext) ? _a : []; for (const provider of staticProviders.filter( - (provider) => provider.includeInNonPublicTenantsByDefault === true + (provider) => + provider.includeInNonPublicTenantsByDefault === true || tenantId === constants_1.DEFAULT_TENANT_ID )) { await multitenancy_1.default.createOrUpdateThirdPartyConfig( tenantId, @@ -63,7 +66,7 @@ async function createOrUpdateThirdPartyConfig(_, tenantId, options, userContext) defaultRedirectUrl: providerConfig.clients[0].additionalConfig.redirectURLs[0], forceAuthn: false, encodedRawMetadata: providerConfig.clients[0].additionalConfig.samlXML - ? Buffer.from(providerConfig.clients[0].additionalConfig.samlXML).toString("base64") + ? utils_1.encodeBase64(providerConfig.clients[0].additionalConfig.samlXML) : "", redirectUrl: JSON.stringify(providerConfig.clients[0].additionalConfig.redirectURLs), metadataUrl: providerConfig.clients[0].additionalConfig.samlURL || "", diff --git a/lib/build/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.js b/lib/build/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.js index 204ff775b..6bd16f2f9 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.js +++ b/lib/build/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.js @@ -9,6 +9,7 @@ const multitenancy_1 = __importDefault(require("../../../multitenancy")); const recipe_1 = __importDefault(require("../../../multitenancy/recipe")); const error_1 = __importDefault(require("../../../../error")); const multifactorauth_1 = require("../../../multifactorauth"); +const constants_1 = require("../../../multitenancy/constants"); async function deleteThirdPartyConfig(_, tenantId, options, userContext) { var _a; const thirdPartyId = options.req.getKeyValueFromQuery("thirdPartyId"); @@ -33,8 +34,11 @@ async function deleteThirdPartyConfig(_, tenantId, options, userContext) { _a !== void 0 ? _a : []; - let staticProviderIds = staticProviders.map((provider) => provider.config.thirdPartyId); - for (const providerId of staticProviderIds) { + for (const provider of staticProviders.filter( + (provider) => + provider.includeInNonPublicTenantsByDefault === true || tenantId === constants_1.DEFAULT_TENANT_ID + )) { + const providerId = provider.config.thirdPartyId; await multitenancy_1.default.createOrUpdateThirdPartyConfig( tenantId, { diff --git a/lib/build/recipe/dashboard/recipe.js b/lib/build/recipe/dashboard/recipe.js index 17c4a4e8c..5f68a6add 100644 --- a/lib/build/recipe/dashboard/recipe.js +++ b/lib/build/recipe/dashboard/recipe.js @@ -68,6 +68,7 @@ const updateTenantFirstFactor_1 = __importDefault(require("./api/multitenancy/up const updateTenantSecondaryFactor_1 = __importDefault(require("./api/multitenancy/updateTenantSecondaryFactor")); const updateTenantCoreConfig_1 = __importDefault(require("./api/multitenancy/updateTenantCoreConfig")); const getThirdPartyConfig_1 = __importDefault(require("./api/multitenancy/getThirdPartyConfig")); +const utils_2 = require("../../utils"); class Recipe extends recipeModule_1.default { constructor(recipeId, appInfo, isInServerlessEnv, config) { super(recipeId, appInfo); @@ -602,7 +603,7 @@ class Recipe extends recipeModule_1.default { }; } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_2.isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/build/recipe/emailpassword/api/implementation.js b/lib/build/recipe/emailpassword/api/implementation.js index 8e5e65db9..0d4ebc815 100644 --- a/lib/build/recipe/emailpassword/api/implementation.js +++ b/lib/build/recipe/emailpassword/api/implementation.js @@ -717,11 +717,15 @@ function getAPIImplementation() { userContext, }); if (postAuthChecks.status !== "OK") { - return authUtils_1.AuthUtils.getErrorStatusResponseWithReason( + // It should never actually come here, but we do it cause of consistency. + // If it does come here (in case there is a bug), it would make this func throw + // anyway, cause there is no SIGN_IN_NOT_ALLOWED in the errorCodeMap. + authUtils_1.AuthUtils.getErrorStatusResponseWithReason( postAuthChecks, errorCodeMap, "SIGN_UP_NOT_ALLOWED" ); + throw new Error("This should never happen"); } return { status: "OK", diff --git a/lib/build/recipe/emailpassword/api/utils.js b/lib/build/recipe/emailpassword/api/utils.js index ead402cfb..afbca42de 100644 --- a/lib/build/recipe/emailpassword/api/utils.js +++ b/lib/build/recipe/emailpassword/api/utils.js @@ -50,37 +50,44 @@ function newBadRequestError(message) { message, }); } -// We check that the number of fields in input and config form field is the same. -// We check that each item in the config form field is also present in the input form field +// We check to make sure we are validating each required form field +// and also validate optional form fields only when present async function validateFormOrThrowError(inputs, configFormFields, tenantId, userContext) { let validationErrors = []; - if (configFormFields.length !== inputs.length) { - throw newBadRequestError("Are you sending too many / too few formFields?"); + // Throw an error if the user has provided more than the allowed + // formFields. + if (inputs.length > configFormFields.length) { + throw newBadRequestError("Are you sending too many formFields?"); } - // Loop through all form fields. - for (let i = 0; i < configFormFields.length; i++) { - const field = configFormFields[i]; - // Find corresponding input value. - const input = inputs.find((i) => i.id === field.id); - // Absent or not optional empty field - if (input === undefined || (input.value === "" && !field.optional)) { + // NOTE: We don't need to check for required fields at all as that will + // be picked up in the below codeblock. + for (const formField of configFormFields) { + const input = inputs.find((input) => input.id === formField.id); + // Add the not optional error if input is not passed + // and the field is not optional. + const isValidInput = + !!input && + ((typeof input.value === "string" + ? input.value.length > 0 + : input.value !== null && typeof input.value !== "undefined") || + (typeof input.value === "object" && Object.values(input.value).length > 0)); + if (!formField.optional && !isValidInput) { validationErrors.push({ error: "Field is not optional", - id: field.id, + id: formField.id, }); - } else { - // Otherwise, use validate function. - const error = await field.validate(input.value, tenantId, userContext); - // If error, add it. - if (error !== undefined) { + } + if (isValidInput) { + const error = await formField.validate(input.value, tenantId, userContext); + if (error) { validationErrors.push({ error, - id: field.id, + id: formField.id, }); } } } - if (validationErrors.length !== 0) { + if (validationErrors.length > 0) { throw new error_1.default({ type: error_1.default.FIELD_ERROR, payload: validationErrors, diff --git a/lib/build/recipe/emailpassword/passwordResetFunctions.js b/lib/build/recipe/emailpassword/passwordResetFunctions.js index 04a611730..23ec9186f 100644 --- a/lib/build/recipe/emailpassword/passwordResetFunctions.js +++ b/lib/build/recipe/emailpassword/passwordResetFunctions.js @@ -18,7 +18,7 @@ exports.createAndSendEmailUsingSupertokensService = void 0; const utils_1 = require("../../utils"); async function createAndSendEmailUsingSupertokensService(appInfo, user, passwordResetURLWithToken) { // related issue: https://github.com/supertokens/supertokens-node/issues/38 - if (process.env.TEST_MODE === "testing") { + if (utils_1.isTestEnv()) { return; } await utils_1.postWithFetch( diff --git a/lib/build/recipe/emailpassword/recipe.js b/lib/build/recipe/emailpassword/recipe.js index 901741090..dc968c536 100644 --- a/lib/build/recipe/emailpassword/recipe.js +++ b/lib/build/recipe/emailpassword/recipe.js @@ -291,7 +291,7 @@ class Recipe extends recipeModule_1.default { }; } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_2.isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/build/recipe/emailverification/emailVerificationFunctions.js b/lib/build/recipe/emailverification/emailVerificationFunctions.js index ded4afd5a..fb6b03bfc 100644 --- a/lib/build/recipe/emailverification/emailVerificationFunctions.js +++ b/lib/build/recipe/emailverification/emailVerificationFunctions.js @@ -17,7 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.createAndSendEmailUsingSupertokensService = void 0; const utils_1 = require("../../utils"); async function createAndSendEmailUsingSupertokensService(appInfo, user, emailVerifyURLWithToken) { - if (process.env.TEST_MODE === "testing") { + if (utils_1.isTestEnv()) { return; } await utils_1.postWithFetch( diff --git a/lib/build/recipe/emailverification/recipe.js b/lib/build/recipe/emailverification/recipe.js index 9c0703a91..9f22a9552 100644 --- a/lib/build/recipe/emailverification/recipe.js +++ b/lib/build/recipe/emailverification/recipe.js @@ -38,6 +38,7 @@ const error_2 = __importDefault(require("../session/error")); const session_1 = __importDefault(require("../session")); const __1 = require("../.."); const logger_1 = require("../../logger"); +const utils_2 = require("../../utils"); class Recipe extends recipeModule_1.default { constructor(recipeId, appInfo, isInServerlessEnv, config, ingredients) { super(recipeId, appInfo); @@ -314,7 +315,7 @@ class Recipe extends recipeModule_1.default { }; } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_2.isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/build/recipe/jwt/recipe.js b/lib/build/recipe/jwt/recipe.js index d95d074b0..bb92d24a8 100644 --- a/lib/build/recipe/jwt/recipe.js +++ b/lib/build/recipe/jwt/recipe.js @@ -23,11 +23,12 @@ const error_1 = __importDefault(require("../../error")); const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); const querier_1 = require("../../querier"); const recipeModule_1 = __importDefault(require("../../recipeModule")); +const utils_1 = require("../../utils"); const getJWKS_1 = __importDefault(require("./api/getJWKS")); const implementation_1 = __importDefault(require("./api/implementation")); const constants_1 = require("./constants"); const recipeImplementation_1 = __importDefault(require("./recipeImplementation")); -const utils_1 = require("./utils"); +const utils_2 = require("./utils"); const supertokens_js_override_1 = __importDefault(require("supertokens-js-override")); class Recipe extends recipeModule_1.default { constructor(recipeId, appInfo, isInServerlessEnv, config) { @@ -43,7 +44,7 @@ class Recipe extends recipeModule_1.default { }; return await getJWKS_1.default(this.apiImpl, options, userContext); }; - this.config = utils_1.validateAndNormaliseUserInput(this, appInfo, config); + this.config = utils_2.validateAndNormaliseUserInput(this, appInfo, config); this.isInServerlessEnv = isInServerlessEnv; { let builder = new supertokens_js_override_1.default( @@ -78,7 +79,7 @@ class Recipe extends recipeModule_1.default { }; } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_1.isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/build/recipe/multifactorauth/recipe.js b/lib/build/recipe/multifactorauth/recipe.js index c1b433469..31b8241a8 100644 --- a/lib/build/recipe/multifactorauth/recipe.js +++ b/lib/build/recipe/multifactorauth/recipe.js @@ -33,6 +33,7 @@ const recipe_1 = __importDefault(require("../session/recipe")); const postSuperTokensInitCallbacks_1 = require("../../postSuperTokensInitCallbacks"); const recipe_2 = __importDefault(require("../multitenancy/recipe")); const querier_1 = require("../../querier"); +const utils_2 = require("../../utils"); class Recipe extends recipeModule_1.default { constructor(recipeId, appInfo, isInServerlessEnv, config) { var _a; @@ -197,7 +198,7 @@ class Recipe extends recipeModule_1.default { }; } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_2.isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/build/recipe/multitenancy/recipe.js b/lib/build/recipe/multitenancy/recipe.js index b6070232e..20f9c22be 100644 --- a/lib/build/recipe/multitenancy/recipe.js +++ b/lib/build/recipe/multitenancy/recipe.js @@ -32,6 +32,7 @@ const constants_1 = require("./constants"); const allowedDomainsClaim_1 = require("./allowedDomainsClaim"); const utils_1 = require("./utils"); const loginMethods_1 = __importDefault(require("./api/loginMethods")); +const utils_2 = require("../../utils"); class Recipe extends recipeModule_1.default { constructor(recipeId, appInfo, isInServerlessEnv, config) { super(recipeId, appInfo); @@ -120,7 +121,7 @@ class Recipe extends recipeModule_1.default { }; } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_2.isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/build/recipe/multitenancy/utils.js b/lib/build/recipe/multitenancy/utils.js index 162c51333..3883f88f5 100644 --- a/lib/build/recipe/multitenancy/utils.js +++ b/lib/build/recipe/multitenancy/utils.js @@ -70,12 +70,6 @@ const isValidFirstFactor = async function (tenantId, factorId, userContext) { } from tenant config` ); logger_1.logDebugMessage(`isValidFirstFactor got ${firstFactorsFromMFA} from MFA`); - logger_1.logDebugMessage( - `isValidFirstFactor tenantconfig enables: ${Object.keys(tenantConfig).filter((k) => { - var _a; - return (_a = tenantConfig[k]) === null || _a === void 0 ? void 0 : _a.enabled; - })}` - ); // first factors configured in core is prioritised over the ones configured statically let configuredFirstFactors = tenantConfig.firstFactors !== undefined ? tenantConfig.firstFactors : firstFactorsFromMFA; diff --git a/lib/build/recipe/openid/recipe.js b/lib/build/recipe/openid/recipe.js index 4e0eb29e1..9528e93d9 100644 --- a/lib/build/recipe/openid/recipe.js +++ b/lib/build/recipe/openid/recipe.js @@ -29,6 +29,7 @@ const implementation_1 = __importDefault(require("./api/implementation")); const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); const constants_1 = require("./constants"); const getOpenIdDiscoveryConfiguration_1 = __importDefault(require("./api/getOpenIdDiscoveryConfiguration")); +const utils_2 = require("../../utils"); class OpenIdRecipe extends recipeModule_1.default { constructor(recipeId, appInfo, isInServerlessEnv, config) { super(recipeId, appInfo); @@ -102,7 +103,7 @@ class OpenIdRecipe extends recipeModule_1.default { }; } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_2.isTestEnv()) { throw new Error("calling testing function in non testing env"); } OpenIdRecipe.instance = undefined; diff --git a/lib/build/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.js b/lib/build/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.js index c901bd9b3..aacff4c5d 100644 --- a/lib/build/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.js +++ b/lib/build/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.js @@ -2,7 +2,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("../../../../../utils"); async function createAndSendEmailUsingSupertokensService(input) { - if (process.env.TEST_MODE === "testing") { + if (utils_1.isTestEnv()) { return; } const result = await utils_1.postWithFetch( diff --git a/lib/build/recipe/passwordless/recipe.js b/lib/build/recipe/passwordless/recipe.js index 641ed598b..6ff155b8b 100644 --- a/lib/build/recipe/passwordless/recipe.js +++ b/lib/build/recipe/passwordless/recipe.js @@ -40,6 +40,7 @@ const recipe_1 = __importDefault(require("../multifactorauth/recipe")); const recipe_2 = __importDefault(require("../multitenancy/recipe")); const utils_2 = require("../thirdparty/utils"); const multifactorauth_1 = require("../multifactorauth"); +const utils_3 = require("../../utils"); class Recipe extends recipeModule_1.default { constructor(recipeId, appInfo, isInServerlessEnv, config, ingredients) { super(recipeId, appInfo); @@ -570,7 +571,7 @@ class Recipe extends recipeModule_1.default { }; } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_3.isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/build/recipe/passwordless/recipeImplementation.js b/lib/build/recipe/passwordless/recipeImplementation.js index 2ec207ff3..d2fb36376 100644 --- a/lib/build/recipe/passwordless/recipeImplementation.js +++ b/lib/build/recipe/passwordless/recipeImplementation.js @@ -37,12 +37,6 @@ function getRecipeInterface(querier) { logger_1.logDebugMessage("Passwordless.consumeCode code consumed OK"); response.user = new user_1.User(response.user); response.recipeUserId = new recipeUserId_1.default(response.recipeUserId); - if (response.status !== "OK") { - return response; - } - if (response.status !== "OK") { - return response; - } // Attempt account linking (this is a sign up) let updatedUser = response.user; const linkResult = await authUtils_1.AuthUtils.linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo( @@ -59,9 +53,6 @@ function getRecipeInterface(querier) { return linkResult; } updatedUser = linkResult.user; - if (updatedUser === undefined) { - throw new Error("Should never come here."); - } response.user = updatedUser; return Object.assign(Object.assign({}, response), { consumedDevice: response.consumedDevice, diff --git a/lib/build/recipe/session/cookieAndHeaders.js b/lib/build/recipe/session/cookieAndHeaders.js index 149a3838d..553671956 100644 --- a/lib/build/recipe/session/cookieAndHeaders.js +++ b/lib/build/recipe/session/cookieAndHeaders.js @@ -22,6 +22,7 @@ exports.hasMultipleCookiesForTokenType = exports.clearSessionCookiesFromOlderCoo */ const constants_1 = require("../../constants"); const logger_1 = require("../../logger"); +const utils_1 = require("../../utils"); const constants_2 = require("./constants"); const error_1 = __importDefault(require("./error")); const authorizationHeaderKey = "authorization"; @@ -71,7 +72,7 @@ function buildFrontToken(userId, atExpiry, accessTokenPayload) { ate: atExpiry, up: accessTokenPayload, }; - return Buffer.from(JSON.stringify(tokenInfo)).toString("base64"); + return utils_1.encodeBase64(JSON.stringify(tokenInfo)); } exports.buildFrontToken = buildFrontToken; function setFrontTokenInHeaders(res, frontToken) { diff --git a/lib/build/recipe/session/jwt.js b/lib/build/recipe/session/jwt.js index 097ead1e3..8d8fd813e 100644 --- a/lib/build/recipe/session/jwt.js +++ b/lib/build/recipe/session/jwt.js @@ -16,21 +16,22 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.parseJWTWithoutSignatureVerification = void 0; const logger_1 = require("../../logger"); +const utils_1 = require("../../utils"); const HEADERS = new Set([ - Buffer.from( + utils_1.encodeBase64( JSON.stringify({ alg: "RS256", typ: "JWT", version: "1", }) - ).toString("base64"), - Buffer.from( + ), + utils_1.encodeBase64( JSON.stringify({ alg: "RS256", typ: "JWT", version: "2", }) - ).toString("base64"), + ), ]); function parseJWTWithoutSignatureVerification(jwt) { const splittedInput = jwt.split("."); @@ -44,7 +45,7 @@ function parseJWTWithoutSignatureVerification(jwt) { // V2 or older tokens did not save the key id; // checking header if (!HEADERS.has(splittedInput[0])) { - const parsedHeader = JSON.parse(Buffer.from(splittedInput[0], "base64").toString()); + const parsedHeader = JSON.parse(utils_1.decodeBase64(splittedInput[0])); if (parsedHeader.version !== undefined) { // We have to ensure version is a string, otherwise Number.parseInt can have unexpected results if (typeof parsedHeader.version !== "string") { @@ -72,7 +73,7 @@ function parseJWTWithoutSignatureVerification(jwt) { header: splittedInput[0], // Ideally we would only parse this after the signature verification is done. // We do this at the start, since we want to check if a token can be a supertokens access token or not - payload: JSON.parse(Buffer.from(splittedInput[1], "base64").toString()), + payload: JSON.parse(utils_1.decodeBase64(splittedInput[1])), signature: splittedInput[2], }; } diff --git a/lib/build/recipe/session/recipe.js b/lib/build/recipe/session/recipe.js index b7307ae08..c24e2c6d7 100644 --- a/lib/build/recipe/session/recipe.js +++ b/lib/build/recipe/session/recipe.js @@ -35,6 +35,7 @@ const recipe_1 = __importDefault(require("../openid/recipe")); const logger_1 = require("../../logger"); const combinedRemoteJWKSet_1 = require("../../combinedRemoteJWKSet"); const sessionRequestFunctions_1 = require("./sessionRequestFunctions"); +const utils_2 = require("../../utils"); // For Express class SessionRecipe extends recipeModule_1.default { constructor(recipeId, appInfo, isInServerlessEnv, config) { @@ -244,7 +245,7 @@ class SessionRecipe extends recipeModule_1.default { }; } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_2.isTestEnv()) { throw new Error("calling testing function in non testing env"); } SessionRecipe.instance = undefined; diff --git a/lib/build/recipe/session/recipeImplementation.js b/lib/build/recipe/session/recipeImplementation.js index 143db8845..7dbba30ec 100644 --- a/lib/build/recipe/session/recipeImplementation.js +++ b/lib/build/recipe/session/recipeImplementation.js @@ -53,6 +53,7 @@ const error_1 = __importDefault(require("./error")); const recipeUserId_1 = __importDefault(require("../../recipeUserId")); const constants_1 = require("../multitenancy/constants"); const constants_2 = require("./constants"); +const utils_2 = require("../../utils"); function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverrides) { let obj = { createNewSession: async function ({ @@ -410,7 +411,7 @@ function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverride appInfo, getRecipeImpl: getRecipeImplAfterOverrides, }; - if (process.env.TEST_MODE === "testing") { + if (utils_2.isTestEnv()) { // testing mode, we add some of the help functions to the obj obj.helpers = helpers; } diff --git a/lib/build/recipe/thirdparty/api/implementation.js b/lib/build/recipe/thirdparty/api/implementation.js index 0188b26dd..1fed7ca95 100644 --- a/lib/build/recipe/thirdparty/api/implementation.js +++ b/lib/build/recipe/thirdparty/api/implementation.js @@ -9,6 +9,7 @@ const emailverification_1 = __importDefault(require("../../emailverification")); const recipe_1 = __importDefault(require("../../emailverification/recipe")); const authUtils_1 = require("../../../authUtils"); const logger_1 = require("../../../logger"); +const utils_1 = require("../../../utils"); function getAPIInterface() { return { authorisationUrlGET: async function ({ provider, redirectURIOnProviderDashboard, userContext }) { @@ -204,7 +205,7 @@ function getAPIInterface() { }, appleRedirectHandlerPOST: async function ({ formPostInfoFromProvider, options }) { const stateInBase64 = formPostInfoFromProvider.state; - const state = Buffer.from(stateInBase64, "base64").toString(); + const state = utils_1.decodeBase64(stateInBase64); const stateObj = JSON.parse(state); const redirectURI = stateObj.frontendRedirectURI; const urlObj = new URL(redirectURI); diff --git a/lib/build/recipe/thirdparty/providers/activeDirectory.js b/lib/build/recipe/thirdparty/providers/activeDirectory.js index 3119966b4..bb48e32c7 100644 --- a/lib/build/recipe/thirdparty/providers/activeDirectory.js +++ b/lib/build/recipe/thirdparty/providers/activeDirectory.js @@ -30,19 +30,15 @@ function ActiveDirectory(input) { const oGetConfig = originalImplementation.getConfigForClientType; originalImplementation.getConfigForClientType = async function ({ clientType, userContext }) { const config = await oGetConfig({ clientType, userContext }); - if (config.additionalConfig == undefined || config.additionalConfig.directoryId == undefined) { - if (config.oidcDiscoveryEndpoint === undefined) { - throw new Error( - "Please provide the directoryId in the additionalConfig of the Active Directory provider." - ); - } - } else { + if (config.additionalConfig !== undefined && config.additionalConfig.directoryId !== undefined) { config.oidcDiscoveryEndpoint = `https://login.microsoftonline.com/${config.additionalConfig.directoryId}/v2.0/.well-known/openid-configuration`; } - // The config could be coming from core where we didn't add the well-known previously - config.oidcDiscoveryEndpoint = utils_1.normaliseOIDCEndpointToIncludeWellKnown( - config.oidcDiscoveryEndpoint - ); + if (config.oidcDiscoveryEndpoint !== undefined) { + // The config could be coming from core where we didn't add the well-known previously + config.oidcDiscoveryEndpoint = utils_1.normaliseOIDCEndpointToIncludeWellKnown( + config.oidcDiscoveryEndpoint + ); + } if (config.scope === undefined) { config.scope = ["openid", "email"]; } diff --git a/lib/build/recipe/thirdparty/providers/github.js b/lib/build/recipe/thirdparty/providers/github.js index 1f3c86029..ced201b08 100644 --- a/lib/build/recipe/thirdparty/providers/github.js +++ b/lib/build/recipe/thirdparty/providers/github.js @@ -5,6 +5,21 @@ 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 utils_1 = require("../../../utils"); const custom_1 = __importDefault(require("./custom")); const thirdpartyUtils_1 = require("../../../thirdpartyUtils"); function getSupertokensUserInfoFromRawUserInfoResponseForGithub(rawUserInfoResponse) { @@ -41,9 +56,9 @@ function Github(input) { } if (input.config.validateAccessToken === undefined) { input.config.validateAccessToken = async ({ accessToken, clientConfig }) => { - const basicAuthToken = Buffer.from( + const basicAuthToken = utils_1.encodeBase64( `${clientConfig.clientId}:${clientConfig.clientSecret === undefined ? "" : clientConfig.clientSecret}` - ).toString("base64"); + ); const applicationResponse = await thirdpartyUtils_1.doPostRequest( `https://api.github.com/applications/${clientConfig.clientId}/token`, { diff --git a/lib/build/recipe/thirdparty/providers/okta.js b/lib/build/recipe/thirdparty/providers/okta.js index 84bffd5e4..2fdffd98b 100644 --- a/lib/build/recipe/thirdparty/providers/okta.js +++ b/lib/build/recipe/thirdparty/providers/okta.js @@ -32,19 +32,17 @@ function Okta(input) { const oGetConfig = originalImplementation.getConfigForClientType; originalImplementation.getConfigForClientType = async function (input) { const config = await oGetConfig(input); - if (config.additionalConfig == undefined || config.additionalConfig.oktaDomain == undefined) { - if (config.oidcDiscoveryEndpoint === undefined) { - throw new Error("Please provide the oktaDomain in the additionalConfig of the Okta provider."); - } - } else { + if (config.additionalConfig !== undefined && config.additionalConfig.oktaDomain !== undefined) { const oidcDomain = new normalisedURLDomain_1.default(config.additionalConfig.oktaDomain); const oidcPath = new normalisedURLPath_1.default("/.well-known/openid-configuration"); config.oidcDiscoveryEndpoint = oidcDomain.getAsStringDangerous() + oidcPath.getAsStringDangerous(); } - // The config could be coming from core where we didn't add the well-known previously - config.oidcDiscoveryEndpoint = utils_1.normaliseOIDCEndpointToIncludeWellKnown( - config.oidcDiscoveryEndpoint - ); + if (config.oidcDiscoveryEndpoint !== undefined) { + // The config could be coming from core where we didn't add the well-known previously + config.oidcDiscoveryEndpoint = utils_1.normaliseOIDCEndpointToIncludeWellKnown( + config.oidcDiscoveryEndpoint + ); + } if (config.scope === undefined) { config.scope = ["openid", "email"]; } diff --git a/lib/build/recipe/thirdparty/providers/twitter.js b/lib/build/recipe/thirdparty/providers/twitter.js index 7a7078b51..ec82e5638 100644 --- a/lib/build/recipe/thirdparty/providers/twitter.js +++ b/lib/build/recipe/thirdparty/providers/twitter.js @@ -51,6 +51,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); * under the License. */ const logger_1 = require("../../../logger"); +const utils_1 = require("../../../utils"); const custom_1 = __importStar(require("./custom")); const thirdpartyUtils_1 = require("../../../thirdpartyUtils"); function Twitter(input) { @@ -102,10 +103,7 @@ function Twitter(input) { redirectUri = custom_1.DEV_OAUTH_REDIRECT_URL; } /* Transformation needed for dev keys END */ - const basicAuthToken = Buffer.from( - `${clientId}:${originalImplementation.config.clientSecret}`, - "utf8" - ).toString("base64"); + const basicAuthToken = utils_1.encodeBase64(`${clientId}:${originalImplementation.config.clientSecret}`); const twitterOauthTokenParams = Object.assign( { grant_type: "authorization_code", diff --git a/lib/build/recipe/thirdparty/providers/utils.d.ts b/lib/build/recipe/thirdparty/providers/utils.d.ts index 05e453182..e09a4d2bc 100644 --- a/lib/build/recipe/thirdparty/providers/utils.d.ts +++ b/lib/build/recipe/thirdparty/providers/utils.d.ts @@ -1,4 +1,36 @@ // @ts-nocheck +import * as jose from "jose"; import { ProviderConfigForClientType } from "../types"; +export declare function doGetRequest( + url: string, + queryParams?: { + [key: string]: string; + }, + headers?: { + [key: string]: string; + } +): Promise<{ + jsonResponse: Record | undefined; + status: number; + stringResponse: string; +}>; +export declare function doPostRequest( + url: string, + params: { + [key: string]: any; + }, + headers?: { + [key: string]: string; + } +): Promise<{ + jsonResponse: Record | undefined; + status: number; + stringResponse: string; +}>; +export declare function verifyIdTokenFromJWKSEndpointAndGetPayload( + idToken: string, + jwks: jose.JWTVerifyGetKey, + otherOptions: jose.JWTVerifyOptions +): Promise; export declare function discoverOIDCEndpoints(config: ProviderConfigForClientType): Promise; export declare function normaliseOIDCEndpointToIncludeWellKnown(url: string): string; diff --git a/lib/build/recipe/thirdparty/providers/utils.js b/lib/build/recipe/thirdparty/providers/utils.js index 4b2590693..bacd7b02f 100644 --- a/lib/build/recipe/thirdparty/providers/utils.js +++ b/lib/build/recipe/thirdparty/providers/utils.js @@ -1,14 +1,111 @@ "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 __importDefault = (this && this.__importDefault) || function (mod) { return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.normaliseOIDCEndpointToIncludeWellKnown = exports.discoverOIDCEndpoints = void 0; +exports.normaliseOIDCEndpointToIncludeWellKnown = exports.discoverOIDCEndpoints = exports.verifyIdTokenFromJWKSEndpointAndGetPayload = exports.doPostRequest = exports.doGetRequest = void 0; +const jose = __importStar(require("jose")); const thirdpartyUtils_1 = require("../../../thirdpartyUtils"); const normalisedURLDomain_1 = __importDefault(require("../../../normalisedURLDomain")); const normalisedURLPath_1 = __importDefault(require("../../../normalisedURLPath")); +const logger_1 = require("../../../logger"); +const utils_1 = require("../../../utils"); +async function doGetRequest(url, queryParams, headers) { + logger_1.logDebugMessage( + `GET request to ${url}, with query params ${JSON.stringify(queryParams)} and headers ${JSON.stringify(headers)}` + ); + if ((headers === null || headers === void 0 ? void 0 : headers["Accept"]) === undefined) { + headers = Object.assign(Object.assign({}, headers), { Accept: "application/json" }); + } + const finalURL = new URL(url); + finalURL.search = new URLSearchParams(queryParams).toString(); + let response = await utils_1.doFetch(finalURL.toString(), { + headers: headers, + }); + const stringResponse = await response.text(); + let jsonResponse = undefined; + logger_1.logDebugMessage(`Received response with status ${response.status} and body ${stringResponse}`); + if (response.status < 400) { + jsonResponse = JSON.parse(stringResponse); + } + return { + stringResponse, + status: response.status, + jsonResponse, + }; +} +exports.doGetRequest = doGetRequest; +async function doPostRequest(url, params, headers) { + if (headers === undefined) { + headers = {}; + } + headers["Content-Type"] = "application/x-www-form-urlencoded"; + headers["Accept"] = "application/json"; // few providers like github don't send back json response by default + logger_1.logDebugMessage( + `POST request to ${url}, with params ${JSON.stringify(params)} and headers ${JSON.stringify(headers)}` + ); + const body = new URLSearchParams(params).toString(); + let response = await utils_1.doFetch(url, { + method: "POST", + body, + headers, + }); + const stringResponse = await response.text(); + let jsonResponse = undefined; + logger_1.logDebugMessage(`Received response with status ${response.status} and body ${stringResponse}`); + if (response.status < 400) { + jsonResponse = JSON.parse(stringResponse); + } + return { + stringResponse, + status: response.status, + jsonResponse, + }; +} +exports.doPostRequest = doPostRequest; +async function verifyIdTokenFromJWKSEndpointAndGetPayload(idToken, jwks, otherOptions) { + const { payload } = await jose.jwtVerify(idToken, jwks, otherOptions); + return payload; +} +exports.verifyIdTokenFromJWKSEndpointAndGetPayload = verifyIdTokenFromJWKSEndpointAndGetPayload; async function discoverOIDCEndpoints(config) { if (config.oidcDiscoveryEndpoint !== undefined) { const oidcInfo = await thirdpartyUtils_1.getOIDCDiscoveryInfo(config.oidcDiscoveryEndpoint); diff --git a/lib/build/recipe/thirdparty/recipe.js b/lib/build/recipe/thirdparty/recipe.js index ef0908761..d9daed748 100644 --- a/lib/build/recipe/thirdparty/recipe.js +++ b/lib/build/recipe/thirdparty/recipe.js @@ -34,6 +34,7 @@ const appleRedirect_1 = __importDefault(require("./api/appleRedirect")); const supertokens_js_override_1 = __importDefault(require("supertokens-js-override")); const postSuperTokensInitCallbacks_1 = require("../../postSuperTokensInitCallbacks"); const multifactorauth_1 = require("../multifactorauth"); +const utils_2 = require("../../utils"); class Recipe extends recipeModule_1.default { constructor(recipeId, appInfo, isInServerlessEnv, config, _recipes, _ingredients) { super(recipeId, appInfo); @@ -135,7 +136,7 @@ class Recipe extends recipeModule_1.default { throw new Error("Initialisation not done. Did you forget to call the ThirdParty.init function?"); } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_2.isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/build/recipe/totp/recipe.js b/lib/build/recipe/totp/recipe.js index e33e44030..fb146942b 100644 --- a/lib/build/recipe/totp/recipe.js +++ b/lib/build/recipe/totp/recipe.js @@ -35,6 +35,7 @@ const listDevices_1 = __importDefault(require("./api/listDevices")); const removeDevice_1 = __importDefault(require("./api/removeDevice")); const postSuperTokensInitCallbacks_1 = require("../../postSuperTokensInitCallbacks"); const recipe_1 = __importDefault(require("../multifactorauth/recipe")); +const utils_2 = require("../../utils"); class Recipe extends recipeModule_1.default { constructor(recipeId, appInfo, isInServerlessEnv, config) { super(recipeId, appInfo); @@ -157,7 +158,7 @@ class Recipe extends recipeModule_1.default { }; } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_2.isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/build/recipe/usermetadata/recipe.js b/lib/build/recipe/usermetadata/recipe.js index 96b98096a..600238705 100644 --- a/lib/build/recipe/usermetadata/recipe.js +++ b/lib/build/recipe/usermetadata/recipe.js @@ -22,8 +22,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); const error_1 = __importDefault(require("../../error")); const querier_1 = require("../../querier"); const recipeModule_1 = __importDefault(require("../../recipeModule")); +const utils_1 = require("../../utils"); const recipeImplementation_1 = __importDefault(require("./recipeImplementation")); -const utils_1 = require("./utils"); +const utils_2 = require("./utils"); const supertokens_js_override_1 = __importDefault(require("supertokens-js-override")); class Recipe extends recipeModule_1.default { constructor(recipeId, appInfo, isInServerlessEnv, config) { @@ -32,7 +33,7 @@ class Recipe extends recipeModule_1.default { this.handleAPIRequest = async (_, _tenantId, __, ___, ____, _____) => { throw new Error("Should never come here"); }; - this.config = utils_1.validateAndNormaliseUserInput(this, appInfo, config); + this.config = utils_2.validateAndNormaliseUserInput(this, appInfo, config); this.isInServerlessEnv = isInServerlessEnv; { let builder = new supertokens_js_override_1.default( @@ -61,7 +62,7 @@ class Recipe extends recipeModule_1.default { }; } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_1.isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/build/recipe/userroles/recipe.js b/lib/build/recipe/userroles/recipe.js index c341f1c19..3f16cf7be 100644 --- a/lib/build/recipe/userroles/recipe.js +++ b/lib/build/recipe/userroles/recipe.js @@ -31,6 +31,7 @@ const recipe_2 = __importDefault(require("../oauth2provider/recipe")); const userRoleClaim_1 = require("./userRoleClaim"); const permissionClaim_1 = require("./permissionClaim"); const session_1 = require("../session"); +const utils_2 = require("../../utils"); class Recipe extends recipeModule_1.default { constructor(recipeId, appInfo, isInServerlessEnv, config) { super(recipeId, appInfo); @@ -150,7 +151,7 @@ class Recipe extends recipeModule_1.default { }; } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_2.isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/build/supertokens.js b/lib/build/supertokens.js index 2da1ac7bb..5092d3852 100644 --- a/lib/build/supertokens.js +++ b/lib/build/supertokens.js @@ -419,7 +419,7 @@ class SuperTokens { if (!oauth2Found) { this.recipeModules.push(OAuth2ProviderRecipe.init()(this.appInfo, this.isInServerlessEnv)); } - this.telemetryEnabled = config.telemetry === undefined ? process.env.TEST_MODE !== "testing" : config.telemetry; + this.telemetryEnabled = config.telemetry === undefined ? !utils_1.isTestEnv() : config.telemetry; } static init(config) { if (SuperTokens.instance === undefined) { @@ -428,7 +428,7 @@ class SuperTokens { } } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!utils_1.isTestEnv()) { throw new Error("calling testing function in non testing env"); } querier_1.Querier.reset(); diff --git a/lib/build/utils.d.ts b/lib/build/utils.d.ts index 8743e5767..b681642e1 100644 --- a/lib/build/utils.d.ts +++ b/lib/build/utils.d.ts @@ -66,3 +66,9 @@ export declare function transformObjectKeys( }, caseType: "snake-case" | "camelCase" ): T; +export declare const getProcess: () => any; +export declare const getBuffer: () => any; +export declare const isTestEnv: () => boolean; +export declare const encodeBase64: (value: string) => string; +export declare const decodeBase64: (value: string) => string; +export declare const isBuffer: (obj: any) => boolean; diff --git a/lib/build/utils.js b/lib/build/utils.js index 30bbed8ea..7f1b05eed 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.transformObjectKeys = exports.toSnakeCase = exports.toCamelCase = exports.normaliseEmail = exports.postWithFetch = exports.getFromObjectCaseInsensitive = exports.getTopLevelDomainForSameSiteResolution = exports.setRequestInUserContextIfNotDefined = exports.getUserContext = exports.makeDefaultUserContextFromAPI = exports.humaniseMilliseconds = exports.frontendHasInterceptor = exports.getRidFromHeader = exports.hasGreaterThanEqualToFDI = exports.getLatestFDIVersionFromFDIList = exports.getBackwardsCompatibleUserInfo = exports.getNormalisedShouldTryLinkingWithSessionUserFlag = exports.isAnIpAddress = exports.send200Response = exports.sendNon200Response = exports.sendNon200ResponseWithMessage = exports.normaliseHttpMethod = exports.normaliseInputAppInfoOrThrowError = exports.maxVersion = exports.getLargestVersionFromIntersection = exports.doFetch = void 0; +exports.isBuffer = exports.decodeBase64 = exports.encodeBase64 = exports.isTestEnv = exports.getBuffer = exports.getProcess = exports.transformObjectKeys = exports.toSnakeCase = exports.toCamelCase = exports.normaliseEmail = exports.postWithFetch = exports.getFromObjectCaseInsensitive = exports.getTopLevelDomainForSameSiteResolution = exports.setRequestInUserContextIfNotDefined = exports.getUserContext = exports.makeDefaultUserContextFromAPI = exports.humaniseMilliseconds = exports.frontendHasInterceptor = exports.getRidFromHeader = exports.hasGreaterThanEqualToFDI = exports.getLatestFDIVersionFromFDIList = exports.getBackwardsCompatibleUserInfo = exports.getNormalisedShouldTryLinkingWithSessionUserFlag = exports.isAnIpAddress = exports.send200Response = exports.sendNon200Response = exports.sendNon200ResponseWithMessage = exports.normaliseHttpMethod = exports.normaliseInputAppInfoOrThrowError = exports.maxVersion = exports.getLargestVersionFromIntersection = exports.doFetch = void 0; const psl = __importStar(require("psl")); const normalisedURLDomain_1 = __importDefault(require("./normalisedURLDomain")); const normalisedURLPath_1 = __importDefault(require("./normalisedURLPath")); @@ -455,3 +455,54 @@ function transformObjectKeys(obj, caseType) { }, {}); } exports.transformObjectKeys = transformObjectKeys; +const getProcess = () => { + /** + * Return the process instance if it is available falling back + * to one that is compatible where process may not be available + * (like `edge` runtime). + */ + if (typeof process !== "undefined") return process; + const ponyFilledProcess = require("process"); + return ponyFilledProcess; +}; +exports.getProcess = getProcess; +const getBuffer = () => { + /** + * Return the Buffer instance if it is available falling back + * to one that is compatible where it may not be available + * (like `edge` runtime). + */ + if (typeof Buffer !== "undefined") return Buffer; + const ponyFilledBuffer = require("buffer").Buffer; + return ponyFilledBuffer; +}; +exports.getBuffer = getBuffer; +const isTestEnv = () => { + /** + * Check if test mode is enabled by reading the environment variable. + */ + return exports.getProcess().env.TEST_MODE === "testing"; +}; +exports.isTestEnv = isTestEnv; +const encodeBase64 = (value) => { + /** + * Encode the passed value to base64 and return the encoded value. + */ + return exports.getBuffer().from(value).toString("base64"); +}; +exports.encodeBase64 = encodeBase64; +const decodeBase64 = (value) => { + /** + * Decode the passed value with base64 encoded and return the + * decoded value. + */ + return exports.getBuffer().from(value, "base64").toString(); +}; +exports.decodeBase64 = decodeBase64; +const isBuffer = (obj) => { + /** + * Check if the passed object is a buffer or not. + */ + return exports.getBuffer().isBuffer(obj); +}; +exports.isBuffer = isBuffer; diff --git a/lib/build/version.d.ts b/lib/build/version.d.ts index ba4e3898a..cc8742596 100644 --- a/lib/build/version.d.ts +++ b/lib/build/version.d.ts @@ -1,4 +1,4 @@ // @ts-nocheck -export declare const version = "20.0.2"; +export declare const version = "20.1.2"; export declare const cdiSupported: string[]; export declare const dashboardVersion = "0.13"; diff --git a/lib/build/version.js b/lib/build/version.js index 0d9902d49..fe52b9d4f 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 = "20.0.2"; +exports.version = "20.1.2"; exports.cdiSupported = ["5.1"]; // Note: The actual script import for dashboard uses v{DASHBOARD_VERSION} exports.dashboardVersion = "0.13"; diff --git a/lib/ts/framework/awsLambda/framework.ts b/lib/ts/framework/awsLambda/framework.ts index ae9d247de..137a2dbf2 100644 --- a/lib/ts/framework/awsLambda/framework.ts +++ b/lib/ts/framework/awsLambda/framework.ts @@ -30,7 +30,7 @@ import { COOKIE_HEADER } from "../constants"; import { SessionContainerInterface } from "../../recipe/session/types"; import SuperTokens from "../../supertokens"; import { Framework } from "../types"; -import { parse } from "querystring"; +import STError from "../../error"; export class AWSRequest extends BaseRequest { private event: APIGatewayProxyEventV2 | APIGatewayProxyEvent; @@ -45,8 +45,15 @@ export class AWSRequest extends BaseRequest { if (this.event.body === null || this.event.body === undefined) { return {}; } else { - const parsedUrlEncodedFormData = parse(this.event.body); - return parsedUrlEncodedFormData === undefined ? {} : parsedUrlEncodedFormData; + try { + const parsedUrlEncodedFormData = Object.fromEntries(new URLSearchParams(this.event.body).entries()); + return parsedUrlEncodedFormData === undefined ? {} : parsedUrlEncodedFormData; + } catch (err) { + throw new STError({ + type: STError.BAD_INPUT_ERROR, + message: "API input error: Please make sure to pass valid url encoded form in the request body", + }); + } } }; diff --git a/lib/ts/framework/constants.ts b/lib/ts/framework/constants.ts index 603783285..acd184dec 100644 --- a/lib/ts/framework/constants.ts +++ b/lib/ts/framework/constants.ts @@ -13,3 +13,7 @@ * under the License. */ export const COOKIE_HEADER = "Set-Cookie"; + +// Define error message for brotli decompression not being supported +export const BROTLI_DECOMPRESSION_ERROR_MESSAGE = + "Brotli decompression not implement, Please add a middleware that handles decompression before the SuperTokens middleware."; diff --git a/lib/ts/framework/custom/nodeHeaders.ts b/lib/ts/framework/custom/nodeHeaders.ts index 478ba0e2d..c7849388b 100644 --- a/lib/ts/framework/custom/nodeHeaders.ts +++ b/lib/ts/framework/custom/nodeHeaders.ts @@ -15,7 +15,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI */ -import { types } from "util"; +import { isBoxedPrimitive } from "../utils"; const validateHeaderName = (name) => { if (!/^[\^`\-\w!#$%&'*+.|~]+$/.test(name)) { @@ -64,7 +64,7 @@ export default class Headers extends URLSearchParams { } else if (init == null) { // eslint-disable-line no-eq-null, eqeqeq // No op - } else if (typeof init === "object" && !types.isBoxedPrimitive(init)) { + } else if (typeof init === "object" && !isBoxedPrimitive(init)) { const method = init[Symbol.iterator]; // eslint-disable-next-line no-eq-null, eqeqeq if (method == null) { @@ -79,7 +79,7 @@ export default class Headers extends URLSearchParams { // Note: per spec we have to first exhaust the lists then process them result = [...init] .map((pair) => { - if (typeof pair !== "object" || types.isBoxedPrimitive(pair)) { + if (typeof pair !== "object" || isBoxedPrimitive(pair)) { throw new TypeError("Each header pair must be an iterable object"); } diff --git a/lib/ts/framework/express/framework.ts b/lib/ts/framework/express/framework.ts index 28848b22f..a9f66a1c9 100644 --- a/lib/ts/framework/express/framework.ts +++ b/lib/ts/framework/express/framework.ts @@ -98,7 +98,7 @@ export class ExpressResponse extends BaseResponse { * like response as well as nextjs like response */ this.response.setHeader("Content-Type", "text/html"); - this.response.status(this.statusCode).send(Buffer.from(html)); + this.response.status(this.statusCode).send(html); } }; diff --git a/lib/ts/framework/loopback/framework.ts b/lib/ts/framework/loopback/framework.ts index 21a535ef7..bcb09bfe3 100644 --- a/lib/ts/framework/loopback/framework.ts +++ b/lib/ts/framework/loopback/framework.ts @@ -92,7 +92,7 @@ export class LoopbackResponse extends BaseResponse { sendHTMLResponse = (html: string) => { if (!this.response.writableEnded) { this.response.set("Content-Type", "text/html"); - this.response.status(this.statusCode).send(Buffer.from(html)); + this.response.status(this.statusCode).send(html); } }; diff --git a/lib/ts/framework/utils.ts b/lib/ts/framework/utils.ts index 287a5db18..b8c7db0b5 100644 --- a/lib/ts/framework/utils.ts +++ b/lib/ts/framework/utils.ts @@ -13,17 +13,52 @@ * under the License. */ -import { Readable } from "stream"; import { parse, serialize } from "cookie"; import type { Request, Response } from "express"; import type { IncomingMessage } from "http"; import { ServerResponse } from "http"; import STError from "../error"; import type { HTTPMethod } from "../types"; -import { COOKIE_HEADER } from "./constants"; -import { getFromObjectCaseInsensitive } from "../utils"; +import { BROTLI_DECOMPRESSION_ERROR_MESSAGE, COOKIE_HEADER } from "./constants"; +import { getBuffer, getFromObjectCaseInsensitive, isBuffer } from "../utils"; import contentType from "content-type"; -import inflate from "inflation"; +import pako from "pako"; + +async function inflate(stream: IncomingMessage): Promise { + if (!stream) { + throw new TypeError("argument stream is required"); + } + + const encoding = (stream.headers && stream.headers["content-encoding"]) || "identity"; + + let decompressedData: Uint8Array | string; + + if (encoding === "gzip" || encoding === "deflate") { + const inflator = new pako.Inflate(); + + for await (const chunk of stream) { + inflator.push(chunk, false); + } + + if (inflator.err) { + throw new Error(`Decompression error: ${inflator.msg}`); + } + + decompressedData = inflator.result; + } else if (encoding === "br") { + throw new Error(BROTLI_DECOMPRESSION_ERROR_MESSAGE); + } else { + // Handle identity or unsupported encoding + decompressedData = getBuffer().concat([]); + for await (const chunk of stream) { + decompressedData = getBuffer().concat([decompressedData, chunk]); + } + } + + if (typeof decompressedData === "string") return decompressedData; + + return new TextDecoder().decode(decompressedData); +} export function getCookieValueFromHeaders(headers: any, key: string): string | undefined { if (headers === undefined || headers === null) { @@ -123,8 +158,7 @@ export async function parseJSONBodyFromRequest(req: IncomingMessage) { if (!encoding.startsWith("utf-")) { throw new Error(`unsupported charset ${encoding.toUpperCase()}`); } - const buffer = await getBody(inflate(req)); - const str = buffer.toString(encoding as BufferEncoding); + const str = await inflate(req); if (str.length === 0) { return {}; @@ -137,8 +171,7 @@ export async function parseURLEncodedFormData(req: IncomingMessage) { if (!encoding.startsWith("utf-")) { throw new Error(`unsupported charset ${encoding.toUpperCase()}`); } - const buffer = await getBody(inflate(req)); - const str = buffer.toString(encoding as BufferEncoding); + const str = await inflate(req); let body: any = {}; for (const [key, val] of new URLSearchParams(str).entries()) { @@ -173,13 +206,22 @@ export async function assertThatBodyParserHasBeenUsedForExpressLikeRequest(metho } } else if ( request.body === undefined || - Buffer.isBuffer(request.body) || + isBuffer(request.body) || (Object.keys(request.body).length === 0 && request.readable) ) { try { // parsing it again to make sure that the request is parsed atleast once by a json parser request.body = await parseJSONBodyFromRequest(request); - } catch { + } catch (err) { + // If the error message matches the brotli decompression + // related error, then throw that error. + if ((err as any).message === BROTLI_DECOMPRESSION_ERROR_MESSAGE) { + throw new STError({ + type: STError.BAD_INPUT_ERROR, + message: `API input error: ${BROTLI_DECOMPRESSION_ERROR_MESSAGE}`, + }); + } + throw new STError({ type: STError.BAD_INPUT_ERROR, message: "API input error: Please make sure to pass a valid JSON input in the request body", @@ -205,7 +247,7 @@ export async function assertFormDataBodyParserHasBeenUsedForExpressLikeRequest(r } } else if ( request.body === undefined || - Buffer.isBuffer(request.body) || + isBuffer(request.body) || (Object.keys(request.body).length === 0 && request.readable) ) { try { @@ -255,7 +297,12 @@ export function setHeaderForExpressLikeResponse(res: Response, key: string, valu } } catch (err) { throw new Error( - "Error while setting header with key: " + key + " and value: " + value + "\nError: " + (err.message ?? err) + "Error while setting header with key: " + + key + + " and value: " + + value + + "\nError: " + + ((err as any).message ?? err) ); } } @@ -361,16 +408,8 @@ export function serializeCookieValue( return serialize(key, value, opts); } -// based on https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction -function getBody(request: Readable) { - return new Promise((resolve) => { - const bodyParts: Uint8Array[] = []; - request - .on("data", (chunk) => { - bodyParts.push(chunk); - }) - .on("end", () => { - resolve(Buffer.concat(bodyParts)); - }); - }); +export function isBoxedPrimitive(value: any): boolean { + const boxedTypes = [Boolean, Number, String, Symbol, BigInt]; + + return boxedTypes.some((type) => value instanceof type); } diff --git a/lib/ts/nextjs.ts b/lib/ts/nextjs.ts index 59a4ed42e..266213b22 100644 --- a/lib/ts/nextjs.ts +++ b/lib/ts/nextjs.ts @@ -12,6 +12,7 @@ * License for the specific language governing permissions and limitations * under the License. */ + import { serialize } from "cookie"; import { errorHandler } from "./framework/express"; import { getUserContext } from "./utils"; diff --git a/lib/ts/processState.ts b/lib/ts/processState.ts index 0cbbb0478..3216a268f 100644 --- a/lib/ts/processState.ts +++ b/lib/ts/processState.ts @@ -13,6 +13,8 @@ * under the License. */ +import { isTestEnv } from "./utils"; + export enum PROCESS_STATE { CALLING_SERVICE_IN_VERIFY, CALLING_SERVICE_IN_GET_API_VERSION, @@ -41,7 +43,7 @@ export class ProcessState { } addState = (state: PROCESS_STATE) => { - if (process.env.TEST_MODE === "testing") { + if (isTestEnv()) { this.history.push(state); } }; diff --git a/lib/ts/querier.ts b/lib/ts/querier.ts index 075652d3f..1c8af9b2e 100644 --- a/lib/ts/querier.ts +++ b/lib/ts/querier.ts @@ -12,7 +12,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { doFetch, getLargestVersionFromIntersection } from "./utils"; +import { doFetch, getLargestVersionFromIntersection, isTestEnv } from "./utils"; import { cdiSupported } from "./version"; import NormalisedURLDomain from "./normalisedURLDomain"; import NormalisedURLPath from "./normalisedURLPath"; @@ -112,7 +112,7 @@ export class Querier { }; static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw Error("calling testing function in non testing env"); } Querier.initCalled = false; @@ -120,7 +120,7 @@ export class Querier { } getHostsAliveForTesting = () => { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw Error("calling testing function in non testing env"); } return Querier.hostsAliveForTesting; @@ -607,7 +607,7 @@ export class Querier { ProcessState.getInstance().addState(PROCESS_STATE.CALLING_SERVICE_IN_REQUEST_HELPER); logDebugMessage(`core-call: ${method} ${url}`); let response = await requestFunc(url); - if (process.env.TEST_MODE === "testing") { + if (isTestEnv()) { Querier.hostsAliveForTesting.add(currentDomain + currentBasePath); } diff --git a/lib/ts/recipe/accountlinking/recipe.ts b/lib/ts/recipe/accountlinking/recipe.ts index b57b9329a..177d61def 100644 --- a/lib/ts/recipe/accountlinking/recipe.ts +++ b/lib/ts/recipe/accountlinking/recipe.ts @@ -31,6 +31,7 @@ import { logDebugMessage } from "../../logger"; import EmailVerificationRecipe from "../emailverification/recipe"; import { LoginMethod } from "../../user"; import { SessionContainerInterface } from "../session/types"; +import { isTestEnv } from "../../utils"; export default class Recipe extends RecipeModule { private static instance: Recipe | undefined = undefined; @@ -125,7 +126,7 @@ export default class Recipe extends RecipeModule { } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/ts/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.ts b/lib/ts/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.ts index 83e72e604..c57cc7b0d 100644 --- a/lib/ts/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.ts +++ b/lib/ts/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.ts @@ -19,6 +19,8 @@ import { UserContext } from "../../../../types"; import NormalisedURLDomain from "../../../../normalisedURLDomain"; import NormalisedURLPath from "../../../../normalisedURLPath"; import { doPostRequest } from "../../../../thirdpartyUtils"; +import { DEFAULT_TENANT_ID } from "../../../multitenancy/constants"; +import { encodeBase64 } from "../../../../utils"; export type Response = | { @@ -50,7 +52,7 @@ export default async function createOrUpdateThirdPartyConfig( const mtRecipe = MultitenancyRecipe.getInstance(); const staticProviders = mtRecipe?.staticThirdPartyProviders ?? []; for (const provider of staticProviders.filter( - (provider) => provider.includeInNonPublicTenantsByDefault === true + (provider) => provider.includeInNonPublicTenantsByDefault === true || tenantId === DEFAULT_TENANT_ID )) { await Multitenancy.createOrUpdateThirdPartyConfig( tenantId, @@ -86,7 +88,7 @@ export default async function createOrUpdateThirdPartyConfig( defaultRedirectUrl: providerConfig.clients[0].additionalConfig.redirectURLs[0], forceAuthn: false, encodedRawMetadata: providerConfig.clients[0].additionalConfig.samlXML - ? Buffer.from(providerConfig.clients[0].additionalConfig.samlXML).toString("base64") + ? encodeBase64(providerConfig.clients[0].additionalConfig.samlXML) : "", redirectUrl: JSON.stringify(providerConfig.clients[0].additionalConfig.redirectURLs), metadataUrl: providerConfig.clients[0].additionalConfig.samlURL || "", diff --git a/lib/ts/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.ts b/lib/ts/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.ts index 5de215c9c..c857377d8 100644 --- a/lib/ts/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.ts +++ b/lib/ts/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.ts @@ -18,6 +18,7 @@ import MultitenancyRecipe from "../../../multitenancy/recipe"; import SuperTokensError from "../../../../error"; import { FactorIds } from "../../../multifactorauth"; import { UserContext } from "../../../../types"; +import { DEFAULT_TENANT_ID } from "../../../multitenancy/constants"; export type Response = | { @@ -56,9 +57,11 @@ export default async function deleteThirdPartyConfig( // this means that the tenant was using the static list of providers, we need to add them all before deleting one const mtRecipe = MultitenancyRecipe.getInstance(); const staticProviders = mtRecipe?.staticThirdPartyProviders ?? []; - let staticProviderIds = staticProviders.map((provider) => provider.config.thirdPartyId); - for (const providerId of staticProviderIds) { + for (const provider of staticProviders.filter( + (provider) => provider.includeInNonPublicTenantsByDefault === true || tenantId === DEFAULT_TENANT_ID + )) { + const providerId = provider.config.thirdPartyId; await Multitenancy.createOrUpdateThirdPartyConfig( tenantId, { diff --git a/lib/ts/recipe/dashboard/recipe.ts b/lib/ts/recipe/dashboard/recipe.ts index 4552185ab..1d82f5753 100644 --- a/lib/ts/recipe/dashboard/recipe.ts +++ b/lib/ts/recipe/dashboard/recipe.ts @@ -94,6 +94,7 @@ import updateTenantFirstFactor from "./api/multitenancy/updateTenantFirstFactor" import updateTenantSecondaryFactor from "./api/multitenancy/updateTenantSecondaryFactor"; import updateTenantCoreConfig from "./api/multitenancy/updateTenantCoreConfig"; import getThirdPartyConfig from "./api/multitenancy/getThirdPartyConfig"; +import { isTestEnv } from "../../utils"; export default class Recipe extends RecipeModule { private static instance: Recipe | undefined = undefined; @@ -142,7 +143,7 @@ export default class Recipe extends RecipeModule { } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/ts/recipe/emailpassword/api/implementation.ts b/lib/ts/recipe/emailpassword/api/implementation.ts index 2e35c5edf..e08c0ea09 100644 --- a/lib/ts/recipe/emailpassword/api/implementation.ts +++ b/lib/ts/recipe/emailpassword/api/implementation.ts @@ -816,7 +816,11 @@ export default function getAPIImplementation(): APIInterface { }); if (postAuthChecks.status !== "OK") { - return AuthUtils.getErrorStatusResponseWithReason(postAuthChecks, errorCodeMap, "SIGN_UP_NOT_ALLOWED"); + // It should never actually come here, but we do it cause of consistency. + // If it does come here (in case there is a bug), it would make this func throw + // anyway, cause there is no SIGN_IN_NOT_ALLOWED in the errorCodeMap. + AuthUtils.getErrorStatusResponseWithReason(postAuthChecks, errorCodeMap, "SIGN_UP_NOT_ALLOWED"); + throw new Error("This should never happen"); } return { diff --git a/lib/ts/recipe/emailpassword/api/utils.ts b/lib/ts/recipe/emailpassword/api/utils.ts index ae944e1f9..23023ae1f 100644 --- a/lib/ts/recipe/emailpassword/api/utils.ts +++ b/lib/ts/recipe/emailpassword/api/utils.ts @@ -82,12 +82,12 @@ function newBadRequestError(message: string) { }); } -// We check that the number of fields in input and config form field is the same. -// We check that each item in the config form field is also present in the input form field +// We check to make sure we are validating each required form field +// and also validate optional form fields only when present async function validateFormOrThrowError( inputs: { id: string; - value: string; + value: any | undefined; }[], configFormFields: NormalisedFormField[], tenantId: string, @@ -95,37 +95,45 @@ async function validateFormOrThrowError( ) { let validationErrors: { id: string; error: string }[] = []; - if (configFormFields.length !== inputs.length) { - throw newBadRequestError("Are you sending too many / too few formFields?"); + // Throw an error if the user has provided more than the allowed + // formFields. + if (inputs.length > configFormFields.length) { + throw newBadRequestError("Are you sending too many formFields?"); } - // Loop through all form fields. - for (let i = 0; i < configFormFields.length; i++) { - const field = configFormFields[i]; + // NOTE: We don't need to check for required fields at all as that will + // be picked up in the below codeblock. - // Find corresponding input value. - const input = inputs.find((i) => i.id === field.id); + for (const formField of configFormFields) { + const input = inputs.find((input) => input.id === formField.id); - // Absent or not optional empty field - if (input === undefined || (input.value === "" && !field.optional)) { + // Add the not optional error if input is not passed + // and the field is not optional. + const isValidInput = + !!input && + ((typeof input.value === "string" + ? input.value.length > 0 + : input.value !== null && typeof input.value !== "undefined") || + (typeof input.value === "object" && Object.values(input.value).length > 0)); + if (!formField.optional && !isValidInput) { validationErrors.push({ error: "Field is not optional", - id: field.id, + id: formField.id, }); - } else { - // Otherwise, use validate function. - const error = await field.validate(input.value, tenantId, userContext); - // If error, add it. - if (error !== undefined) { + } + + if (isValidInput) { + const error = await formField.validate(input!.value, tenantId, userContext); + if (error) { validationErrors.push({ error, - id: field.id, + id: formField.id, }); } } } - if (validationErrors.length !== 0) { + if (validationErrors.length > 0) { throw new STError({ type: STError.FIELD_ERROR, payload: validationErrors, diff --git a/lib/ts/recipe/emailpassword/passwordResetFunctions.ts b/lib/ts/recipe/emailpassword/passwordResetFunctions.ts index d935f07be..ca23af864 100644 --- a/lib/ts/recipe/emailpassword/passwordResetFunctions.ts +++ b/lib/ts/recipe/emailpassword/passwordResetFunctions.ts @@ -14,7 +14,7 @@ */ import { NormalisedAppinfo } from "../../types"; -import { postWithFetch } from "../../utils"; +import { isTestEnv, postWithFetch } from "../../utils"; export async function createAndSendEmailUsingSupertokensService( appInfo: NormalisedAppinfo, @@ -25,7 +25,7 @@ export async function createAndSendEmailUsingSupertokensService( passwordResetURLWithToken: string ) { // related issue: https://github.com/supertokens/supertokens-node/issues/38 - if (process.env.TEST_MODE === "testing") { + if (isTestEnv()) { return; } diff --git a/lib/ts/recipe/emailpassword/recipe.ts b/lib/ts/recipe/emailpassword/recipe.ts index 3d899d77d..f6f98431d 100644 --- a/lib/ts/recipe/emailpassword/recipe.ts +++ b/lib/ts/recipe/emailpassword/recipe.ts @@ -31,7 +31,7 @@ import signUpAPI from "./api/signup"; import signInAPI from "./api/signin"; import generatePasswordResetTokenAPI from "./api/generatePasswordResetToken"; import passwordResetAPI from "./api/passwordReset"; -import { send200Response } from "../../utils"; +import { isTestEnv, send200Response } from "../../utils"; import emailExistsAPI from "./api/emailExists"; import RecipeImplementation from "./recipeImplementation"; import APIImplementation from "./api/implementation"; @@ -244,7 +244,7 @@ export default class Recipe extends RecipeModule { } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/ts/recipe/emailverification/emailVerificationFunctions.ts b/lib/ts/recipe/emailverification/emailVerificationFunctions.ts index ff8dc9ec1..e0ab293a7 100644 --- a/lib/ts/recipe/emailverification/emailVerificationFunctions.ts +++ b/lib/ts/recipe/emailverification/emailVerificationFunctions.ts @@ -15,14 +15,14 @@ import { UserEmailInfo } from "./types"; import { NormalisedAppinfo } from "../../types"; -import { postWithFetch } from "../../utils"; +import { isTestEnv, postWithFetch } from "../../utils"; export async function createAndSendEmailUsingSupertokensService( appInfo: NormalisedAppinfo, user: UserEmailInfo, emailVerifyURLWithToken: string ) { - if (process.env.TEST_MODE === "testing") { + if (isTestEnv()) { return; } await postWithFetch( diff --git a/lib/ts/recipe/emailverification/recipe.ts b/lib/ts/recipe/emailverification/recipe.ts index 37378d499..d7ad46e38 100644 --- a/lib/ts/recipe/emailverification/recipe.ts +++ b/lib/ts/recipe/emailverification/recipe.ts @@ -38,6 +38,7 @@ import Session from "../session"; import { getUser } from "../.."; import RecipeUserId from "../../recipeUserId"; import { logDebugMessage } from "../../logger"; +import { isTestEnv } from "../../utils"; export default class Recipe extends RecipeModule { private static instance: Recipe | undefined = undefined; @@ -125,7 +126,7 @@ export default class Recipe extends RecipeModule { } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/ts/recipe/jwt/recipe.ts b/lib/ts/recipe/jwt/recipe.ts index 5e7006a06..2abb9c1ec 100644 --- a/lib/ts/recipe/jwt/recipe.ts +++ b/lib/ts/recipe/jwt/recipe.ts @@ -21,6 +21,7 @@ import normalisedURLPath from "../../normalisedURLPath"; import { Querier } from "../../querier"; import RecipeModule from "../../recipeModule"; import { APIHandled, HTTPMethod, NormalisedAppinfo, RecipeListFunction, UserContext } from "../../types"; +import { isTestEnv } from "../../utils"; import getJWKS from "./api/getJWKS"; import APIImplementation from "./api/implementation"; import { GET_JWKS_API } from "./constants"; @@ -76,7 +77,7 @@ export default class Recipe extends RecipeModule { } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/ts/recipe/multifactorauth/recipe.ts b/lib/ts/recipe/multifactorauth/recipe.ts index 9294987af..f39435498 100644 --- a/lib/ts/recipe/multifactorauth/recipe.ts +++ b/lib/ts/recipe/multifactorauth/recipe.ts @@ -42,6 +42,7 @@ import RecipeUserId from "../../recipeUserId"; import MultitenancyRecipe from "../multitenancy/recipe"; import { Querier } from "../../querier"; import { TenantConfig } from "../multitenancy/types"; +import { isTestEnv } from "../../utils"; export default class Recipe extends RecipeModule { private static instance: Recipe | undefined = undefined; @@ -128,7 +129,7 @@ export default class Recipe extends RecipeModule { } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/ts/recipe/multitenancy/recipe.ts b/lib/ts/recipe/multitenancy/recipe.ts index e606c521a..5a87ec40b 100644 --- a/lib/ts/recipe/multitenancy/recipe.ts +++ b/lib/ts/recipe/multitenancy/recipe.ts @@ -30,6 +30,7 @@ import { AllowedDomainsClaim } from "./allowedDomainsClaim"; import { APIInterface, RecipeInterface, TypeInput, TypeNormalisedInput } from "./types"; import { validateAndNormaliseUserInput } from "./utils"; import loginMethodsAPI from "./api/loginMethods"; +import { isTestEnv } from "../../utils"; export default class Recipe extends RecipeModule { private static instance: Recipe | undefined = undefined; @@ -102,7 +103,7 @@ export default class Recipe extends RecipeModule { } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/ts/recipe/multitenancy/utils.ts b/lib/ts/recipe/multitenancy/utils.ts index cd18005a6..49642b4f3 100644 --- a/lib/ts/recipe/multitenancy/utils.ts +++ b/lib/ts/recipe/multitenancy/utils.ts @@ -64,11 +64,6 @@ export const isValidFirstFactor = async function ( logDebugMessage(`isValidFirstFactor got ${tenantConfig.firstFactors?.join(", ")} from tenant config`); logDebugMessage(`isValidFirstFactor got ${firstFactorsFromMFA} from MFA`); - logDebugMessage( - `isValidFirstFactor tenantconfig enables: ${Object.keys(tenantConfig).filter( - (k) => (tenantConfig as any)[k]?.enabled - )}` - ); // first factors configured in core is prioritised over the ones configured statically let configuredFirstFactors: string[] | undefined = diff --git a/lib/ts/recipe/openid/recipe.ts b/lib/ts/recipe/openid/recipe.ts index 1726f9c43..ad8c93086 100644 --- a/lib/ts/recipe/openid/recipe.ts +++ b/lib/ts/recipe/openid/recipe.ts @@ -26,6 +26,7 @@ import APIImplementation from "./api/implementation"; import NormalisedURLPath from "../../normalisedURLPath"; import { GET_DISCOVERY_CONFIG_URL } from "./constants"; import getOpenIdDiscoveryConfiguration from "./api/getOpenIdDiscoveryConfiguration"; +import { isTestEnv } from "../../utils"; export default class OpenIdRecipe extends RecipeModule { static RECIPE_ID = "openid"; @@ -74,7 +75,7 @@ export default class OpenIdRecipe extends RecipeModule { } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw new Error("calling testing function in non testing env"); } OpenIdRecipe.instance = undefined; diff --git a/lib/ts/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.ts b/lib/ts/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.ts index 7c0c7fb15..3ee2fc5ac 100644 --- a/lib/ts/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.ts +++ b/lib/ts/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.ts @@ -15,7 +15,7 @@ import { TypePasswordlessEmailDeliveryInput } from "../../../types"; import { EmailDeliveryInterface } from "../../../../../ingredients/emaildelivery/types"; import { NormalisedAppinfo, UserContext } from "../../../../../types"; -import { postWithFetch } from "../../../../../utils"; +import { isTestEnv, postWithFetch } from "../../../../../utils"; async function createAndSendEmailUsingSupertokensService(input: { appInfo: NormalisedAppinfo; @@ -28,7 +28,7 @@ async function createAndSendEmailUsingSupertokensService(input: { codeLifetime: number; isFirstFactor: boolean; }): Promise { - if (process.env.TEST_MODE === "testing") { + if (isTestEnv()) { return; } const result = await postWithFetch( diff --git a/lib/ts/recipe/passwordless/recipe.ts b/lib/ts/recipe/passwordless/recipe.ts index 5ec867387..8ad1c11c4 100644 --- a/lib/ts/recipe/passwordless/recipe.ts +++ b/lib/ts/recipe/passwordless/recipe.ts @@ -48,6 +48,7 @@ import { User } from "../../user"; import { isFakeEmail } from "../thirdparty/utils"; import { FactorIds } from "../multifactorauth"; import { SessionContainerInterface } from "../session/types"; +import { isTestEnv } from "../../utils"; export default class Recipe extends RecipeModule { private static instance: Recipe | undefined = undefined; @@ -447,7 +448,7 @@ export default class Recipe extends RecipeModule { } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/ts/recipe/passwordless/recipeImplementation.ts b/lib/ts/recipe/passwordless/recipeImplementation.ts index df4ad34c4..1732a61b8 100644 --- a/lib/ts/recipe/passwordless/recipeImplementation.ts +++ b/lib/ts/recipe/passwordless/recipeImplementation.ts @@ -40,14 +40,6 @@ export default function getRecipeInterface(querier: Querier): RecipeInterface { response.user = new User(response.user); response.recipeUserId = new RecipeUserId(response.recipeUserId); - if (response.status !== "OK") { - return response; - } - - if (response.status !== "OK") { - return response; - } - // Attempt account linking (this is a sign up) let updatedUser = response.user; @@ -65,10 +57,6 @@ export default function getRecipeInterface(querier: Querier): RecipeInterface { } updatedUser = linkResult.user; - if (updatedUser === undefined) { - throw new Error("Should never come here."); - } - response.user = updatedUser; return { diff --git a/lib/ts/recipe/session/cookieAndHeaders.ts b/lib/ts/recipe/session/cookieAndHeaders.ts index 8d3165adf..206c7cfbf 100644 --- a/lib/ts/recipe/session/cookieAndHeaders.ts +++ b/lib/ts/recipe/session/cookieAndHeaders.ts @@ -16,6 +16,7 @@ import { HEADER_RID } from "../../constants"; import type { BaseRequest, BaseResponse } from "../../framework"; import { logDebugMessage } from "../../logger"; import { UserContext } from "../../types"; +import { encodeBase64 } from "../../utils"; import { availableTokenTransferMethods } from "./constants"; import SessionError from "./error"; import { TokenTransferMethod, TokenType, TypeNormalisedInput } from "./types"; @@ -83,7 +84,7 @@ export function buildFrontToken(userId: string, atExpiry: number, accessTokenPay ate: atExpiry, up: accessTokenPayload, }; - return Buffer.from(JSON.stringify(tokenInfo)).toString("base64"); + return encodeBase64(JSON.stringify(tokenInfo)); } export function setFrontTokenInHeaders(res: BaseResponse, frontToken: string) { diff --git a/lib/ts/recipe/session/jwt.ts b/lib/ts/recipe/session/jwt.ts index c89841bc1..32079b6bb 100644 --- a/lib/ts/recipe/session/jwt.ts +++ b/lib/ts/recipe/session/jwt.ts @@ -14,22 +14,23 @@ */ import { logDebugMessage } from "../../logger"; +import { decodeBase64, encodeBase64 } from "../../utils"; const HEADERS = new Set([ - Buffer.from( + encodeBase64( JSON.stringify({ alg: "RS256", typ: "JWT", version: "1", }) - ).toString("base64"), - Buffer.from( + ), + encodeBase64( JSON.stringify({ alg: "RS256", typ: "JWT", version: "2", }) - ).toString("base64"), + ), ]); export type ParsedJWTInfo = { @@ -56,7 +57,7 @@ export function parseJWTWithoutSignatureVerification(jwt: string): ParsedJWTInfo // V2 or older tokens did not save the key id; // checking header if (!HEADERS.has(splittedInput[0])) { - const parsedHeader = JSON.parse(Buffer.from(splittedInput[0], "base64").toString()); + const parsedHeader = JSON.parse(decodeBase64(splittedInput[0])); if (parsedHeader.version !== undefined) { // We have to ensure version is a string, otherwise Number.parseInt can have unexpected results @@ -88,7 +89,7 @@ export function parseJWTWithoutSignatureVerification(jwt: string): ParsedJWTInfo header: splittedInput[0], // Ideally we would only parse this after the signature verification is done. // We do this at the start, since we want to check if a token can be a supertokens access token or not - payload: JSON.parse(Buffer.from(splittedInput[1], "base64").toString()), + payload: JSON.parse(decodeBase64(splittedInput[1])), signature: splittedInput[2], }; } diff --git a/lib/ts/recipe/session/recipe.ts b/lib/ts/recipe/session/recipe.ts index 57a7b42be..5e9178167 100644 --- a/lib/ts/recipe/session/recipe.ts +++ b/lib/ts/recipe/session/recipe.ts @@ -44,6 +44,7 @@ import OpenIdRecipe from "../openid/recipe"; import { logDebugMessage } from "../../logger"; import { resetCombinedJWKS } from "../../combinedRemoteJWKSet"; import { getAccessTokenFromRequest } from "./sessionRequestFunctions"; +import { isTestEnv } from "../../utils"; // For Express export default class SessionRecipe extends RecipeModule { @@ -123,7 +124,7 @@ export default class SessionRecipe extends RecipeModule { } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw new Error("calling testing function in non testing env"); } SessionRecipe.instance = undefined; diff --git a/lib/ts/recipe/session/recipeImplementation.ts b/lib/ts/recipe/session/recipeImplementation.ts index 0e8e67040..359c843ee 100644 --- a/lib/ts/recipe/session/recipeImplementation.ts +++ b/lib/ts/recipe/session/recipeImplementation.ts @@ -22,6 +22,7 @@ import SessionError from "./error"; import RecipeUserId from "../../recipeUserId"; import { DEFAULT_TENANT_ID } from "../multitenancy/constants"; import { protectedProps } from "./constants"; +import { isTestEnv } from "../../utils"; export type Helpers = { querier: Querier; @@ -570,7 +571,7 @@ export default function getRecipeInterface( getRecipeImpl: getRecipeImplAfterOverrides, }; - if (process.env.TEST_MODE === "testing") { + if (isTestEnv()) { // testing mode, we add some of the help functions to the obj (obj as any).helpers = helpers; } diff --git a/lib/ts/recipe/thirdparty/api/implementation.ts b/lib/ts/recipe/thirdparty/api/implementation.ts index 889ba3685..1b633a3e6 100644 --- a/lib/ts/recipe/thirdparty/api/implementation.ts +++ b/lib/ts/recipe/thirdparty/api/implementation.ts @@ -3,6 +3,7 @@ import EmailVerification from "../../emailverification"; import EmailVerificationRecipe from "../../emailverification/recipe"; import { AuthUtils } from "../../../authUtils"; import { logDebugMessage } from "../../../logger"; +import { decodeBase64 } from "../../../utils"; export default function getAPIInterface(): APIInterface { return { @@ -214,7 +215,7 @@ export default function getAPIInterface(): APIInterface { appleRedirectHandlerPOST: async function ({ formPostInfoFromProvider, options }): Promise { const stateInBase64 = formPostInfoFromProvider.state; - const state = Buffer.from(stateInBase64, "base64").toString(); + const state = decodeBase64(stateInBase64); const stateObj = JSON.parse(state); const redirectURI = stateObj.frontendRedirectURI; diff --git a/lib/ts/recipe/thirdparty/providers/activeDirectory.ts b/lib/ts/recipe/thirdparty/providers/activeDirectory.ts index 410294042..458837465 100644 --- a/lib/ts/recipe/thirdparty/providers/activeDirectory.ts +++ b/lib/ts/recipe/thirdparty/providers/activeDirectory.ts @@ -29,18 +29,14 @@ export default function ActiveDirectory(input: ProviderInput): TypeProvider { originalImplementation.getConfigForClientType = async function ({ clientType, userContext }) { const config = await oGetConfig({ clientType, userContext }); - if (config.additionalConfig == undefined || config.additionalConfig.directoryId == undefined) { - if (config.oidcDiscoveryEndpoint === undefined) { - throw new Error( - "Please provide the directoryId in the additionalConfig of the Active Directory provider." - ); - } - } else { + if (config.additionalConfig !== undefined && config.additionalConfig.directoryId !== undefined) { config.oidcDiscoveryEndpoint = `https://login.microsoftonline.com/${config.additionalConfig.directoryId}/v2.0/.well-known/openid-configuration`; } - // The config could be coming from core where we didn't add the well-known previously - config.oidcDiscoveryEndpoint = normaliseOIDCEndpointToIncludeWellKnown(config.oidcDiscoveryEndpoint); + if (config.oidcDiscoveryEndpoint !== undefined) { + // The config could be coming from core where we didn't add the well-known previously + config.oidcDiscoveryEndpoint = normaliseOIDCEndpointToIncludeWellKnown(config.oidcDiscoveryEndpoint); + } if (config.scope === undefined) { config.scope = ["openid", "email"]; diff --git a/lib/ts/recipe/thirdparty/providers/github.ts b/lib/ts/recipe/thirdparty/providers/github.ts index e1f218143..445cc992f 100644 --- a/lib/ts/recipe/thirdparty/providers/github.ts +++ b/lib/ts/recipe/thirdparty/providers/github.ts @@ -12,6 +12,7 @@ * License for the specific language governing permissions and limitations * under the License. */ +import { encodeBase64 } from "../../../utils"; import { ProviderInput, TypeProvider, UserInfo } from "../types"; import NewProvider from "./custom"; import { doGetRequest, doPostRequest } from "../../../thirdpartyUtils"; @@ -60,9 +61,9 @@ export default function Github(input: ProviderInput): TypeProvider { if (input.config.validateAccessToken === undefined) { input.config.validateAccessToken = async ({ accessToken, clientConfig }) => { - const basicAuthToken = Buffer.from( + const basicAuthToken = encodeBase64( `${clientConfig.clientId}:${clientConfig.clientSecret === undefined ? "" : clientConfig.clientSecret}` - ).toString("base64"); + ); const applicationResponse = await doPostRequest( `https://api.github.com/applications/${clientConfig.clientId}/token`, diff --git a/lib/ts/recipe/thirdparty/providers/okta.ts b/lib/ts/recipe/thirdparty/providers/okta.ts index c1eae03eb..f7834ee34 100644 --- a/lib/ts/recipe/thirdparty/providers/okta.ts +++ b/lib/ts/recipe/thirdparty/providers/okta.ts @@ -30,19 +30,17 @@ export default function Okta(input: ProviderInput): TypeProvider { originalImplementation.getConfigForClientType = async function (input) { const config = await oGetConfig(input); - if (config.additionalConfig == undefined || config.additionalConfig.oktaDomain == undefined) { - if (config.oidcDiscoveryEndpoint === undefined) { - throw new Error("Please provide the oktaDomain in the additionalConfig of the Okta provider."); - } - } else { + if (config.additionalConfig !== undefined && config.additionalConfig.oktaDomain !== undefined) { const oidcDomain = new NormalisedURLDomain(config.additionalConfig.oktaDomain); const oidcPath = new NormalisedURLPath("/.well-known/openid-configuration"); config.oidcDiscoveryEndpoint = oidcDomain.getAsStringDangerous() + oidcPath.getAsStringDangerous(); } - // The config could be coming from core where we didn't add the well-known previously - config.oidcDiscoveryEndpoint = normaliseOIDCEndpointToIncludeWellKnown(config.oidcDiscoveryEndpoint); + if (config.oidcDiscoveryEndpoint !== undefined) { + // The config could be coming from core where we didn't add the well-known previously + config.oidcDiscoveryEndpoint = normaliseOIDCEndpointToIncludeWellKnown(config.oidcDiscoveryEndpoint); + } if (config.scope === undefined) { config.scope = ["openid", "email"]; diff --git a/lib/ts/recipe/thirdparty/providers/twitter.ts b/lib/ts/recipe/thirdparty/providers/twitter.ts index 083cf821f..fec417766 100644 --- a/lib/ts/recipe/thirdparty/providers/twitter.ts +++ b/lib/ts/recipe/thirdparty/providers/twitter.ts @@ -13,6 +13,7 @@ * under the License. */ import { logDebugMessage } from "../../../logger"; +import { encodeBase64 } from "../../../utils"; import { ProviderInput, TypeProvider } from "../types"; import NewProvider, { DEV_OAUTH_REDIRECT_URL, @@ -80,10 +81,7 @@ export default function Twitter(input: ProviderInput): TypeProvider { } /* Transformation needed for dev keys END */ - const basicAuthToken = Buffer.from( - `${clientId}:${originalImplementation.config.clientSecret}`, - "utf8" - ).toString("base64"); + const basicAuthToken = encodeBase64(`${clientId}:${originalImplementation.config.clientSecret}`); const twitterOauthTokenParams = { grant_type: "authorization_code", client_id: clientId, diff --git a/lib/ts/recipe/thirdparty/providers/utils.ts b/lib/ts/recipe/thirdparty/providers/utils.ts index a82280d32..56544f48f 100644 --- a/lib/ts/recipe/thirdparty/providers/utils.ts +++ b/lib/ts/recipe/thirdparty/providers/utils.ts @@ -1,7 +1,103 @@ +import * as jose from "jose"; import { ProviderConfigForClientType } from "../types"; import { getOIDCDiscoveryInfo } from "../../../thirdpartyUtils"; import NormalisedURLDomain from "../../../normalisedURLDomain"; import NormalisedURLPath from "../../../normalisedURLPath"; +import { logDebugMessage } from "../../../logger"; +import { doFetch } from "../../../utils"; + +export async function doGetRequest( + url: string, + queryParams?: { [key: string]: string }, + headers?: { [key: string]: string } +): Promise<{ + jsonResponse: Record | undefined; + status: number; + stringResponse: string; +}> { + logDebugMessage( + `GET request to ${url}, with query params ${JSON.stringify(queryParams)} and headers ${JSON.stringify(headers)}` + ); + if (headers?.["Accept"] === undefined) { + headers = { + ...headers, + Accept: "application/json", // few providers like github don't send back json response by default + }; + } + const finalURL = new URL(url); + finalURL.search = new URLSearchParams(queryParams).toString(); + let response = await doFetch(finalURL.toString(), { + headers: headers, + }); + + const stringResponse = await response.text(); + let jsonResponse: Record | undefined = undefined; + + logDebugMessage(`Received response with status ${response.status} and body ${stringResponse}`); + + if (response.status < 400) { + jsonResponse = JSON.parse(stringResponse); + } + + return { + stringResponse, + status: response.status, + jsonResponse, + }; +} + +export async function doPostRequest( + url: string, + params: { [key: string]: any }, + headers?: { [key: string]: string } +): Promise<{ + jsonResponse: Record | undefined; + status: number; + stringResponse: string; +}> { + if (headers === undefined) { + headers = {}; + } + + headers["Content-Type"] = "application/x-www-form-urlencoded"; + headers["Accept"] = "application/json"; // few providers like github don't send back json response by default + + logDebugMessage( + `POST request to ${url}, with params ${JSON.stringify(params)} and headers ${JSON.stringify(headers)}` + ); + + const body = new URLSearchParams(params).toString(); + let response = await doFetch(url, { + method: "POST", + body, + headers, + }); + + const stringResponse = await response.text(); + let jsonResponse: Record | undefined = undefined; + + logDebugMessage(`Received response with status ${response.status} and body ${stringResponse}`); + + if (response.status < 400) { + jsonResponse = JSON.parse(stringResponse); + } + + return { + stringResponse, + status: response.status, + jsonResponse, + }; +} + +export async function verifyIdTokenFromJWKSEndpointAndGetPayload( + idToken: string, + jwks: jose.JWTVerifyGetKey, + otherOptions: jose.JWTVerifyOptions +): Promise { + const { payload } = await jose.jwtVerify(idToken, jwks, otherOptions); + + return payload; +} export async function discoverOIDCEndpoints(config: ProviderConfigForClientType): Promise { if (config.oidcDiscoveryEndpoint !== undefined) { diff --git a/lib/ts/recipe/thirdparty/recipe.ts b/lib/ts/recipe/thirdparty/recipe.ts index 1c342df13..d21ac782a 100644 --- a/lib/ts/recipe/thirdparty/recipe.ts +++ b/lib/ts/recipe/thirdparty/recipe.ts @@ -32,6 +32,7 @@ import appleRedirectHandler from "./api/appleRedirect"; import OverrideableBuilder from "supertokens-js-override"; import { PostSuperTokensInitCallbacks } from "../../postSuperTokensInitCallbacks"; import { FactorIds } from "../multifactorauth"; +import { isTestEnv } from "../../utils"; export default class Recipe extends RecipeModule { private static instance: Recipe | undefined = undefined; @@ -110,7 +111,7 @@ export default class Recipe extends RecipeModule { } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/ts/recipe/totp/recipe.ts b/lib/ts/recipe/totp/recipe.ts index d1f776927..3c0e0bbaf 100644 --- a/lib/ts/recipe/totp/recipe.ts +++ b/lib/ts/recipe/totp/recipe.ts @@ -40,6 +40,7 @@ import removeDeviceAPI from "./api/removeDevice"; import { User } from "../.."; import { PostSuperTokensInitCallbacks } from "../../postSuperTokensInitCallbacks"; import MultiFactorAuthRecipe from "../multifactorauth/recipe"; +import { isTestEnv } from "../../utils"; export default class Recipe extends RecipeModule { private static instance: Recipe | undefined = undefined; @@ -118,7 +119,7 @@ export default class Recipe extends RecipeModule { } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/ts/recipe/usermetadata/recipe.ts b/lib/ts/recipe/usermetadata/recipe.ts index e292ceb22..5cac41875 100644 --- a/lib/ts/recipe/usermetadata/recipe.ts +++ b/lib/ts/recipe/usermetadata/recipe.ts @@ -20,6 +20,7 @@ import normalisedURLPath from "../../normalisedURLPath"; import { Querier } from "../../querier"; import RecipeModule from "../../recipeModule"; import { APIHandled, HTTPMethod, NormalisedAppinfo, RecipeListFunction } from "../../types"; +import { isTestEnv } from "../../utils"; import RecipeImplementation from "./recipeImplementation"; import { RecipeInterface, TypeInput, TypeNormalisedInput } from "./types"; @@ -68,7 +69,7 @@ export default class Recipe extends RecipeModule { } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/ts/recipe/userroles/recipe.ts b/lib/ts/recipe/userroles/recipe.ts index 36befb4f2..be699c436 100644 --- a/lib/ts/recipe/userroles/recipe.ts +++ b/lib/ts/recipe/userroles/recipe.ts @@ -32,6 +32,7 @@ import { UserRoleClaim } from "./userRoleClaim"; import { PermissionClaim } from "./permissionClaim"; import { User } from "../../user"; import { getSessionInformation } from "../session"; +import { isTestEnv } from "../../utils"; export default class Recipe extends RecipeModule { static RECIPE_ID = "userroles"; @@ -192,7 +193,7 @@ export default class Recipe extends RecipeModule { } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw new Error("calling testing function in non testing env"); } Recipe.instance = undefined; diff --git a/lib/ts/supertokens.ts b/lib/ts/supertokens.ts index 9f5df3e0b..6829e9925 100644 --- a/lib/ts/supertokens.ts +++ b/lib/ts/supertokens.ts @@ -20,6 +20,7 @@ import { normaliseHttpMethod, sendNon200ResponseWithMessage, getRidFromHeader, + isTestEnv, } from "./utils"; import { Querier } from "./querier"; import RecipeModule from "./recipeModule"; @@ -150,7 +151,7 @@ export default class SuperTokens { if (!oauth2Found) { this.recipeModules.push(OAuth2ProviderRecipe.init()(this.appInfo, this.isInServerlessEnv)); } - this.telemetryEnabled = config.telemetry === undefined ? process.env.TEST_MODE !== "testing" : config.telemetry; + this.telemetryEnabled = config.telemetry === undefined ? !isTestEnv() : config.telemetry; } static init(config: TypeInput) { @@ -161,7 +162,7 @@ export default class SuperTokens { } static reset() { - if (process.env.TEST_MODE !== "testing") { + if (!isTestEnv()) { throw new Error("calling testing function in non testing env"); } Querier.reset(); diff --git a/lib/ts/utils.ts b/lib/ts/utils.ts index 144fd04a9..074bdb96e 100644 --- a/lib/ts/utils.ts +++ b/lib/ts/utils.ts @@ -451,3 +451,54 @@ export function transformObjectKeys(obj: { [key: string]: any }, caseType: "s return result; }, {} as any) as T; } + +export const getProcess = () => { + /** + * Return the process instance if it is available falling back + * to one that is compatible where process may not be available + * (like `edge` runtime). + */ + if (typeof process !== "undefined") return process; + const ponyFilledProcess = require("process"); + return ponyFilledProcess; +}; + +export const getBuffer = () => { + /** + * Return the Buffer instance if it is available falling back + * to one that is compatible where it may not be available + * (like `edge` runtime). + */ + if (typeof Buffer !== "undefined") return Buffer; + const ponyFilledBuffer = require("buffer").Buffer; + return ponyFilledBuffer; +}; + +export const isTestEnv = (): boolean => { + /** + * Check if test mode is enabled by reading the environment variable. + */ + return getProcess().env.TEST_MODE === "testing"; +}; + +export const encodeBase64 = (value: string): string => { + /** + * Encode the passed value to base64 and return the encoded value. + */ + return getBuffer().from(value).toString("base64"); +}; + +export const decodeBase64 = (value: string): string => { + /** + * Decode the passed value with base64 encoded and return the + * decoded value. + */ + return getBuffer().from(value, "base64").toString(); +}; + +export const isBuffer = (obj: any): boolean => { + /** + * Check if the passed object is a buffer or not. + */ + return getBuffer().isBuffer(obj); +}; diff --git a/lib/ts/version.ts b/lib/ts/version.ts index 22817ea60..9dd48baaf 100644 --- a/lib/ts/version.ts +++ b/lib/ts/version.ts @@ -12,7 +12,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -export const version = "20.0.2"; +export const version = "20.1.2"; export const cdiSupported = ["5.1"]; diff --git a/package-lock.json b/package-lock.json index 238781e13..083fc9cf1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,23 +1,25 @@ { "name": "supertokens-node", - "version": "20.0.2", + "version": "20.1.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "supertokens-node", - "version": "20.0.2", + "version": "20.1.2", "license": "Apache-2.0", "dependencies": { + "buffer": "^6.0.3", "content-type": "^1.0.5", "cookie": "0.4.0", "cross-fetch": "^3.1.6", "debug": "^4.3.3", - "inflation": "^2.0.0", "jose": "^4.13.1", "libphonenumber-js": "^1.9.44", "nodemailer": "^6.7.2", + "pako": "^2.1.0", "pkce-challenge": "^3.0.0", + "process": "^0.11.10", "psl": "1.8.0", "set-cookie-parser": "^2.6.0", "supertokens-js-override": "^0.0.4", @@ -30,6 +32,7 @@ "@loopback/repository": "3.7.1", "@loopback/rest": "9.3.0", "@types/aws-lambda": "8.10.77", + "@types/brotli": "^1.3.4", "@types/co-body": "^5.1.1", "@types/content-type": "^1.1.5", "@types/cookie": "0.3.3", @@ -39,6 +42,7 @@ "@types/koa": "^2.13.4", "@types/koa-bodyparser": "^4.3.3", "@types/nodemailer": "^6.4.4", + "@types/pako": "^2.0.3", "@types/psl": "1.1.0", "@types/set-cookie-parser": "^2.4.9", "@types/validator": "10.11.0", @@ -1435,6 +1439,15 @@ "@types/node": "*" } }, + "node_modules/@types/brotli": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/brotli/-/brotli-1.3.4.tgz", + "integrity": "sha512-cKYjgaS2DMdCKF7R0F5cgx1nfBYObN2ihIuPGQ4/dlIY6RpV7OWNwe9L8V4tTVKL2eZqOkNM9FM/rgTvLf4oXw==", + "dev": true, + "dependencies": { + "@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", @@ -1677,6 +1690,12 @@ "@types/node": "*" } }, + "node_modules/@types/pako": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.3.tgz", + "integrity": "sha512-bq0hMV9opAcrmE0Byyo0fY3Ew4tgOevJmQ9grUhpXQhYfyLJ1Kqg3P33JT5fdbT2AjeAjR51zqqVjAL/HMkx7Q==", + "dev": true + }, "node_modules/@types/psl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@types/psl/-/psl-1.1.0.tgz", @@ -2121,6 +2140,17 @@ "node": ">=8" } }, + "node_modules/aws-sdk/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/aws-sdk/node_modules/uuid": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", @@ -2163,7 +2193,6 @@ "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", @@ -2377,14 +2406,26 @@ } }, "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, + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, "node_modules/buffer-equal-constant-time": { @@ -2392,6 +2433,25 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, + "node_modules/buffer/node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "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/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -4110,14 +4170,6 @@ "node": ">=8" } }, - "node_modules/inflation": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.1.0.tgz", - "integrity": "sha512-t54PPJHG1Pp7VQvxyVCJ9mBbjG3Hqryges9bXoOO6GExCPa+//i/d5GSuFtpx3ALLd7lgIAur6zrIlBQyJuMlQ==", - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/inflection": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", @@ -6160,6 +6212,11 @@ "node": ">=8" } }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -6492,6 +6549,14 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "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", @@ -9298,6 +9363,15 @@ "@types/node": "*" } }, + "@types/brotli": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/brotli/-/brotli-1.3.4.tgz", + "integrity": "sha512-cKYjgaS2DMdCKF7R0F5cgx1nfBYObN2ihIuPGQ4/dlIY6RpV7OWNwe9L8V4tTVKL2eZqOkNM9FM/rgTvLf4oXw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/co-body": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@types/co-body/-/co-body-5.1.1.tgz", @@ -9540,6 +9614,12 @@ "@types/node": "*" } }, + "@types/pako": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.3.tgz", + "integrity": "sha512-bq0hMV9opAcrmE0Byyo0fY3Ew4tgOevJmQ9grUhpXQhYfyLJ1Kqg3P33JT5fdbT2AjeAjR51zqqVjAL/HMkx7Q==", + "dev": true + }, "@types/psl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@types/psl/-/psl-1.1.0.tgz", @@ -9836,6 +9916,17 @@ "xml2js": "0.6.2" }, "dependencies": { + "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" + } + }, "uuid": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", @@ -9951,8 +10042,7 @@ "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 + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "bcp47": { "version": "1.1.2", @@ -10111,14 +10201,19 @@ } }, "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, + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + }, + "dependencies": { + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + } } }, "buffer-equal-constant-time": { @@ -11429,11 +11524,6 @@ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true }, - "inflation": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.1.0.tgz", - "integrity": "sha512-t54PPJHG1Pp7VQvxyVCJ9mBbjG3Hqryges9bXoOO6GExCPa+//i/d5GSuFtpx3ALLd7lgIAur6zrIlBQyJuMlQ==" - }, "inflection": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", @@ -13000,6 +13090,11 @@ "release-zalgo": "^1.0.0" } }, + "pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, "param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -13238,6 +13333,11 @@ } } }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", diff --git a/package.json b/package.json index fa879d3ec..c6637800f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "supertokens-node", - "version": "20.0.2", + "version": "20.1.2", "description": "NodeJS driver for SuperTokens core", "main": "index.js", "scripts": { @@ -113,15 +113,17 @@ }, "homepage": "https://github.com/supertokens/supertokens-node#readme", "dependencies": { + "buffer": "^6.0.3", "content-type": "^1.0.5", "cookie": "0.4.0", "cross-fetch": "^3.1.6", "debug": "^4.3.3", - "inflation": "^2.0.0", "jose": "^4.13.1", "libphonenumber-js": "^1.9.44", "nodemailer": "^6.7.2", + "pako": "^2.1.0", "pkce-challenge": "^3.0.0", + "process": "^0.11.10", "psl": "1.8.0", "set-cookie-parser": "^2.6.0", "supertokens-js-override": "^0.0.4", @@ -134,6 +136,7 @@ "@loopback/repository": "3.7.1", "@loopback/rest": "9.3.0", "@types/aws-lambda": "8.10.77", + "@types/brotli": "^1.3.4", "@types/co-body": "^5.1.1", "@types/content-type": "^1.1.5", "@types/cookie": "0.3.3", @@ -143,6 +146,7 @@ "@types/koa": "^2.13.4", "@types/koa-bodyparser": "^4.3.3", "@types/nodemailer": "^6.4.4", + "@types/pako": "^2.0.3", "@types/psl": "1.1.0", "@types/set-cookie-parser": "^2.4.9", "@types/validator": "10.11.0", diff --git a/test/dashboard/createOrUpdateThirdPartyConfig.test.js b/test/dashboard/createOrUpdateThirdPartyConfig.test.js deleted file mode 100644 index 24a2379be..000000000 --- a/test/dashboard/createOrUpdateThirdPartyConfig.test.js +++ /dev/null @@ -1,112 +0,0 @@ -/* Copyright (c) 2024, 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 { ProcessState } = require("../../lib/build/processState"); -const { printPath, killAllST, setupST, cleanST, startSTWithMultitenancy } = require("../utils"); -let STExpress = require("../../"); -let Dashboard = require("../../recipe/dashboard"); -let Multitenancy = require("../../recipe/multitenancy"); -let EmailPassword = require("../../recipe/emailpassword"); -const express = require("express"); -let { middleware, errorHandler } = require("../../framework/express"); -const request = require("supertest"); -let Session = require("../../recipe/session"); -let assert = require("assert"); - -describe(`User Dashboard createOrUpdateThirdPartyConfig: ${printPath( - "[test/dashboard/createOrUpdateThirdPartyConfig.test.js]" -)}`, () => { - beforeEach(async () => { - await killAllST(); - await setupST(); - ProcessState.getInstance().reset(); - }); - - after(async function () { - await killAllST(); - await cleanST(); - }); - - it("Test that API creates a new third party config for the given tenant", async () => { - const connectionURI = await startSTWithMultitenancy(); - STExpress.init({ - supertokens: { - connectionURI, - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Dashboard.init({ - apiKey: "testapikey", - }), - EmailPassword.init(), - Session.init(), - ], - }); - - const app = express(); - - app.use(middleware()); - - app.use(errorHandler()); - - const tenantName = "tenant1"; - - await Multitenancy.createOrUpdateTenant(tenantName, { - firstFactors: ["emailpassword", "thirdparty"], - }); - - const createThirdPartyConfigURL = `/auth/${tenantName}/dashboard/api/thirdparty/config`; - - let thirdPartyConfigResponse = await new Promise((res) => { - request(app) - .put(createThirdPartyConfigURL) - .set("Authorization", "Bearer testapikey") - .set("Content-Type", "application/json") - .send( - JSON.stringify({ - providerConfig: { - thirdPartyId: "google", - name: "google", - clients: [ - { - clientId: "GOOGLE_CLIENT_ID", - clientSecret: "GOOGLE_CLIENT_SECRET", - }, - ], - }, - }) - ) - .end((err, response) => { - if (err) { - console.log(err); - res(undefined); - } else { - console.log(response.text); - res(JSON.parse(response.text)); - } - }); - }); - - assert.strictEqual(thirdPartyConfigResponse.status, "OK"); - assert.strictEqual(thirdPartyConfigResponse.createdNew, true); - - const tenant = await Multitenancy.getTenant(tenantName); - assert.strictEqual(tenant.thirdParty.providers.length, 1); - assert.strictEqual(tenant.thirdParty.providers[0].thirdPartyId, "google"); - }); -}); diff --git a/test/dashboard/deleteTenant.test.js b/test/dashboard/deleteTenant.test.js deleted file mode 100644 index 6a5477dd9..000000000 --- a/test/dashboard/deleteTenant.test.js +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright (c) 2024, 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 { ProcessState } = require("../../lib/build/processState"); -const { printPath, killAllST, setupST, cleanST, startSTWithMultitenancy } = require("../utils"); -let STExpress = require("../../"); -let Dashboard = require("../../recipe/dashboard"); -let Multitenancy = require("../../recipe/multitenancy"); -let EmailPassword = require("../../recipe/emailpassword"); -const express = require("express"); -let { middleware, errorHandler } = require("../../framework/express"); -const request = require("supertest"); -let Session = require("../../recipe/session"); -let assert = require("assert"); - -describe(`User Dashboard deleteTenant: ${printPath("[test/dashboard/deleteTenant.test.js]")}`, () => { - beforeEach(async () => { - await killAllST(); - await setupST(); - ProcessState.getInstance().reset(); - }); - - after(async function () { - await killAllST(); - await cleanST(); - }); - - it("Test that API successfully deletes a tenant", async () => { - const connectionURI = await startSTWithMultitenancy(); - STExpress.init({ - supertokens: { - connectionURI, - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Dashboard.init({ - apiKey: "testapikey", - }), - EmailPassword.init(), - Session.init(), - ], - }); - - const app = express(); - - app.use(middleware()); - - app.use(errorHandler()); - - const tenantName = "tenant1"; - - await Multitenancy.createOrUpdateTenant(tenantName, { - firstFactors: ["emailpassword", "thirdparty"], - }); - - const deleteTenantURL = `/auth/${tenantName}/dashboard/api/tenant`; - - let tenantInfoResponse = await new Promise((res) => { - request(app) - .delete(deleteTenantURL) - .set("Authorization", "Bearer testapikey") - .end((err, response) => { - if (err) { - res(undefined); - } else { - res(JSON.parse(response.text)); - } - }); - }); - - assert.strictEqual(tenantInfoResponse.status, "OK"); - assert.strictEqual(tenantInfoResponse.didExist, true); - - const tenantsRes = await Multitenancy.listAllTenants(); - assert.strictEqual(tenantsRes.tenants.length, 1); - assert.strictEqual(tenantsRes.tenants[0].tenantId, "public"); - }); - - it("Test that API throws error when tenantId is missing", async () => { - const connectionURI = await startSTWithMultitenancy(); - STExpress.init({ - supertokens: { - connectionURI, - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Dashboard.init({ - apiKey: "testapikey", - }), - EmailPassword.init(), - Session.init(), - ], - }); - - const app = express(); - - app.use(middleware()); - - app.use(errorHandler()); - - const deleteTenantURL = `/auth/dashboard/api/tenant`; - - let responseStatus = 200; - let tenantInfoResponse = await new Promise((res) => { - request(app) - .delete(deleteTenantURL) - .set("Authorization", "Bearer testapikey") - .end((err, response) => { - responseStatus = response.statusCode; - if (err) { - res(undefined); - } else { - res(JSON.parse(response.text)); - } - }); - }); - - assert.strictEqual(responseStatus, 200); - assert.strictEqual(tenantInfoResponse.status, "CANNOT_DELETE_PUBLIC_TENANT_ERROR"); - }); -}); diff --git a/test/dashboard/deleteThirdPartyConfig.test.js b/test/dashboard/deleteThirdPartyConfig.test.js deleted file mode 100644 index cbc7316a8..000000000 --- a/test/dashboard/deleteThirdPartyConfig.test.js +++ /dev/null @@ -1,154 +0,0 @@ -/* Copyright (c) 2024, 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 { ProcessState } = require("../../lib/build/processState"); -const { printPath, killAllST, setupST, cleanST, startSTWithMultitenancy } = require("../utils"); -let STExpress = require("../../"); -let Dashboard = require("../../recipe/dashboard"); -let Multitenancy = require("../../recipe/multitenancy"); -let EmailPassword = require("../../recipe/emailpassword"); -const express = require("express"); -let { middleware, errorHandler } = require("../../framework/express"); -const request = require("supertest"); -let Session = require("../../recipe/session"); -let assert = require("assert"); - -describe(`User Dashboard deleteThirdPartyConfig: ${printPath( - "[test/dashboard/deleteThirdPartyConfig.test.js]" -)}`, () => { - beforeEach(async () => { - await killAllST(); - await setupST(); - ProcessState.getInstance().reset(); - }); - - after(async function () { - await killAllST(); - await cleanST(); - }); - - it("Test that API successfully deletes third party config for a tenant", async () => { - const connectionURI = await startSTWithMultitenancy(); - STExpress.init({ - supertokens: { - connectionURI, - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Dashboard.init({ - apiKey: "testapikey", - }), - EmailPassword.init(), - Session.init(), - ], - }); - - const app = express(); - - app.use(middleware()); - - app.use(errorHandler()); - - const tenantName = "tenant1"; - - await Multitenancy.createOrUpdateTenant(tenantName, { - firstFactors: ["emailpassword", "thirdparty"], - }); - - await Multitenancy.createOrUpdateThirdPartyConfig(tenantName, { - thirdPartyId: "google", - name: "google", - clients: [ - { - clientId: "GOOGLE_CLIENT_ID", - clientSecret: "GOOGLE_CLIENT_SECRET", - }, - ], - }); - - const deleteThirdPartyConfigURL = `/auth/${tenantName}/dashboard/api/thirdparty/config?thirdPartyId=google`; - - let tenantInfoResponse = await new Promise((res) => { - request(app) - .delete(deleteThirdPartyConfigURL) - .set("Authorization", "Bearer testapikey") - .end((err, response) => { - if (err) { - res(undefined); - } else { - res(JSON.parse(response.text)); - } - }); - }); - - assert.strictEqual(tenantInfoResponse.status, "OK"); - - const tenantsRes = await Multitenancy.getTenant(tenantName); - assert.strictEqual(tenantsRes.thirdParty.providers.length, 0); - }); - - it("Test that API throws error when tenantId or thirdPartyId is missing", async () => { - const connectionURI = await startSTWithMultitenancy(); - STExpress.init({ - supertokens: { - connectionURI, - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Dashboard.init({ - apiKey: "testapikey", - }), - EmailPassword.init(), - Session.init(), - ], - }); - - const app = express(); - - app.use(middleware()); - - app.use(errorHandler()); - - const deleteThirdPartyConfigURL = `/auth/dashboard/api/thirdparty/config`; - - let responseStatus = 200; - let deleteThirdPartyConfigResponse = await new Promise((res) => { - request(app) - .delete(deleteThirdPartyConfigURL) - .set("Authorization", "Bearer testapikey") - .end((err, response) => { - responseStatus = response.statusCode; - if (err) { - res(undefined); - } else { - res(JSON.parse(response.text)); - } - }); - }); - - assert.strictEqual(responseStatus, 400); - assert.strictEqual( - deleteThirdPartyConfigResponse.message, - "Missing required parameter 'tenantId' or 'thirdPartyId'" - ); - }); -}); diff --git a/test/dashboard/getTenantInfo.test.js b/test/dashboard/getTenantInfo.test.js deleted file mode 100644 index f3736c0fd..000000000 --- a/test/dashboard/getTenantInfo.test.js +++ /dev/null @@ -1,211 +0,0 @@ -/* Copyright (c) 2024, 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 { ProcessState } = require("../../lib/build/processState"); -const { printPath, killAllST, setupST, cleanST, startSTWithMultitenancy } = require("../utils"); -let STExpress = require("../../"); -let Dashboard = require("../../recipe/dashboard"); -let Multitenancy = require("../../recipe/multitenancy"); -let ThirdParty = require("../../lib/build/recipe/thirdparty"); -let EmailPassword = require("../../lib/build/recipe/emailpassword"); -const express = require("express"); -let { middleware, errorHandler } = require("../../framework/express"); -const request = require("supertest"); -let Session = require("../../recipe/session"); -let assert = require("assert"); - -describe(`User Dashboard getTenantInfo: ${printPath("[test/dashboard/getTenantInfo.test.js]")}`, () => { - beforeEach(async () => { - await killAllST(); - await setupST(); - ProcessState.getInstance().reset(); - }); - - after(async function () { - await killAllST(); - await cleanST(); - }); - - it("Test that API returns all the info for the given tenant id", async () => { - const connectionURI = await startSTWithMultitenancy(); - STExpress.init({ - supertokens: { - connectionURI, - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Dashboard.init({ - apiKey: "testapikey", - }), - ThirdParty.init(), - EmailPassword.init(), - Session.init(), - ], - }); - - const app = express(); - - app.use(middleware()); - - app.use(errorHandler()); - - const tenantName = "tenant1"; - - await Multitenancy.createOrUpdateTenant(tenantName, { - firstFactors: ["emailpassword", "thirdparty"], - }); - - await Multitenancy.createOrUpdateThirdPartyConfig(tenantName, { - thirdPartyId: "google", - name: "google", - clients: [ - { - clientId: "GOOGLE_CLIENT_ID", - clientSecret: "GOOGLE_CLIENT_SECRET", - }, - ], - }); - - await EmailPassword.signUp(tenantName, "test@supertokens.com", "abcd1235"); - - const getTenantInfoURL = `/auth/${tenantName}/dashboard/api/tenant`; - - let tenantInfoResponse = await new Promise((res) => { - request(app) - .get(getTenantInfoURL) - .set("Authorization", "Bearer testapikey") - .end((err, response) => { - if (err) { - res(undefined); - } else { - res(JSON.parse(response.text)); - } - }); - }); - - assert.strictEqual(tenantInfoResponse.status, "OK"); - assert.strictEqual(tenantInfoResponse.tenant.tenantId, "tenant1"); - assert.strictEqual(tenantInfoResponse.tenant.thirdParty.providers.length, 1); - assert.strictEqual(tenantInfoResponse.tenant.thirdParty.providers.length, 1); - assert.strictEqual(tenantInfoResponse.tenant.thirdParty.providers[0].thirdPartyId, "google"); - assert.strictEqual(tenantInfoResponse.tenant.userCount, 1); - assert.strictEqual(tenantInfoResponse.tenant.firstFactors.length, 2); - assert.strictEqual(tenantInfoResponse.tenant.firstFactors.includes("emailpassword"), true); - assert.strictEqual(tenantInfoResponse.tenant.firstFactors.includes("thirdparty"), true); - }); - - it("Test that API returns error if tenant does not exist", async () => { - const connectionURI = await startSTWithMultitenancy(); - STExpress.init({ - supertokens: { - connectionURI, - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Dashboard.init({ - apiKey: "testapikey", - }), - ThirdParty.init(), - EmailPassword.init(), - Session.init(), - ], - }); - - const app = express(); - - app.use(middleware()); - - app.use(errorHandler()); - - const tenantName = "tenant1"; - - const getTenantInfoURL = `/auth/${tenantName}/dashboard/api/tenant`; - - let tenantInfoResponse = await new Promise((res) => { - request(app) - .get(getTenantInfoURL) - .set("Authorization", "Bearer testapikey") - .end((err, response) => { - if (err) { - res(undefined); - } else { - res(JSON.parse(response.text)); - } - }); - }); - - assert.strictEqual(tenantInfoResponse.status, "UNKNOWN_TENANT_ERROR"); - }); - - it("Test that API returns public tenant if tenant id is not provided", async () => { - const connectionURI = await startSTWithMultitenancy(); - STExpress.init({ - supertokens: { - connectionURI, - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Dashboard.init({ - apiKey: "testapikey", - }), - ThirdParty.init(), - EmailPassword.init(), - Session.init(), - ], - }); - - const app = express(); - - app.use(middleware()); - - app.use(errorHandler()); - - const getTenantInfoURL = `/auth/dashboard/api/tenant`; - - let responseStatus = 200; - let tenantInfoResponse = await new Promise((res) => { - request(app) - .get(getTenantInfoURL) - .set("Authorization", "Bearer testapikey") - .end((err, response) => { - responseStatus = response.statusCode; - if (err) { - res(undefined); - } else { - res(JSON.parse(response.text)); - } - }); - }); - - assert.strictEqual(responseStatus, 200); - assert.strictEqual(tenantInfoResponse.status, "OK"); - assert.strictEqual(tenantInfoResponse.tenant.tenantId, "public"); - assert.strictEqual(tenantInfoResponse.tenant.thirdParty.providers.length, 0); - assert.strictEqual(tenantInfoResponse.tenant.firstFactors.length, 2); - assert.strictEqual(tenantInfoResponse.tenant.firstFactors.includes("emailpassword"), true); - assert.strictEqual(tenantInfoResponse.tenant.firstFactors.includes("thirdparty"), true); - }); -}); diff --git a/test/dashboard/listTenants.test.js b/test/dashboard/listTenants.test.js deleted file mode 100644 index b034cc948..000000000 --- a/test/dashboard/listTenants.test.js +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (c) 2024, 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 { ProcessState } = require("../../lib/build/processState"); -const { printPath, killAllST, setupST, cleanST, startSTWithMultitenancy } = require("../utils"); -let STExpress = require("../.."); -let Dashboard = require("../../recipe/dashboard"); -let Multitenancy = require("../../recipe/multitenancy"); -let EmailPassword = require("../../recipe/emailpassword"); -const express = require("express"); -let { middleware, errorHandler } = require("../../framework/express"); -const request = require("supertest"); -let Session = require("../../recipe/session"); -let assert = require("assert"); - -describe(`User Dashboard listTenants: ${printPath("[test/dashboard/listTenants.test.js]")}`, () => { - beforeEach(async () => { - await killAllST(); - await setupST(); - ProcessState.getInstance().reset(); - }); - - after(async function () { - await killAllST(); - await cleanST(); - }); - - it("Test that API returns all the tenants", async () => { - const connectionURI = await startSTWithMultitenancy(); - STExpress.init({ - supertokens: { - connectionURI, - }, - appInfo: { - apiDomain: "api.supertokens.io", - appName: "SuperTokens", - websiteDomain: "supertokens.io", - }, - recipeList: [ - Dashboard.init({ - apiKey: "testapikey", - }), - EmailPassword.init(), - Session.init(), - ], - }); - - const app = express(); - - app.use(middleware()); - - app.use(errorHandler()); - - const tenantName = "tenant1"; - - await Multitenancy.createOrUpdateTenant(tenantName, { - firstFactors: ["emailpassword", "thirdparty"], - }); - - const listAllTenantsURL = "/auth/dashboard/api/tenants"; - - let tenantInfoResponse = await new Promise((res) => { - request(app) - .get(listAllTenantsURL) - .set("Authorization", "Bearer testapikey") - .end((err, response) => { - if (err) { - res(undefined); - } else { - res(JSON.parse(response.text)); - } - }); - }); - - assert.strictEqual(tenantInfoResponse.status, "OK"); - assert.strictEqual(tenantInfoResponse.tenants.length, 2); - - const tenant1 = tenantInfoResponse.tenants.find((tenant) => tenant.tenantId === tenantName); - }); -}); diff --git a/test/emailpassword/signinFeature.test.js b/test/emailpassword/signinFeature.test.js index 7fddc9d1a..21e6e0d5c 100644 --- a/test/emailpassword/signinFeature.test.js +++ b/test/emailpassword/signinFeature.test.js @@ -1038,7 +1038,6 @@ describe(`signinFeature: ${printPath("[test/emailpassword/signinFeature.test.js] }, ], }) - .expect(400) .end((err, res) => { if (err) { resolve(undefined); @@ -1047,7 +1046,10 @@ describe(`signinFeature: ${printPath("[test/emailpassword/signinFeature.test.js] resolve(JSON.parse(res.text)); }) ); - assert(response.message === "Are you sending too many / too few formFields?"); + assert(response.status === "FIELD_ERROR"); + assert(response.formFields.length === 1); + assert(response.formFields[0].error === "Field is not optional"); + assert(response.formFields[0].id === "email"); }); // Input formFields has no password field @@ -1087,7 +1089,6 @@ describe(`signinFeature: ${printPath("[test/emailpassword/signinFeature.test.js] }, ], }) - .expect(400) .end((err, res) => { if (err) { resolve(undefined); @@ -1096,7 +1097,10 @@ describe(`signinFeature: ${printPath("[test/emailpassword/signinFeature.test.js] resolve(JSON.parse(res.text)); }) ); - assert(response.message === "Are you sending too many / too few formFields?"); + assert(response.status === "FIELD_ERROR"); + assert(response.formFields.length === 1); + assert(response.formFields[0].error === "Field is not optional"); + assert(response.formFields[0].id === "password"); }); // Provide invalid (wrong syntax) email and wrong password, and you should get form field error diff --git a/test/emailpassword/signupFeature.test.js b/test/emailpassword/signupFeature.test.js index 7c19a062f..4f337ef8b 100644 --- a/test/emailpassword/signupFeature.test.js +++ b/test/emailpassword/signupFeature.test.js @@ -727,7 +727,7 @@ describe(`signupFeature: ${printPath("[test/emailpassword/signupFeature.test.js] * - Make sure that the input email is trimmed * - Pass a non string value in the formFields array and make sure it passes through the signUp API and is sent in the handlePostSignup as that type */ - it("test formFields added in config but not in inout to signup, check error about it being missing", async function () { + it("test formFields added in config but not in input to signup, check error about it being missing", async function () { const connectionURI = await startST(); STExpress.init({ supertokens: { @@ -757,10 +757,12 @@ describe(`signupFeature: ${printPath("[test/emailpassword/signupFeature.test.js] app.use(errorHandler()); - let response = await signUPRequest(app, "random@gmail.com", "validpass123"); - assert(response.status === 400); - - assert(JSON.parse(response.text).message === "Are you sending too many / too few formFields?"); + let rawResponse = await signUPRequest(app, "random@gmail.com", "validpass123"); + const response = JSON.parse(rawResponse.text); + assert(response.status === "FIELD_ERROR"); + assert(response.formFields.length === 1); + assert(response.formFields[0].error === "Field is not optional"); + assert(response.formFields[0].id === "testField"); }); //- Good test case without optional @@ -828,6 +830,136 @@ describe(`signupFeature: ${printPath("[test/emailpassword/signupFeature.test.js] assert(response.user.emails[0] === "random@gmail.com"); }); + it("test valid boolean formFields with optional", async function () { + const connectionURI = await startST(); + STExpress.init({ + supertokens: { + connectionURI, + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + EmailPassword.init({ + signUpFeature: { + formFields: [ + { + id: "autoVerify", + optional: false, + }, + ], + }, + }), + Session.init({ getTokenTransferMethod: () => "cookie" }), + ], + }); + const app = express(); + + app.use(middleware()); + + app.use(errorHandler()); + + let response = await new Promise((resolve) => + request(app) + .post("/auth/signup") + .send({ + formFields: [ + { + id: "password", + value: "validpass123", + }, + { + id: "email", + value: "random@gmail.com", + }, + { + id: "autoVerify", + value: false, + }, + ], + }) + .expect(200) + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(JSON.parse(res.text)); + } + }) + ); + + assert(response.status === "OK"); + assert(response.user.id !== undefined); + assert(response.user.emails[0] === "random@gmail.com"); + }); + + it("test valid int formFields with optional", async function () { + const connectionURI = await startST(); + STExpress.init({ + supertokens: { + connectionURI, + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + EmailPassword.init({ + signUpFeature: { + formFields: [ + { + id: "intField", + optional: false, + }, + ], + }, + }), + Session.init({ getTokenTransferMethod: () => "cookie" }), + ], + }); + const app = express(); + + app.use(middleware()); + + app.use(errorHandler()); + + let response = await new Promise((resolve) => + request(app) + .post("/auth/signup") + .send({ + formFields: [ + { + id: "password", + value: "validpass123", + }, + { + id: "email", + value: "random@gmail.com", + }, + { + id: "intField", + value: 23, + }, + ], + }) + .expect(200) + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(JSON.parse(res.text)); + } + }) + ); + + assert(response.status === "OK"); + assert(response.user.id !== undefined); + assert(response.user.emails[0] === "random@gmail.com"); + }); + //- Bad test case without optional (something is missing, and it's not optional) it("test bad case input to signup without optional", async function () { const connectionURI = await startST(); @@ -990,7 +1122,6 @@ describe(`signupFeature: ${printPath("[test/emailpassword/signupFeature.test.js] }, ], }) - .expect(400) .end((err, res) => { if (err) { resolve(undefined); @@ -999,7 +1130,10 @@ describe(`signupFeature: ${printPath("[test/emailpassword/signupFeature.test.js] } }) ); - assert(response.message === "Are you sending too many / too few formFields?"); + assert(response.status === "FIELD_ERROR"); + assert(response.formFields.length === 1); + assert(response.formFields[0].error === "Field is not optional"); + assert(response.formFields[0].id === "email"); }); // Input formFields has no password field (and not in config @@ -1033,7 +1167,6 @@ describe(`signupFeature: ${printPath("[test/emailpassword/signupFeature.test.js] }, ], }) - .expect(400) .end((err, res) => { if (err) { resolve(undefined); @@ -1042,7 +1175,10 @@ describe(`signupFeature: ${printPath("[test/emailpassword/signupFeature.test.js] } }) ); - assert(response.message === "Are you sending too many / too few formFields?"); + assert(response.status === "FIELD_ERROR"); + assert(response.formFields.length === 1); + assert(response.formFields[0].error === "Field is not optional"); + assert(response.formFields[0].id === "password"); }); // Input form field has different number of custom fields than in config form fields) @@ -1099,7 +1235,6 @@ describe(`signupFeature: ${printPath("[test/emailpassword/signupFeature.test.js] }, ], }) - .expect(400) .end((err, res) => { if (err) { resolve(undefined); @@ -1108,7 +1243,10 @@ describe(`signupFeature: ${printPath("[test/emailpassword/signupFeature.test.js] } }) ); - assert(response.message === "Are you sending too many / too few formFields?"); + assert(response.status === "FIELD_ERROR"); + assert(response.formFields.length === 1); + assert(response.formFields[0].error === "Field is not optional"); + assert(response.formFields[0].id === "testField2"); }); // Input form field has same number of custom fields as in config form field, but some ids mismatch @@ -1185,6 +1323,72 @@ describe(`signupFeature: ${printPath("[test/emailpassword/signupFeature.test.js] assert(response.formFields[0].id === "testField2"); }); + // Custom optional field missing in the payload should not throw an error + it("Custom optional field missing in the payload should not throw an error", async function () { + const connectionURI = await startST(); + STExpress.init({ + supertokens: { + connectionURI, + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + EmailPassword.init({ + signUpFeature: { + formFields: [ + { + id: "testField", + optional: true, + }, + { + id: "testField1", + optional: true, + }, + ], + }, + }), + Session.init({ getTokenTransferMethod: () => "cookie" }), + ], + }); + const app = express(); + + app.use(middleware()); + + app.use(errorHandler()); + + let response = await new Promise((resolve) => + request(app) + .post("/auth/signup") + .send({ + formFields: [ + { + id: "password", + value: "validpass123", + }, + { + id: "email", + value: "random@gmail.com", + }, + ], + }) + .expect(200) + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(JSON.parse(res.text)); + } + }) + ); + + assert(response.status === "OK"); + assert(response.user.id !== undefined); + assert(response.user.emails[0] === "random@gmail.com"); + }); + // Test custom field validation error (one and two custom fields) it("test custom field validation error", async function () { const connectionURI = await startST(); @@ -1766,4 +1970,71 @@ describe(`signupFeature: ${printPath("[test/emailpassword/signupFeature.test.js] assert(r3.failureReason === "Password should be greater than 5 characters"); } }); + + // test case where more than the configured form fields are passed. + it("test bad case when too many formFields are passed", async function () { + const connectionURI = await startST(); + STExpress.init({ + supertokens: { + connectionURI, + }, + appInfo: { + apiDomain: "api.supertokens.io", + appName: "SuperTokens", + websiteDomain: "supertokens.io", + }, + recipeList: [ + EmailPassword.init({ + signUpFeature: { + formFields: [ + { + id: "testField", + }, + ], + }, + }), + Session.init({ getTokenTransferMethod: () => "cookie" }), + ], + }); + const app = express(); + + app.use(middleware()); + + app.use(errorHandler()); + + let response = await new Promise((resolve) => + request(app) + .post("/auth/signup") + .send({ + formFields: [ + { + id: "password", + value: "validpass123", + }, + { + id: "email", + value: "random@gmail.com", + }, + { + id: "testField", + value: "some value", + }, + { + id: "extraField", + value: "some value", + }, + ], + }) + .expect(400) + .end((err, res) => { + if (err) { + resolve(undefined); + } else { + resolve(JSON.parse(res.text)); + } + }) + ); + + assert(response.message == "Are you sending too many formFields?"); + }); }); diff --git a/test/test-server/src/index.ts b/test/test-server/src/index.ts index 018d8a7d5..e41f2f41e 100644 --- a/test/test-server/src/index.ts +++ b/test/test-server/src/index.ts @@ -55,6 +55,8 @@ import TOTPRoutes from "./totp"; import { getFunc, resetOverrideParams, getOverrideParams } from "./testFunctionMapper"; import OverrideableBuilder from "supertokens-js-override"; import { resetOverrideLogs, logOverrideEvent, getOverrideLogs } from "./overrideLogging"; +import Dashboard from "../../../recipe/dashboard"; +import DashboardRecipe from "../../../lib/build/recipe/dashboard/recipe"; const { logDebugMessage } = logger("com.supertokens:node-test-server"); @@ -71,7 +73,12 @@ function defaultSTInit() { supertokens: { connectionURI: process.env.ST_CONNECTION_URI || "http://localhost:8080", }, - recipeList: [Session.init()], + recipeList: [ + Session.init(), + Dashboard.init({ + apiKey: "test", + }), + ], }); } @@ -95,12 +102,17 @@ function STReset() { OAuth2ProviderRecipe.reset(); OAuth2ClientRecipe.reset(); SuperTokensRecipe.reset(); + DashboardRecipe.reset(); } function initST(config: any) { STReset(); - const recipeList: RecipeListFunction[] = []; + const recipeList: RecipeListFunction[] = [ + Dashboard.init({ + apiKey: "test", + }), + ]; const parsedConfig = JSON.parse(config); const init = { diff --git a/test/test-server/src/thirdparty.ts b/test/test-server/src/thirdparty.ts index 53fcdfbaa..bfe828661 100644 --- a/test/test-server/src/thirdparty.ts +++ b/test/test-server/src/thirdparty.ts @@ -6,23 +6,43 @@ import { logger } from "./logger"; const namespace = "com.supertokens:node-test-server:thirdparty"; const { logDebugMessage } = logger(namespace); -const router = Router().post("/manuallycreateorupdateuser", async (req, res, next) => { - try { - logDebugMessage("ThirdParty:manuallyCreateOrUpdateUser %j", req.body); - let session = req.body.session && (await convertRequestSessionToSessionObject(req.body.session)); - const response = await ThirdParty.manuallyCreateOrUpdateUser( +const router = Router() + .post("/manuallycreateorupdateuser", async (req, res, next) => { + try { + logDebugMessage("ThirdParty:manuallyCreateOrUpdateUser %j", req.body); + let session = req.body.session && (await convertRequestSessionToSessionObject(req.body.session)); + const response = await ThirdParty.manuallyCreateOrUpdateUser( + req.body.tenantId || "public", + req.body.thirdPartyId, + req.body.thirdPartyUserId, + req.body.email, + req.body.isVerified, + session, + req.body.userContext + ); + await serializeResponse(req, res, response); + } catch (e) { + next(e); + } + }) + .post("/getprovider", async (req, res, next) => { + logDebugMessage("ThirdParty:getProvider %j", req.body); + let provider = await ThirdParty.getProvider( req.body.tenantId || "public", req.body.thirdPartyId, - req.body.thirdPartyUserId, - req.body.email, - req.body.isVerified, - session, + req.body.clientType, req.body.userContext ); - await serializeResponse(req, res, response); - } catch (e) { - next(e); - } -}); + + if (provider === undefined) { + await serializeResponse(req, res, {}); + return; + } + + await serializeResponse(req, res, { + id: provider.id, + config: provider.config, + }); + }); export default router;