@hexclave/js 1.0.123 → 1.0.126

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/dist/{admin-app-impl-Cxer4EIA.d.ts → admin-app-impl-Df-WtGg0.d.ts} +29 -13
  2. package/dist/admin-app-impl-Df-WtGg0.d.ts.map +1 -0
  3. package/dist/clickmap/clickmap-core.d.ts +1 -1
  4. package/dist/clickmap/index.d.ts +1 -1
  5. package/dist/{client-app-DLFxr4f7.d.ts → client-app-C7Tnf0n1.d.ts} +34 -6
  6. package/dist/client-app-C7Tnf0n1.d.ts.map +1 -0
  7. package/dist/{common-BDyEKSM6.d.ts → common-Dii3iHJR.d.ts} +15 -3
  8. package/dist/common-Dii3iHJR.d.ts.map +1 -0
  9. package/dist/{common-CRu2FsO9.d.ts → common-GgG4l8fG.d.ts} +2 -2
  10. package/dist/{common-CRu2FsO9.d.ts.map → common-GgG4l8fG.d.ts.map} +1 -1
  11. package/dist/dev-tool/dev-tool-core.d.ts +1 -1
  12. package/dist/dev-tool/index.d.ts +1 -1
  13. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +4 -4
  14. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  15. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +18 -2
  16. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  17. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.external-token-store.test.d.ts +1 -0
  18. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.external-token-store.test.js +382 -0
  19. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.external-token-store.test.js.map +1 -0
  20. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.init-analytics.test.d.ts +1 -0
  21. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.init-analytics.test.js +66 -0
  22. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.init-analytics.test.js.map +1 -0
  23. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js +66 -14
  24. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  25. package/dist/esm/lib/hexclave-app/apps/implementations/common.js +2 -2
  26. package/dist/esm/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.d.ts +31 -0
  27. package/dist/esm/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.d.ts.map +1 -0
  28. package/dist/esm/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.js +115 -0
  29. package/dist/esm/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.js.map +1 -0
  30. package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.d.ts +16 -1
  31. package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.d.ts.map +1 -1
  32. package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.js.map +1 -1
  33. package/dist/esm/lib/hexclave-app/common.d.ts +14 -2
  34. package/dist/esm/lib/hexclave-app/common.d.ts.map +1 -1
  35. package/dist/esm/lib/hexclave-app/common.js +17 -1
  36. package/dist/esm/lib/hexclave-app/common.js.map +1 -1
  37. package/dist/esm/lib/hexclave-app/index.d.ts +2 -2
  38. package/dist/esm/lib/hexclave-app/index.js +2 -2
  39. package/dist/esm/lib/hexclave-app/users/index.d.ts +14 -1
  40. package/dist/esm/lib/hexclave-app/users/index.d.ts.map +1 -1
  41. package/dist/esm/lib/hexclave-app/users/index.js.map +1 -1
  42. package/dist/{index-ZiEXZJBF.d.ts → index-BTa6Yu7N.d.ts} +2 -2
  43. package/dist/{index-ZiEXZJBF.d.ts.map → index-BTa6Yu7N.d.ts.map} +1 -1
  44. package/dist/{index-DLPccxVU.d.ts → index-DlOcbI9W.d.ts} +2 -2
  45. package/dist/{index-DLPccxVU.d.ts.map → index-DlOcbI9W.d.ts.map} +1 -1
  46. package/dist/index.d.ts +4 -4
  47. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +1 -1
  48. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +1 -1
  49. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.external-token-store.test.d.ts +1 -0
  50. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.external-token-store.test.js +381 -0
  51. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.external-token-store.test.js.map +1 -0
  52. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.init-analytics.test.d.ts +1 -0
  53. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.init-analytics.test.js +65 -0
  54. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.init-analytics.test.js.map +1 -0
  55. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js +65 -13
  56. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  57. package/dist/lib/hexclave-app/apps/implementations/common.d.ts +1 -1
  58. package/dist/lib/hexclave-app/apps/implementations/common.js +2 -2
  59. package/dist/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.d.ts +31 -0
  60. package/dist/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.d.ts.map +1 -0
  61. package/dist/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.js +117 -0
  62. package/dist/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.js.map +1 -0
  63. package/dist/lib/hexclave-app/apps/implementations/index.d.ts +1 -1
  64. package/dist/lib/hexclave-app/apps/implementations/redirect-page-urls.d.ts +1 -1
  65. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +1 -1
  66. package/dist/lib/hexclave-app/apps/index.d.ts +1 -1
  67. package/dist/lib/hexclave-app/apps/interfaces/admin-app.d.ts +1 -1
  68. package/dist/lib/hexclave-app/apps/interfaces/client-app.d.ts +1 -1
  69. package/dist/lib/hexclave-app/apps/interfaces/client-app.js.map +1 -1
  70. package/dist/lib/hexclave-app/apps/interfaces/server-app.d.ts +1 -1
  71. package/dist/lib/hexclave-app/common.d.ts +2 -2
  72. package/dist/lib/hexclave-app/common.js +19 -0
  73. package/dist/lib/hexclave-app/common.js.map +1 -1
  74. package/dist/lib/hexclave-app/customers/index.d.ts +1 -1
  75. package/dist/lib/hexclave-app/data-vault/index.d.ts +1 -1
  76. package/dist/lib/hexclave-app/index.d.ts +4 -4
  77. package/dist/lib/hexclave-app/index.js +18 -0
  78. package/dist/lib/hexclave-app/projects/index.d.ts +1 -1
  79. package/dist/lib/hexclave-app/teams/index.d.ts +1 -1
  80. package/dist/lib/hexclave-app/url-targets.d.ts +1 -1
  81. package/dist/lib/hexclave-app/users/index.d.ts +1 -1
  82. package/dist/lib/hexclave-app/users/index.js.map +1 -1
  83. package/dist/pushed-config-error-overlay/index.d.ts +1 -1
  84. package/dist/{redirect-page-urls-C2CXwCcv.d.ts → redirect-page-urls-DCSFN6dg.d.ts} +2 -2
  85. package/dist/{redirect-page-urls-C2CXwCcv.d.ts.map → redirect-page-urls-DCSFN6dg.d.ts.map} +1 -1
  86. package/dist/{url-targets-BJgkwPGW.d.ts → url-targets-DYLcHumF.d.ts} +2 -2
  87. package/dist/{url-targets-BJgkwPGW.d.ts.map → url-targets-DYLcHumF.d.ts.map} +1 -1
  88. package/package.json +2 -2
  89. package/src/lib/hexclave-app/apps/implementations/client-app-impl.external-token-store.test.ts +425 -0
  90. package/src/lib/hexclave-app/apps/implementations/client-app-impl.init-analytics.test.ts +79 -0
  91. package/src/lib/hexclave-app/apps/implementations/client-app-impl.ts +124 -13
  92. package/src/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.ts +190 -0
  93. package/src/lib/hexclave-app/apps/interfaces/client-app.ts +17 -0
  94. package/src/lib/hexclave-app/common.ts +33 -0
  95. package/src/lib/hexclave-app/index.ts +4 -0
  96. package/src/lib/hexclave-app/users/index.ts +13 -1
  97. package/dist/admin-app-impl-Cxer4EIA.d.ts.map +0 -1
  98. package/dist/client-app-DLFxr4f7.d.ts.map +0 -1
  99. package/dist/common-BDyEKSM6.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/lib/hexclave-app/users/index.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { KnownErrors } from \"@hexclave/shared\";\nimport { CurrentUserCrud } from \"@hexclave/shared/dist/interface/crud/current-user\";\nimport { UsersCrud } from \"@hexclave/shared/dist/interface/crud/users\";\nimport type { RestrictedReason } from \"@hexclave/shared/dist/schema-fields\";\nimport { InternalSession } from \"@hexclave/shared/dist/sessions\";\nimport { encodeBase64 } from \"@hexclave/shared/dist/utils/bytes\";\nimport { GeoInfo } from \"@hexclave/shared/dist/utils/geo\";\nimport { ReadonlyJson } from \"@hexclave/shared/dist/utils/json\";\nimport { ProviderType } from \"@hexclave/shared/dist/utils/oauth\";\nimport { Result } from \"@hexclave/shared/dist/utils/results\";\nimport { ApiKeyCreationOptions, UserApiKey, UserApiKeyFirstView } from \"../api-keys\";\nimport { AsyncStoreProperty, AuthLike } from \"../common\";\nimport { DeprecatedOAuthConnection, OAuthConnection } from \"../connected-accounts\";\nimport { ContactChannel, ContactChannelCreateOptions, ServerContactChannel, ServerContactChannelCreateOptions } from \"../contact-channels\";\nimport { Customer } from \"../customers\";\nimport { NotificationCategory } from \"../notification-categories\";\nimport { AdminTeamPermission, TeamPermission } from \"../permissions\";\nimport { AdminOwnedProject, AdminProjectCreateOptions } from \"../projects\";\nimport { EditableTeamMemberProfile, ReceivedTeamInvitation, ServerListTeamsOptions, ServerTeam, ServerTeamCreateOptions, Team, TeamCreateOptions } from \"../teams\";\n\nconst userGetterErrorMessage = \"Hexclave: useUser() already returns the user object. Use `const user = useUser()` (or `const user = await app.getUser()`) instead of destructuring it like `const { user } = ...`.\";\n\nexport function withUserDestructureGuard<T extends object>(target: T): T {\n Object.freeze(target);\n return new Proxy(target, {\n get(target, prop, receiver) {\n if (prop === \"user\") {\n return guardGetter();\n }\n return target[prop as keyof T];\n },\n });\n}\n\nfunction guardGetter(): never {\n throw new Error(userGetterErrorMessage);\n}\n\nexport type OAuthProvider = {\n readonly id: string,\n readonly type: string,\n readonly userId: string,\n readonly accountId?: string,\n readonly email?: string,\n readonly allowSignIn: boolean,\n readonly allowConnectedAccounts: boolean,\n update(data: { allowSignIn?: boolean, allowConnectedAccounts?: boolean }): Promise<Result<void,\n InstanceType<typeof KnownErrors.OAuthProviderAccountIdAlreadyUsedForSignIn>\n >>,\n delete(): Promise<void>,\n};\n\nexport type ServerOAuthProvider = {\n readonly id: string,\n readonly type: string,\n readonly userId: string,\n readonly accountId: string,\n readonly email?: string,\n readonly allowSignIn: boolean,\n readonly allowConnectedAccounts: boolean,\n update(data: { accountId?: string, email?: string, allowSignIn?: boolean, allowConnectedAccounts?: boolean }): Promise<Result<void,\n InstanceType<typeof KnownErrors.OAuthProviderAccountIdAlreadyUsedForSignIn>\n >>,\n delete(): Promise<void>,\n};\n\n\n/**\n * Contains everything related to the current user session.\n */\nexport type Auth = AuthLike<{}> & {\n readonly _internalSession: InternalSession,\n readonly currentSession: {\n getTokens(): Promise<{ accessToken: string | null, refreshToken: string | null }>,\n },\n};\n\n/**\n * ```\n * +----------+-------------+-------------------+\n * | \\ | !Server | Server |\n * +----------+-------------+-------------------+\n * | !Session | User | ServerUser |\n * | Session | CurrentUser | CurrentServerUser |\n * +----------+-------------+-------------------+\n * ```\n *\n * The fields on each of these types are available iff:\n * BaseUser: true\n * Auth: Session\n * ServerBaseUser: Server\n * UserExtra: Session OR Server\n *\n * The types are defined as follows (in the typescript manner):\n * User = BaseUser\n * CurrentUser = BaseUser & Auth & UserExtra\n * ServerUser = BaseUser & ServerBaseUser & UserExtra\n * CurrentServerUser = BaseUser & ServerBaseUser & Auth & UserExtra\n **/\n\nexport type BaseUser = {\n readonly id: string,\n\n readonly displayName: string | null,\n\n /**\n * The user's email address.\n *\n * Note: This might NOT be unique across multiple users, so always use `id` for unique identification.\n */\n readonly primaryEmail: string | null,\n readonly primaryEmailVerified: boolean,\n readonly profileImageUrl: string | null,\n\n readonly signedUpAt: Date,\n\n readonly clientMetadata: any,\n readonly clientReadOnlyMetadata: any,\n\n /**\n * Whether the user has a password set.\n */\n readonly hasPassword: boolean,\n readonly otpAuthEnabled: boolean,\n readonly passkeyAuthEnabled: boolean,\n\n readonly isMultiFactorRequired: boolean,\n readonly isAnonymous: boolean,\n /**\n * Whether the user is in restricted state (signed up but hasn't completed onboarding requirements).\n * For example, if email verification is required but the user hasn't verified their email yet.\n */\n readonly isRestricted: boolean,\n /**\n * The reason why the user is restricted, e.g., { type: \"email_not_verified\" }, { type: \"anonymous\" }, or { type: \"restricted_by_administrator\" }.\n * Null if the user is not restricted.\n */\n readonly restrictedReason: RestrictedReason | null,\n /** Whether the user is restricted by an administrator. Can be set manually or by sign-up rules. */\n readonly restrictedByAdmin: boolean,\n /**\n * Public reason shown to the user explaining why an administrator restricted them, or null if none was given.\n *\n * This is intentionally readable by the user themselves (unlike `restrictedByAdminPrivateDetails`, which is\n * server-only), so onboarding screens can tell them why they can't continue.\n */\n readonly restrictedByAdminReason: string | null,\n toClientJson(): CurrentUserCrud[\"Client\"][\"Read\"],\n\n /**\n * @deprecated, use contact channel's usedForAuth instead\n */\n readonly emailAuthEnabled: boolean,\n /**\n * @deprecated\n */\n readonly oauthProviders: readonly { id: string }[],\n}\n\nexport type UserExtra = {\n setDisplayName(displayName: string | null): Promise<void>,\n /** @deprecated Use contact channel's sendVerificationEmail instead */\n sendVerificationEmail(): Promise<KnownErrors[\"EmailAlreadyVerified\"] | void>,\n setClientMetadata(metadata: any): Promise<void>,\n updatePassword(options: { oldPassword: string, newPassword: string}): Promise<KnownErrors[\"PasswordConfirmationMismatch\"] | KnownErrors[\"PasswordRequirementsNotMet\"] | void>,\n setPassword(options: { password: string }): Promise<KnownErrors[\"PasswordRequirementsNotMet\"] | void>,\n\n /**\n * A shorthand method to update multiple fields of the user at once.\n */\n update(update: UserUpdateOptions): Promise<void>,\n\n listContactChannels(): Promise<ContactChannel[]>,\n createContactChannel(data: ContactChannelCreateOptions): Promise<ContactChannel>,\n\n listNotificationCategories(): Promise<NotificationCategory[]>,\n\n delete(): Promise<void>,\n\n /** @deprecated Use `getOrLinkConnectedAccount` for redirect behavior, or `getConnectedAccount({ provider, providerAccountId })` for existence check. */\n getConnectedAccount(id: ProviderType, options: { or: 'redirect', scopes?: string[] }): Promise<DeprecatedOAuthConnection>,\n /** @deprecated Use `getConnectedAccount({ provider, providerAccountId })` for existence check, or `getOrLinkConnectedAccount` for redirect behavior. */\n getConnectedAccount(id: ProviderType, options?: { or?: 'redirect' | 'throw' | 'return-null', scopes?: string[] }): Promise<DeprecatedOAuthConnection | null>,\n /** Get a specific connected account by provider and providerAccountId. Returns null if not found. */\n getConnectedAccount(account: { provider: string, providerAccountId: string }): Promise<OAuthConnection | null>,\n\n\n /** List all connected accounts for this user (only those with allowConnectedAccounts enabled). */\n listConnectedAccounts(): Promise<OAuthConnection[]>,\n /** React hook to list all connected accounts. */\n /** Redirect the user to the OAuth flow to link a new connected account. Always redirects, never returns. */\n linkConnectedAccount(provider: string, options?: { scopes?: string[] }): Promise<void>,\n /** Get a connected account for the given provider, or redirect to link one if none exists or the token/scopes are insufficient. */\n getOrLinkConnectedAccount(provider: string, options?: { scopes?: string[] }): Promise<OAuthConnection>,\n /** React hook: get a connected account for the given provider, or redirect to link one if none exists or the token/scopes are insufficient. */\n\n hasPermission(scope: Team, permissionId: string): Promise<boolean>,\n hasPermission(permissionId: string): Promise<boolean>,\n\n getPermission(scope: Team, permissionId: string): Promise<TeamPermission | null>,\n getPermission(permissionId: string): Promise<TeamPermission | null>,\n\n listPermissions(scope: Team, options?: { recursive?: boolean }): Promise<TeamPermission[]>,\n listPermissions(options?: { recursive?: boolean }): Promise<TeamPermission[]>,\n\n\n readonly selectedTeam: Team | null,\n setSelectedTeam(teamOrId: string | Team | null): Promise<void>,\n createTeam(data: TeamCreateOptions): Promise<Team>,\n leaveTeam(team: Team): Promise<void>,\n\n /**\n * Lists all pending team invitations sent to any of the current user's verified email addresses.\n *\n * This allows the user to discover which teams have invited them, even if they haven't\n * joined those teams yet. Only invitations sent to verified email addresses are included.\n *\n * @returns An array of `ReceivedTeamInvitation` objects, each containing the team ID, team\n * display name, recipient email, and expiration date.\n *\n * @example\n * ```ts\n * const invitations = await user.listTeamInvitations();\n * for (const invitation of invitations) {\n * console.log(`Invited to ${invitation.teamDisplayName} via ${invitation.recipientEmail}`);\n * }\n * ```\n */\n listTeamInvitations(): Promise<ReceivedTeamInvitation[]>,\n /**\n * Lists all pending team invitations sent to any of the current user's verified email addresses.\n *\n * React hook version of `listTeamInvitations()`. Automatically re-renders when invitations change.\n */\n\n getActiveSessions(): Promise<ActiveSession[]>,\n revokeSession(sessionId: string): Promise<void>,\n getTeamProfile(team: Team): Promise<EditableTeamMemberProfile>,\n\n createApiKey(options: ApiKeyCreationOptions<\"user\">): Promise<UserApiKeyFirstView>,\n\n listOAuthProviders(): Promise<OAuthProvider[]>,\n\n getOAuthProvider(id: string): Promise<OAuthProvider | null>,\n\n registerPasskey(options?: { hostname?: string }): Promise<Result<undefined, KnownErrors[\"PasskeyRegistrationFailed\"] | KnownErrors[\"PasskeyWebAuthnError\"]>>,\n}\n& AsyncStoreProperty<\"apiKeys\", [], UserApiKey[], true>\n& AsyncStoreProperty<\"team\", [id: string], Team | null, false>\n& AsyncStoreProperty<\"teams\", [], Team[], true>\n& AsyncStoreProperty<\"teamInvitations\", [], ReceivedTeamInvitation[], true>\n& AsyncStoreProperty<\"permission\", [scope: Team, permissionId: string, options?: { recursive?: boolean }], TeamPermission | null, false>\n& AsyncStoreProperty<\"permissions\", [scope: Team, options?: { recursive?: boolean }], TeamPermission[], true>;\n\nexport type InternalUserExtra =\n & {\n createProject(newProject: AdminProjectCreateOptions): Promise<AdminOwnedProject>,\n transferProject(projectIdToTransfer: string, newTeamId: string): Promise<void>,\n }\n & AsyncStoreProperty<\"ownedProjects\", [], AdminOwnedProject[], true>\n\nexport type User = BaseUser;\n\nexport type CurrentUser = BaseUser & Auth & UserExtra & Customer;\n\nexport type CurrentInternalUser = CurrentUser & InternalUserExtra;\n\nexport type ProjectCurrentUser<ProjectId> = ProjectId extends \"internal\" ? CurrentInternalUser : CurrentUser;\n\nexport type TokenPartialUser = Pick<\n User,\n | \"id\"\n | \"displayName\"\n | \"primaryEmail\"\n | \"primaryEmailVerified\"\n | \"isAnonymous\"\n | \"isMultiFactorRequired\"\n | \"isRestricted\"\n | \"restrictedReason\"\n>\n\nexport type SyncedPartialUser = TokenPartialUser & Pick<\n User,\n | \"id\"\n | \"displayName\"\n | \"primaryEmail\"\n | \"primaryEmailVerified\"\n | \"profileImageUrl\"\n | \"signedUpAt\"\n | \"clientMetadata\"\n | \"clientReadOnlyMetadata\"\n | \"isAnonymous\"\n | \"hasPassword\"\n | \"isRestricted\"\n | \"restrictedReason\"\n>;\n\n\nexport type ActiveSession = {\n id: string,\n userId: string,\n createdAt: Date,\n isImpersonation: boolean,\n lastUsedAt: Date | undefined,\n isCurrentSession: boolean,\n geoInfo?: GeoInfo,\n};\n\nexport type UserUpdateOptions = {\n displayName?: string | null,\n clientMetadata?: ReadonlyJson,\n selectedTeamId?: string | null,\n totpMultiFactorSecret?: Uint8Array | null,\n profileImageUrl?: string | null,\n otpAuthEnabled?: boolean,\n passkeyAuthEnabled?: boolean,\n primaryEmail?: string | null,\n}\nexport function userUpdateOptionsToCrud(options: UserUpdateOptions): CurrentUserCrud[\"Client\"][\"Update\"] {\n return {\n display_name: options.displayName,\n client_metadata: options.clientMetadata,\n selected_team_id: options.selectedTeamId,\n totp_secret_base64: options.totpMultiFactorSecret != null ? encodeBase64(options.totpMultiFactorSecret) : options.totpMultiFactorSecret,\n profile_image_url: options.profileImageUrl,\n otp_auth_enabled: options.otpAuthEnabled,\n passkey_auth_enabled: options.passkeyAuthEnabled,\n primary_email: options.primaryEmail,\n };\n}\n\n\nexport type ServerBaseUser = {\n setPrimaryEmail(email: string | null, options?: { verified?: boolean | undefined }): Promise<void>,\n\n readonly lastActiveAt: Date,\n\n readonly serverMetadata: any,\n setServerMetadata(metadata: any): Promise<void>,\n setClientReadOnlyMetadata(metadata: any): Promise<void>,\n\n /** Private details about the restriction (e.g., which sign-up rule triggered). Only visible to server access and above. */\n readonly restrictedByAdminPrivateDetails: string | null,\n /** Best-effort ISO country code captured at sign-up time from request geo headers. */\n readonly countryCode: string | null,\n /** Server-only risk scores used during sign-up risk evaluation. */\n readonly riskScores: {\n readonly signUp: {\n readonly bot: number,\n readonly freeTrialAbuse: number,\n },\n },\n\n createTeam(data: Omit<ServerTeamCreateOptions, \"creatorUserId\">): Promise<ServerTeam>,\n\n listContactChannels(): Promise<ServerContactChannel[]>,\n createContactChannel(data: ServerContactChannelCreateOptions): Promise<ServerContactChannel>,\n\n update(user: ServerUserUpdateOptions): Promise<void>,\n\n grantPermission(scope: Team, permissionId: string): Promise<void>,\n grantPermission(permissionId: string): Promise<void>,\n\n revokePermission(scope: Team, permissionId: string): Promise<void>,\n revokePermission(permissionId: string): Promise<void>,\n\n getPermission(scope: Team, permissionId: string): Promise<TeamPermission | null>,\n getPermission(permissionId: string): Promise<TeamPermission | null>,\n\n hasPermission(scope: Team, permissionId: string): Promise<boolean>,\n hasPermission(permissionId: string): Promise<boolean>,\n\n listPermissions(scope: Team, options?: { recursive?: boolean }): Promise<TeamPermission[]>,\n listPermissions(options?: { recursive?: boolean }): Promise<TeamPermission[]>,\n\n\n listOAuthProviders(): Promise<ServerOAuthProvider[]>,\n\n getOAuthProvider(id: string): Promise<ServerOAuthProvider | null>,\n\n /**\n * Creates a new session object with a refresh token for this user. Can be used to impersonate them.\n */\n createSession(options?: { expiresInMillis?: number, isImpersonation?: boolean }): Promise<{\n getTokens(): Promise<{ accessToken: string | null, refreshToken: string | null }>,\n }>,\n}\n& AsyncStoreProperty<\"team\", [id: string], ServerTeam | null, false>\n& AsyncStoreProperty<\"teams\", [options?: ServerListTeamsOptions], ServerTeam[] & { nextCursor: string | null }, true>\n& AsyncStoreProperty<\"permission\", [scope: Team, permissionId: string, options?: { direct?: boolean }], AdminTeamPermission | null, false>\n& AsyncStoreProperty<\"permissions\", [scope: Team, options?: { direct?: boolean }], AdminTeamPermission[], true>;\n\n/**\n * A user including sensitive fields that should only be used on the server, never sent to the client\n * (such as sensitive information and serverMetadata).\n */\nexport type ServerUser = ServerBaseUser & BaseUser & UserExtra & Customer<true>;\n\nexport type CurrentServerUser = Auth & ServerUser;\n\nexport type CurrentInternalServerUser = CurrentServerUser & InternalUserExtra;\n\nexport type ProjectCurrentServerUser<ProjectId> = ProjectId extends \"internal\" ? CurrentInternalServerUser : CurrentServerUser;\n\nexport type SyncedPartialServerUser = SyncedPartialUser & Pick<\n ServerUser,\n | \"serverMetadata\"\n>;\n\nexport type ServerUserUpdateOptions = {\n primaryEmail?: string | null,\n primaryEmailVerified?: boolean,\n primaryEmailAuthEnabled?: boolean,\n clientReadOnlyMetadata?: ReadonlyJson,\n serverMetadata?: ReadonlyJson,\n password?: string,\n restrictedByAdmin?: boolean,\n restrictedByAdminReason?: string | null,\n restrictedByAdminPrivateDetails?: string | null,\n countryCode?: string | null,\n riskScores?: {\n signUp: {\n bot: number,\n freeTrialAbuse: number,\n },\n },\n} & UserUpdateOptions;\nexport function serverUserUpdateOptionsToCrud(options: ServerUserUpdateOptions): CurrentUserCrud[\"Server\"][\"Update\"] {\n // Base update options\n const baseUpdate: CurrentUserCrud[\"Server\"][\"Update\"] = {\n display_name: options.displayName,\n primary_email: options.primaryEmail,\n client_metadata: options.clientMetadata,\n client_read_only_metadata: options.clientReadOnlyMetadata,\n server_metadata: options.serverMetadata,\n selected_team_id: options.selectedTeamId,\n primary_email_auth_enabled: options.primaryEmailAuthEnabled,\n primary_email_verified: options.primaryEmailVerified,\n password: options.password,\n profile_image_url: options.profileImageUrl,\n totp_secret_base64: options.totpMultiFactorSecret != null ? encodeBase64(options.totpMultiFactorSecret) : options.totpMultiFactorSecret,\n };\n return {\n ...baseUpdate,\n restricted_by_admin: options.restrictedByAdmin,\n restricted_by_admin_reason: options.restrictedByAdminReason,\n restricted_by_admin_private_details: options.restrictedByAdminPrivateDetails,\n country_code: options.countryCode,\n risk_scores: options.riskScores ? {\n sign_up: {\n bot: options.riskScores.signUp.bot,\n free_trial_abuse: options.riskScores.signUp.freeTrialAbuse,\n },\n } : undefined,\n };\n}\n\n\nexport type ServerUserCreateOptions = {\n primaryEmail?: string | null,\n primaryEmailAuthEnabled?: boolean,\n password?: string,\n otpAuthEnabled?: boolean,\n displayName?: string,\n primaryEmailVerified?: boolean,\n clientMetadata?: any,\n clientReadOnlyMetadata?: any,\n serverMetadata?: any,\n countryCode?: string | null,\n riskScores?: {\n signUp: {\n bot: number,\n freeTrialAbuse: number,\n },\n },\n}\nexport function serverUserCreateOptionsToCrud(options: ServerUserCreateOptions): UsersCrud[\"Server\"][\"Create\"] {\n return {\n primary_email: options.primaryEmail,\n password: options.password,\n otp_auth_enabled: options.otpAuthEnabled,\n primary_email_auth_enabled: options.primaryEmailAuthEnabled,\n display_name: options.displayName,\n primary_email_verified: options.primaryEmailVerified,\n client_metadata: options.clientMetadata,\n client_read_only_metadata: options.clientReadOnlyMetadata,\n server_metadata: options.serverMetadata,\n country_code: options.countryCode,\n risk_scores: options.riskScores ? {\n sign_up: {\n bot: options.riskScores.signUp.bot,\n free_trial_abuse: options.riskScores.signUp.freeTrialAbuse,\n },\n } : undefined,\n };\n}\n"],"mappings":";;AAwBA,MAAM,yBAAyB;AAE/B,SAAgB,yBAA2C,QAAc;CACvE,OAAO,OAAO,MAAM;CACpB,OAAO,IAAI,MAAM,QAAQ,EACvB,IAAI,QAAQ,MAAM,UAAU;EAC1B,IAAI,SAAS,QACX,OAAO,YAAY;EAErB,OAAO,OAAO;CAChB,EACF,CAAC;AACH;AAEA,SAAS,cAAqB;CAC5B,MAAM,IAAI,MAAM,sBAAsB;AACxC;AA0RA,SAAgB,wBAAwB,SAAiE;CACvG,OAAO;EACL,cAAc,QAAQ;EACtB,iBAAiB,QAAQ;EACzB,kBAAkB,QAAQ;EAC1B,oBAAoB,QAAQ,yBAAyB,OAAO,aAAa,QAAQ,qBAAqB,IAAI,QAAQ;EAClH,mBAAmB,QAAQ;EAC3B,kBAAkB,QAAQ;EAC1B,sBAAsB,QAAQ;EAC9B,eAAe,QAAQ;CACzB;AACF;AAkGA,SAAgB,8BAA8B,SAAuE;CAenH,OAAO;EAZL,cAAc,QAAQ;EACtB,eAAe,QAAQ;EACvB,iBAAiB,QAAQ;EACzB,2BAA2B,QAAQ;EACnC,iBAAiB,QAAQ;EACzB,kBAAkB,QAAQ;EAC1B,4BAA4B,QAAQ;EACpC,wBAAwB,QAAQ;EAChC,UAAU,QAAQ;EAClB,mBAAmB,QAAQ;EAC3B,oBAAoB,QAAQ,yBAAyB,OAAO,aAAa,QAAQ,qBAAqB,IAAI,QAAQ;EAIlH,qBAAqB,QAAQ;EAC7B,4BAA4B,QAAQ;EACpC,qCAAqC,QAAQ;EAC7C,cAAc,QAAQ;EACtB,aAAa,QAAQ,aAAa,EAChC,SAAS;GACP,KAAK,QAAQ,WAAW,OAAO;GAC/B,kBAAkB,QAAQ,WAAW,OAAO;EAC9C,EACF,IAAI,KAAA;CACN;AACF;AAqBA,SAAgB,8BAA8B,SAAiE;CAC7G,OAAO;EACL,eAAe,QAAQ;EACvB,UAAU,QAAQ;EAClB,kBAAkB,QAAQ;EAC1B,4BAA4B,QAAQ;EACpC,cAAc,QAAQ;EACtB,wBAAwB,QAAQ;EAChC,iBAAiB,QAAQ;EACzB,2BAA2B,QAAQ;EACnC,iBAAiB,QAAQ;EACzB,cAAc,QAAQ;EACtB,aAAa,QAAQ,aAAa,EAChC,SAAS;GACP,KAAK,QAAQ,WAAW,OAAO;GAC/B,kBAAkB,QAAQ,WAAW,OAAO;EAC9C,EACF,IAAI,KAAA;CACN;AACF"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/lib/hexclave-app/users/index.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { KnownErrors } from \"@hexclave/shared\";\nimport { CurrentUserCrud } from \"@hexclave/shared/dist/interface/crud/current-user\";\nimport { UsersCrud } from \"@hexclave/shared/dist/interface/crud/users\";\nimport type { RestrictedReason } from \"@hexclave/shared/dist/schema-fields\";\nimport { InternalSession } from \"@hexclave/shared/dist/sessions\";\nimport { encodeBase64 } from \"@hexclave/shared/dist/utils/bytes\";\nimport { GeoInfo } from \"@hexclave/shared/dist/utils/geo\";\nimport { ReadonlyJson } from \"@hexclave/shared/dist/utils/json\";\nimport { ProviderType } from \"@hexclave/shared/dist/utils/oauth\";\nimport { Result } from \"@hexclave/shared/dist/utils/results\";\nimport { ApiKeyCreationOptions, UserApiKey, UserApiKeyFirstView } from \"../api-keys\";\nimport { AsyncStoreProperty, AuthLike } from \"../common\";\nimport { DeprecatedOAuthConnection, OAuthConnection } from \"../connected-accounts\";\nimport { ContactChannel, ContactChannelCreateOptions, ServerContactChannel, ServerContactChannelCreateOptions } from \"../contact-channels\";\nimport { Customer } from \"../customers\";\nimport { NotificationCategory } from \"../notification-categories\";\nimport { AdminTeamPermission, TeamPermission } from \"../permissions\";\nimport { AdminOwnedProject, AdminProjectCreateOptions } from \"../projects\";\nimport { EditableTeamMemberProfile, ReceivedTeamInvitation, ServerListTeamsOptions, ServerTeam, ServerTeamCreateOptions, Team, TeamCreateOptions } from \"../teams\";\n\nconst userGetterErrorMessage = \"Hexclave: useUser() already returns the user object. Use `const user = useUser()` (or `const user = await app.getUser()`) instead of destructuring it like `const { user } = ...`.\";\n\nexport function withUserDestructureGuard<T extends object>(target: T): T {\n Object.freeze(target);\n return new Proxy(target, {\n get(target, prop, receiver) {\n if (prop === \"user\") {\n return guardGetter();\n }\n return target[prop as keyof T];\n },\n });\n}\n\nfunction guardGetter(): never {\n throw new Error(userGetterErrorMessage);\n}\n\nexport type OAuthProvider = {\n readonly id: string,\n readonly type: string,\n readonly userId: string,\n readonly accountId?: string,\n readonly email?: string,\n readonly allowSignIn: boolean,\n readonly allowConnectedAccounts: boolean,\n update(data: { allowSignIn?: boolean, allowConnectedAccounts?: boolean }): Promise<Result<void,\n InstanceType<typeof KnownErrors.OAuthProviderAccountIdAlreadyUsedForSignIn>\n >>,\n delete(): Promise<void>,\n};\n\nexport type ServerOAuthProvider = {\n readonly id: string,\n readonly type: string,\n readonly userId: string,\n readonly accountId: string,\n readonly email?: string,\n readonly allowSignIn: boolean,\n readonly allowConnectedAccounts: boolean,\n update(data: { accountId?: string, email?: string, allowSignIn?: boolean, allowConnectedAccounts?: boolean }): Promise<Result<void,\n InstanceType<typeof KnownErrors.OAuthProviderAccountIdAlreadyUsedForSignIn>\n >>,\n delete(): Promise<void>,\n};\n\n\n/**\n * Contains everything related to the current user session.\n */\nexport type Auth = AuthLike<{}> & {\n readonly _internalSession: InternalSession,\n readonly currentSession: {\n getTokens(): Promise<{ accessToken: string | null, refreshToken: string | null }>,\n },\n};\n\n/**\n * ```\n * +----------+-------------+-------------------+\n * | \\ | !Server | Server |\n * +----------+-------------+-------------------+\n * | !Session | User | ServerUser |\n * | Session | CurrentUser | CurrentServerUser |\n * +----------+-------------+-------------------+\n * ```\n *\n * The fields on each of these types are available iff:\n * BaseUser: true\n * Auth: Session\n * ServerBaseUser: Server\n * UserExtra: Session OR Server\n *\n * The types are defined as follows (in the typescript manner):\n * User = BaseUser\n * CurrentUser = BaseUser & Auth & UserExtra\n * ServerUser = BaseUser & ServerBaseUser & UserExtra\n * CurrentServerUser = BaseUser & ServerBaseUser & Auth & UserExtra\n **/\n\nexport type BaseUser = {\n readonly id: string,\n\n readonly displayName: string | null,\n\n /**\n * The user's email address.\n *\n * Note: This might NOT be unique across multiple users, so always use `id` for unique identification.\n */\n readonly primaryEmail: string | null,\n readonly primaryEmailVerified: boolean,\n readonly profileImageUrl: string | null,\n\n readonly signedUpAt: Date,\n\n readonly clientMetadata: any,\n readonly clientReadOnlyMetadata: any,\n\n /**\n * Whether the user has a password set.\n */\n readonly hasPassword: boolean,\n readonly otpAuthEnabled: boolean,\n readonly passkeyAuthEnabled: boolean,\n\n readonly isMultiFactorRequired: boolean,\n readonly isAnonymous: boolean,\n /**\n * Whether the user is in restricted state (signed up but hasn't completed onboarding requirements).\n * For example, if email verification is required but the user hasn't verified their email yet.\n */\n readonly isRestricted: boolean,\n /**\n * The reason why the user is restricted, e.g., { type: \"email_not_verified\" }, { type: \"anonymous\" }, or { type: \"restricted_by_administrator\" }.\n * Null if the user is not restricted.\n */\n readonly restrictedReason: RestrictedReason | null,\n /** Whether the user is restricted by an administrator. Can be set manually or by sign-up rules. */\n readonly restrictedByAdmin: boolean,\n /**\n * Public reason shown to the user explaining why an administrator restricted them, or null if none was given.\n *\n * This is intentionally readable by the user themselves (unlike `restrictedByAdminPrivateDetails`, which is\n * server-only), so onboarding screens can tell them why they can't continue.\n */\n readonly restrictedByAdminReason: string | null,\n toClientJson(): CurrentUserCrud[\"Client\"][\"Read\"],\n\n /**\n * @deprecated, use contact channel's usedForAuth instead\n */\n readonly emailAuthEnabled: boolean,\n /**\n * @deprecated\n */\n readonly oauthProviders: readonly { id: string }[],\n readonly externalAuthProviders: readonly { id: string }[],\n}\n\nexport type UserExtra = {\n setDisplayName(displayName: string | null): Promise<void>,\n /** @deprecated Use contact channel's sendVerificationEmail instead */\n sendVerificationEmail(): Promise<KnownErrors[\"EmailAlreadyVerified\"] | void>,\n setClientMetadata(metadata: any): Promise<void>,\n updatePassword(options: { oldPassword: string, newPassword: string}): Promise<KnownErrors[\"PasswordConfirmationMismatch\"] | KnownErrors[\"PasswordRequirementsNotMet\"] | void>,\n setPassword(options: { password: string }): Promise<KnownErrors[\"PasswordRequirementsNotMet\"] | void>,\n\n /**\n * A shorthand method to update multiple fields of the user at once.\n */\n update(update: UserUpdateOptions): Promise<void>,\n\n listContactChannels(): Promise<ContactChannel[]>,\n createContactChannel(data: ContactChannelCreateOptions): Promise<ContactChannel>,\n\n listNotificationCategories(): Promise<NotificationCategory[]>,\n\n delete(): Promise<void>,\n\n /** @deprecated Use `getOrLinkConnectedAccount` for redirect behavior, or `getConnectedAccount({ provider, providerAccountId })` for existence check. */\n getConnectedAccount(id: ProviderType, options: { or: 'redirect', scopes?: string[] }): Promise<DeprecatedOAuthConnection>,\n /** @deprecated Use `getConnectedAccount({ provider, providerAccountId })` for existence check, or `getOrLinkConnectedAccount` for redirect behavior. */\n getConnectedAccount(id: ProviderType, options?: { or?: 'redirect' | 'throw' | 'return-null', scopes?: string[] }): Promise<DeprecatedOAuthConnection | null>,\n /** Get a specific connected account by provider and providerAccountId. Returns null if not found. */\n getConnectedAccount(account: { provider: string, providerAccountId: string }): Promise<OAuthConnection | null>,\n\n\n /** List all connected accounts for this user (only those with allowConnectedAccounts enabled). */\n listConnectedAccounts(): Promise<OAuthConnection[]>,\n /** React hook to list all connected accounts. */\n /** Redirect the user to the OAuth flow to link a new connected account. Always redirects, never returns. */\n linkConnectedAccount(provider: string, options?: { scopes?: string[] }): Promise<void>,\n /** Get a connected account for the given provider, or redirect to link one if none exists or the token/scopes are insufficient. */\n getOrLinkConnectedAccount(provider: string, options?: { scopes?: string[] }): Promise<OAuthConnection>,\n /** React hook: get a connected account for the given provider, or redirect to link one if none exists or the token/scopes are insufficient. */\n\n hasPermission(scope: Team, permissionId: string): Promise<boolean>,\n hasPermission(permissionId: string): Promise<boolean>,\n\n getPermission(scope: Team, permissionId: string): Promise<TeamPermission | null>,\n getPermission(permissionId: string): Promise<TeamPermission | null>,\n\n listPermissions(scope: Team, options?: { recursive?: boolean }): Promise<TeamPermission[]>,\n listPermissions(options?: { recursive?: boolean }): Promise<TeamPermission[]>,\n\n\n readonly selectedTeam: Team | null,\n setSelectedTeam(teamOrId: string | Team | null): Promise<void>,\n createTeam(data: TeamCreateOptions): Promise<Team>,\n leaveTeam(team: Team): Promise<void>,\n\n /**\n * Lists all pending team invitations sent to any of the current user's verified email addresses.\n *\n * This allows the user to discover which teams have invited them, even if they haven't\n * joined those teams yet. Only invitations sent to verified email addresses are included.\n *\n * @returns An array of `ReceivedTeamInvitation` objects, each containing the team ID, team\n * display name, recipient email, and expiration date.\n *\n * @example\n * ```ts\n * const invitations = await user.listTeamInvitations();\n * for (const invitation of invitations) {\n * console.log(`Invited to ${invitation.teamDisplayName} via ${invitation.recipientEmail}`);\n * }\n * ```\n */\n listTeamInvitations(): Promise<ReceivedTeamInvitation[]>,\n /**\n * Lists all pending team invitations sent to any of the current user's verified email addresses.\n *\n * React hook version of `listTeamInvitations()`. Automatically re-renders when invitations change.\n */\n\n getActiveSessions(): Promise<ActiveSession[]>,\n revokeSession(sessionId: string): Promise<void>,\n getTeamProfile(team: Team): Promise<EditableTeamMemberProfile>,\n\n createApiKey(options: ApiKeyCreationOptions<\"user\">): Promise<UserApiKeyFirstView>,\n\n listOAuthProviders(): Promise<OAuthProvider[]>,\n\n getOAuthProvider(id: string): Promise<OAuthProvider | null>,\n\n registerPasskey(options?: { hostname?: string }): Promise<Result<undefined, KnownErrors[\"PasskeyRegistrationFailed\"] | KnownErrors[\"PasskeyWebAuthnError\"]>>,\n}\n& AsyncStoreProperty<\"apiKeys\", [], UserApiKey[], true>\n& AsyncStoreProperty<\"team\", [id: string], Team | null, false>\n& AsyncStoreProperty<\"teams\", [], Team[], true>\n& AsyncStoreProperty<\"teamInvitations\", [], ReceivedTeamInvitation[], true>\n& AsyncStoreProperty<\"permission\", [scope: Team, permissionId: string, options?: { recursive?: boolean }], TeamPermission | null, false>\n& AsyncStoreProperty<\"permissions\", [scope: Team, options?: { recursive?: boolean }], TeamPermission[], true>;\n\nexport type InternalUserExtra =\n & {\n createProject(newProject: AdminProjectCreateOptions): Promise<AdminOwnedProject>,\n transferProject(projectIdToTransfer: string, newTeamId: string): Promise<void>,\n }\n & AsyncStoreProperty<\"ownedProjects\", [], AdminOwnedProject[], true>\n\nexport type User = BaseUser;\n\nexport type CurrentUser = BaseUser & Auth & UserExtra & Customer;\n\nexport type CurrentInternalUser = CurrentUser & InternalUserExtra;\n\nexport type ProjectCurrentUser<ProjectId> = ProjectId extends \"internal\" ? CurrentInternalUser : CurrentUser;\n\nexport type TokenPartialUser = Pick<\n User,\n | \"id\"\n | \"displayName\"\n | \"primaryEmail\"\n | \"primaryEmailVerified\"\n | \"isAnonymous\"\n | \"isMultiFactorRequired\"\n | \"isRestricted\"\n | \"restrictedReason\"\n> & {\n /**\n * The ID of the user's selected team, read from the `selected_team_id` claim of the access token or Convex identity.\n */\n readonly selectedTeamId: string | null,\n}\n\nexport type SyncedPartialUser = TokenPartialUser & Pick<\n User,\n | \"id\"\n | \"displayName\"\n | \"primaryEmail\"\n | \"primaryEmailVerified\"\n | \"profileImageUrl\"\n | \"signedUpAt\"\n | \"clientMetadata\"\n | \"clientReadOnlyMetadata\"\n | \"isAnonymous\"\n | \"hasPassword\"\n | \"isRestricted\"\n | \"restrictedReason\"\n>;\n\n\nexport type ActiveSession = {\n id: string,\n userId: string,\n createdAt: Date,\n isImpersonation: boolean,\n lastUsedAt: Date | undefined,\n isCurrentSession: boolean,\n geoInfo?: GeoInfo,\n};\n\nexport type UserUpdateOptions = {\n displayName?: string | null,\n clientMetadata?: ReadonlyJson,\n selectedTeamId?: string | null,\n totpMultiFactorSecret?: Uint8Array | null,\n profileImageUrl?: string | null,\n otpAuthEnabled?: boolean,\n passkeyAuthEnabled?: boolean,\n primaryEmail?: string | null,\n}\nexport function userUpdateOptionsToCrud(options: UserUpdateOptions): CurrentUserCrud[\"Client\"][\"Update\"] {\n return {\n display_name: options.displayName,\n client_metadata: options.clientMetadata,\n selected_team_id: options.selectedTeamId,\n totp_secret_base64: options.totpMultiFactorSecret != null ? encodeBase64(options.totpMultiFactorSecret) : options.totpMultiFactorSecret,\n profile_image_url: options.profileImageUrl,\n otp_auth_enabled: options.otpAuthEnabled,\n passkey_auth_enabled: options.passkeyAuthEnabled,\n primary_email: options.primaryEmail,\n };\n}\n\n\nexport type ServerBaseUser = {\n /**\n * The selected team is a `ServerTeam` when non-null, so `listUsers()` returns full member details\n * without fetching the team again.\n */\n readonly selectedTeam: ServerTeam | null,\n\n setPrimaryEmail(email: string | null, options?: { verified?: boolean | undefined }): Promise<void>,\n\n readonly lastActiveAt: Date,\n\n readonly serverMetadata: any,\n setServerMetadata(metadata: any): Promise<void>,\n setClientReadOnlyMetadata(metadata: any): Promise<void>,\n\n /** Private details about the restriction (e.g., which sign-up rule triggered). Only visible to server access and above. */\n readonly restrictedByAdminPrivateDetails: string | null,\n /** Best-effort ISO country code captured at sign-up time from request geo headers. */\n readonly countryCode: string | null,\n /** Server-only risk scores used during sign-up risk evaluation. */\n readonly riskScores: {\n readonly signUp: {\n readonly bot: number,\n readonly freeTrialAbuse: number,\n },\n },\n\n createTeam(data: Omit<ServerTeamCreateOptions, \"creatorUserId\">): Promise<ServerTeam>,\n\n listContactChannels(): Promise<ServerContactChannel[]>,\n createContactChannel(data: ServerContactChannelCreateOptions): Promise<ServerContactChannel>,\n\n update(user: ServerUserUpdateOptions): Promise<void>,\n\n grantPermission(scope: Team, permissionId: string): Promise<void>,\n grantPermission(permissionId: string): Promise<void>,\n\n revokePermission(scope: Team, permissionId: string): Promise<void>,\n revokePermission(permissionId: string): Promise<void>,\n\n getPermission(scope: Team, permissionId: string): Promise<TeamPermission | null>,\n getPermission(permissionId: string): Promise<TeamPermission | null>,\n\n hasPermission(scope: Team, permissionId: string): Promise<boolean>,\n hasPermission(permissionId: string): Promise<boolean>,\n\n listPermissions(scope: Team, options?: { recursive?: boolean }): Promise<TeamPermission[]>,\n listPermissions(options?: { recursive?: boolean }): Promise<TeamPermission[]>,\n\n\n listOAuthProviders(): Promise<ServerOAuthProvider[]>,\n\n getOAuthProvider(id: string): Promise<ServerOAuthProvider | null>,\n\n /**\n * Creates a new session object with a refresh token for this user. Can be used to impersonate them.\n */\n createSession(options?: { expiresInMillis?: number, isImpersonation?: boolean }): Promise<{\n getTokens(): Promise<{ accessToken: string | null, refreshToken: string | null }>,\n }>,\n}\n& AsyncStoreProperty<\"team\", [id: string], ServerTeam | null, false>\n& AsyncStoreProperty<\"teams\", [options?: ServerListTeamsOptions], ServerTeam[] & { nextCursor: string | null }, true>\n& AsyncStoreProperty<\"permission\", [scope: Team, permissionId: string, options?: { direct?: boolean }], AdminTeamPermission | null, false>\n& AsyncStoreProperty<\"permissions\", [scope: Team, options?: { direct?: boolean }], AdminTeamPermission[], true>;\n\n/**\n * A user including sensitive fields that should only be used on the server, never sent to the client\n * (such as sensitive information and serverMetadata).\n */\nexport type ServerUser = ServerBaseUser & BaseUser & UserExtra & Customer<true>;\n\nexport type CurrentServerUser = Auth & ServerUser;\n\nexport type CurrentInternalServerUser = CurrentServerUser & InternalUserExtra;\n\nexport type ProjectCurrentServerUser<ProjectId> = ProjectId extends \"internal\" ? CurrentInternalServerUser : CurrentServerUser;\n\nexport type SyncedPartialServerUser = SyncedPartialUser & Pick<\n ServerUser,\n | \"serverMetadata\"\n>;\n\nexport type ServerUserUpdateOptions = {\n primaryEmail?: string | null,\n primaryEmailVerified?: boolean,\n primaryEmailAuthEnabled?: boolean,\n clientReadOnlyMetadata?: ReadonlyJson,\n serverMetadata?: ReadonlyJson,\n password?: string,\n restrictedByAdmin?: boolean,\n restrictedByAdminReason?: string | null,\n restrictedByAdminPrivateDetails?: string | null,\n countryCode?: string | null,\n riskScores?: {\n signUp: {\n bot: number,\n freeTrialAbuse: number,\n },\n },\n} & UserUpdateOptions;\nexport function serverUserUpdateOptionsToCrud(options: ServerUserUpdateOptions): CurrentUserCrud[\"Server\"][\"Update\"] {\n // Base update options\n const baseUpdate: CurrentUserCrud[\"Server\"][\"Update\"] = {\n display_name: options.displayName,\n primary_email: options.primaryEmail,\n client_metadata: options.clientMetadata,\n client_read_only_metadata: options.clientReadOnlyMetadata,\n server_metadata: options.serverMetadata,\n selected_team_id: options.selectedTeamId,\n primary_email_auth_enabled: options.primaryEmailAuthEnabled,\n primary_email_verified: options.primaryEmailVerified,\n password: options.password,\n profile_image_url: options.profileImageUrl,\n totp_secret_base64: options.totpMultiFactorSecret != null ? encodeBase64(options.totpMultiFactorSecret) : options.totpMultiFactorSecret,\n };\n return {\n ...baseUpdate,\n restricted_by_admin: options.restrictedByAdmin,\n restricted_by_admin_reason: options.restrictedByAdminReason,\n restricted_by_admin_private_details: options.restrictedByAdminPrivateDetails,\n country_code: options.countryCode,\n risk_scores: options.riskScores ? {\n sign_up: {\n bot: options.riskScores.signUp.bot,\n free_trial_abuse: options.riskScores.signUp.freeTrialAbuse,\n },\n } : undefined,\n };\n}\n\n\nexport type ServerUserCreateOptions = {\n primaryEmail?: string | null,\n primaryEmailAuthEnabled?: boolean,\n password?: string,\n otpAuthEnabled?: boolean,\n displayName?: string,\n primaryEmailVerified?: boolean,\n clientMetadata?: any,\n clientReadOnlyMetadata?: any,\n serverMetadata?: any,\n countryCode?: string | null,\n riskScores?: {\n signUp: {\n bot: number,\n freeTrialAbuse: number,\n },\n },\n}\nexport function serverUserCreateOptionsToCrud(options: ServerUserCreateOptions): UsersCrud[\"Server\"][\"Create\"] {\n return {\n primary_email: options.primaryEmail,\n password: options.password,\n otp_auth_enabled: options.otpAuthEnabled,\n primary_email_auth_enabled: options.primaryEmailAuthEnabled,\n display_name: options.displayName,\n primary_email_verified: options.primaryEmailVerified,\n client_metadata: options.clientMetadata,\n client_read_only_metadata: options.clientReadOnlyMetadata,\n server_metadata: options.serverMetadata,\n country_code: options.countryCode,\n risk_scores: options.riskScores ? {\n sign_up: {\n bot: options.riskScores.signUp.bot,\n free_trial_abuse: options.riskScores.signUp.freeTrialAbuse,\n },\n } : undefined,\n };\n}\n"],"mappings":";;AAwBA,MAAM,yBAAyB;AAE/B,SAAgB,yBAA2C,QAAc;CACvE,OAAO,OAAO,MAAM;CACpB,OAAO,IAAI,MAAM,QAAQ,EACvB,IAAI,QAAQ,MAAM,UAAU;EAC1B,IAAI,SAAS,QACX,OAAO,YAAY;EAErB,OAAO,OAAO;CAChB,EACF,CAAC;AACH;AAEA,SAAS,cAAqB;CAC5B,MAAM,IAAI,MAAM,sBAAsB;AACxC;AAgSA,SAAgB,wBAAwB,SAAiE;CACvG,OAAO;EACL,cAAc,QAAQ;EACtB,iBAAiB,QAAQ;EACzB,kBAAkB,QAAQ;EAC1B,oBAAoB,QAAQ,yBAAyB,OAAO,aAAa,QAAQ,qBAAqB,IAAI,QAAQ;EAClH,mBAAmB,QAAQ;EAC3B,kBAAkB,QAAQ;EAC1B,sBAAsB,QAAQ;EAC9B,eAAe,QAAQ;CACzB;AACF;AAwGA,SAAgB,8BAA8B,SAAuE;CAenH,OAAO;EAZL,cAAc,QAAQ;EACtB,eAAe,QAAQ;EACvB,iBAAiB,QAAQ;EACzB,2BAA2B,QAAQ;EACnC,iBAAiB,QAAQ;EACzB,kBAAkB,QAAQ;EAC1B,4BAA4B,QAAQ;EACpC,wBAAwB,QAAQ;EAChC,UAAU,QAAQ;EAClB,mBAAmB,QAAQ;EAC3B,oBAAoB,QAAQ,yBAAyB,OAAO,aAAa,QAAQ,qBAAqB,IAAI,QAAQ;EAIlH,qBAAqB,QAAQ;EAC7B,4BAA4B,QAAQ;EACpC,qCAAqC,QAAQ;EAC7C,cAAc,QAAQ;EACtB,aAAa,QAAQ,aAAa,EAChC,SAAS;GACP,KAAK,QAAQ,WAAW,OAAO;GAC/B,kBAAkB,QAAQ,WAAW,OAAO;EAC9C,EACF,IAAI,KAAA;CACN;AACF;AAqBA,SAAgB,8BAA8B,SAAiE;CAC7G,OAAO;EACL,eAAe,QAAQ;EACvB,UAAU,QAAQ;EAClB,kBAAkB,QAAQ;EAC1B,4BAA4B,QAAQ;EACpC,cAAc,QAAQ;EACtB,wBAAwB,QAAQ;EAChC,iBAAiB,QAAQ;EACzB,2BAA2B,QAAQ;EACnC,iBAAiB,QAAQ;EACzB,cAAc,QAAQ;EACtB,aAAa,QAAQ,aAAa,EAChC,SAAS;GACP,KAAK,QAAQ,WAAW,OAAO;GAC/B,kBAAkB,QAAQ,WAAW,OAAO;EAC9C,EACF,IAAI,KAAA;CACN;AACF"}
@@ -1,4 +1,4 @@
1
- import { t as AsyncStoreProperty } from "./common-BDyEKSM6.js";
1
+ import { t as AsyncStoreProperty } from "./common-Dii3iHJR.js";
2
2
  import { inlineProductSchema } from "@hexclave/shared/dist/schema-fields";
3
3
  import * as yup from "yup";
4
4
 
@@ -126,4 +126,4 @@ type Customer<IsServer extends boolean = false> = {
126
126
  } : {});
127
127
  //#endregion
128
128
  export { CustomerInvoiceStatus as a, CustomerInvoicesRequestOptions as c, CustomerProductsList as d, CustomerProductsListOptions as f, ServerItem as g, Item as h, CustomerInvoice as i, CustomerPaymentMethodSetupIntent as l, InlineProduct as m, CustomerBilling as n, CustomerInvoicesList as o, CustomerProductsRequestOptions as p, CustomerDefaultPaymentMethod as r, CustomerInvoicesListOptions as s, Customer as t, CustomerProduct as u };
129
- //# sourceMappingURL=index-ZiEXZJBF.d.ts.map
129
+ //# sourceMappingURL=index-BTa6Yu7N.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-ZiEXZJBF.d.ts","names":[],"sources":["../src/lib/hexclave-app/customers/index.ts"],"mappings":";;;;;KAQY,aAAA,GAAgB,GAAA,CAAI,SAAS,QAAQ,mBAAA;AAAA,KAErC,IAAA;EACV,WAAA;EAHuB;;;EAOvB,QAAA;EAP8B;;;EAW9B,mBAAA;AAAA;AAAA,KAGU,UAAA,GAAa,IAAA;EACvB,gBAAA,CAAiB,MAAA,WAAiB,OAAA;EAbpB;;;;;EAmBd,gBAAA,CAAiB,MAAA,WAAiB,OAAA;EAPxB;;;;;EAaV,mBAAA,CAAoB,MAAA,WAAiB,OAAA;AAAA;AAAA,KAG3B,eAAA;EACV,EAAA;EACA,QAAA;EACA,WAAA;EACA,YAAA;EACA,YAAA;EACA,SAAA,WAfiB;EAiBjB,IAAA;EACA,YAAA;IACE,cAAA;IACA,gBAAA,EAAkB,IAAA;IAClB,iBAAA;IACA,YAAA;EAAA;EAEF,aAAA,GAAgB,KAAA;IACd,SAAA;IACA,WAAA;IACA,MAAA,EAAQ,aAAA;EAAA;AAAA;AAAA,KAIA,oBAAA,GAAuB,eAAe;EAChD,UAAU;AAAA;AAAA,KAGA,2BAAA;EACV,MAAA;EACA,KAAK;AAAA;AAAA,KAGK,8BAAA;EACL,MAAA;AAAA,IAAmB,2BAAA;EACnB,MAAA;AAAA,IAAmB,2BAAA;EACnB,gBAAA;AAAA,IAA6B,2BAAA;AAAA,KAExB,qBAAA;AAAA,KAEA,eAAA;EACV,SAAA,EAAW,IAAA;EACX,MAAA,EAAQ,qBAAqB;EAC7B,WAAA;EACA,gBAAA;AAAA;AAAA,KAGU,oBAAA,GAAuB,eAAe;EAChD,UAAU;AAAA;AAAA,KAGA,2BAAA;EACV,MAAA;EACA,KAAK;AAAA;AAAA,KAGK,8BAAA;EACL,MAAA;AAAA,IAAmB,2BAAA;EACnB,MAAA;AAAA,IAAmB,2BAA2B;AAAA,KAEzC,4BAAA;EACV,EAAA;EACA,KAAA;EACA,KAAA;EACA,SAAA;EACA,QAAA;AAAA;AAAA,KAGU,eAAA;EACV,WAAA;EACA,oBAAA,EAAsB,4BAA4B;AAAA;AAAA,KAGxC,gCAAA;EACV,YAAA;EACA,eAAe;AAAA;AAAA,KAGL,QAAA;EAAA,SAEC,EAAA;EAET,iBAAA,CAAkB,OAAA;IACZ,SAAA;IAAmB,SAAA;EAAA,KACpB,QAAA;IAA0B,OAAA,EAAS,aAAA;IAAe,SAAA;EAAA,cACnD,OAAA;EAEJ,8BAAA,IAAkC,OAAA,CAAQ,gCAAA;EAE1C,sCAAA,CAAuC,aAAA,WAAwB,OAAA,CAAQ,4BAAA;EAEvE,kBAAA,CAAmB,OAAA;IAAW,aAAA;IAAuB,WAAA;IAAqB,OAAA;IAAkB,QAAA;EAAA,IAAsB,OAAA;AAAA,IAElH,kBAAA,gBAGA,eAAA,WAGA,kBAAA,UAEC,MAAA,WACD,QAAA,gBAAwB,UAAA,GAAa,IAAA,WAGrC,kBAAA,cAEC,OAAA,GAAU,2BAAA,GACX,oBAAA,UAGA,kBAAA,cAEC,OAAA,GAAU,2BAAA,GACX,oBAAA,WAGC,QAAA;EACD,YAAA,CACE,OAAA;IAAW,SAAA;IAAmB,QAAA;EAAA;IAAwB,OAAA,EAAS,aAAA;IAAe,QAAA;EAAA,IAC7E,OAAA;AAAA"}
1
+ {"version":3,"file":"index-BTa6Yu7N.d.ts","names":[],"sources":["../src/lib/hexclave-app/customers/index.ts"],"mappings":";;;;;KAQY,aAAA,GAAgB,GAAA,CAAI,SAAS,QAAQ,mBAAA;AAAA,KAErC,IAAA;EACV,WAAA;EAHuB;;;EAOvB,QAAA;EAP8B;;;EAW9B,mBAAA;AAAA;AAAA,KAGU,UAAA,GAAa,IAAA;EACvB,gBAAA,CAAiB,MAAA,WAAiB,OAAA;EAbpB;;;;;EAmBd,gBAAA,CAAiB,MAAA,WAAiB,OAAA;EAPxB;;;;;EAaV,mBAAA,CAAoB,MAAA,WAAiB,OAAA;AAAA;AAAA,KAG3B,eAAA;EACV,EAAA;EACA,QAAA;EACA,WAAA;EACA,YAAA;EACA,YAAA;EACA,SAAA,WAfiB;EAiBjB,IAAA;EACA,YAAA;IACE,cAAA;IACA,gBAAA,EAAkB,IAAA;IAClB,iBAAA;IACA,YAAA;EAAA;EAEF,aAAA,GAAgB,KAAA;IACd,SAAA;IACA,WAAA;IACA,MAAA,EAAQ,aAAA;EAAA;AAAA;AAAA,KAIA,oBAAA,GAAuB,eAAe;EAChD,UAAU;AAAA;AAAA,KAGA,2BAAA;EACV,MAAA;EACA,KAAK;AAAA;AAAA,KAGK,8BAAA;EACL,MAAA;AAAA,IAAmB,2BAAA;EACnB,MAAA;AAAA,IAAmB,2BAAA;EACnB,gBAAA;AAAA,IAA6B,2BAAA;AAAA,KAExB,qBAAA;AAAA,KAEA,eAAA;EACV,SAAA,EAAW,IAAA;EACX,MAAA,EAAQ,qBAAqB;EAC7B,WAAA;EACA,gBAAA;AAAA;AAAA,KAGU,oBAAA,GAAuB,eAAe;EAChD,UAAU;AAAA;AAAA,KAGA,2BAAA;EACV,MAAA;EACA,KAAK;AAAA;AAAA,KAGK,8BAAA;EACL,MAAA;AAAA,IAAmB,2BAAA;EACnB,MAAA;AAAA,IAAmB,2BAA2B;AAAA,KAEzC,4BAAA;EACV,EAAA;EACA,KAAA;EACA,KAAA;EACA,SAAA;EACA,QAAA;AAAA;AAAA,KAGU,eAAA;EACV,WAAA;EACA,oBAAA,EAAsB,4BAA4B;AAAA;AAAA,KAGxC,gCAAA;EACV,YAAA;EACA,eAAe;AAAA;AAAA,KAGL,QAAA;EAAA,SAEC,EAAA;EAET,iBAAA,CAAkB,OAAA;IACZ,SAAA;IAAmB,SAAA;EAAA,KACpB,QAAA;IAA0B,OAAA,EAAS,aAAA;IAAe,SAAA;EAAA,cACnD,OAAA;EAEJ,8BAAA,IAAkC,OAAA,CAAQ,gCAAA;EAE1C,sCAAA,CAAuC,aAAA,WAAwB,OAAA,CAAQ,4BAAA;EAEvE,kBAAA,CAAmB,OAAA;IAAW,aAAA;IAAuB,WAAA;IAAqB,OAAA;IAAkB,QAAA;EAAA,IAAsB,OAAA;AAAA,IAElH,kBAAA,gBAGA,eAAA,WAGA,kBAAA,UAEC,MAAA,WACD,QAAA,gBAAwB,UAAA,GAAa,IAAA,WAGrC,kBAAA,cAEC,OAAA,GAAU,2BAAA,GACX,oBAAA,UAGA,kBAAA,cAEC,OAAA,GAAU,2BAAA,GACX,oBAAA,WAGC,QAAA;EACD,YAAA,CACE,OAAA;IAAW,SAAA;IAAmB,QAAA;EAAA;IAAwB,OAAA,EAAS,aAAA;IAAe,QAAA;EAAA,IAC7E,OAAA;AAAA"}
@@ -1,4 +1,4 @@
1
- import { t as AsyncStoreProperty } from "./common-BDyEKSM6.js";
1
+ import { t as AsyncStoreProperty } from "./common-Dii3iHJR.js";
2
2
 
3
3
  //#region src/lib/hexclave-app/data-vault/index.d.ts
4
4
  type DataVaultStore = {
@@ -11,4 +11,4 @@ type DataVaultStore = {
11
11
  }], string | null, false>;
12
12
  //#endregion
13
13
  export { DataVaultStore as t };
14
- //# sourceMappingURL=index-DLPccxVU.d.ts.map
14
+ //# sourceMappingURL=index-DlOcbI9W.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-DLPccxVU.d.ts","names":[],"sources":["../src/lib/hexclave-app/data-vault/index.ts"],"mappings":";;;KAMY,cAAA;EAER,EAAA;EACA,QAAA,GAAW,GAAA,UAAa,KAAA,UAAe,OAAA;IAAW,MAAA;EAAA,MAAqB,OAAA;AAAA,IAExE,kBAAkB,WAAW,GAAA,UAAa,OAAA;EAAW,MAAA;AAAA"}
1
+ {"version":3,"file":"index-DlOcbI9W.d.ts","names":[],"sources":["../src/lib/hexclave-app/data-vault/index.ts"],"mappings":";;;KAMY,cAAA;EAER,EAAA;EACA,QAAA,GAAW,GAAA,UAAa,KAAA,UAAe,OAAA;IAAW,MAAA;EAAA,MAAqB,OAAA;AAAA,IAExE,kBAAkB,WAAW,GAAA,UAAa,OAAA;EAAW,MAAA;AAAA"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as ResolvedHandlerUrls, f as HandlerUrls, p as OAuthScopesOnSignIn, s as GetCurrentUserOptions, u as HandlerUrlOptions, y as hexclaveAppInternalsSymbol } from "./common-BDyEKSM6.js";
1
+ import { C as workosTokenStore, S as hexclaveAppInternalsSymbol, b as betterAuthTokenStore, c as GetCurrentUserOptions, d as HandlerUrlOptions, m as OAuthScopesOnSignIn, o as ExternalTokenStore, p as HandlerUrls, v as ResolvedHandlerUrls, x as clerkTokenStore } from "./common-Dii3iHJR.js";
2
2
  import { S as AdminSentEmail, b as AdminEmailOutboxStatus, d as AdminEmailOutboxRecipient, t as AdminEmailOutbox, v as AdminEmailOutboxSimpleStatus, x as AdminSendAttemptError } from "./index-CBDR4cNg.js";
3
3
  import { a as InternalApiKeyFirstView, i as InternalApiKeyCreateOptions, n as InternalApiKeyBase, r as InternalApiKeyBaseCrudRead, t as InternalApiKey } from "./index-TUtJOdMm.js";
4
4
  import { a as AdminTeamPermission, c as AdminTeamPermissionDefinitionUpdateOptions, i as AdminProjectPermissionDefinitionUpdateOptions, n as AdminProjectPermissionDefinition, o as AdminTeamPermissionDefinition, r as AdminProjectPermissionDefinitionCreateOptions, s as AdminTeamPermissionDefinitionCreateOptions, t as AdminProjectPermission } from "./index-DSzMf-rS.js";
@@ -6,10 +6,10 @@ import { a as PlanUsageRow, i as PlanUsagePlanId, n as PlanUsageKind, r as PlanU
6
6
  import { a as AdminWorkflowRunState, c as AdminWorkflowStepAttempt, d as AdminWorkflowUpgradeResult, f as AdminWorkflowVersion, i as AdminWorkflowRunDetails, l as AdminWorkflowSyncResult, n as AdminWorkflowDivergenceDiagnostic, o as AdminWorkflowRunsFilter, r as AdminWorkflowRun, s as AdminWorkflowStep, t as AdminWorkflow, u as AdminWorkflowTrigger } from "./workflows-DhWZSQCI.js";
7
7
  import { r as OAuthConnection, t as Connection } from "./index-ClBTM-St.js";
8
8
  import { i as ServerContactChannel, t as ContactChannel } from "./index-DN04TjLM.js";
9
- import { $ as Team, A as HexclaveAdminAppConstructorOptions, B as StackServerApp, Ct as ServerUser, D as EmailOutboxUpdateOptions, E as EmailOutboxListResult, F as StackAdminAppConstructor, G as SentTeamInvitation, H as StackServerAppConstructorOptions, I as StackAdminAppConstructorOptions, J as ServerTeam, L as HexclaveServerApp, O as HexclaveAdminApp, P as StackAdminApp, Q as ServerTeamUser, R as HexclaveServerAppConstructor, S as PushedConfigSource, St as ServerOAuthProvider, T as EmailOutboxListOptions, U as EditableTeamMemberProfile, V as StackServerAppConstructor, W as ReceivedTeamInvitation, X as ServerTeamMemberProfile, Y as ServerTeamCreateOptions, Z as ServerTeamUpdateOptions, _ as AdminProjectCreateOptions, a as StackClientApp, at as TeamUser, b as Project, c as StackClientAppJson, d as AdminDeploymentJson, dt as Auth, et as TeamCreateOptions, f as AdminDeploymentServiceJson, g as AdminProject, gt as CurrentUser, h as AdminOwnedProject, ht as CurrentServerUser, i as HexclaveClientAppJson, it as TeamUpdateOptions, k as HexclaveAdminAppConstructor, kt as User, l as AdminDeploymentDomainJson, m as AdminDeploymentServiceOutcomeJson, mt as CurrentInternalUser, n as HexclaveClientAppConstructor, nt as TeamMemberProfile, o as StackClientAppConstructor, p as AdminDeploymentServiceLogLineJson, pt as CurrentInternalServerUser, q as ServerListUsersOptions, r as HexclaveClientAppConstructorOptions, s as StackClientAppConstructorOptions, t as HexclaveClientApp, tt as TeamInvitation, u as AdminDeploymentEnvVarJson, v as AdminProjectSecretJson, vt as OAuthProvider, y as AdminProjectUpdateOptions, z as HexclaveServerAppConstructorOptions } from "./client-app-DLFxr4f7.js";
9
+ import { $ as Team, A as HexclaveAdminAppConstructorOptions, B as StackServerApp, Ct as ServerUser, D as EmailOutboxUpdateOptions, E as EmailOutboxListResult, F as StackAdminAppConstructor, G as SentTeamInvitation, H as StackServerAppConstructorOptions, I as StackAdminAppConstructorOptions, J as ServerTeam, L as HexclaveServerApp, O as HexclaveAdminApp, P as StackAdminApp, Q as ServerTeamUser, R as HexclaveServerAppConstructor, S as PushedConfigSource, St as ServerOAuthProvider, T as EmailOutboxListOptions, U as EditableTeamMemberProfile, V as StackServerAppConstructor, W as ReceivedTeamInvitation, X as ServerTeamMemberProfile, Y as ServerTeamCreateOptions, Z as ServerTeamUpdateOptions, _ as AdminProjectCreateOptions, a as StackClientApp, at as TeamUser, b as Project, c as StackClientAppJson, d as AdminDeploymentJson, dt as Auth, et as TeamCreateOptions, f as AdminDeploymentServiceJson, g as AdminProject, gt as CurrentUser, h as AdminOwnedProject, ht as CurrentServerUser, i as HexclaveClientAppJson, it as TeamUpdateOptions, k as HexclaveAdminAppConstructor, kt as User, l as AdminDeploymentDomainJson, m as AdminDeploymentServiceOutcomeJson, mt as CurrentInternalUser, n as HexclaveClientAppConstructor, nt as TeamMemberProfile, o as StackClientAppConstructor, p as AdminDeploymentServiceLogLineJson, pt as CurrentInternalServerUser, q as ServerListUsersOptions, r as HexclaveClientAppConstructorOptions, s as StackClientAppConstructorOptions, t as HexclaveClientApp, tt as TeamInvitation, u as AdminDeploymentEnvVarJson, v as AdminProjectSecretJson, vt as OAuthProvider, y as AdminProjectUpdateOptions, z as HexclaveServerAppConstructorOptions } from "./client-app-C7Tnf0n1.js";
10
10
  import { a as ListSessionReplaysOptions, i as ListSessionReplayChunksResult, n as AdminSessionReplayChunk, o as ListSessionReplaysResult, r as ListSessionReplayChunksOptions, s as SessionReplayAllEventsResult, t as AdminSessionReplay } from "./index-Cf1wOohp.js";
11
11
  import { a as AdminProjectConfigUpdateOptions, i as AdminProjectConfig, n as AdminEmailConfig, o as OAuthProviderConfig, r as AdminOAuthProviderConfig, s as ProjectConfig, t as AdminDomainConfig } from "./index-B-MazpM_.js";
12
- import { r as getPagePrompt } from "./url-targets-BJgkwPGW.js";
12
+ import { r as getPagePrompt } from "./url-targets-DYLcHumF.js";
13
13
  import { getConvexProvidersConfig } from "./integrations/convex.js";
14
14
  import { HexclaveConfig, HexclaveDeploymentConfig, HexclaveDeploymentContext, HexclaveDeploymentReference, HexclaveEnvVarValue, HexclavePersistentVolume, HexclaveServerService, HexclaveServerlessService, HexclaveService, HexclaveServiceOutputs, StackConfig, defineHexclaveConfig, defineStackConfig } from "@hexclave/shared/config";
15
- export { type AdminDeploymentDomainJson, type AdminDeploymentEnvVarJson, type AdminDeploymentJson, type AdminDeploymentServiceJson, type AdminDeploymentServiceLogLineJson, type AdminDeploymentServiceOutcomeJson, type AdminDomainConfig, type AdminEmailConfig, type AdminEmailOutbox, type AdminEmailOutboxRecipient, type AdminEmailOutboxSimpleStatus, type AdminEmailOutboxStatus, type AdminOAuthProviderConfig, type AdminOwnedProject, type AdminProject, type AdminProjectConfig, type AdminProjectConfigUpdateOptions, type AdminProjectCreateOptions, type AdminProjectPermission, type AdminProjectPermissionDefinition, type AdminProjectPermissionDefinitionCreateOptions, type AdminProjectPermissionDefinitionUpdateOptions, type AdminProjectSecretJson, type AdminProjectUpdateOptions, type AdminSendAttemptError, type AdminSentEmail, type AdminSessionReplay, type AdminSessionReplayChunk, type AdminTeamPermission, type AdminTeamPermissionDefinition, type AdminTeamPermissionDefinitionCreateOptions, type AdminTeamPermissionDefinitionUpdateOptions, type AdminWorkflow, type AdminWorkflowDivergenceDiagnostic, type AdminWorkflowRun, type AdminWorkflowRunDetails, type AdminWorkflowRunState, type AdminWorkflowRunsFilter, type AdminWorkflowStep, type AdminWorkflowStepAttempt, type AdminWorkflowSyncResult, type AdminWorkflowTrigger, type AdminWorkflowUpgradeResult, type AdminWorkflowVersion, type Auth, type Connection, type ContactChannel, type CurrentInternalServerUser, type CurrentInternalUser, type CurrentServerUser, type CurrentUser, type EditableTeamMemberProfile, type EmailOutboxListOptions, type EmailOutboxListResult, type EmailOutboxUpdateOptions, type GetCurrentUserOptions, type GetCurrentUserOptions as GetUserOptions, type HandlerUrlOptions, type HandlerUrls, HexclaveAdminApp, type HexclaveAdminAppConstructor, type HexclaveAdminAppConstructorOptions, HexclaveClientApp, type HexclaveClientAppConstructor, type HexclaveClientAppConstructorOptions, type HexclaveClientAppJson, type HexclaveConfig, type HexclaveDeploymentConfig, type HexclaveDeploymentContext, type HexclaveDeploymentReference, type HexclaveEnvVarValue, type HexclavePersistentVolume, HexclaveServerApp, type HexclaveServerAppConstructor, type HexclaveServerAppConstructorOptions, type HexclaveServerService, type HexclaveServerlessService, type HexclaveService, type HexclaveServiceOutputs, type InternalApiKey, type InternalApiKeyBase, type InternalApiKeyBaseCrudRead, type InternalApiKeyCreateOptions, type InternalApiKeyFirstView, type ListSessionReplayChunksOptions, type ListSessionReplayChunksResult, type ListSessionReplaysOptions, type ListSessionReplaysResult, type OAuthConnection, type OAuthProvider, type OAuthProviderConfig, type OAuthScopesOnSignIn, type PlanUsage, type PlanUsageKind, type PlanUsageNextPlanId, type PlanUsagePlanId, type PlanUsageRow, type Project, type ProjectConfig, type PushedConfigSource, type ReceivedTeamInvitation, type ResolvedHandlerUrls, type SentTeamInvitation, type ServerContactChannel, type ServerListUsersOptions, type ServerOAuthProvider, type ServerTeam, type ServerTeamCreateOptions, type ServerTeamMemberProfile, type ServerTeamUpdateOptions, type ServerTeamUser, type ServerUser, type SessionReplayAllEventsResult, StackAdminApp, type StackAdminAppConstructor, type StackAdminAppConstructorOptions, StackClientApp, type StackClientAppConstructor, type StackClientAppConstructorOptions, type StackClientAppJson, type StackConfig, StackServerApp, type StackServerAppConstructor, type StackServerAppConstructorOptions, type Team, type TeamCreateOptions, type TeamInvitation, type TeamMemberProfile, type TeamUpdateOptions, type TeamUser, type User, defineHexclaveConfig, defineStackConfig, getConvexProvidersConfig, getPagePrompt, hexclaveAppInternalsSymbol };
15
+ export { type AdminDeploymentDomainJson, type AdminDeploymentEnvVarJson, type AdminDeploymentJson, type AdminDeploymentServiceJson, type AdminDeploymentServiceLogLineJson, type AdminDeploymentServiceOutcomeJson, type AdminDomainConfig, type AdminEmailConfig, type AdminEmailOutbox, type AdminEmailOutboxRecipient, type AdminEmailOutboxSimpleStatus, type AdminEmailOutboxStatus, type AdminOAuthProviderConfig, type AdminOwnedProject, type AdminProject, type AdminProjectConfig, type AdminProjectConfigUpdateOptions, type AdminProjectCreateOptions, type AdminProjectPermission, type AdminProjectPermissionDefinition, type AdminProjectPermissionDefinitionCreateOptions, type AdminProjectPermissionDefinitionUpdateOptions, type AdminProjectSecretJson, type AdminProjectUpdateOptions, type AdminSendAttemptError, type AdminSentEmail, type AdminSessionReplay, type AdminSessionReplayChunk, type AdminTeamPermission, type AdminTeamPermissionDefinition, type AdminTeamPermissionDefinitionCreateOptions, type AdminTeamPermissionDefinitionUpdateOptions, type AdminWorkflow, type AdminWorkflowDivergenceDiagnostic, type AdminWorkflowRun, type AdminWorkflowRunDetails, type AdminWorkflowRunState, type AdminWorkflowRunsFilter, type AdminWorkflowStep, type AdminWorkflowStepAttempt, type AdminWorkflowSyncResult, type AdminWorkflowTrigger, type AdminWorkflowUpgradeResult, type AdminWorkflowVersion, type Auth, type Connection, type ContactChannel, type CurrentInternalServerUser, type CurrentInternalUser, type CurrentServerUser, type CurrentUser, type EditableTeamMemberProfile, type EmailOutboxListOptions, type EmailOutboxListResult, type EmailOutboxUpdateOptions, type ExternalTokenStore, type GetCurrentUserOptions, type GetCurrentUserOptions as GetUserOptions, type HandlerUrlOptions, type HandlerUrls, HexclaveAdminApp, type HexclaveAdminAppConstructor, type HexclaveAdminAppConstructorOptions, HexclaveClientApp, type HexclaveClientAppConstructor, type HexclaveClientAppConstructorOptions, type HexclaveClientAppJson, type HexclaveConfig, type HexclaveDeploymentConfig, type HexclaveDeploymentContext, type HexclaveDeploymentReference, type HexclaveEnvVarValue, type HexclavePersistentVolume, HexclaveServerApp, type HexclaveServerAppConstructor, type HexclaveServerAppConstructorOptions, type HexclaveServerService, type HexclaveServerlessService, type HexclaveService, type HexclaveServiceOutputs, type InternalApiKey, type InternalApiKeyBase, type InternalApiKeyBaseCrudRead, type InternalApiKeyCreateOptions, type InternalApiKeyFirstView, type ListSessionReplayChunksOptions, type ListSessionReplayChunksResult, type ListSessionReplaysOptions, type ListSessionReplaysResult, type OAuthConnection, type OAuthProvider, type OAuthProviderConfig, type OAuthScopesOnSignIn, type PlanUsage, type PlanUsageKind, type PlanUsageNextPlanId, type PlanUsagePlanId, type PlanUsageRow, type Project, type ProjectConfig, type PushedConfigSource, type ReceivedTeamInvitation, type ResolvedHandlerUrls, type SentTeamInvitation, type ServerContactChannel, type ServerListUsersOptions, type ServerOAuthProvider, type ServerTeam, type ServerTeamCreateOptions, type ServerTeamMemberProfile, type ServerTeamUpdateOptions, type ServerTeamUser, type ServerUser, type SessionReplayAllEventsResult, StackAdminApp, type StackAdminAppConstructor, type StackAdminAppConstructorOptions, StackClientApp, type StackClientAppConstructor, type StackClientAppConstructorOptions, type StackClientAppJson, type StackConfig, StackServerApp, type StackServerAppConstructor, type StackServerAppConstructorOptions, type Team, type TeamCreateOptions, type TeamInvitation, type TeamMemberProfile, type TeamUpdateOptions, type TeamUser, type User, betterAuthTokenStore, clerkTokenStore, defineHexclaveConfig, defineStackConfig, getConvexProvidersConfig, getPagePrompt, hexclaveAppInternalsSymbol, workosTokenStore };
@@ -1,2 +1,2 @@
1
- import { t as _HexclaveAdminAppImplIncomplete } from "../../../../admin-app-impl-Cxer4EIA.js";
1
+ import { t as _HexclaveAdminAppImplIncomplete } from "../../../../admin-app-impl-Df-WtGg0.js";
2
2
  export { _HexclaveAdminAppImplIncomplete };
@@ -1,2 +1,2 @@
1
- import { i as stripBrowserActionQueryParam, r as _HexclaveClientAppImplIncomplete } from "../../../../admin-app-impl-Cxer4EIA.js";
1
+ import { i as stripBrowserActionQueryParam, r as _HexclaveClientAppImplIncomplete } from "../../../../admin-app-impl-Df-WtGg0.js";
2
2
  export { _HexclaveClientAppImplIncomplete, stripBrowserActionQueryParam };
@@ -0,0 +1,381 @@
1
+ let vitest = require("vitest");
2
+ let _hexclave_shared = require("@hexclave/shared");
3
+ let ______common_js = require("../../common.js");
4
+ let ___interfaces_client_app_js = require("../interfaces/client-app.js");
5
+ //#region src/lib/hexclave-app/apps/implementations/client-app-impl.external-token-store.test.ts
6
+ function createAccessTokenString(refreshTokenId, issuedAtOffsetSeconds = 0) {
7
+ const encode = (value) => Buffer.from(JSON.stringify(value)).toString("base64url");
8
+ const nowSeconds = Math.floor(Date.now() / 1e3) + issuedAtOffsetSeconds;
9
+ return [
10
+ encode({
11
+ alg: "none",
12
+ typ: "JWT"
13
+ }),
14
+ encode({
15
+ sub: "user-id",
16
+ exp: nowSeconds + 60,
17
+ iat: nowSeconds,
18
+ iss: "http://localhost:12345",
19
+ aud: "00000000-0000-4000-8000-000000000000",
20
+ project_id: "00000000-0000-4000-8000-000000000000",
21
+ branch_id: "main",
22
+ refresh_token_id: refreshTokenId,
23
+ role: "authenticated",
24
+ name: "Test User",
25
+ email: "test@example.com",
26
+ email_verified: true,
27
+ selected_team_id: null,
28
+ signed_up_at: nowSeconds,
29
+ is_anonymous: false,
30
+ is_restricted: false,
31
+ restricted_reason: null,
32
+ requires_totp_mfa: false
33
+ }),
34
+ ""
35
+ ].join(".");
36
+ }
37
+ (0, vitest.describe)("StackClientApp external token stores", () => {
38
+ (0, vitest.it)("does not reuse a cached token when the provider session has ended", async () => {
39
+ let providerSessionId = "clerk-session";
40
+ const clientApp = new ___interfaces_client_app_js.StackClientApp({
41
+ automaticSideEffects: false,
42
+ baseUrl: "http://localhost:12345",
43
+ projectId: "00000000-0000-4000-8000-000000000000",
44
+ publishableClientKey: "stack-pk-test",
45
+ tokenStore: (0, ______common_js.clerkTokenStore)({
46
+ getSessionId: () => providerSessionId,
47
+ getToken: async () => "stale-provider-token"
48
+ }),
49
+ redirectMethod: "none"
50
+ });
51
+ const getSession = Reflect.get(clientApp, "_getSession");
52
+ const authenticatedSession = await getSession.call(clientApp);
53
+ providerSessionId = null;
54
+ const signedOutSession = await getSession.call(clientApp);
55
+ (0, vitest.expect)(signedOutSession.sessionKey).toBe("not-logged-in");
56
+ (0, vitest.expect)(signedOutSession).not.toBe(authenticatedSession);
57
+ (0, vitest.expect)(signedOutSession.getAccessTokenIfNotExpiredYet(0, null)).toBeNull();
58
+ });
59
+ (0, vitest.it)("exchanges provider tokens and preserves the session across token rotations", async () => {
60
+ let providerSessionId = "clerk-session";
61
+ let notifyProviderChange;
62
+ let exchangeCount = 0;
63
+ const clientApp = new ___interfaces_client_app_js.StackClientApp({
64
+ automaticSideEffects: false,
65
+ baseUrl: "http://localhost:12345",
66
+ projectId: "00000000-0000-4000-8000-000000000000",
67
+ publishableClientKey: "stack-pk-test",
68
+ tokenStore: (0, ______common_js.clerkTokenStore)({
69
+ getSessionId: () => providerSessionId,
70
+ getToken: async () => "clerk-token",
71
+ subscribe: (callback) => {
72
+ notifyProviderChange = callback;
73
+ return () => {};
74
+ }
75
+ }),
76
+ redirectMethod: "none"
77
+ });
78
+ const clientInterface = Reflect.get(clientApp, "_interface");
79
+ Reflect.set(clientInterface, "exchangeExternalAuthToken", async () => {
80
+ exchangeCount += 1;
81
+ return {
82
+ status: "ok",
83
+ data: {
84
+ accessToken: createAccessTokenString("hexclave-external-session", exchangeCount),
85
+ sessionId: "hexclave-external-session",
86
+ userId: "user-id"
87
+ }
88
+ };
89
+ });
90
+ const getSession = Reflect.get(clientApp, "_getSession");
91
+ const firstSession = await getSession.call(clientApp);
92
+ (0, vitest.expect)(firstSession.sessionKey).toBe("external-clerk-integration-clerk-session");
93
+ await firstSession.getOrFetchLikelyValidTokens(2e4, null);
94
+ (0, vitest.expect)(exchangeCount).toBe(1);
95
+ notifyProviderChange?.();
96
+ const refreshedSession = await getSession.call(clientApp);
97
+ (0, vitest.expect)(refreshedSession).toBe(firstSession);
98
+ await refreshedSession.getOrFetchLikelyValidTokens(2e4, null);
99
+ (0, vitest.expect)(exchangeCount).toBe(2);
100
+ providerSessionId = "another-clerk-session";
101
+ notifyProviderChange?.();
102
+ const switchedSession = await getSession.call(clientApp);
103
+ (0, vitest.expect)(switchedSession).not.toBe(firstSession);
104
+ (0, vitest.expect)(switchedSession.sessionKey).toBe("external-clerk-integration-another-clerk-session");
105
+ });
106
+ (0, vitest.it)("retries a rejected exchange once with a fresh provider token before giving up", async () => {
107
+ let tokenCounter = 0;
108
+ const exchangedTokens = [];
109
+ const clientApp = new ___interfaces_client_app_js.StackClientApp({
110
+ automaticSideEffects: false,
111
+ baseUrl: "http://localhost:12345",
112
+ projectId: "00000000-0000-4000-8000-000000000000",
113
+ publishableClientKey: "stack-pk-test",
114
+ tokenStore: (0, ______common_js.clerkTokenStore)({
115
+ getSessionId: () => "clerk-session",
116
+ getToken: async () => `clerk-token-${++tokenCounter}`
117
+ }),
118
+ redirectMethod: "none"
119
+ });
120
+ const clientInterface = Reflect.get(clientApp, "_interface");
121
+ Reflect.set(clientInterface, "exchangeExternalAuthToken", async (_providerId, token) => {
122
+ exchangedTokens.push(token);
123
+ if (exchangedTokens.length === 1) return {
124
+ status: "error",
125
+ error: new _hexclave_shared.KnownErrors.InvalidExternalAuthToken("malformed_token")
126
+ };
127
+ return {
128
+ status: "ok",
129
+ data: {
130
+ accessToken: createAccessTokenString("hexclave-external-session"),
131
+ sessionId: "hexclave-external-session",
132
+ userId: "user-id"
133
+ }
134
+ };
135
+ });
136
+ const session = await Reflect.get(clientApp, "_getSession").call(clientApp);
137
+ (0, vitest.expect)(await session.getOrFetchLikelyValidTokens(2e4, null)).not.toBeNull();
138
+ (0, vitest.expect)(exchangedTokens).toEqual(["clerk-token-1", "clerk-token-2"]);
139
+ (0, vitest.expect)(session.isKnownToBeInvalid()).toBe(false);
140
+ });
141
+ (0, vitest.it)("does not retry into a different provider session after an exchange rejection", async () => {
142
+ let providerSessionId = "clerk-session-a";
143
+ let exchangeCount = 0;
144
+ const clientApp = new ___interfaces_client_app_js.StackClientApp({
145
+ automaticSideEffects: false,
146
+ baseUrl: "http://localhost:12345",
147
+ projectId: "00000000-0000-4000-8000-000000000000",
148
+ publishableClientKey: "stack-pk-test",
149
+ tokenStore: (0, ______common_js.clerkTokenStore)({
150
+ getSessionId: () => providerSessionId,
151
+ getToken: async () => "clerk-token"
152
+ }),
153
+ redirectMethod: "none"
154
+ });
155
+ const clientInterface = Reflect.get(clientApp, "_interface");
156
+ Reflect.set(clientInterface, "exchangeExternalAuthToken", async () => {
157
+ exchangeCount += 1;
158
+ providerSessionId = "clerk-session-b";
159
+ return {
160
+ status: "error",
161
+ error: new _hexclave_shared.KnownErrors.InvalidExternalAuthToken("malformed_token")
162
+ };
163
+ });
164
+ const session = await Reflect.get(clientApp, "_getSession").call(clientApp);
165
+ await (0, vitest.expect)(session.getOrFetchLikelyValidTokens(2e4, null)).rejects.toThrow("provider session changed");
166
+ (0, vitest.expect)(exchangeCount).toBe(1);
167
+ (0, vitest.expect)(session.isKnownToBeInvalid()).toBe(false);
168
+ (0, vitest.expect)(session.getAccessTokenIfNotExpiredYet(0, null)).toBeNull();
169
+ });
170
+ (0, vitest.it)("does not refresh a session after the provider switches before refresh starts", async () => {
171
+ let providerSessionId = "clerk-session-a";
172
+ let exchangeCount = 0;
173
+ const clientApp = new ___interfaces_client_app_js.StackClientApp({
174
+ automaticSideEffects: false,
175
+ baseUrl: "http://localhost:12345",
176
+ projectId: "00000000-0000-4000-8000-000000000000",
177
+ publishableClientKey: "stack-pk-test",
178
+ tokenStore: (0, ______common_js.clerkTokenStore)({
179
+ getSessionId: () => providerSessionId,
180
+ getToken: async () => "clerk-token"
181
+ }),
182
+ redirectMethod: "none"
183
+ });
184
+ const clientInterface = Reflect.get(clientApp, "_interface");
185
+ Reflect.set(clientInterface, "exchangeExternalAuthToken", async () => {
186
+ exchangeCount += 1;
187
+ return {
188
+ status: "ok",
189
+ data: {
190
+ accessToken: createAccessTokenString("hexclave-external-session"),
191
+ sessionId: "hexclave-external-session",
192
+ userId: "user-id"
193
+ }
194
+ };
195
+ });
196
+ const session = await Reflect.get(clientApp, "_getSession").call(clientApp);
197
+ providerSessionId = "clerk-session-b";
198
+ await (0, vitest.expect)(session.getOrFetchLikelyValidTokens(2e4, null)).rejects.toThrow("provider session changed");
199
+ (0, vitest.expect)(exchangeCount).toBe(0);
200
+ (0, vitest.expect)(session.getAccessTokenIfNotExpiredYet(0, null)).toBeNull();
201
+ (0, vitest.expect)(session.isKnownToBeInvalid()).toBe(false);
202
+ });
203
+ (0, vitest.it)("does not install a token when the provider switches accounts mid-exchange", async () => {
204
+ let providerSessionId = "clerk-session-a";
205
+ let resolveExchange;
206
+ const clientApp = new ___interfaces_client_app_js.StackClientApp({
207
+ automaticSideEffects: false,
208
+ baseUrl: "http://localhost:12345",
209
+ projectId: "00000000-0000-4000-8000-000000000000",
210
+ publishableClientKey: "stack-pk-test",
211
+ tokenStore: (0, ______common_js.clerkTokenStore)({
212
+ getSessionId: () => providerSessionId,
213
+ getToken: async () => "clerk-token"
214
+ }),
215
+ redirectMethod: "none"
216
+ });
217
+ const clientInterface = Reflect.get(clientApp, "_interface");
218
+ Reflect.set(clientInterface, "exchangeExternalAuthToken", () => new Promise((resolve) => {
219
+ resolveExchange = (accessToken) => resolve({
220
+ status: "ok",
221
+ data: {
222
+ accessToken,
223
+ sessionId: "hexclave-external-session",
224
+ userId: "user-id"
225
+ }
226
+ });
227
+ }));
228
+ const session = await Reflect.get(clientApp, "_getSession").call(clientApp);
229
+ const pending = session.getOrFetchLikelyValidTokens(2e4, null);
230
+ await vitest.vi.waitFor(() => (0, vitest.expect)(resolveExchange).toBeDefined());
231
+ providerSessionId = "clerk-session-b";
232
+ resolveExchange?.(createAccessTokenString("hexclave-external-session"));
233
+ await (0, vitest.expect)(pending).rejects.toThrow("provider session changed");
234
+ (0, vitest.expect)(session.isKnownToBeInvalid()).toBe(false);
235
+ (0, vitest.expect)(session.getAccessTokenIfNotExpiredYet(0, null)).toBeNull();
236
+ });
237
+ (0, vitest.it)("does not install a token when the provider switches away and back during token retrieval", async () => {
238
+ let providerSessionId = "clerk-session-a";
239
+ let notifyProviderChange;
240
+ let resolveProviderToken;
241
+ const clientApp = new ___interfaces_client_app_js.StackClientApp({
242
+ automaticSideEffects: false,
243
+ baseUrl: "http://localhost:12345",
244
+ projectId: "00000000-0000-4000-8000-000000000000",
245
+ publishableClientKey: "stack-pk-test",
246
+ tokenStore: (0, ______common_js.clerkTokenStore)({
247
+ getSessionId: () => providerSessionId,
248
+ getToken: () => new Promise((resolve) => {
249
+ resolveProviderToken = resolve;
250
+ }),
251
+ subscribe: (callback) => {
252
+ notifyProviderChange = callback;
253
+ return () => {};
254
+ }
255
+ }),
256
+ redirectMethod: "none"
257
+ });
258
+ const clientInterface = Reflect.get(clientApp, "_interface");
259
+ Reflect.set(clientInterface, "exchangeExternalAuthToken", async () => ({
260
+ status: "ok",
261
+ data: {
262
+ accessToken: createAccessTokenString("hexclave-external-session"),
263
+ sessionId: "hexclave-external-session",
264
+ userId: "user-id"
265
+ }
266
+ }));
267
+ const session = await Reflect.get(clientApp, "_getSession").call(clientApp);
268
+ const pending = session.getOrFetchLikelyValidTokens(2e4, null);
269
+ await vitest.vi.waitFor(() => (0, vitest.expect)(resolveProviderToken).toBeDefined());
270
+ providerSessionId = "clerk-session-b";
271
+ notifyProviderChange?.();
272
+ providerSessionId = "clerk-session-a";
273
+ notifyProviderChange?.();
274
+ resolveProviderToken?.("clerk-token");
275
+ await (0, vitest.expect)(pending).rejects.toThrow("provider session changed");
276
+ (0, vitest.expect)(session.getAccessTokenIfNotExpiredYet(0, null)).toBeNull();
277
+ (0, vitest.expect)(session.isKnownToBeInvalid()).toBe(false);
278
+ });
279
+ (0, vitest.it)("surfaces the rejection without invalidating the session when the retried exchange is rejected too", async () => {
280
+ let exchangeCount = 0;
281
+ const clientApp = new ___interfaces_client_app_js.StackClientApp({
282
+ automaticSideEffects: false,
283
+ baseUrl: "http://localhost:12345",
284
+ projectId: "00000000-0000-4000-8000-000000000000",
285
+ publishableClientKey: "stack-pk-test",
286
+ tokenStore: (0, ______common_js.clerkTokenStore)({
287
+ getSessionId: () => "clerk-session",
288
+ getToken: async () => "clerk-token"
289
+ }),
290
+ redirectMethod: "none"
291
+ });
292
+ const clientInterface = Reflect.get(clientApp, "_interface");
293
+ Reflect.set(clientInterface, "exchangeExternalAuthToken", async () => {
294
+ exchangeCount += 1;
295
+ return {
296
+ status: "error",
297
+ error: new _hexclave_shared.KnownErrors.InvalidExternalAuthToken("malformed_token")
298
+ };
299
+ });
300
+ const session = await Reflect.get(clientApp, "_getSession").call(clientApp);
301
+ await (0, vitest.expect)(session.getOrFetchLikelyValidTokens(2e4, null)).rejects.toBeInstanceOf(_hexclave_shared.KnownErrors.InvalidExternalAuthToken);
302
+ (0, vitest.expect)(exchangeCount).toBe(2);
303
+ (0, vitest.expect)(session.isKnownToBeInvalid()).toBe(false);
304
+ });
305
+ (0, vitest.it)("rejects first-party sign-in with Hexclave tokens for an app with an external token store", async () => {
306
+ const clientApp = new ___interfaces_client_app_js.StackClientApp({
307
+ automaticSideEffects: false,
308
+ baseUrl: "http://localhost:12345",
309
+ projectId: "00000000-0000-4000-8000-000000000000",
310
+ publishableClientKey: "stack-pk-test",
311
+ tokenStore: (0, ______common_js.clerkTokenStore)({
312
+ getSessionId: () => "clerk-session",
313
+ getToken: async () => "clerk-token"
314
+ }),
315
+ redirectMethod: "none"
316
+ });
317
+ await (0, vitest.expect)(Reflect.get(clientApp, "_signInToAccountWithTokens").call(clientApp, {
318
+ accessToken: createAccessTokenString("unrelated-session"),
319
+ refreshToken: "unrelated-refresh-token"
320
+ })).rejects.toThrow("cannot sign in with Hexclave tokens");
321
+ });
322
+ (0, vitest.it)("treats a missing provider token as transient while the provider still reports a session", async () => {
323
+ let providerToken = null;
324
+ let exchangeCount = 0;
325
+ const clientApp = new ___interfaces_client_app_js.StackClientApp({
326
+ automaticSideEffects: false,
327
+ baseUrl: "http://localhost:12345",
328
+ projectId: "00000000-0000-4000-8000-000000000000",
329
+ publishableClientKey: "stack-pk-test",
330
+ tokenStore: (0, ______common_js.clerkTokenStore)({
331
+ getSessionId: () => "clerk-session",
332
+ getToken: async () => providerToken
333
+ }),
334
+ redirectMethod: "none"
335
+ });
336
+ const clientInterface = Reflect.get(clientApp, "_interface");
337
+ Reflect.set(clientInterface, "exchangeExternalAuthToken", async () => {
338
+ exchangeCount += 1;
339
+ return {
340
+ status: "ok",
341
+ data: {
342
+ accessToken: createAccessTokenString("hexclave-external-session"),
343
+ sessionId: "hexclave-external-session",
344
+ userId: "user-id"
345
+ }
346
+ };
347
+ });
348
+ const session = await Reflect.get(clientApp, "_getSession").call(clientApp);
349
+ await (0, vitest.expect)(session.getOrFetchLikelyValidTokens(2e4, null)).rejects.toThrow("external token store returned no token");
350
+ (0, vitest.expect)(session.isKnownToBeInvalid()).toBe(false);
351
+ (0, vitest.expect)(exchangeCount).toBe(0);
352
+ providerToken = "clerk-token";
353
+ (0, vitest.expect)(await session.getOrFetchLikelyValidTokens(2e4, null)).not.toBeNull();
354
+ (0, vitest.expect)(exchangeCount).toBe(1);
355
+ });
356
+ (0, vitest.it)("rejects signing out an external session without revoking the Hexclave session", async () => {
357
+ const clientApp = new ___interfaces_client_app_js.StackClientApp({
358
+ automaticSideEffects: false,
359
+ baseUrl: "http://localhost:12345",
360
+ projectId: "00000000-0000-4000-8000-000000000000",
361
+ publishableClientKey: "stack-pk-test",
362
+ tokenStore: (0, ______common_js.clerkTokenStore)({
363
+ getSessionId: () => "clerk-session",
364
+ getToken: async () => "clerk-token"
365
+ }),
366
+ redirectMethod: "none"
367
+ });
368
+ const clientInterface = Reflect.get(clientApp, "_interface");
369
+ let hexclaveSignOutCount = 0;
370
+ Reflect.set(clientInterface, "signOut", async () => {
371
+ hexclaveSignOutCount += 1;
372
+ });
373
+ Reflect.set(clientApp, "_redirectToDefaultAfterSignOut", async () => {});
374
+ const session = await Reflect.get(clientApp, "_getSession").call(clientApp);
375
+ await (0, vitest.expect)(Reflect.get(clientApp, "_signOut").call(clientApp, session)).rejects.toThrow("Cannot sign out an externally authenticated session through Hexclave");
376
+ (0, vitest.expect)(hexclaveSignOutCount).toBe(0);
377
+ });
378
+ });
379
+ //#endregion
380
+
381
+ //# sourceMappingURL=client-app-impl.external-token-store.test.js.map