@meistrari/auth-core 1.5.1 → 1.6.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/README.md CHANGED
@@ -157,14 +157,10 @@ const organizations = await authClient.organization.listOrganizations()
157
157
 
158
158
  #### getOrganization
159
159
 
160
- Retrieves a single organization with optional related data.
160
+ Retrieves a single organization with teams, invites and members.
161
161
 
162
162
  ```typescript
163
- const organization = await authClient.organization.getOrganization('org-123', {
164
- includeMembers: true,
165
- includeInvitations: true,
166
- includeTeams: true
167
- })
163
+ const organization = await authClient.organization.getOrganization('org-123')
168
164
  ```
169
165
 
170
166
  #### setActiveOrganization
package/dist/index.d.mts CHANGED
@@ -2665,6 +2665,70 @@ 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
+ };
2668
2732
  } & {
2669
2733
  $Infer: {
2670
2734
  ActiveOrganization: {
@@ -5553,6 +5617,70 @@ declare const stub: {
5553
5617
  code?: string | undefined;
5554
5618
  message?: string | undefined;
5555
5619
  }, FetchOptions["throw"] extends true ? true : true>>;
5620
+ } & {
5621
+ applications: {
5622
+ listCandidateOrganizations: (applicationId: string) => Promise<{
5623
+ data: {
5624
+ organizations: ExtendedOrganization[];
5625
+ application?: Application | undefined;
5626
+ };
5627
+ error: null;
5628
+ } | {
5629
+ data: {
5630
+ organizations: ExtendedOrganization[];
5631
+ application?: Application | undefined;
5632
+ };
5633
+ error: {
5634
+ message?: string | undefined;
5635
+ status: number;
5636
+ statusText: string;
5637
+ };
5638
+ }>;
5639
+ startAuthorizationFlow: (applicationId: string, redirectUri: string, codeChallenge: string, organizationId: string) => Promise<{
5640
+ data: null;
5641
+ error: {
5642
+ message?: string | undefined;
5643
+ status: number;
5644
+ statusText: string;
5645
+ };
5646
+ } | {
5647
+ data: StartAuthorizationFlowResponse;
5648
+ error: null;
5649
+ }>;
5650
+ completeAuthorizationFlow: (code: string, codeVerifier: string) => Promise<{
5651
+ data: null;
5652
+ error: {
5653
+ message?: string | undefined;
5654
+ status: number;
5655
+ statusText: string;
5656
+ };
5657
+ } | {
5658
+ data: CompleteAuthorizationFlowResponse;
5659
+ error: null;
5660
+ }>;
5661
+ refreshAccessToken: (refreshToken?: 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
+ whoAmI: (accessToken?: string) => Promise<{
5673
+ data: null;
5674
+ error: {
5675
+ message?: string | undefined;
5676
+ status: number;
5677
+ statusText: string;
5678
+ };
5679
+ } | {
5680
+ data: WhoAmIResponse;
5681
+ error: null;
5682
+ }>;
5683
+ };
5556
5684
  } & {
5557
5685
  $Infer: {
5558
5686
  ActiveOrganization: {
@@ -5985,9 +6113,9 @@ type ExtendedOrganization = Organization & {
5985
6113
  settings?: OrganizationSettings;
5986
6114
  };
5987
6115
  type FullOrganization = ExtendedOrganization & {
5988
- members?: Member[];
5989
- invitations?: Invitation[];
5990
- teams?: Team[];
6116
+ members: Member[];
6117
+ invitations: Invitation[];
6118
+ teams: Team[];
5991
6119
  };
5992
6120
  type TeamMember = {
5993
6121
  id: string;
@@ -5996,11 +6124,117 @@ type TeamMember = {
5996
6124
  createdAt: Date;
5997
6125
  };
5998
6126
 
5999
- type GetOrganizationOptions = {
6000
- includeMembers?: boolean;
6001
- includeInvitations?: boolean;
6002
- includeTeams?: boolean;
6127
+ type InternalOrganization = {
6128
+ id: string;
6129
+ title: string;
6130
+ slug: string | null;
6131
+ avatarUrl: string | null;
6132
+ createdAt: Date;
6133
+ metadata: string | null;
6134
+ settings: unknown;
6003
6135
  };
6136
+ type Application = {
6137
+ id: string;
6138
+ name: string;
6139
+ description: string;
6140
+ redirectUris: string[];
6141
+ };
6142
+ type ListCandidateOrganizationsResponse = {
6143
+ application: Application;
6144
+ organizations: InternalOrganization[];
6145
+ };
6146
+ type StartAuthorizationFlowResponse = {
6147
+ code: string;
6148
+ };
6149
+ type CompleteAuthorizationFlowResponse = {
6150
+ accessToken: string;
6151
+ refreshToken: string;
6152
+ user: User;
6153
+ organization: InternalOrganization;
6154
+ };
6155
+ type WhoAmIResponse = {
6156
+ user: User;
6157
+ organization: InternalOrganization;
6158
+ };
6159
+
6160
+ declare class BaseError extends Error {
6161
+ code: string;
6162
+ constructor(code: string, message: string, options?: ErrorOptions);
6163
+ }
6164
+
6165
+ declare class ApplicationError extends BaseError {
6166
+ constructor(message: string, options?: ErrorOptions);
6167
+ }
6168
+ declare class RefreshTokenExpiredError extends ApplicationError {
6169
+ constructor(options?: ErrorOptions);
6170
+ }
6171
+ declare class AuthorizationFlowError extends ApplicationError {
6172
+ constructor(message: string, options?: ErrorOptions);
6173
+ }
6174
+
6175
+ /**
6176
+ * Service for managing applications and their candidate organizations.
6177
+ *
6178
+ * Provides functionality for:
6179
+ * - Listing candidate organizations for an application
6180
+ */
6181
+ declare class ApplicationService {
6182
+ private client;
6183
+ /**
6184
+ * Creates a new ApplicationService instance.
6185
+ *
6186
+ * @param client - The API client for making application requests
6187
+ */
6188
+ constructor(client: APIClient);
6189
+ /**
6190
+ * Lists candidate organizations for a specific application.
6191
+ *
6192
+ * Returns organizations where the authenticated user is a member and
6193
+ * the application has been enabled with appropriate entitlement rules.
6194
+ *
6195
+ * @param applicationId - The application ID to get candidate organizations for
6196
+ * @returns The application details and list of candidate organizations
6197
+ */
6198
+ listCandidateOrganizations(applicationId: string): Promise<{
6199
+ organizations: ExtendedOrganization[];
6200
+ application?: Application | undefined;
6201
+ } | {
6202
+ organizations: ExtendedOrganization[];
6203
+ application?: Application | undefined;
6204
+ }>;
6205
+ /**
6206
+ * Starts an authorization flow for a specific application.
6207
+ *
6208
+ * @param applicationId - The application ID to start the authorization flow for
6209
+ * @param redirectUri - The redirect URI to use for the authorization flow
6210
+ * @param codeChallenge - The code challenge to use for the authorization flow
6211
+ * @param organizationId - The organization ID to start the authorization flow for
6212
+ */
6213
+ startAuthorizationFlow(applicationId: string, redirectUri: string, codeChallenge: string, organizationId: string): Promise<StartAuthorizationFlowResponse>;
6214
+ /**
6215
+ * Completes an authorization flow for a specific application.
6216
+ *
6217
+ * @param code - The code to use for the authorization flow
6218
+ * @param codeVerifier - The code verifier to use for the authorization flow
6219
+ */
6220
+ completeAuthorizationFlow(code: string, codeVerifier: string): Promise<CompleteAuthorizationFlowResponse>;
6221
+ /**
6222
+ * Refreshes an authentication token for a specific application.
6223
+ *
6224
+ * @param refreshToken - The refresh token to use for the authentication token refresh
6225
+ * @throws {RefreshTokenExpiredError} When the refresh token has expired or is invalid
6226
+ * @throws {ApplicationError} For other API errors
6227
+ */
6228
+ refreshAccessToken(): Promise<CompleteAuthorizationFlowResponse>;
6229
+ /**
6230
+ * Gets the current user and organization for a specific application.
6231
+ *
6232
+ * @param accessToken - The access token to use for the who am I request
6233
+ * @returns The current user and organization
6234
+ */
6235
+ whoAmI(accessToken?: string): Promise<WhoAmIResponse>;
6236
+ }
6237
+
6004
6238
  type UpdateOrganizationPayload = Partial<Pick<ExtendedOrganization, 'name' | 'logo' | 'settings'>>;
6005
6239
  type ListMembersOptions = {
6006
6240
  limit?: number;
@@ -6047,21 +6281,24 @@ declare class OrganizationService {
6047
6281
  * Retrieves a single organization by ID with optional related data.
6048
6282
  *
6049
6283
  * @param id - The organization ID
6050
- * @param options - Configuration for including related data
6051
- * @param options.includeMembers - Include organization members
6052
- * @param options.includeInvitations - Include pending invitations
6053
- * @param options.includeTeams - Include organization teams
6054
- * @returns The organization with optionally included related data
6284
+ * @returns The organization with members, invitations, and teams
6055
6285
  */
6056
- getOrganization(id: string, options?: GetOrganizationOptions): Promise<{
6057
- teams?: {
6286
+ getOrganization(id: string): Promise<{
6287
+ members: {
6058
6288
  id: string;
6059
- name: string;
6060
6289
  organizationId: string;
6290
+ role: "org:admin" | "org:member" | "org:reviewer";
6061
6291
  createdAt: Date;
6062
- updatedAt?: Date | undefined;
6063
- }[] | undefined;
6064
- invitations?: {
6292
+ userId: string;
6293
+ teamId?: string | undefined | undefined;
6294
+ user: {
6295
+ id: string;
6296
+ email: string;
6297
+ name: string;
6298
+ image?: string | undefined;
6299
+ };
6300
+ }[];
6301
+ invitations: {
6065
6302
  id: string;
6066
6303
  organizationId: string;
6067
6304
  email: string;
@@ -6071,38 +6308,21 @@ declare class OrganizationService {
6071
6308
  expiresAt: Date;
6072
6309
  createdAt: Date;
6073
6310
  teamId?: string | undefined | undefined;
6074
- }[] | undefined;
6075
- members?: ({
6311
+ }[];
6312
+ teams: {
6076
6313
  id: string;
6314
+ name: string;
6077
6315
  organizationId: string;
6078
- role: "org:admin" | "org:member" | "org:reviewer";
6079
6316
  createdAt: Date;
6080
- userId: string;
6081
- teamId?: string | undefined | undefined;
6082
- user: {
6083
- id: string;
6084
- email: string;
6085
- name: string;
6086
- image?: string | undefined;
6087
- };
6088
- } & {
6089
- user: {
6090
- id: string;
6091
- name: string;
6092
- email: string;
6093
- image: string | null | undefined;
6094
- };
6095
- })[] | undefined;
6317
+ updatedAt?: Date | undefined;
6318
+ }[];
6319
+ } & {
6096
6320
  id: string;
6097
6321
  name: string;
6098
6322
  slug: string;
6099
6323
  createdAt: Date;
6100
- logo?: string | null | undefined;
6324
+ logo?: string | null | undefined | undefined;
6101
6325
  metadata?: any;
6102
- settings?: {
6103
- disableStorage?: boolean;
6104
- dataRetentionHours?: number;
6105
- };
6106
6326
  }>;
6107
6327
  /**
6108
6328
  * Lists all organizations accessible to the current user.
@@ -6586,11 +6806,6 @@ declare class ApiKeyService {
6586
6806
  }>;
6587
6807
  }
6588
6808
 
6589
- declare class BaseError extends Error {
6590
- code: string;
6591
- constructor(code: string, message: string, options?: ErrorOptions);
6592
- }
6593
-
6594
6809
  /**
6595
6810
  * Error thrown when an invalid social provider is specified.
6596
6811
  */
@@ -6643,6 +6858,10 @@ declare class AuthClient {
6643
6858
  * Organization management service for multi-tenant operations
6644
6859
  */
6645
6860
  organization: OrganizationService;
6861
+ /**
6862
+ * Application management service for application operations
6863
+ */
6864
+ application: ApplicationService;
6646
6865
  /**
6647
6866
  * API key management service for API key operations
6648
6867
  */
@@ -6657,20 +6876,28 @@ declare class AuthClient {
6657
6876
  }
6658
6877
 
6659
6878
  /**
6660
- * Checks if a JWT token has expired based on the `exp` claim.
6879
+ * Checks if a JWT token has expired or will expire within a specified time window.
6661
6880
  *
6662
6881
  * @param token - The JWT token string to check
6663
- * @returns `true` if the token is expired, `false` otherwise
6882
+ * @param expiresInMs - Optional time window in milliseconds. If provided, returns `true` if the token will expire within this time window
6883
+ * @returns `true` if the token is expired (or will expire within the specified window), `false` otherwise
6664
6884
  *
6665
6885
  * @example
6666
6886
  * ```typescript
6667
6887
  * const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...'
6888
+ *
6889
+ * // Check if token is already expired
6668
6890
  * if (isTokenExpired(token)) {
6669
6891
  * console.log('Token has expired')
6670
6892
  * }
6893
+ *
6894
+ * // Check if token will expire in the next 5 minutes
6895
+ * if (isTokenExpired(token, 5 * 60 * 1000)) {
6896
+ * console.log('Token will expire in the next 5 minutes')
6897
+ * }
6671
6898
  * ```
6672
6899
  */
6673
- declare function isTokenExpired(token: string): any;
6900
+ declare function isTokenExpired(token: string, expiresInMs?: number): boolean;
6674
6901
  /**
6675
6902
  * Validates a JWT token by checking its expiration and verifying its signature
6676
6903
  * against the JWKS endpoint.
@@ -6709,5 +6936,5 @@ declare function validateToken(token: string, apiUrl: string): Promise<boolean>;
6709
6936
  */
6710
6937
  declare function extractTokenPayload(token: string): JWTTokenPayload;
6711
6938
 
6712
- export { AuthClient, EmailRequired, InvalidCallbackURL, InvalidSocialProvider, Roles, ac, createAPIClient, extractTokenPayload, isTokenExpired, organizationAdditionalFields, rolesAccessControl, userAdditionalFields, validateToken };
6713
- export type { APIClient, ApiKeyMetadata, CreateApiKeyPayload, CreateTeamPayload, FullOrganization, GetOrganizationOptions, Invitation, InviteUserToOrganizationOptions, JWTTokenPayload, ListMembersOptions, ExtendedMember as Member, ExtendedOrganization as Organization, RemoveUserFromOrganizationOptions, Role, Session, SignInWithEmailAndPasswordOptions, SignInWithSamlOptions, SocialSignInOptions, Team, TeamMember, UpdateApiKeyPayload, UpdateMemberRoleOptions, UpdateOrganizationPayload, UpdateTeamPayload, User };
6939
+ export { ApplicationError, AuthClient, AuthorizationFlowError, EmailRequired, InvalidCallbackURL, InvalidSocialProvider, RefreshTokenExpiredError, Roles, ac, createAPIClient, extractTokenPayload, isTokenExpired, organizationAdditionalFields, rolesAccessControl, userAdditionalFields, validateToken };
6940
+ 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
@@ -2665,6 +2665,70 @@ 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
+ };
2668
2732
  } & {
2669
2733
  $Infer: {
2670
2734
  ActiveOrganization: {
@@ -5553,6 +5617,70 @@ declare const stub: {
5553
5617
  code?: string | undefined;
5554
5618
  message?: string | undefined;
5555
5619
  }, FetchOptions["throw"] extends true ? true : true>>;
5620
+ } & {
5621
+ applications: {
5622
+ listCandidateOrganizations: (applicationId: string) => Promise<{
5623
+ data: {
5624
+ organizations: ExtendedOrganization[];
5625
+ application?: Application | undefined;
5626
+ };
5627
+ error: null;
5628
+ } | {
5629
+ data: {
5630
+ organizations: ExtendedOrganization[];
5631
+ application?: Application | undefined;
5632
+ };
5633
+ error: {
5634
+ message?: string | undefined;
5635
+ status: number;
5636
+ statusText: string;
5637
+ };
5638
+ }>;
5639
+ startAuthorizationFlow: (applicationId: string, redirectUri: string, codeChallenge: string, organizationId: string) => Promise<{
5640
+ data: null;
5641
+ error: {
5642
+ message?: string | undefined;
5643
+ status: number;
5644
+ statusText: string;
5645
+ };
5646
+ } | {
5647
+ data: StartAuthorizationFlowResponse;
5648
+ error: null;
5649
+ }>;
5650
+ completeAuthorizationFlow: (code: string, codeVerifier: string) => Promise<{
5651
+ data: null;
5652
+ error: {
5653
+ message?: string | undefined;
5654
+ status: number;
5655
+ statusText: string;
5656
+ };
5657
+ } | {
5658
+ data: CompleteAuthorizationFlowResponse;
5659
+ error: null;
5660
+ }>;
5661
+ refreshAccessToken: (refreshToken?: 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
+ whoAmI: (accessToken?: string) => Promise<{
5673
+ data: null;
5674
+ error: {
5675
+ message?: string | undefined;
5676
+ status: number;
5677
+ statusText: string;
5678
+ };
5679
+ } | {
5680
+ data: WhoAmIResponse;
5681
+ error: null;
5682
+ }>;
5683
+ };
5556
5684
  } & {
5557
5685
  $Infer: {
5558
5686
  ActiveOrganization: {
@@ -5985,9 +6113,9 @@ type ExtendedOrganization = Organization & {
5985
6113
  settings?: OrganizationSettings;
5986
6114
  };
5987
6115
  type FullOrganization = ExtendedOrganization & {
5988
- members?: Member[];
5989
- invitations?: Invitation[];
5990
- teams?: Team[];
6116
+ members: Member[];
6117
+ invitations: Invitation[];
6118
+ teams: Team[];
5991
6119
  };
5992
6120
  type TeamMember = {
5993
6121
  id: string;
@@ -5996,11 +6124,117 @@ type TeamMember = {
5996
6124
  createdAt: Date;
5997
6125
  };
5998
6126
 
5999
- type GetOrganizationOptions = {
6000
- includeMembers?: boolean;
6001
- includeInvitations?: boolean;
6002
- includeTeams?: boolean;
6127
+ type InternalOrganization = {
6128
+ id: string;
6129
+ title: string;
6130
+ slug: string | null;
6131
+ avatarUrl: string | null;
6132
+ createdAt: Date;
6133
+ metadata: string | null;
6134
+ settings: unknown;
6003
6135
  };
6136
+ type Application = {
6137
+ id: string;
6138
+ name: string;
6139
+ description: string;
6140
+ redirectUris: string[];
6141
+ };
6142
+ type ListCandidateOrganizationsResponse = {
6143
+ application: Application;
6144
+ organizations: InternalOrganization[];
6145
+ };
6146
+ type StartAuthorizationFlowResponse = {
6147
+ code: string;
6148
+ };
6149
+ type CompleteAuthorizationFlowResponse = {
6150
+ accessToken: string;
6151
+ refreshToken: string;
6152
+ user: User;
6153
+ organization: InternalOrganization;
6154
+ };
6155
+ type WhoAmIResponse = {
6156
+ user: User;
6157
+ organization: InternalOrganization;
6158
+ };
6159
+
6160
+ declare class BaseError extends Error {
6161
+ code: string;
6162
+ constructor(code: string, message: string, options?: ErrorOptions);
6163
+ }
6164
+
6165
+ declare class ApplicationError extends BaseError {
6166
+ constructor(message: string, options?: ErrorOptions);
6167
+ }
6168
+ declare class RefreshTokenExpiredError extends ApplicationError {
6169
+ constructor(options?: ErrorOptions);
6170
+ }
6171
+ declare class AuthorizationFlowError extends ApplicationError {
6172
+ constructor(message: string, options?: ErrorOptions);
6173
+ }
6174
+
6175
+ /**
6176
+ * Service for managing applications and their candidate organizations.
6177
+ *
6178
+ * Provides functionality for:
6179
+ * - Listing candidate organizations for an application
6180
+ */
6181
+ declare class ApplicationService {
6182
+ private client;
6183
+ /**
6184
+ * Creates a new ApplicationService instance.
6185
+ *
6186
+ * @param client - The API client for making application requests
6187
+ */
6188
+ constructor(client: APIClient);
6189
+ /**
6190
+ * Lists candidate organizations for a specific application.
6191
+ *
6192
+ * Returns organizations where the authenticated user is a member and
6193
+ * the application has been enabled with appropriate entitlement rules.
6194
+ *
6195
+ * @param applicationId - The application ID to get candidate organizations for
6196
+ * @returns The application details and list of candidate organizations
6197
+ */
6198
+ listCandidateOrganizations(applicationId: string): Promise<{
6199
+ organizations: ExtendedOrganization[];
6200
+ application?: Application | undefined;
6201
+ } | {
6202
+ organizations: ExtendedOrganization[];
6203
+ application?: Application | undefined;
6204
+ }>;
6205
+ /**
6206
+ * Starts an authorization flow for a specific application.
6207
+ *
6208
+ * @param applicationId - The application ID to start the authorization flow for
6209
+ * @param redirectUri - The redirect URI to use for the authorization flow
6210
+ * @param codeChallenge - The code challenge to use for the authorization flow
6211
+ * @param organizationId - The organization ID to start the authorization flow for
6212
+ */
6213
+ startAuthorizationFlow(applicationId: string, redirectUri: string, codeChallenge: string, organizationId: string): Promise<StartAuthorizationFlowResponse>;
6214
+ /**
6215
+ * Completes an authorization flow for a specific application.
6216
+ *
6217
+ * @param code - The code to use for the authorization flow
6218
+ * @param codeVerifier - The code verifier to use for the authorization flow
6219
+ */
6220
+ completeAuthorizationFlow(code: string, codeVerifier: string): Promise<CompleteAuthorizationFlowResponse>;
6221
+ /**
6222
+ * Refreshes an authentication token for a specific application.
6223
+ *
6224
+ * @param refreshToken - The refresh token to use for the authentication token refresh
6225
+ * @throws {RefreshTokenExpiredError} When the refresh token has expired or is invalid
6226
+ * @throws {ApplicationError} For other API errors
6227
+ */
6228
+ refreshAccessToken(): Promise<CompleteAuthorizationFlowResponse>;
6229
+ /**
6230
+ * Gets the current user and organization for a specific application.
6231
+ *
6232
+ * @param accessToken - The access token to use for the who am I request
6233
+ * @returns The current user and organization
6234
+ */
6235
+ whoAmI(accessToken?: string): Promise<WhoAmIResponse>;
6236
+ }
6237
+
6004
6238
  type UpdateOrganizationPayload = Partial<Pick<ExtendedOrganization, 'name' | 'logo' | 'settings'>>;
6005
6239
  type ListMembersOptions = {
6006
6240
  limit?: number;
@@ -6047,21 +6281,24 @@ declare class OrganizationService {
6047
6281
  * Retrieves a single organization by ID with optional related data.
6048
6282
  *
6049
6283
  * @param id - The organization ID
6050
- * @param options - Configuration for including related data
6051
- * @param options.includeMembers - Include organization members
6052
- * @param options.includeInvitations - Include pending invitations
6053
- * @param options.includeTeams - Include organization teams
6054
- * @returns The organization with optionally included related data
6284
+ * @returns The organization with members, invitations, and teams
6055
6285
  */
6056
- getOrganization(id: string, options?: GetOrganizationOptions): Promise<{
6057
- teams?: {
6286
+ getOrganization(id: string): Promise<{
6287
+ members: {
6058
6288
  id: string;
6059
- name: string;
6060
6289
  organizationId: string;
6290
+ role: "org:admin" | "org:member" | "org:reviewer";
6061
6291
  createdAt: Date;
6062
- updatedAt?: Date | undefined;
6063
- }[] | undefined;
6064
- invitations?: {
6292
+ userId: string;
6293
+ teamId?: string | undefined | undefined;
6294
+ user: {
6295
+ id: string;
6296
+ email: string;
6297
+ name: string;
6298
+ image?: string | undefined;
6299
+ };
6300
+ }[];
6301
+ invitations: {
6065
6302
  id: string;
6066
6303
  organizationId: string;
6067
6304
  email: string;
@@ -6071,38 +6308,21 @@ declare class OrganizationService {
6071
6308
  expiresAt: Date;
6072
6309
  createdAt: Date;
6073
6310
  teamId?: string | undefined | undefined;
6074
- }[] | undefined;
6075
- members?: ({
6311
+ }[];
6312
+ teams: {
6076
6313
  id: string;
6314
+ name: string;
6077
6315
  organizationId: string;
6078
- role: "org:admin" | "org:member" | "org:reviewer";
6079
6316
  createdAt: Date;
6080
- userId: string;
6081
- teamId?: string | undefined | undefined;
6082
- user: {
6083
- id: string;
6084
- email: string;
6085
- name: string;
6086
- image?: string | undefined;
6087
- };
6088
- } & {
6089
- user: {
6090
- id: string;
6091
- name: string;
6092
- email: string;
6093
- image: string | null | undefined;
6094
- };
6095
- })[] | undefined;
6317
+ updatedAt?: Date | undefined;
6318
+ }[];
6319
+ } & {
6096
6320
  id: string;
6097
6321
  name: string;
6098
6322
  slug: string;
6099
6323
  createdAt: Date;
6100
- logo?: string | null | undefined;
6324
+ logo?: string | null | undefined | undefined;
6101
6325
  metadata?: any;
6102
- settings?: {
6103
- disableStorage?: boolean;
6104
- dataRetentionHours?: number;
6105
- };
6106
6326
  }>;
6107
6327
  /**
6108
6328
  * Lists all organizations accessible to the current user.
@@ -6586,11 +6806,6 @@ declare class ApiKeyService {
6586
6806
  }>;
6587
6807
  }
6588
6808
 
6589
- declare class BaseError extends Error {
6590
- code: string;
6591
- constructor(code: string, message: string, options?: ErrorOptions);
6592
- }
6593
-
6594
6809
  /**
6595
6810
  * Error thrown when an invalid social provider is specified.
6596
6811
  */
@@ -6643,6 +6858,10 @@ declare class AuthClient {
6643
6858
  * Organization management service for multi-tenant operations
6644
6859
  */
6645
6860
  organization: OrganizationService;
6861
+ /**
6862
+ * Application management service for application operations
6863
+ */
6864
+ application: ApplicationService;
6646
6865
  /**
6647
6866
  * API key management service for API key operations
6648
6867
  */
@@ -6657,20 +6876,28 @@ declare class AuthClient {
6657
6876
  }
6658
6877
 
6659
6878
  /**
6660
- * Checks if a JWT token has expired based on the `exp` claim.
6879
+ * Checks if a JWT token has expired or will expire within a specified time window.
6661
6880
  *
6662
6881
  * @param token - The JWT token string to check
6663
- * @returns `true` if the token is expired, `false` otherwise
6882
+ * @param expiresInMs - Optional time window in milliseconds. If provided, returns `true` if the token will expire within this time window
6883
+ * @returns `true` if the token is expired (or will expire within the specified window), `false` otherwise
6664
6884
  *
6665
6885
  * @example
6666
6886
  * ```typescript
6667
6887
  * const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...'
6888
+ *
6889
+ * // Check if token is already expired
6668
6890
  * if (isTokenExpired(token)) {
6669
6891
  * console.log('Token has expired')
6670
6892
  * }
6893
+ *
6894
+ * // Check if token will expire in the next 5 minutes
6895
+ * if (isTokenExpired(token, 5 * 60 * 1000)) {
6896
+ * console.log('Token will expire in the next 5 minutes')
6897
+ * }
6671
6898
  * ```
6672
6899
  */
6673
- declare function isTokenExpired(token: string): any;
6900
+ declare function isTokenExpired(token: string, expiresInMs?: number): boolean;
6674
6901
  /**
6675
6902
  * Validates a JWT token by checking its expiration and verifying its signature
6676
6903
  * against the JWKS endpoint.
@@ -6709,5 +6936,5 @@ declare function validateToken(token: string, apiUrl: string): Promise<boolean>;
6709
6936
  */
6710
6937
  declare function extractTokenPayload(token: string): JWTTokenPayload;
6711
6938
 
6712
- export { AuthClient, EmailRequired, InvalidCallbackURL, InvalidSocialProvider, Roles, ac, createAPIClient, extractTokenPayload, isTokenExpired, organizationAdditionalFields, rolesAccessControl, userAdditionalFields, validateToken };
6713
- export type { APIClient, ApiKeyMetadata, CreateApiKeyPayload, CreateTeamPayload, FullOrganization, GetOrganizationOptions, Invitation, InviteUserToOrganizationOptions, JWTTokenPayload, ListMembersOptions, ExtendedMember as Member, ExtendedOrganization as Organization, RemoveUserFromOrganizationOptions, Role, Session, SignInWithEmailAndPasswordOptions, SignInWithSamlOptions, SocialSignInOptions, Team, TeamMember, UpdateApiKeyPayload, UpdateMemberRoleOptions, UpdateOrganizationPayload, UpdateTeamPayload, User };
6939
+ export { ApplicationError, AuthClient, AuthorizationFlowError, EmailRequired, InvalidCallbackURL, InvalidSocialProvider, RefreshTokenExpiredError, Roles, ac, createAPIClient, extractTokenPayload, isTokenExpired, organizationAdditionalFields, rolesAccessControl, userAdditionalFields, validateToken };
6940
+ 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.1";
9
+ const version = "1.6.0";
10
10
 
11
11
  const statements = {
12
12
  ...defaultStatements,
@@ -48,6 +48,80 @@ 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
+ }
120
+ };
121
+ }
122
+ };
123
+ }
124
+
51
125
  function customEndpointsPluginClient() {
52
126
  return {
53
127
  id: "custom-endpoints",
@@ -94,7 +168,8 @@ function createAPIClient(apiUrl, fetchOptions = {}) {
94
168
  adminClient(),
95
169
  inferAdditionalFields({
96
170
  user: userAdditionalFields
97
- })
171
+ }),
172
+ applicationsPluginClient()
98
173
  ],
99
174
  fetchOptions: {
100
175
  ...fetchOptions,
@@ -109,6 +184,119 @@ function createAPIClient(apiUrl, fetchOptions = {}) {
109
184
  }
110
185
  createAPIClient("");
111
186
 
187
+ class BaseError extends Error {
188
+ code;
189
+ constructor(code, message, options) {
190
+ super(message, options);
191
+ this.code = code;
192
+ }
193
+ }
194
+
195
+ class ApplicationError extends BaseError {
196
+ constructor(message, options) {
197
+ super("APPLICATION_ERROR", message, options);
198
+ }
199
+ }
200
+ class RefreshTokenExpiredError extends ApplicationError {
201
+ constructor(options) {
202
+ super("Refresh token has expired or is invalid", options);
203
+ this.code = "REFRESH_TOKEN_EXPIRED";
204
+ }
205
+ }
206
+ class AuthorizationFlowError extends ApplicationError {
207
+ constructor(message, options) {
208
+ super(message, options);
209
+ this.code = "AUTHORIZATION_FLOW_ERROR";
210
+ }
211
+ }
212
+
213
+ class ApplicationService {
214
+ /**
215
+ * Creates a new ApplicationService instance.
216
+ *
217
+ * @param client - The API client for making application requests
218
+ */
219
+ constructor(client) {
220
+ this.client = client;
221
+ }
222
+ /**
223
+ * Lists candidate organizations for a specific application.
224
+ *
225
+ * Returns organizations where the authenticated user is a member and
226
+ * the application has been enabled with appropriate entitlement rules.
227
+ *
228
+ * @param applicationId - The application ID to get candidate organizations for
229
+ * @returns The application details and list of candidate organizations
230
+ */
231
+ async listCandidateOrganizations(applicationId) {
232
+ const response = await this.client.applications.listCandidateOrganizations(applicationId);
233
+ if (!response.data) {
234
+ throw new Error("No data returned from the API", { cause: response.error });
235
+ }
236
+ return response.data;
237
+ }
238
+ /**
239
+ * Starts an authorization flow for a specific application.
240
+ *
241
+ * @param applicationId - The application ID to start the authorization flow for
242
+ * @param redirectUri - The redirect URI to use for the authorization flow
243
+ * @param codeChallenge - The code challenge to use for the authorization flow
244
+ * @param organizationId - The organization ID to start the authorization flow for
245
+ */
246
+ async startAuthorizationFlow(applicationId, redirectUri, codeChallenge, organizationId) {
247
+ const response = await this.client.applications.startAuthorizationFlow(applicationId, redirectUri, codeChallenge, organizationId);
248
+ if (!response.data) {
249
+ throw new Error("No data returned from the API", { cause: response.error });
250
+ }
251
+ return response.data;
252
+ }
253
+ /**
254
+ * Completes an authorization flow for a specific application.
255
+ *
256
+ * @param code - The code to use for the authorization flow
257
+ * @param codeVerifier - The code verifier to use for the authorization flow
258
+ */
259
+ async completeAuthorizationFlow(code, codeVerifier) {
260
+ const response = await this.client.applications.completeAuthorizationFlow(code, codeVerifier);
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
+ * Refreshes an authentication token for a specific application.
268
+ *
269
+ * @param refreshToken - The refresh token to use for the authentication token refresh
270
+ * @throws {RefreshTokenExpiredError} When the refresh token has expired or is invalid
271
+ * @throws {ApplicationError} For other API errors
272
+ */
273
+ async refreshAccessToken() {
274
+ const response = await this.client.applications.refreshAccessToken();
275
+ if (!response.data) {
276
+ const error = response.error;
277
+ const status = error?.status;
278
+ if (status === 404) {
279
+ throw new RefreshTokenExpiredError({ cause: error });
280
+ }
281
+ throw new ApplicationError(error?.message || "Failed to refresh access token", { cause: error });
282
+ }
283
+ return response.data;
284
+ }
285
+ /**
286
+ * Gets the current user and organization for a specific application.
287
+ *
288
+ * @param accessToken - The access token to use for the who am I request
289
+ * @returns The current user and organization
290
+ */
291
+ async whoAmI(accessToken) {
292
+ const response = await this.client.applications.whoAmI(accessToken);
293
+ if (!response.data) {
294
+ throw new Error("No data returned from the API", { cause: response.error });
295
+ }
296
+ return response.data;
297
+ }
298
+ }
299
+
112
300
  class OrganizationService {
113
301
  /**
114
302
  * Creates a new OrganizationService instance.
@@ -122,40 +310,15 @@ class OrganizationService {
122
310
  * Retrieves a single organization by ID with optional related data.
123
311
  *
124
312
  * @param id - The organization ID
125
- * @param options - Configuration for including related data
126
- * @param options.includeMembers - Include organization members
127
- * @param options.includeInvitations - Include pending invitations
128
- * @param options.includeTeams - Include organization teams
129
- * @returns The organization with optionally included related data
130
- */
131
- async getOrganization(id, options) {
132
- const organizationPromise = this.client.organization.list({
133
- query: {
134
- id
135
- }
136
- });
137
- const membersPromise = options?.includeMembers ? this.client.organization.listMembers({
138
- query: {
139
- organizationId: id
140
- }
141
- }) : void 0;
142
- const invitationsPromise = options?.includeInvitations ? this.client.organization.listInvitations({
143
- query: {
144
- organizationId: id
145
- }
146
- }) : void 0;
147
- const teamsPromise = options?.includeTeams ? this.client.organization.listTeams({
313
+ * @returns The organization with members, invitations, and teams
314
+ */
315
+ async getOrganization(id) {
316
+ const organization = await this.client.organization.getFullOrganization({
148
317
  query: {
149
318
  organizationId: id
150
319
  }
151
- }) : void 0;
152
- const [organization, members, invitations, teams] = await Promise.all([organizationPromise, membersPromise, invitationsPromise, teamsPromise]);
153
- return {
154
- ...organization[0],
155
- ...members && { members: members.members },
156
- ...invitations && { invitations },
157
- ...teams && { teams }
158
- };
320
+ });
321
+ return organization;
159
322
  }
160
323
  /**
161
324
  * Lists all organizations accessible to the current user.
@@ -362,14 +525,6 @@ class OrganizationService {
362
525
  }
363
526
  }
364
527
 
365
- class BaseError extends Error {
366
- code;
367
- constructor(code, message, options) {
368
- super(message, options);
369
- this.code = code;
370
- }
371
- }
372
-
373
528
  class InvalidSocialProvider extends BaseError {
374
529
  constructor(message) {
375
530
  super("INVALID_SOCIAL_PROVIDER", message);
@@ -608,6 +763,10 @@ class AuthClient {
608
763
  * Organization management service for multi-tenant operations
609
764
  */
610
765
  organization;
766
+ /**
767
+ * Application management service for application operations
768
+ */
769
+ application;
611
770
  /**
612
771
  * API key management service for API key operations
613
772
  */
@@ -622,13 +781,21 @@ class AuthClient {
622
781
  this.client = createAPIClient(apiUrl, fetchOptions);
623
782
  this.session = new SessionService(this.client, apiUrl);
624
783
  this.organization = new OrganizationService(this.client);
784
+ this.application = new ApplicationService(this.client);
625
785
  this.apiKey = new ApiKeyService(this.client);
626
786
  }
627
787
  }
628
788
 
629
- function isTokenExpired(token) {
789
+ function isTokenExpired(token, expiresInMs) {
630
790
  const payload = JSON.parse(atob(token.split(".")[1] ?? ""));
631
- return payload.exp && Date.now() / 1e3 > payload.exp;
791
+ if (!payload.exp) return false;
792
+ const nowInSeconds = Date.now() / 1e3;
793
+ const expirationTime = payload.exp;
794
+ if (expiresInMs !== void 0) {
795
+ const futureTimeInSeconds = nowInSeconds + expiresInMs / 1e3;
796
+ return futureTimeInSeconds >= expirationTime;
797
+ }
798
+ return nowInSeconds > expirationTime;
632
799
  }
633
800
  async function validateToken(token, apiUrl) {
634
801
  if (isTokenExpired(token)) {
@@ -651,4 +818,4 @@ function extractTokenPayload(token) {
651
818
  return payload;
652
819
  }
653
820
 
654
- export { AuthClient, EmailRequired, InvalidCallbackURL, InvalidSocialProvider, Roles, ac, extractTokenPayload, isTokenExpired, organizationAdditionalFields, rolesAccessControl, userAdditionalFields, validateToken };
821
+ 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.1",
3
+ "version": "1.6.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {