@meistrari/auth-core 1.5.2 → 1.7.0

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.
package/dist/index.d.mts CHANGED
@@ -2,8 +2,8 @@ import * as better_auth_plugins from 'better-auth/plugins';
2
2
  import * as better_auth from 'better-auth';
3
3
  import { JWTPayload } from 'better-auth';
4
4
  import { BetterFetchOption } from 'better-auth/client';
5
- import * as jose from 'jose';
6
5
  import * as _better_auth_sso from '@better-auth/sso';
6
+ import * as better_call from 'better-call';
7
7
  import * as nanostores from 'nanostores';
8
8
  import * as _better_fetch_fetch from '@better-fetch/fetch';
9
9
  export { BetterFetchError as APIError } from '@better-fetch/fetch';
@@ -308,7 +308,7 @@ declare function createAPIClient(apiUrl: string, fetchOptions?: BetterFetchOptio
308
308
  };
309
309
  fetchOptions?: FetchOptions | undefined;
310
310
  }>, data_1?: FetchOptions | undefined) => Promise<_better_fetch_fetch.BetterFetchResponse<{
311
- status: ("OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "I'M_A_TEAPOT" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "TOO_EARLY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "VARIANT_ALSO_NEGOTIATES" | "INSUFFICIENT_STORAGE" | "LOOP_DETECTED" | "NOT_EXTENDED" | "NETWORK_AUTHENTICATION_REQUIRED") | better_auth.Status;
311
+ status: ("OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "I'M_A_TEAPOT" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "TOO_EARLY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "VARIANT_ALSO_NEGOTIATES" | "INSUFFICIENT_STORAGE" | "LOOP_DETECTED" | "NOT_EXTENDED" | "NETWORK_AUTHENTICATION_REQUIRED") | better_call.Status;
312
312
  body: ({
313
313
  message?: string;
314
314
  code?: string;
@@ -2665,6 +2665,81 @@ declare function createAPIClient(apiUrl: string, fetchOptions?: BetterFetchOptio
2665
2665
  code?: string | undefined;
2666
2666
  message?: string | undefined;
2667
2667
  }, FetchOptions["throw"] extends true ? true : true>>;
2668
+ } & {
2669
+ applications: {
2670
+ listCandidateOrganizations: (applicationId: string) => Promise<{
2671
+ data: {
2672
+ organizations: ExtendedOrganization[];
2673
+ application?: Application | undefined;
2674
+ };
2675
+ error: null;
2676
+ } | {
2677
+ data: {
2678
+ organizations: ExtendedOrganization[];
2679
+ application?: Application | undefined;
2680
+ };
2681
+ error: {
2682
+ message?: string | undefined;
2683
+ status: number;
2684
+ statusText: string;
2685
+ };
2686
+ }>;
2687
+ startAuthorizationFlow: (applicationId: string, redirectUri: string, codeChallenge: string, organizationId: string) => Promise<{
2688
+ data: null;
2689
+ error: {
2690
+ message?: string | undefined;
2691
+ status: number;
2692
+ statusText: string;
2693
+ };
2694
+ } | {
2695
+ data: StartAuthorizationFlowResponse;
2696
+ error: null;
2697
+ }>;
2698
+ completeAuthorizationFlow: (code: string, codeVerifier: string) => Promise<{
2699
+ data: null;
2700
+ error: {
2701
+ message?: string | undefined;
2702
+ status: number;
2703
+ statusText: string;
2704
+ };
2705
+ } | {
2706
+ data: CompleteAuthorizationFlowResponse;
2707
+ error: null;
2708
+ }>;
2709
+ refreshAccessToken: (refreshToken?: string) => Promise<{
2710
+ data: null;
2711
+ error: {
2712
+ message?: string | undefined;
2713
+ status: number;
2714
+ statusText: string;
2715
+ };
2716
+ } | {
2717
+ data: CompleteAuthorizationFlowResponse;
2718
+ error: null;
2719
+ }>;
2720
+ whoAmI: (accessToken?: string) => Promise<{
2721
+ data: null;
2722
+ error: {
2723
+ message?: string | undefined;
2724
+ status: number;
2725
+ statusText: string;
2726
+ };
2727
+ } | {
2728
+ data: WhoAmIResponse;
2729
+ error: null;
2730
+ }>;
2731
+ switchOrganization: (organizationId: string, accessToken?: string) => Promise<{
2732
+ data: null;
2733
+ error: {
2734
+ message?: string | undefined;
2735
+ status: number;
2736
+ statusText: string;
2737
+ };
2738
+ } | {
2739
+ data: CompleteAuthorizationFlowResponse;
2740
+ error: null;
2741
+ }>;
2742
+ };
2668
2743
  } & {
2669
2744
  $Infer: {
2670
2745
  ActiveOrganization: {
@@ -2783,7 +2858,7 @@ declare function createAPIClient(apiUrl: string, fetchOptions?: BetterFetchOptio
2783
2858
  statusText: string;
2784
2859
  };
2785
2860
  } | {
2786
- data: jose.JSONWebKeySet;
2861
+ data: better_auth.JSONWebKeySet;
2787
2862
  error: null;
2788
2863
  }>;
2789
2864
  } & {
@@ -3196,7 +3271,7 @@ declare const stub: {
3196
3271
  };
3197
3272
  fetchOptions?: FetchOptions | undefined;
3198
3273
  }>, data_1?: FetchOptions | undefined) => Promise<_better_fetch_fetch.BetterFetchResponse<{
3199
- status: ("OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "I'M_A_TEAPOT" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "TOO_EARLY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "VARIANT_ALSO_NEGOTIATES" | "INSUFFICIENT_STORAGE" | "LOOP_DETECTED" | "NOT_EXTENDED" | "NETWORK_AUTHENTICATION_REQUIRED") | better_auth.Status;
3274
+ status: ("OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "I'M_A_TEAPOT" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "TOO_EARLY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "VARIANT_ALSO_NEGOTIATES" | "INSUFFICIENT_STORAGE" | "LOOP_DETECTED" | "NOT_EXTENDED" | "NETWORK_AUTHENTICATION_REQUIRED") | better_call.Status;
3200
3275
  body: ({
3201
3276
  message?: string;
3202
3277
  code?: string;
@@ -5553,6 +5628,81 @@ declare const stub: {
5553
5628
  code?: string | undefined;
5554
5629
  message?: string | undefined;
5555
5630
  }, FetchOptions["throw"] extends true ? true : true>>;
5631
+ } & {
5632
+ applications: {
5633
+ listCandidateOrganizations: (applicationId: string) => Promise<{
5634
+ data: {
5635
+ organizations: ExtendedOrganization[];
5636
+ application?: Application | undefined;
5637
+ };
5638
+ error: null;
5639
+ } | {
5640
+ data: {
5641
+ organizations: ExtendedOrganization[];
5642
+ application?: Application | undefined;
5643
+ };
5644
+ error: {
5645
+ message?: string | undefined;
5646
+ status: number;
5647
+ statusText: string;
5648
+ };
5649
+ }>;
5650
+ startAuthorizationFlow: (applicationId: string, redirectUri: string, codeChallenge: string, organizationId: string) => Promise<{
5651
+ data: null;
5652
+ error: {
5653
+ message?: string | undefined;
5654
+ status: number;
5655
+ statusText: string;
5656
+ };
5657
+ } | {
5658
+ data: StartAuthorizationFlowResponse;
5659
+ error: null;
5660
+ }>;
5661
+ completeAuthorizationFlow: (code: string, codeVerifier: string) => Promise<{
5662
+ data: null;
5663
+ error: {
5664
+ message?: string | undefined;
5665
+ status: number;
5666
+ statusText: string;
5667
+ };
5668
+ } | {
5669
+ data: CompleteAuthorizationFlowResponse;
5670
+ error: null;
5671
+ }>;
5672
+ refreshAccessToken: (refreshToken?: string) => Promise<{
5673
+ data: null;
5674
+ error: {
5675
+ message?: string | undefined;
5676
+ status: number;
5677
+ statusText: string;
5678
+ };
5679
+ } | {
5680
+ data: CompleteAuthorizationFlowResponse;
5681
+ error: null;
5682
+ }>;
5683
+ whoAmI: (accessToken?: string) => Promise<{
5684
+ data: null;
5685
+ error: {
5686
+ message?: string | undefined;
5687
+ status: number;
5688
+ statusText: string;
5689
+ };
5690
+ } | {
5691
+ data: WhoAmIResponse;
5692
+ error: null;
5693
+ }>;
5694
+ switchOrganization: (organizationId: string, accessToken?: string) => Promise<{
5695
+ data: null;
5696
+ error: {
5697
+ message?: string | undefined;
5698
+ status: number;
5699
+ statusText: string;
5700
+ };
5701
+ } | {
5702
+ data: CompleteAuthorizationFlowResponse;
5703
+ error: null;
5704
+ }>;
5705
+ };
5556
5706
  } & {
5557
5707
  $Infer: {
5558
5708
  ActiveOrganization: {
@@ -5671,7 +5821,7 @@ declare const stub: {
5671
5821
  statusText: string;
5672
5822
  };
5673
5823
  } | {
5674
- data: jose.JSONWebKeySet;
5824
+ data: better_auth.JSONWebKeySet;
5675
5825
  error: null;
5676
5826
  }>;
5677
5827
  } & {
@@ -5996,6 +6146,129 @@ type TeamMember = {
5996
6146
  createdAt: Date;
5997
6147
  };
5998
6148
 
6149
+ type InternalOrganization = {
6150
+ id: string;
6151
+ title: string;
6152
+ slug: string | null;
6153
+ avatarUrl: string | null;
6154
+ createdAt: Date;
6155
+ metadata: string | null;
6156
+ settings: unknown;
6157
+ };
6158
+ type Application = {
6159
+ id: string;
6160
+ name: string;
6161
+ description: string;
6162
+ redirectUris: string[];
6163
+ };
6164
+ type ListCandidateOrganizationsResponse = {
6165
+ application: Application;
6166
+ organizations: InternalOrganization[];
6167
+ };
6168
+ type StartAuthorizationFlowResponse = {
6169
+ code: string;
6170
+ };
6171
+ type CompleteAuthorizationFlowResponse = {
6172
+ accessToken: string;
6173
+ refreshToken: string;
6174
+ user: User;
6175
+ organization: InternalOrganization;
6176
+ };
6177
+ type WhoAmIResponse = {
6178
+ user: User;
6179
+ organization: InternalOrganization;
6180
+ };
6181
+
6182
+ declare class BaseError extends Error {
6183
+ code: string;
6184
+ constructor(code: string, message: string, options?: ErrorOptions);
6185
+ }
6186
+
6187
+ declare class ApplicationError extends BaseError {
6188
+ constructor(message: string, options?: ErrorOptions);
6189
+ }
6190
+ declare class RefreshTokenExpiredError extends ApplicationError {
6191
+ constructor(options?: ErrorOptions);
6192
+ }
6193
+ declare class AuthorizationFlowError extends ApplicationError {
6194
+ constructor(message: string, options?: ErrorOptions);
6195
+ }
6196
+
6197
+ /**
6198
+ * Service for managing applications and their candidate organizations.
6199
+ *
6200
+ * Provides functionality for:
6201
+ * - Listing candidate organizations for an application
6202
+ */
6203
+ declare class ApplicationService {
6204
+ private client;
6205
+ /**
6206
+ * Creates a new ApplicationService instance.
6207
+ *
6208
+ * @param client - The API client for making application requests
6209
+ */
6210
+ constructor(client: APIClient);
6211
+ /**
6212
+ * Lists candidate organizations for a specific application.
6213
+ *
6214
+ * Returns organizations where the authenticated user is a member and
6215
+ * the application has been enabled with appropriate entitlement rules.
6216
+ *
6217
+ * @param applicationId - The application ID to get candidate organizations for
6218
+ * @returns The application details and list of candidate organizations
6219
+ */
6220
+ listCandidateOrganizations(applicationId: string): Promise<{
6221
+ organizations: ExtendedOrganization[];
6222
+ application?: Application | undefined;
6223
+ } | {
6224
+ organizations: ExtendedOrganization[];
6225
+ application?: Application | undefined;
6226
+ }>;
6227
+ /**
6228
+ * Starts an authorization flow for a specific application.
6229
+ *
6230
+ * @param applicationId - The application ID to start the authorization flow for
6231
+ * @param redirectUri - The redirect URI to use for the authorization flow
6232
+ * @param codeChallenge - The code challenge to use for the authorization flow
6233
+ * @param organizationId - The organization ID to start the authorization flow for
6234
+ */
6235
+ startAuthorizationFlow(applicationId: string, redirectUri: string, codeChallenge: string, organizationId: string): Promise<StartAuthorizationFlowResponse>;
6236
+ /**
6237
+ * Completes an authorization flow for a specific application.
6238
+ *
6239
+ * @param code - The code to use for the authorization flow
6240
+ * @param codeVerifier - The code verifier to use for the authorization flow
6241
+ */
6242
+ completeAuthorizationFlow(code: string, codeVerifier: string): Promise<CompleteAuthorizationFlowResponse>;
6243
+ /**
6244
+ * Refreshes an authentication token for a specific application.
6245
+ *
6246
+ * @param refreshToken - The refresh token to use for the authentication token refresh
6247
+ * @throws {RefreshTokenExpiredError} When the refresh token has expired or is invalid
6248
+ * @throws {ApplicationError} For other API errors
6249
+ */
6250
+ refreshAccessToken(): Promise<CompleteAuthorizationFlowResponse>;
6251
+ /**
6252
+ * Gets the current user and organization for a specific application.
6253
+ *
6254
+ * @param accessToken - The access token to use for the who am I request
6255
+ * @returns The current user and organization
6256
+ */
6257
+ whoAmI(accessToken?: string): Promise<WhoAmIResponse>;
6258
+ /**
6259
+ * Switches the active organization for the authenticated user.
6260
+ *
6261
+ * Issues new access and refresh tokens scoped to the specified organization.
6262
+ * The target organization must be entitled to the application and the entitlement's
6263
+ * access rules must allow the current user.
6264
+ *
6265
+ * @param organizationId - The ID of the organization to switch to
6266
+ * @param accessToken - Optional access token for authentication (uses cookie if not provided)
6267
+ * @returns New authentication tokens and user/organization details
6268
+ */
6269
+ switchOrganization(organizationId: string, accessToken?: string): Promise<CompleteAuthorizationFlowResponse>;
6270
+ }
6271
+
5999
6272
  type UpdateOrganizationPayload = Partial<Pick<ExtendedOrganization, 'name' | 'logo' | 'settings'>>;
6000
6273
  type ListMembersOptions = {
6001
6274
  limit?: number;
@@ -6567,11 +6840,6 @@ declare class ApiKeyService {
6567
6840
  }>;
6568
6841
  }
6569
6842
 
6570
- declare class BaseError extends Error {
6571
- code: string;
6572
- constructor(code: string, message: string, options?: ErrorOptions);
6573
- }
6574
-
6575
6843
  /**
6576
6844
  * Error thrown when an invalid social provider is specified.
6577
6845
  */
@@ -6624,6 +6892,10 @@ declare class AuthClient {
6624
6892
  * Organization management service for multi-tenant operations
6625
6893
  */
6626
6894
  organization: OrganizationService;
6895
+ /**
6896
+ * Application management service for application operations
6897
+ */
6898
+ application: ApplicationService;
6627
6899
  /**
6628
6900
  * API key management service for API key operations
6629
6901
  */
@@ -6638,20 +6910,28 @@ declare class AuthClient {
6638
6910
  }
6639
6911
 
6640
6912
  /**
6641
- * Checks if a JWT token has expired based on the `exp` claim.
6913
+ * Checks if a JWT token has expired or will expire within a specified time window.
6642
6914
  *
6643
6915
  * @param token - The JWT token string to check
6644
- * @returns `true` if the token is expired, `false` otherwise
6916
+ * @param expiresInMs - Optional time window in milliseconds. If provided, returns `true` if the token will expire within this time window
6917
+ * @returns `true` if the token is expired (or will expire within the specified window), `false` otherwise
6645
6918
  *
6646
6919
  * @example
6647
6920
  * ```typescript
6648
6921
  * const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...'
6922
+ *
6923
+ * // Check if token is already expired
6649
6924
  * if (isTokenExpired(token)) {
6650
6925
  * console.log('Token has expired')
6651
6926
  * }
6927
+ *
6928
+ * // Check if token will expire in the next 5 minutes
6929
+ * if (isTokenExpired(token, 5 * 60 * 1000)) {
6930
+ * console.log('Token will expire in the next 5 minutes')
6931
+ * }
6652
6932
  * ```
6653
6933
  */
6654
- declare function isTokenExpired(token: string): any;
6934
+ declare function isTokenExpired(token: string, expiresInMs?: number): boolean;
6655
6935
  /**
6656
6936
  * Validates a JWT token by checking its expiration and verifying its signature
6657
6937
  * against the JWKS endpoint.
@@ -6690,5 +6970,5 @@ declare function validateToken(token: string, apiUrl: string): Promise<boolean>;
6690
6970
  */
6691
6971
  declare function extractTokenPayload(token: string): JWTTokenPayload;
6692
6972
 
6693
- export { AuthClient, EmailRequired, InvalidCallbackURL, InvalidSocialProvider, Roles, ac, createAPIClient, extractTokenPayload, isTokenExpired, organizationAdditionalFields, rolesAccessControl, userAdditionalFields, validateToken };
6694
- export type { APIClient, ApiKeyMetadata, CreateApiKeyPayload, CreateTeamPayload, FullOrganization, Invitation, InviteUserToOrganizationOptions, JWTTokenPayload, ListMembersOptions, ExtendedMember as Member, ExtendedOrganization as Organization, RemoveUserFromOrganizationOptions, Role, Session, SignInWithEmailAndPasswordOptions, SignInWithSamlOptions, SocialSignInOptions, Team, TeamMember, UpdateApiKeyPayload, UpdateMemberRoleOptions, UpdateOrganizationPayload, UpdateTeamPayload, User };
6973
+ export { ApplicationError, AuthClient, AuthorizationFlowError, EmailRequired, InvalidCallbackURL, InvalidSocialProvider, RefreshTokenExpiredError, Roles, ac, createAPIClient, extractTokenPayload, isTokenExpired, organizationAdditionalFields, rolesAccessControl, userAdditionalFields, validateToken };
6974
+ export type { APIClient, ApiKeyMetadata, Application, CompleteAuthorizationFlowResponse, CreateApiKeyPayload, CreateTeamPayload, FullOrganization, Invitation, InviteUserToOrganizationOptions, JWTTokenPayload, ListCandidateOrganizationsResponse, ListMembersOptions, ExtendedMember as Member, ExtendedOrganization as Organization, RemoveUserFromOrganizationOptions, Role, Session, SignInWithEmailAndPasswordOptions, SignInWithSamlOptions, SocialSignInOptions, StartAuthorizationFlowResponse, Team, TeamMember, UpdateApiKeyPayload, UpdateMemberRoleOptions, UpdateOrganizationPayload, UpdateTeamPayload, User, WhoAmIResponse };
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@ import * as better_auth_plugins from 'better-auth/plugins';
2
2
  import * as better_auth from 'better-auth';
3
3
  import { JWTPayload } from 'better-auth';
4
4
  import { BetterFetchOption } from 'better-auth/client';
5
- import * as jose from 'jose';
6
5
  import * as _better_auth_sso from '@better-auth/sso';
6
+ import * as better_call from 'better-call';
7
7
  import * as nanostores from 'nanostores';
8
8
  import * as _better_fetch_fetch from '@better-fetch/fetch';
9
9
  export { BetterFetchError as APIError } from '@better-fetch/fetch';
@@ -308,7 +308,7 @@ declare function createAPIClient(apiUrl: string, fetchOptions?: BetterFetchOptio
308
308
  };
309
309
  fetchOptions?: FetchOptions | undefined;
310
310
  }>, data_1?: FetchOptions | undefined) => Promise<_better_fetch_fetch.BetterFetchResponse<{
311
- status: ("OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "I'M_A_TEAPOT" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "TOO_EARLY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "VARIANT_ALSO_NEGOTIATES" | "INSUFFICIENT_STORAGE" | "LOOP_DETECTED" | "NOT_EXTENDED" | "NETWORK_AUTHENTICATION_REQUIRED") | better_auth.Status;
311
+ status: ("OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "I'M_A_TEAPOT" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "TOO_EARLY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "VARIANT_ALSO_NEGOTIATES" | "INSUFFICIENT_STORAGE" | "LOOP_DETECTED" | "NOT_EXTENDED" | "NETWORK_AUTHENTICATION_REQUIRED") | better_call.Status;
312
312
  body: ({
313
313
  message?: string;
314
314
  code?: string;
@@ -2665,6 +2665,81 @@ declare function createAPIClient(apiUrl: string, fetchOptions?: BetterFetchOptio
2665
2665
  code?: string | undefined;
2666
2666
  message?: string | undefined;
2667
2667
  }, FetchOptions["throw"] extends true ? true : true>>;
2668
+ } & {
2669
+ applications: {
2670
+ listCandidateOrganizations: (applicationId: string) => Promise<{
2671
+ data: {
2672
+ organizations: ExtendedOrganization[];
2673
+ application?: Application | undefined;
2674
+ };
2675
+ error: null;
2676
+ } | {
2677
+ data: {
2678
+ organizations: ExtendedOrganization[];
2679
+ application?: Application | undefined;
2680
+ };
2681
+ error: {
2682
+ message?: string | undefined;
2683
+ status: number;
2684
+ statusText: string;
2685
+ };
2686
+ }>;
2687
+ startAuthorizationFlow: (applicationId: string, redirectUri: string, codeChallenge: string, organizationId: string) => Promise<{
2688
+ data: null;
2689
+ error: {
2690
+ message?: string | undefined;
2691
+ status: number;
2692
+ statusText: string;
2693
+ };
2694
+ } | {
2695
+ data: StartAuthorizationFlowResponse;
2696
+ error: null;
2697
+ }>;
2698
+ completeAuthorizationFlow: (code: string, codeVerifier: string) => Promise<{
2699
+ data: null;
2700
+ error: {
2701
+ message?: string | undefined;
2702
+ status: number;
2703
+ statusText: string;
2704
+ };
2705
+ } | {
2706
+ data: CompleteAuthorizationFlowResponse;
2707
+ error: null;
2708
+ }>;
2709
+ refreshAccessToken: (refreshToken?: string) => Promise<{
2710
+ data: null;
2711
+ error: {
2712
+ message?: string | undefined;
2713
+ status: number;
2714
+ statusText: string;
2715
+ };
2716
+ } | {
2717
+ data: CompleteAuthorizationFlowResponse;
2718
+ error: null;
2719
+ }>;
2720
+ whoAmI: (accessToken?: string) => Promise<{
2721
+ data: null;
2722
+ error: {
2723
+ message?: string | undefined;
2724
+ status: number;
2725
+ statusText: string;
2726
+ };
2727
+ } | {
2728
+ data: WhoAmIResponse;
2729
+ error: null;
2730
+ }>;
2731
+ switchOrganization: (organizationId: string, accessToken?: string) => Promise<{
2732
+ data: null;
2733
+ error: {
2734
+ message?: string | undefined;
2735
+ status: number;
2736
+ statusText: string;
2737
+ };
2738
+ } | {
2739
+ data: CompleteAuthorizationFlowResponse;
2740
+ error: null;
2741
+ }>;
2742
+ };
2668
2743
  } & {
2669
2744
  $Infer: {
2670
2745
  ActiveOrganization: {
@@ -2783,7 +2858,7 @@ declare function createAPIClient(apiUrl: string, fetchOptions?: BetterFetchOptio
2783
2858
  statusText: string;
2784
2859
  };
2785
2860
  } | {
2786
- data: jose.JSONWebKeySet;
2861
+ data: better_auth.JSONWebKeySet;
2787
2862
  error: null;
2788
2863
  }>;
2789
2864
  } & {
@@ -3196,7 +3271,7 @@ declare const stub: {
3196
3271
  };
3197
3272
  fetchOptions?: FetchOptions | undefined;
3198
3273
  }>, data_1?: FetchOptions | undefined) => Promise<_better_fetch_fetch.BetterFetchResponse<{
3199
- status: ("OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "I'M_A_TEAPOT" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "TOO_EARLY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "VARIANT_ALSO_NEGOTIATES" | "INSUFFICIENT_STORAGE" | "LOOP_DETECTED" | "NOT_EXTENDED" | "NETWORK_AUTHENTICATION_REQUIRED") | better_auth.Status;
3274
+ status: ("OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "I'M_A_TEAPOT" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "TOO_EARLY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "VARIANT_ALSO_NEGOTIATES" | "INSUFFICIENT_STORAGE" | "LOOP_DETECTED" | "NOT_EXTENDED" | "NETWORK_AUTHENTICATION_REQUIRED") | better_call.Status;
3200
3275
  body: ({
3201
3276
  message?: string;
3202
3277
  code?: string;
@@ -5553,6 +5628,81 @@ declare const stub: {
5553
5628
  code?: string | undefined;
5554
5629
  message?: string | undefined;
5555
5630
  }, FetchOptions["throw"] extends true ? true : true>>;
5631
+ } & {
5632
+ applications: {
5633
+ listCandidateOrganizations: (applicationId: string) => Promise<{
5634
+ data: {
5635
+ organizations: ExtendedOrganization[];
5636
+ application?: Application | undefined;
5637
+ };
5638
+ error: null;
5639
+ } | {
5640
+ data: {
5641
+ organizations: ExtendedOrganization[];
5642
+ application?: Application | undefined;
5643
+ };
5644
+ error: {
5645
+ message?: string | undefined;
5646
+ status: number;
5647
+ statusText: string;
5648
+ };
5649
+ }>;
5650
+ startAuthorizationFlow: (applicationId: string, redirectUri: string, codeChallenge: string, organizationId: string) => Promise<{
5651
+ data: null;
5652
+ error: {
5653
+ message?: string | undefined;
5654
+ status: number;
5655
+ statusText: string;
5656
+ };
5657
+ } | {
5658
+ data: StartAuthorizationFlowResponse;
5659
+ error: null;
5660
+ }>;
5661
+ completeAuthorizationFlow: (code: string, codeVerifier: string) => Promise<{
5662
+ data: null;
5663
+ error: {
5664
+ message?: string | undefined;
5665
+ status: number;
5666
+ statusText: string;
5667
+ };
5668
+ } | {
5669
+ data: CompleteAuthorizationFlowResponse;
5670
+ error: null;
5671
+ }>;
5672
+ refreshAccessToken: (refreshToken?: string) => Promise<{
5673
+ data: null;
5674
+ error: {
5675
+ message?: string | undefined;
5676
+ status: number;
5677
+ statusText: string;
5678
+ };
5679
+ } | {
5680
+ data: CompleteAuthorizationFlowResponse;
5681
+ error: null;
5682
+ }>;
5683
+ whoAmI: (accessToken?: string) => Promise<{
5684
+ data: null;
5685
+ error: {
5686
+ message?: string | undefined;
5687
+ status: number;
5688
+ statusText: string;
5689
+ };
5690
+ } | {
5691
+ data: WhoAmIResponse;
5692
+ error: null;
5693
+ }>;
5694
+ switchOrganization: (organizationId: string, accessToken?: string) => Promise<{
5695
+ data: null;
5696
+ error: {
5697
+ message?: string | undefined;
5698
+ status: number;
5699
+ statusText: string;
5700
+ };
5701
+ } | {
5702
+ data: CompleteAuthorizationFlowResponse;
5703
+ error: null;
5704
+ }>;
5705
+ };
5556
5706
  } & {
5557
5707
  $Infer: {
5558
5708
  ActiveOrganization: {
@@ -5671,7 +5821,7 @@ declare const stub: {
5671
5821
  statusText: string;
5672
5822
  };
5673
5823
  } | {
5674
- data: jose.JSONWebKeySet;
5824
+ data: better_auth.JSONWebKeySet;
5675
5825
  error: null;
5676
5826
  }>;
5677
5827
  } & {
@@ -5996,6 +6146,129 @@ type TeamMember = {
5996
6146
  createdAt: Date;
5997
6147
  };
5998
6148
 
6149
+ type InternalOrganization = {
6150
+ id: string;
6151
+ title: string;
6152
+ slug: string | null;
6153
+ avatarUrl: string | null;
6154
+ createdAt: Date;
6155
+ metadata: string | null;
6156
+ settings: unknown;
6157
+ };
6158
+ type Application = {
6159
+ id: string;
6160
+ name: string;
6161
+ description: string;
6162
+ redirectUris: string[];
6163
+ };
6164
+ type ListCandidateOrganizationsResponse = {
6165
+ application: Application;
6166
+ organizations: InternalOrganization[];
6167
+ };
6168
+ type StartAuthorizationFlowResponse = {
6169
+ code: string;
6170
+ };
6171
+ type CompleteAuthorizationFlowResponse = {
6172
+ accessToken: string;
6173
+ refreshToken: string;
6174
+ user: User;
6175
+ organization: InternalOrganization;
6176
+ };
6177
+ type WhoAmIResponse = {
6178
+ user: User;
6179
+ organization: InternalOrganization;
6180
+ };
6181
+
6182
+ declare class BaseError extends Error {
6183
+ code: string;
6184
+ constructor(code: string, message: string, options?: ErrorOptions);
6185
+ }
6186
+
6187
+ declare class ApplicationError extends BaseError {
6188
+ constructor(message: string, options?: ErrorOptions);
6189
+ }
6190
+ declare class RefreshTokenExpiredError extends ApplicationError {
6191
+ constructor(options?: ErrorOptions);
6192
+ }
6193
+ declare class AuthorizationFlowError extends ApplicationError {
6194
+ constructor(message: string, options?: ErrorOptions);
6195
+ }
6196
+
6197
+ /**
6198
+ * Service for managing applications and their candidate organizations.
6199
+ *
6200
+ * Provides functionality for:
6201
+ * - Listing candidate organizations for an application
6202
+ */
6203
+ declare class ApplicationService {
6204
+ private client;
6205
+ /**
6206
+ * Creates a new ApplicationService instance.
6207
+ *
6208
+ * @param client - The API client for making application requests
6209
+ */
6210
+ constructor(client: APIClient);
6211
+ /**
6212
+ * Lists candidate organizations for a specific application.
6213
+ *
6214
+ * Returns organizations where the authenticated user is a member and
6215
+ * the application has been enabled with appropriate entitlement rules.
6216
+ *
6217
+ * @param applicationId - The application ID to get candidate organizations for
6218
+ * @returns The application details and list of candidate organizations
6219
+ */
6220
+ listCandidateOrganizations(applicationId: string): Promise<{
6221
+ organizations: ExtendedOrganization[];
6222
+ application?: Application | undefined;
6223
+ } | {
6224
+ organizations: ExtendedOrganization[];
6225
+ application?: Application | undefined;
6226
+ }>;
6227
+ /**
6228
+ * Starts an authorization flow for a specific application.
6229
+ *
6230
+ * @param applicationId - The application ID to start the authorization flow for
6231
+ * @param redirectUri - The redirect URI to use for the authorization flow
6232
+ * @param codeChallenge - The code challenge to use for the authorization flow
6233
+ * @param organizationId - The organization ID to start the authorization flow for
6234
+ */
6235
+ startAuthorizationFlow(applicationId: string, redirectUri: string, codeChallenge: string, organizationId: string): Promise<StartAuthorizationFlowResponse>;
6236
+ /**
6237
+ * Completes an authorization flow for a specific application.
6238
+ *
6239
+ * @param code - The code to use for the authorization flow
6240
+ * @param codeVerifier - The code verifier to use for the authorization flow
6241
+ */
6242
+ completeAuthorizationFlow(code: string, codeVerifier: string): Promise<CompleteAuthorizationFlowResponse>;
6243
+ /**
6244
+ * Refreshes an authentication token for a specific application.
6245
+ *
6246
+ * @param refreshToken - The refresh token to use for the authentication token refresh
6247
+ * @throws {RefreshTokenExpiredError} When the refresh token has expired or is invalid
6248
+ * @throws {ApplicationError} For other API errors
6249
+ */
6250
+ refreshAccessToken(): Promise<CompleteAuthorizationFlowResponse>;
6251
+ /**
6252
+ * Gets the current user and organization for a specific application.
6253
+ *
6254
+ * @param accessToken - The access token to use for the who am I request
6255
+ * @returns The current user and organization
6256
+ */
6257
+ whoAmI(accessToken?: string): Promise<WhoAmIResponse>;
6258
+ /**
6259
+ * Switches the active organization for the authenticated user.
6260
+ *
6261
+ * Issues new access and refresh tokens scoped to the specified organization.
6262
+ * The target organization must be entitled to the application and the entitlement's
6263
+ * access rules must allow the current user.
6264
+ *
6265
+ * @param organizationId - The ID of the organization to switch to
6266
+ * @param accessToken - Optional access token for authentication (uses cookie if not provided)
6267
+ * @returns New authentication tokens and user/organization details
6268
+ */
6269
+ switchOrganization(organizationId: string, accessToken?: string): Promise<CompleteAuthorizationFlowResponse>;
6270
+ }
6271
+
5999
6272
  type UpdateOrganizationPayload = Partial<Pick<ExtendedOrganization, 'name' | 'logo' | 'settings'>>;
6000
6273
  type ListMembersOptions = {
6001
6274
  limit?: number;
@@ -6567,11 +6840,6 @@ declare class ApiKeyService {
6567
6840
  }>;
6568
6841
  }
6569
6842
 
6570
- declare class BaseError extends Error {
6571
- code: string;
6572
- constructor(code: string, message: string, options?: ErrorOptions);
6573
- }
6574
-
6575
6843
  /**
6576
6844
  * Error thrown when an invalid social provider is specified.
6577
6845
  */
@@ -6624,6 +6892,10 @@ declare class AuthClient {
6624
6892
  * Organization management service for multi-tenant operations
6625
6893
  */
6626
6894
  organization: OrganizationService;
6895
+ /**
6896
+ * Application management service for application operations
6897
+ */
6898
+ application: ApplicationService;
6627
6899
  /**
6628
6900
  * API key management service for API key operations
6629
6901
  */
@@ -6638,20 +6910,28 @@ declare class AuthClient {
6638
6910
  }
6639
6911
 
6640
6912
  /**
6641
- * Checks if a JWT token has expired based on the `exp` claim.
6913
+ * Checks if a JWT token has expired or will expire within a specified time window.
6642
6914
  *
6643
6915
  * @param token - The JWT token string to check
6644
- * @returns `true` if the token is expired, `false` otherwise
6916
+ * @param expiresInMs - Optional time window in milliseconds. If provided, returns `true` if the token will expire within this time window
6917
+ * @returns `true` if the token is expired (or will expire within the specified window), `false` otherwise
6645
6918
  *
6646
6919
  * @example
6647
6920
  * ```typescript
6648
6921
  * const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...'
6922
+ *
6923
+ * // Check if token is already expired
6649
6924
  * if (isTokenExpired(token)) {
6650
6925
  * console.log('Token has expired')
6651
6926
  * }
6927
+ *
6928
+ * // Check if token will expire in the next 5 minutes
6929
+ * if (isTokenExpired(token, 5 * 60 * 1000)) {
6930
+ * console.log('Token will expire in the next 5 minutes')
6931
+ * }
6652
6932
  * ```
6653
6933
  */
6654
- declare function isTokenExpired(token: string): any;
6934
+ declare function isTokenExpired(token: string, expiresInMs?: number): boolean;
6655
6935
  /**
6656
6936
  * Validates a JWT token by checking its expiration and verifying its signature
6657
6937
  * against the JWKS endpoint.
@@ -6690,5 +6970,5 @@ declare function validateToken(token: string, apiUrl: string): Promise<boolean>;
6690
6970
  */
6691
6971
  declare function extractTokenPayload(token: string): JWTTokenPayload;
6692
6972
 
6693
- export { AuthClient, EmailRequired, InvalidCallbackURL, InvalidSocialProvider, Roles, ac, createAPIClient, extractTokenPayload, isTokenExpired, organizationAdditionalFields, rolesAccessControl, userAdditionalFields, validateToken };
6694
- export type { APIClient, ApiKeyMetadata, CreateApiKeyPayload, CreateTeamPayload, FullOrganization, Invitation, InviteUserToOrganizationOptions, JWTTokenPayload, ListMembersOptions, ExtendedMember as Member, ExtendedOrganization as Organization, RemoveUserFromOrganizationOptions, Role, Session, SignInWithEmailAndPasswordOptions, SignInWithSamlOptions, SocialSignInOptions, Team, TeamMember, UpdateApiKeyPayload, UpdateMemberRoleOptions, UpdateOrganizationPayload, UpdateTeamPayload, User };
6973
+ export { ApplicationError, AuthClient, AuthorizationFlowError, EmailRequired, InvalidCallbackURL, InvalidSocialProvider, RefreshTokenExpiredError, Roles, ac, createAPIClient, extractTokenPayload, isTokenExpired, organizationAdditionalFields, rolesAccessControl, userAdditionalFields, validateToken };
6974
+ export type { APIClient, ApiKeyMetadata, Application, CompleteAuthorizationFlowResponse, CreateApiKeyPayload, CreateTeamPayload, FullOrganization, Invitation, InviteUserToOrganizationOptions, JWTTokenPayload, ListCandidateOrganizationsResponse, ListMembersOptions, ExtendedMember as Member, ExtendedOrganization as Organization, RemoveUserFromOrganizationOptions, Role, Session, SignInWithEmailAndPasswordOptions, SignInWithSamlOptions, SocialSignInOptions, StartAuthorizationFlowResponse, Team, TeamMember, UpdateApiKeyPayload, UpdateMemberRoleOptions, UpdateOrganizationPayload, UpdateTeamPayload, User, WhoAmIResponse };
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import { createAccessControl } from 'better-auth/plugins/access';
6
6
  import { defaultStatements } from 'better-auth/plugins/organization/access';
7
7
  export { BetterFetchError as APIError } from '@better-fetch/fetch';
8
8
 
9
- const version = "1.5.2";
9
+ const version = "1.7.0";
10
10
 
11
11
  const statements = {
12
12
  ...defaultStatements,
@@ -48,6 +48,93 @@ const organizationAdditionalFields = {
48
48
  }
49
49
  };
50
50
 
51
+ function applicationsPluginClient() {
52
+ return {
53
+ id: "applications",
54
+ getActions: ($fetch) => {
55
+ return {
56
+ applications: {
57
+ listCandidateOrganizations: async (applicationId) => {
58
+ const response = await $fetch("/applications/candidate-organizations", {
59
+ query: {
60
+ applicationId
61
+ }
62
+ });
63
+ const organizations = response.data?.organizations.map((organization) => ({
64
+ id: organization.id,
65
+ name: organization.title,
66
+ slug: organization.slug ?? "",
67
+ createdAt: organization.createdAt,
68
+ logo: organization.avatarUrl,
69
+ metadata: organization.metadata
70
+ })) ?? [];
71
+ return {
72
+ ...response,
73
+ data: {
74
+ ...response.data,
75
+ organizations
76
+ }
77
+ };
78
+ },
79
+ startAuthorizationFlow: async (applicationId, redirectUri, codeChallenge, organizationId) => {
80
+ return await $fetch("/applications/authorize", {
81
+ method: "POST",
82
+ body: {
83
+ applicationId,
84
+ redirectUri,
85
+ codeChallenge,
86
+ organizationId
87
+ }
88
+ });
89
+ },
90
+ completeAuthorizationFlow: async (code, codeVerifier) => {
91
+ return await $fetch("/applications/token", {
92
+ method: "POST",
93
+ body: {
94
+ code,
95
+ codeVerifier
96
+ }
97
+ });
98
+ },
99
+ refreshAccessToken: async (refreshToken) => {
100
+ const headers = new Headers();
101
+ if (refreshToken) {
102
+ headers.set("Cookie", `tela-refresh-token=${refreshToken}`);
103
+ }
104
+ return await $fetch("/applications/token/refresh", {
105
+ method: "POST",
106
+ headers
107
+ });
108
+ },
109
+ whoAmI: async (accessToken) => {
110
+ const headers = new Headers();
111
+ if (accessToken) {
112
+ headers.set("Cookie", `tela-access-token=${accessToken}`);
113
+ }
114
+ return await $fetch("/applications/whoami", {
115
+ method: "GET",
116
+ headers
117
+ });
118
+ },
119
+ switchOrganization: async (organizationId, accessToken) => {
120
+ const headers = new Headers();
121
+ if (accessToken) {
122
+ headers.set("Cookie", `tela-access-token=${accessToken}`);
123
+ }
124
+ return await $fetch("/applications/switch-organization", {
125
+ method: "POST",
126
+ headers,
127
+ body: {
128
+ organizationId
129
+ }
130
+ });
131
+ }
132
+ }
133
+ };
134
+ }
135
+ };
136
+ }
137
+
51
138
  function customEndpointsPluginClient() {
52
139
  return {
53
140
  id: "custom-endpoints",
@@ -94,7 +181,8 @@ function createAPIClient(apiUrl, fetchOptions = {}) {
94
181
  adminClient(),
95
182
  inferAdditionalFields({
96
183
  user: userAdditionalFields
97
- })
184
+ }),
185
+ applicationsPluginClient()
98
186
  ],
99
187
  fetchOptions: {
100
188
  ...fetchOptions,
@@ -109,6 +197,137 @@ function createAPIClient(apiUrl, fetchOptions = {}) {
109
197
  }
110
198
  createAPIClient("");
111
199
 
200
+ class BaseError extends Error {
201
+ code;
202
+ constructor(code, message, options) {
203
+ super(message, options);
204
+ this.code = code;
205
+ }
206
+ }
207
+
208
+ class ApplicationError extends BaseError {
209
+ constructor(message, options) {
210
+ super("APPLICATION_ERROR", message, options);
211
+ }
212
+ }
213
+ class RefreshTokenExpiredError extends ApplicationError {
214
+ constructor(options) {
215
+ super("Refresh token has expired or is invalid", options);
216
+ this.code = "REFRESH_TOKEN_EXPIRED";
217
+ }
218
+ }
219
+ class AuthorizationFlowError extends ApplicationError {
220
+ constructor(message, options) {
221
+ super(message, options);
222
+ this.code = "AUTHORIZATION_FLOW_ERROR";
223
+ }
224
+ }
225
+
226
+ class ApplicationService {
227
+ /**
228
+ * Creates a new ApplicationService instance.
229
+ *
230
+ * @param client - The API client for making application requests
231
+ */
232
+ constructor(client) {
233
+ this.client = client;
234
+ }
235
+ /**
236
+ * Lists candidate organizations for a specific application.
237
+ *
238
+ * Returns organizations where the authenticated user is a member and
239
+ * the application has been enabled with appropriate entitlement rules.
240
+ *
241
+ * @param applicationId - The application ID to get candidate organizations for
242
+ * @returns The application details and list of candidate organizations
243
+ */
244
+ async listCandidateOrganizations(applicationId) {
245
+ const response = await this.client.applications.listCandidateOrganizations(applicationId);
246
+ if (!response.data) {
247
+ throw new Error("No data returned from the API", { cause: response.error });
248
+ }
249
+ return response.data;
250
+ }
251
+ /**
252
+ * Starts an authorization flow for a specific application.
253
+ *
254
+ * @param applicationId - The application ID to start the authorization flow for
255
+ * @param redirectUri - The redirect URI to use for the authorization flow
256
+ * @param codeChallenge - The code challenge to use for the authorization flow
257
+ * @param organizationId - The organization ID to start the authorization flow for
258
+ */
259
+ async startAuthorizationFlow(applicationId, redirectUri, codeChallenge, organizationId) {
260
+ const response = await this.client.applications.startAuthorizationFlow(applicationId, redirectUri, codeChallenge, organizationId);
261
+ if (!response.data) {
262
+ throw new Error("No data returned from the API", { cause: response.error });
263
+ }
264
+ return response.data;
265
+ }
266
+ /**
267
+ * Completes an authorization flow for a specific application.
268
+ *
269
+ * @param code - The code to use for the authorization flow
270
+ * @param codeVerifier - The code verifier to use for the authorization flow
271
+ */
272
+ async completeAuthorizationFlow(code, codeVerifier) {
273
+ const response = await this.client.applications.completeAuthorizationFlow(code, codeVerifier);
274
+ if (!response.data) {
275
+ throw new Error("No data returned from the API", { cause: response.error });
276
+ }
277
+ return response.data;
278
+ }
279
+ /**
280
+ * Refreshes an authentication token for a specific application.
281
+ *
282
+ * @param refreshToken - The refresh token to use for the authentication token refresh
283
+ * @throws {RefreshTokenExpiredError} When the refresh token has expired or is invalid
284
+ * @throws {ApplicationError} For other API errors
285
+ */
286
+ async refreshAccessToken() {
287
+ const response = await this.client.applications.refreshAccessToken();
288
+ if (!response.data) {
289
+ const error = response.error;
290
+ const status = error?.status;
291
+ if (status === 404) {
292
+ throw new RefreshTokenExpiredError({ cause: error });
293
+ }
294
+ throw new ApplicationError(error?.message || "Failed to refresh access token", { cause: error });
295
+ }
296
+ return response.data;
297
+ }
298
+ /**
299
+ * Gets the current user and organization for a specific application.
300
+ *
301
+ * @param accessToken - The access token to use for the who am I request
302
+ * @returns The current user and organization
303
+ */
304
+ async whoAmI(accessToken) {
305
+ const response = await this.client.applications.whoAmI(accessToken);
306
+ if (!response.data) {
307
+ throw new Error("No data returned from the API", { cause: response.error });
308
+ }
309
+ return response.data;
310
+ }
311
+ /**
312
+ * Switches the active organization for the authenticated user.
313
+ *
314
+ * Issues new access and refresh tokens scoped to the specified organization.
315
+ * The target organization must be entitled to the application and the entitlement's
316
+ * access rules must allow the current user.
317
+ *
318
+ * @param organizationId - The ID of the organization to switch to
319
+ * @param accessToken - Optional access token for authentication (uses cookie if not provided)
320
+ * @returns New authentication tokens and user/organization details
321
+ */
322
+ async switchOrganization(organizationId, accessToken) {
323
+ const response = await this.client.applications.switchOrganization(organizationId, accessToken);
324
+ if (!response.data) {
325
+ throw new Error("No data returned from the API", { cause: response.error });
326
+ }
327
+ return response.data;
328
+ }
329
+ }
330
+
112
331
  class OrganizationService {
113
332
  /**
114
333
  * Creates a new OrganizationService instance.
@@ -337,14 +556,6 @@ class OrganizationService {
337
556
  }
338
557
  }
339
558
 
340
- class BaseError extends Error {
341
- code;
342
- constructor(code, message, options) {
343
- super(message, options);
344
- this.code = code;
345
- }
346
- }
347
-
348
559
  class InvalidSocialProvider extends BaseError {
349
560
  constructor(message) {
350
561
  super("INVALID_SOCIAL_PROVIDER", message);
@@ -583,6 +794,10 @@ class AuthClient {
583
794
  * Organization management service for multi-tenant operations
584
795
  */
585
796
  organization;
797
+ /**
798
+ * Application management service for application operations
799
+ */
800
+ application;
586
801
  /**
587
802
  * API key management service for API key operations
588
803
  */
@@ -597,13 +812,21 @@ class AuthClient {
597
812
  this.client = createAPIClient(apiUrl, fetchOptions);
598
813
  this.session = new SessionService(this.client, apiUrl);
599
814
  this.organization = new OrganizationService(this.client);
815
+ this.application = new ApplicationService(this.client);
600
816
  this.apiKey = new ApiKeyService(this.client);
601
817
  }
602
818
  }
603
819
 
604
- function isTokenExpired(token) {
820
+ function isTokenExpired(token, expiresInMs) {
605
821
  const payload = JSON.parse(atob(token.split(".")[1] ?? ""));
606
- return payload.exp && Date.now() / 1e3 > payload.exp;
822
+ if (!payload.exp) return false;
823
+ const nowInSeconds = Date.now() / 1e3;
824
+ const expirationTime = payload.exp;
825
+ if (expiresInMs !== void 0) {
826
+ const futureTimeInSeconds = nowInSeconds + expiresInMs / 1e3;
827
+ return futureTimeInSeconds >= expirationTime;
828
+ }
829
+ return nowInSeconds > expirationTime;
607
830
  }
608
831
  async function validateToken(token, apiUrl) {
609
832
  if (isTokenExpired(token)) {
@@ -626,4 +849,4 @@ function extractTokenPayload(token) {
626
849
  return payload;
627
850
  }
628
851
 
629
- export { AuthClient, EmailRequired, InvalidCallbackURL, InvalidSocialProvider, Roles, ac, extractTokenPayload, isTokenExpired, organizationAdditionalFields, rolesAccessControl, userAdditionalFields, validateToken };
852
+ export { ApplicationError, AuthClient, AuthorizationFlowError, EmailRequired, InvalidCallbackURL, InvalidSocialProvider, RefreshTokenExpiredError, Roles, ac, extractTokenPayload, isTokenExpired, organizationAdditionalFields, rolesAccessControl, userAdditionalFields, validateToken };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/auth-core",
3
- "version": "1.5.2",
3
+ "version": "1.7.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {