@heymantle/core-api-client 0.3.4 → 0.4.5

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
@@ -4887,6 +4887,8 @@ type paths = {
4887
4887
  appIds?: string[];
4888
4888
  /** @description The cursor to paginate from */
4889
4889
  cursor?: components["parameters"]["cursor"];
4890
+ /** @description An optional custom domain to filter customers by (e.g. example.com). */
4891
+ domain?: string;
4890
4892
  /** @description Email addresses to filter customers by. Can be passed as an array (email=test1@example.com&email=test2@example.com) or a single string. Returns customers with emails matching any of the provided addresses. */
4891
4893
  email?: string[] | string;
4892
4894
  /** @description The maximum date/time (ISO 8601) of the last update to the Customer */
@@ -4897,7 +4899,7 @@ type paths = {
4897
4899
  page?: components["parameters"]["page"];
4898
4900
  /** @description The search term to filter by */
4899
4901
  search?: components["parameters"]["search"];
4900
- /** @description An optional shopify shop domain to filter customers by. */
4902
+ /** @description An optional shopify shop domain (myshopify.com domain) to filter customers by. */
4901
4903
  shopifyShopDomain?: string;
4902
4904
  /** @description An optional shopify shop id to filter customers by. */
4903
4905
  shopifyShopId?: string;
@@ -19406,6 +19408,15 @@ type components = {
19406
19408
  pathItems: never;
19407
19409
  };
19408
19410
 
19411
+ /**
19412
+ * Result returned by the refreshAccessToken callback.
19413
+ */
19414
+ interface TokenRefreshResult {
19415
+ /** The new access token */
19416
+ accessToken: string;
19417
+ /** When the new token expires. Used for preemptive refresh on subsequent requests. */
19418
+ expiresAt?: Date;
19419
+ }
19409
19420
  /**
19410
19421
  * Configuration for the MantleCoreClient
19411
19422
  */
@@ -19416,6 +19427,21 @@ interface MantleCoreClientConfig {
19416
19427
  apiKey?: string;
19417
19428
  /** OAuth access token for authentication */
19418
19429
  accessToken?: string;
19430
+ /**
19431
+ * When the access token expires. If set, the client will proactively
19432
+ * call refreshAccessToken before sending a request with an expired token.
19433
+ */
19434
+ accessTokenExpiresAt?: Date;
19435
+ /**
19436
+ * Callback to obtain a fresh access token. Called automatically when:
19437
+ * - accessTokenExpiresAt is in the past (preemptive, before the request)
19438
+ * - A 401 response is received for an expired/revoked token (reactive)
19439
+ *
19440
+ * The callback owns the full refresh lifecycle: look up the refresh token,
19441
+ * call the auth server, persist the new credentials, and return the new
19442
+ * access token. Concurrent requests will share a single in-flight refresh.
19443
+ */
19444
+ refreshAccessToken?: () => Promise<TokenRefreshResult>;
19419
19445
  /** Request timeout in milliseconds. Defaults to 30000 */
19420
19446
  timeout?: number;
19421
19447
  /** openapi-fetch middleware to register on instantiation */
@@ -27489,6 +27515,9 @@ declare class MantleCoreClient {
27489
27515
  readonly _api: Client<paths>;
27490
27516
  private apiKey?;
27491
27517
  private accessToken?;
27518
+ private accessTokenExpiresAt?;
27519
+ private refreshAccessToken?;
27520
+ private refreshPromise?;
27492
27521
  readonly affiliateCommissions: AffiliateCommissionsResource;
27493
27522
  readonly affiliatePayouts: AffiliatePayoutsResource;
27494
27523
  readonly affiliatePrograms: AffiliateProgramsResource;
@@ -27547,7 +27576,17 @@ declare class MantleCoreClient {
27547
27576
  updateAuth(credentials: {
27548
27577
  apiKey?: string;
27549
27578
  accessToken?: string;
27579
+ accessTokenExpiresAt?: Date;
27550
27580
  }): void;
27581
+ /**
27582
+ * Check if the access token is expired (with a 30-second buffer).
27583
+ */
27584
+ private isTokenExpired;
27585
+ /**
27586
+ * Execute a token refresh, deduplicating concurrent calls.
27587
+ * All concurrent requests will await the same in-flight refresh promise.
27588
+ */
27589
+ private doRefresh;
27551
27590
  }
27552
27591
 
27553
27592
  type AccountOwner = components['schemas']['AccountOwner'];
@@ -27729,7 +27768,9 @@ declare class MantleAPIError extends Error {
27729
27768
  * Authentication failed (401)
27730
27769
  */
27731
27770
  declare class MantleAuthenticationError extends MantleAPIError {
27732
- constructor(message?: string);
27771
+ /** Whether the token has expired (as opposed to being invalid/malformed) */
27772
+ readonly isExpired: boolean;
27773
+ constructor(message?: string, isExpired?: boolean);
27733
27774
  }
27734
27775
  /**
27735
27776
  * Permission denied (403)
@@ -27757,48 +27798,6 @@ declare class MantleRateLimitError extends MantleAPIError {
27757
27798
  constructor(message?: string, retryAfter?: number);
27758
27799
  }
27759
27800
 
27760
- /**
27761
- * Options for the auth refresh middleware
27762
- */
27763
- interface AuthRefreshOptions {
27764
- /**
27765
- * Function to refresh the access token.
27766
- * Should return the new access token.
27767
- */
27768
- refreshToken: () => Promise<string>;
27769
- /**
27770
- * Callback invoked when the client instance's auth should be updated.
27771
- * Receives the new token string.
27772
- */
27773
- updateAuth: (newToken: string) => void;
27774
- /** Optional callback when refresh succeeds */
27775
- onRefreshSuccess?: (newToken: string) => void;
27776
- /** Optional callback when refresh fails */
27777
- onRefreshFailed?: (error: Error) => void;
27778
- /** Maximum refresh attempts per request (default: 1) */
27779
- maxRefreshAttempts?: number;
27780
- }
27781
- /**
27782
- * Creates an openapi-fetch middleware that automatically refreshes access
27783
- * tokens on 401 responses.
27784
- *
27785
- * @example
27786
- * ```typescript
27787
- * const client = new MantleCoreClient({ accessToken: 'initial-token' });
27788
- *
27789
- * client.use(createAuthRefreshMiddleware({
27790
- * refreshToken: async () => {
27791
- * const res = await fetch('/refresh', { method: 'POST' });
27792
- * const data = await res.json();
27793
- * return data.accessToken;
27794
- * },
27795
- * updateAuth: (newToken) => client.updateAuth({ accessToken: newToken }),
27796
- * onRefreshSuccess: (newToken) => localStorage.setItem('accessToken', newToken),
27797
- * }));
27798
- * ```
27799
- */
27800
- declare function createAuthRefreshMiddleware(options: AuthRefreshOptions): Middleware;
27801
-
27802
27801
  /**
27803
27802
  * Options for the rate limit middleware
27804
27803
  */
@@ -27837,4 +27836,4 @@ interface RateLimitOptions {
27837
27836
  */
27838
27837
  declare function createRateLimitMiddleware(options?: RateLimitOptions): Middleware;
27839
27838
 
27840
- export { type AccountOwner, type AccountOwnerType, type Action, type ActiveSubscriptionsResponse, type Affiliate, type AffiliateAttributionWebhook, type AffiliateCommission, AffiliateCommissionsResource, type AffiliateMembershipWebhook, type AffiliatePayout, type AffiliatePayoutWebhook, AffiliatePayoutsResource, type AffiliateProgram, type AffiliateProgramGroup, type AffiliateProgramMembership, type AffiliateProgramWebhook, AffiliateProgramsResource, type AffiliateReferral, AffiliateReferralsResource, type AffiliateRules, type AffiliateRulesWebhook, type AffiliateWebhook, AffiliatesResource, type Agent, type AgentRun, AgentsResource, AiAgentRunsResource, type App, type AppChargeWebhook, type AppEvent, type AppInstallation, type AppInstallationWebhook, type AppWebhook, AppsResource, type AuthRefreshOptions, type BaseCustomerWebhook, BaseResource, ChannelsResource, type Charge, ChargesResource, type Checklist, type ChecklistStep, CompaniesResource, type Company, type Contact, type ContactWebhook, ContactsResource, type CursorPagination, CustomDataResource, type CustomField, type CustomFieldDefaultValue, type Customer, type CustomerContact, type CustomerContactWebhook, type CustomerSegment, CustomerSegmentsResource, type CustomerWebhook, type CustomerWithoutSubscriptionWebhook, CustomersResource, type Deal, type DealAcquirer, DealActivitiesResource, type DealActivity, type DealAffiliate, type DealApp, type DealContact, type DealCustomData, type DealCustomer, type DealEvent, type DealFlow, type DealFlowAffiliate, type DealFlowDefaultSource, type DealFlowPartnership, type DealFlowStage, type DealFlowUser, DealFlowsResource, type DealOwner, type DealPartnership, type DealPlan, type DealStage, DealsResource, type DetailedAffiliate, type DetailedFlow, type DocsCollection, type DocsCollectionResponse, type DocsGenerateJobResponse, type DocsGenerateStatusCompleted, type DocsGenerateStatusFailed, type DocsGenerateStatusPending, type DocsGroup, type DocsGroupResponse, type DocsPage, type DocsPageResponse, type DocsPageSummary, type DocsRepository, DocsResource, type EmailCampaign, type EmailDelivery, type EmailDeliveryStats, type EmailLayout, type EmailPreview, type EmailSender, type EmailUnsubscribeGroup, type EmailUnsubscribeGroupMember, EmailUnsubscribeGroupsResource, EntitiesResource, type EventWebhook, type ExtensionUninstallPayload, type ExtensionWebhook, type Feature, type Flow, type FlowActionRun, FlowExtensionsResource, FlowsResource, type InvalidTokenError, type Invoice, type InvoiceWebhook, JournalEntriesResource, type JournalEntry, type JournalEntryApp, type JournalEntryFile, type List, ListsResource, type LogoChurnResponse, MantleAPIError, MantleAuthenticationError, MantleCoreClient, type MantleCoreClientConfig, MantleNotFoundError, MantlePermissionError, MantleRateLimitError, MantleValidationError, MeResource, type Meeting, type MeetingAttendee, type MeetingAttendeeRef, type MeetingContactRef, type MeetingCustomer, type MeetingDeal, type MeetingPermission, type MeetingTaskSuggestion, type MeetingTranscript, type MeetingUser, type MeetingUtterance, MeetingsResource, MetricsResource, type MissingScopesError, type MrrResponse, type NetInstallsResponse, type NetRevenueResponse, type NetRevenueRetentionResponse, type Organization, OrganizationResource, type Pagination, type PayoutResponse, type Plan, type PlanFeature, type PlanFeatureWebhook, type PlanUsageChargeWebhook, type PlanWebhook, type PredictedLtvResponse, type RateLimitOptions, type RevenueRetentionResponse, type Review, type ReviewWebhook, type StandardMetricResponse, type Subscription, type SubscriptionWebhook, SubscriptionsResource, type SyncedEmail, type SyncedEmailContact, type SyncedEmailCustomer, type SyncedEmailDeal, type SyncedEmailMessage, type SyncedEmailUser, SyncedEmailsResource, type Task, type TaskComment, type TaskTodoItem, TasksResource, type ThreadEventType, type ThreadMessageWebhook, type ThreadWebhook, type Ticket, type TicketAgent, type TicketApp, type TicketAttachment, type TicketChannel, type TicketContact, type TicketCustomer, type TicketEvent, type TicketLoop, type TicketMessage, TicketsResource, type TimeSeriesDataPoint, type TimelineComment, TimelineCommentsResource, type Transaction, type TransactionWebhook, TransactionsResource, type Trigger, type UninstallEventWebhook, type UsageEvent, type UsageEventResponse, UsageEventsResource, type UsageMetric, type UsageMetricResponse, type User, UsersResource, type Webhook, WebhooksResource, type components, createAuthRefreshMiddleware, createRateLimitMiddleware, type paths };
27839
+ export { type AccountOwner, type AccountOwnerType, type Action, type ActiveSubscriptionsResponse, type Affiliate, type AffiliateAttributionWebhook, type AffiliateCommission, AffiliateCommissionsResource, type AffiliateMembershipWebhook, type AffiliatePayout, type AffiliatePayoutWebhook, AffiliatePayoutsResource, type AffiliateProgram, type AffiliateProgramGroup, type AffiliateProgramMembership, type AffiliateProgramWebhook, AffiliateProgramsResource, type AffiliateReferral, AffiliateReferralsResource, type AffiliateRules, type AffiliateRulesWebhook, type AffiliateWebhook, AffiliatesResource, type Agent, type AgentRun, AgentsResource, AiAgentRunsResource, type App, type AppChargeWebhook, type AppEvent, type AppInstallation, type AppInstallationWebhook, type AppWebhook, AppsResource, type BaseCustomerWebhook, BaseResource, ChannelsResource, type Charge, ChargesResource, type Checklist, type ChecklistStep, CompaniesResource, type Company, type Contact, type ContactWebhook, ContactsResource, type CursorPagination, CustomDataResource, type CustomField, type CustomFieldDefaultValue, type Customer, type CustomerContact, type CustomerContactWebhook, type CustomerSegment, CustomerSegmentsResource, type CustomerWebhook, type CustomerWithoutSubscriptionWebhook, CustomersResource, type Deal, type DealAcquirer, DealActivitiesResource, type DealActivity, type DealAffiliate, type DealApp, type DealContact, type DealCustomData, type DealCustomer, type DealEvent, type DealFlow, type DealFlowAffiliate, type DealFlowDefaultSource, type DealFlowPartnership, type DealFlowStage, type DealFlowUser, DealFlowsResource, type DealOwner, type DealPartnership, type DealPlan, type DealStage, DealsResource, type DetailedAffiliate, type DetailedFlow, type DocsCollection, type DocsCollectionResponse, type DocsGenerateJobResponse, type DocsGenerateStatusCompleted, type DocsGenerateStatusFailed, type DocsGenerateStatusPending, type DocsGroup, type DocsGroupResponse, type DocsPage, type DocsPageResponse, type DocsPageSummary, type DocsRepository, DocsResource, type EmailCampaign, type EmailDelivery, type EmailDeliveryStats, type EmailLayout, type EmailPreview, type EmailSender, type EmailUnsubscribeGroup, type EmailUnsubscribeGroupMember, EmailUnsubscribeGroupsResource, EntitiesResource, type EventWebhook, type ExtensionUninstallPayload, type ExtensionWebhook, type Feature, type Flow, type FlowActionRun, FlowExtensionsResource, FlowsResource, type InvalidTokenError, type Invoice, type InvoiceWebhook, JournalEntriesResource, type JournalEntry, type JournalEntryApp, type JournalEntryFile, type List, ListsResource, type LogoChurnResponse, MantleAPIError, MantleAuthenticationError, MantleCoreClient, type MantleCoreClientConfig, MantleNotFoundError, MantlePermissionError, MantleRateLimitError, MantleValidationError, MeResource, type Meeting, type MeetingAttendee, type MeetingAttendeeRef, type MeetingContactRef, type MeetingCustomer, type MeetingDeal, type MeetingPermission, type MeetingTaskSuggestion, type MeetingTranscript, type MeetingUser, type MeetingUtterance, MeetingsResource, MetricsResource, type MissingScopesError, type MrrResponse, type NetInstallsResponse, type NetRevenueResponse, type NetRevenueRetentionResponse, type Organization, OrganizationResource, type Pagination, type PayoutResponse, type Plan, type PlanFeature, type PlanFeatureWebhook, type PlanUsageChargeWebhook, type PlanWebhook, type PredictedLtvResponse, type RateLimitOptions, type RevenueRetentionResponse, type Review, type ReviewWebhook, type StandardMetricResponse, type Subscription, type SubscriptionWebhook, SubscriptionsResource, type SyncedEmail, type SyncedEmailContact, type SyncedEmailCustomer, type SyncedEmailDeal, type SyncedEmailMessage, type SyncedEmailUser, SyncedEmailsResource, type Task, type TaskComment, type TaskTodoItem, TasksResource, type ThreadEventType, type ThreadMessageWebhook, type ThreadWebhook, type Ticket, type TicketAgent, type TicketApp, type TicketAttachment, type TicketChannel, type TicketContact, type TicketCustomer, type TicketEvent, type TicketLoop, type TicketMessage, TicketsResource, type TimeSeriesDataPoint, type TimelineComment, TimelineCommentsResource, type TokenRefreshResult, type Transaction, type TransactionWebhook, TransactionsResource, type Trigger, type UninstallEventWebhook, type UsageEvent, type UsageEventResponse, UsageEventsResource, type UsageMetric, type UsageMetricResponse, type User, UsersResource, type Webhook, WebhooksResource, type components, createRateLimitMiddleware, type paths };
package/dist/index.d.ts CHANGED
@@ -4887,6 +4887,8 @@ type paths = {
4887
4887
  appIds?: string[];
4888
4888
  /** @description The cursor to paginate from */
4889
4889
  cursor?: components["parameters"]["cursor"];
4890
+ /** @description An optional custom domain to filter customers by (e.g. example.com). */
4891
+ domain?: string;
4890
4892
  /** @description Email addresses to filter customers by. Can be passed as an array (email=test1@example.com&email=test2@example.com) or a single string. Returns customers with emails matching any of the provided addresses. */
4891
4893
  email?: string[] | string;
4892
4894
  /** @description The maximum date/time (ISO 8601) of the last update to the Customer */
@@ -4897,7 +4899,7 @@ type paths = {
4897
4899
  page?: components["parameters"]["page"];
4898
4900
  /** @description The search term to filter by */
4899
4901
  search?: components["parameters"]["search"];
4900
- /** @description An optional shopify shop domain to filter customers by. */
4902
+ /** @description An optional shopify shop domain (myshopify.com domain) to filter customers by. */
4901
4903
  shopifyShopDomain?: string;
4902
4904
  /** @description An optional shopify shop id to filter customers by. */
4903
4905
  shopifyShopId?: string;
@@ -19406,6 +19408,15 @@ type components = {
19406
19408
  pathItems: never;
19407
19409
  };
19408
19410
 
19411
+ /**
19412
+ * Result returned by the refreshAccessToken callback.
19413
+ */
19414
+ interface TokenRefreshResult {
19415
+ /** The new access token */
19416
+ accessToken: string;
19417
+ /** When the new token expires. Used for preemptive refresh on subsequent requests. */
19418
+ expiresAt?: Date;
19419
+ }
19409
19420
  /**
19410
19421
  * Configuration for the MantleCoreClient
19411
19422
  */
@@ -19416,6 +19427,21 @@ interface MantleCoreClientConfig {
19416
19427
  apiKey?: string;
19417
19428
  /** OAuth access token for authentication */
19418
19429
  accessToken?: string;
19430
+ /**
19431
+ * When the access token expires. If set, the client will proactively
19432
+ * call refreshAccessToken before sending a request with an expired token.
19433
+ */
19434
+ accessTokenExpiresAt?: Date;
19435
+ /**
19436
+ * Callback to obtain a fresh access token. Called automatically when:
19437
+ * - accessTokenExpiresAt is in the past (preemptive, before the request)
19438
+ * - A 401 response is received for an expired/revoked token (reactive)
19439
+ *
19440
+ * The callback owns the full refresh lifecycle: look up the refresh token,
19441
+ * call the auth server, persist the new credentials, and return the new
19442
+ * access token. Concurrent requests will share a single in-flight refresh.
19443
+ */
19444
+ refreshAccessToken?: () => Promise<TokenRefreshResult>;
19419
19445
  /** Request timeout in milliseconds. Defaults to 30000 */
19420
19446
  timeout?: number;
19421
19447
  /** openapi-fetch middleware to register on instantiation */
@@ -27489,6 +27515,9 @@ declare class MantleCoreClient {
27489
27515
  readonly _api: Client<paths>;
27490
27516
  private apiKey?;
27491
27517
  private accessToken?;
27518
+ private accessTokenExpiresAt?;
27519
+ private refreshAccessToken?;
27520
+ private refreshPromise?;
27492
27521
  readonly affiliateCommissions: AffiliateCommissionsResource;
27493
27522
  readonly affiliatePayouts: AffiliatePayoutsResource;
27494
27523
  readonly affiliatePrograms: AffiliateProgramsResource;
@@ -27547,7 +27576,17 @@ declare class MantleCoreClient {
27547
27576
  updateAuth(credentials: {
27548
27577
  apiKey?: string;
27549
27578
  accessToken?: string;
27579
+ accessTokenExpiresAt?: Date;
27550
27580
  }): void;
27581
+ /**
27582
+ * Check if the access token is expired (with a 30-second buffer).
27583
+ */
27584
+ private isTokenExpired;
27585
+ /**
27586
+ * Execute a token refresh, deduplicating concurrent calls.
27587
+ * All concurrent requests will await the same in-flight refresh promise.
27588
+ */
27589
+ private doRefresh;
27551
27590
  }
27552
27591
 
27553
27592
  type AccountOwner = components['schemas']['AccountOwner'];
@@ -27729,7 +27768,9 @@ declare class MantleAPIError extends Error {
27729
27768
  * Authentication failed (401)
27730
27769
  */
27731
27770
  declare class MantleAuthenticationError extends MantleAPIError {
27732
- constructor(message?: string);
27771
+ /** Whether the token has expired (as opposed to being invalid/malformed) */
27772
+ readonly isExpired: boolean;
27773
+ constructor(message?: string, isExpired?: boolean);
27733
27774
  }
27734
27775
  /**
27735
27776
  * Permission denied (403)
@@ -27757,48 +27798,6 @@ declare class MantleRateLimitError extends MantleAPIError {
27757
27798
  constructor(message?: string, retryAfter?: number);
27758
27799
  }
27759
27800
 
27760
- /**
27761
- * Options for the auth refresh middleware
27762
- */
27763
- interface AuthRefreshOptions {
27764
- /**
27765
- * Function to refresh the access token.
27766
- * Should return the new access token.
27767
- */
27768
- refreshToken: () => Promise<string>;
27769
- /**
27770
- * Callback invoked when the client instance's auth should be updated.
27771
- * Receives the new token string.
27772
- */
27773
- updateAuth: (newToken: string) => void;
27774
- /** Optional callback when refresh succeeds */
27775
- onRefreshSuccess?: (newToken: string) => void;
27776
- /** Optional callback when refresh fails */
27777
- onRefreshFailed?: (error: Error) => void;
27778
- /** Maximum refresh attempts per request (default: 1) */
27779
- maxRefreshAttempts?: number;
27780
- }
27781
- /**
27782
- * Creates an openapi-fetch middleware that automatically refreshes access
27783
- * tokens on 401 responses.
27784
- *
27785
- * @example
27786
- * ```typescript
27787
- * const client = new MantleCoreClient({ accessToken: 'initial-token' });
27788
- *
27789
- * client.use(createAuthRefreshMiddleware({
27790
- * refreshToken: async () => {
27791
- * const res = await fetch('/refresh', { method: 'POST' });
27792
- * const data = await res.json();
27793
- * return data.accessToken;
27794
- * },
27795
- * updateAuth: (newToken) => client.updateAuth({ accessToken: newToken }),
27796
- * onRefreshSuccess: (newToken) => localStorage.setItem('accessToken', newToken),
27797
- * }));
27798
- * ```
27799
- */
27800
- declare function createAuthRefreshMiddleware(options: AuthRefreshOptions): Middleware;
27801
-
27802
27801
  /**
27803
27802
  * Options for the rate limit middleware
27804
27803
  */
@@ -27837,4 +27836,4 @@ interface RateLimitOptions {
27837
27836
  */
27838
27837
  declare function createRateLimitMiddleware(options?: RateLimitOptions): Middleware;
27839
27838
 
27840
- export { type AccountOwner, type AccountOwnerType, type Action, type ActiveSubscriptionsResponse, type Affiliate, type AffiliateAttributionWebhook, type AffiliateCommission, AffiliateCommissionsResource, type AffiliateMembershipWebhook, type AffiliatePayout, type AffiliatePayoutWebhook, AffiliatePayoutsResource, type AffiliateProgram, type AffiliateProgramGroup, type AffiliateProgramMembership, type AffiliateProgramWebhook, AffiliateProgramsResource, type AffiliateReferral, AffiliateReferralsResource, type AffiliateRules, type AffiliateRulesWebhook, type AffiliateWebhook, AffiliatesResource, type Agent, type AgentRun, AgentsResource, AiAgentRunsResource, type App, type AppChargeWebhook, type AppEvent, type AppInstallation, type AppInstallationWebhook, type AppWebhook, AppsResource, type AuthRefreshOptions, type BaseCustomerWebhook, BaseResource, ChannelsResource, type Charge, ChargesResource, type Checklist, type ChecklistStep, CompaniesResource, type Company, type Contact, type ContactWebhook, ContactsResource, type CursorPagination, CustomDataResource, type CustomField, type CustomFieldDefaultValue, type Customer, type CustomerContact, type CustomerContactWebhook, type CustomerSegment, CustomerSegmentsResource, type CustomerWebhook, type CustomerWithoutSubscriptionWebhook, CustomersResource, type Deal, type DealAcquirer, DealActivitiesResource, type DealActivity, type DealAffiliate, type DealApp, type DealContact, type DealCustomData, type DealCustomer, type DealEvent, type DealFlow, type DealFlowAffiliate, type DealFlowDefaultSource, type DealFlowPartnership, type DealFlowStage, type DealFlowUser, DealFlowsResource, type DealOwner, type DealPartnership, type DealPlan, type DealStage, DealsResource, type DetailedAffiliate, type DetailedFlow, type DocsCollection, type DocsCollectionResponse, type DocsGenerateJobResponse, type DocsGenerateStatusCompleted, type DocsGenerateStatusFailed, type DocsGenerateStatusPending, type DocsGroup, type DocsGroupResponse, type DocsPage, type DocsPageResponse, type DocsPageSummary, type DocsRepository, DocsResource, type EmailCampaign, type EmailDelivery, type EmailDeliveryStats, type EmailLayout, type EmailPreview, type EmailSender, type EmailUnsubscribeGroup, type EmailUnsubscribeGroupMember, EmailUnsubscribeGroupsResource, EntitiesResource, type EventWebhook, type ExtensionUninstallPayload, type ExtensionWebhook, type Feature, type Flow, type FlowActionRun, FlowExtensionsResource, FlowsResource, type InvalidTokenError, type Invoice, type InvoiceWebhook, JournalEntriesResource, type JournalEntry, type JournalEntryApp, type JournalEntryFile, type List, ListsResource, type LogoChurnResponse, MantleAPIError, MantleAuthenticationError, MantleCoreClient, type MantleCoreClientConfig, MantleNotFoundError, MantlePermissionError, MantleRateLimitError, MantleValidationError, MeResource, type Meeting, type MeetingAttendee, type MeetingAttendeeRef, type MeetingContactRef, type MeetingCustomer, type MeetingDeal, type MeetingPermission, type MeetingTaskSuggestion, type MeetingTranscript, type MeetingUser, type MeetingUtterance, MeetingsResource, MetricsResource, type MissingScopesError, type MrrResponse, type NetInstallsResponse, type NetRevenueResponse, type NetRevenueRetentionResponse, type Organization, OrganizationResource, type Pagination, type PayoutResponse, type Plan, type PlanFeature, type PlanFeatureWebhook, type PlanUsageChargeWebhook, type PlanWebhook, type PredictedLtvResponse, type RateLimitOptions, type RevenueRetentionResponse, type Review, type ReviewWebhook, type StandardMetricResponse, type Subscription, type SubscriptionWebhook, SubscriptionsResource, type SyncedEmail, type SyncedEmailContact, type SyncedEmailCustomer, type SyncedEmailDeal, type SyncedEmailMessage, type SyncedEmailUser, SyncedEmailsResource, type Task, type TaskComment, type TaskTodoItem, TasksResource, type ThreadEventType, type ThreadMessageWebhook, type ThreadWebhook, type Ticket, type TicketAgent, type TicketApp, type TicketAttachment, type TicketChannel, type TicketContact, type TicketCustomer, type TicketEvent, type TicketLoop, type TicketMessage, TicketsResource, type TimeSeriesDataPoint, type TimelineComment, TimelineCommentsResource, type Transaction, type TransactionWebhook, TransactionsResource, type Trigger, type UninstallEventWebhook, type UsageEvent, type UsageEventResponse, UsageEventsResource, type UsageMetric, type UsageMetricResponse, type User, UsersResource, type Webhook, WebhooksResource, type components, createAuthRefreshMiddleware, createRateLimitMiddleware, type paths };
27839
+ export { type AccountOwner, type AccountOwnerType, type Action, type ActiveSubscriptionsResponse, type Affiliate, type AffiliateAttributionWebhook, type AffiliateCommission, AffiliateCommissionsResource, type AffiliateMembershipWebhook, type AffiliatePayout, type AffiliatePayoutWebhook, AffiliatePayoutsResource, type AffiliateProgram, type AffiliateProgramGroup, type AffiliateProgramMembership, type AffiliateProgramWebhook, AffiliateProgramsResource, type AffiliateReferral, AffiliateReferralsResource, type AffiliateRules, type AffiliateRulesWebhook, type AffiliateWebhook, AffiliatesResource, type Agent, type AgentRun, AgentsResource, AiAgentRunsResource, type App, type AppChargeWebhook, type AppEvent, type AppInstallation, type AppInstallationWebhook, type AppWebhook, AppsResource, type BaseCustomerWebhook, BaseResource, ChannelsResource, type Charge, ChargesResource, type Checklist, type ChecklistStep, CompaniesResource, type Company, type Contact, type ContactWebhook, ContactsResource, type CursorPagination, CustomDataResource, type CustomField, type CustomFieldDefaultValue, type Customer, type CustomerContact, type CustomerContactWebhook, type CustomerSegment, CustomerSegmentsResource, type CustomerWebhook, type CustomerWithoutSubscriptionWebhook, CustomersResource, type Deal, type DealAcquirer, DealActivitiesResource, type DealActivity, type DealAffiliate, type DealApp, type DealContact, type DealCustomData, type DealCustomer, type DealEvent, type DealFlow, type DealFlowAffiliate, type DealFlowDefaultSource, type DealFlowPartnership, type DealFlowStage, type DealFlowUser, DealFlowsResource, type DealOwner, type DealPartnership, type DealPlan, type DealStage, DealsResource, type DetailedAffiliate, type DetailedFlow, type DocsCollection, type DocsCollectionResponse, type DocsGenerateJobResponse, type DocsGenerateStatusCompleted, type DocsGenerateStatusFailed, type DocsGenerateStatusPending, type DocsGroup, type DocsGroupResponse, type DocsPage, type DocsPageResponse, type DocsPageSummary, type DocsRepository, DocsResource, type EmailCampaign, type EmailDelivery, type EmailDeliveryStats, type EmailLayout, type EmailPreview, type EmailSender, type EmailUnsubscribeGroup, type EmailUnsubscribeGroupMember, EmailUnsubscribeGroupsResource, EntitiesResource, type EventWebhook, type ExtensionUninstallPayload, type ExtensionWebhook, type Feature, type Flow, type FlowActionRun, FlowExtensionsResource, FlowsResource, type InvalidTokenError, type Invoice, type InvoiceWebhook, JournalEntriesResource, type JournalEntry, type JournalEntryApp, type JournalEntryFile, type List, ListsResource, type LogoChurnResponse, MantleAPIError, MantleAuthenticationError, MantleCoreClient, type MantleCoreClientConfig, MantleNotFoundError, MantlePermissionError, MantleRateLimitError, MantleValidationError, MeResource, type Meeting, type MeetingAttendee, type MeetingAttendeeRef, type MeetingContactRef, type MeetingCustomer, type MeetingDeal, type MeetingPermission, type MeetingTaskSuggestion, type MeetingTranscript, type MeetingUser, type MeetingUtterance, MeetingsResource, MetricsResource, type MissingScopesError, type MrrResponse, type NetInstallsResponse, type NetRevenueResponse, type NetRevenueRetentionResponse, type Organization, OrganizationResource, type Pagination, type PayoutResponse, type Plan, type PlanFeature, type PlanFeatureWebhook, type PlanUsageChargeWebhook, type PlanWebhook, type PredictedLtvResponse, type RateLimitOptions, type RevenueRetentionResponse, type Review, type ReviewWebhook, type StandardMetricResponse, type Subscription, type SubscriptionWebhook, SubscriptionsResource, type SyncedEmail, type SyncedEmailContact, type SyncedEmailCustomer, type SyncedEmailDeal, type SyncedEmailMessage, type SyncedEmailUser, SyncedEmailsResource, type Task, type TaskComment, type TaskTodoItem, TasksResource, type ThreadEventType, type ThreadMessageWebhook, type ThreadWebhook, type Ticket, type TicketAgent, type TicketApp, type TicketAttachment, type TicketChannel, type TicketContact, type TicketCustomer, type TicketEvent, type TicketLoop, type TicketMessage, TicketsResource, type TimeSeriesDataPoint, type TimelineComment, TimelineCommentsResource, type TokenRefreshResult, type Transaction, type TransactionWebhook, TransactionsResource, type Trigger, type UninstallEventWebhook, type UsageEvent, type UsageEventResponse, UsageEventsResource, type UsageMetric, type UsageMetricResponse, type User, UsersResource, type Webhook, WebhooksResource, type components, createRateLimitMiddleware, type paths };
package/dist/index.js CHANGED
@@ -76,7 +76,6 @@ __export(index_exports, {
76
76
  UsageEventsResource: () => UsageEventsResource,
77
77
  UsersResource: () => UsersResource,
78
78
  WebhooksResource: () => WebhooksResource,
79
- createAuthRefreshMiddleware: () => createAuthRefreshMiddleware,
80
79
  createRateLimitMiddleware: () => createRateLimitMiddleware
81
80
  });
82
81
  module.exports = __toCommonJS(index_exports);
@@ -98,9 +97,10 @@ var MantleAPIError = class _MantleAPIError extends Error {
98
97
  }
99
98
  };
100
99
  var MantleAuthenticationError = class _MantleAuthenticationError extends MantleAPIError {
101
- constructor(message = "Authentication failed") {
100
+ constructor(message = "Authentication failed", isExpired = false) {
102
101
  super(message, 401);
103
102
  this.name = "MantleAuthenticationError";
103
+ this.isExpired = isExpired;
104
104
  Object.setPrototypeOf(this, _MantleAuthenticationError.prototype);
105
105
  }
106
106
  };
@@ -166,7 +166,10 @@ var BaseResource = class {
166
166
  const details = typeof err?.details === "string" ? err.details : void 0;
167
167
  switch (response.status) {
168
168
  case 401:
169
- return new MantleAuthenticationError(message);
169
+ return new MantleAuthenticationError(
170
+ message,
171
+ message.startsWith("token_expired")
172
+ );
170
173
  case 403:
171
174
  return new MantlePermissionError(message);
172
175
  case 404:
@@ -1162,6 +1165,8 @@ var MantleCoreClient = class {
1162
1165
  }
1163
1166
  this.apiKey = config.apiKey;
1164
1167
  this.accessToken = config.accessToken;
1168
+ this.accessTokenExpiresAt = config.accessTokenExpiresAt;
1169
+ this.refreshAccessToken = config.refreshAccessToken;
1165
1170
  const timeoutMs = config.timeout ?? 3e4;
1166
1171
  this._api = (0, import_openapi_fetch.default)({
1167
1172
  baseUrl: config.baseURL || "https://api.heymantle.com/v1",
@@ -1171,12 +1176,39 @@ var MantleCoreClient = class {
1171
1176
  ...config.fetch ? { fetch: config.fetch } : {}
1172
1177
  });
1173
1178
  this._api.use({
1174
- onRequest: ({ request }) => {
1179
+ onRequest: async ({ request }) => {
1180
+ if (this.refreshAccessToken && this.isTokenExpired()) {
1181
+ await this.doRefresh();
1182
+ }
1175
1183
  const token = this.accessToken || this.apiKey;
1176
1184
  if (token) {
1177
1185
  request.headers.set("Authorization", `Bearer ${token}`);
1178
1186
  }
1179
1187
  return request;
1188
+ },
1189
+ onResponse: async ({ request, response }) => {
1190
+ if (response.status !== 401 || !this.refreshAccessToken) return void 0;
1191
+ try {
1192
+ const body = await response.clone().json();
1193
+ const errorMsg = typeof body?.error === "string" ? body.error : "";
1194
+ if (errorMsg.startsWith("invalid_token") || errorMsg.startsWith("invalid_client")) {
1195
+ return void 0;
1196
+ }
1197
+ } catch {
1198
+ }
1199
+ try {
1200
+ const newToken = await this.doRefresh();
1201
+ const headers = new Headers(request.headers);
1202
+ headers.set("Authorization", `Bearer ${newToken}`);
1203
+ return fetch(new Request(request.url, {
1204
+ method: request.method,
1205
+ headers,
1206
+ body: request.body,
1207
+ signal: request.signal
1208
+ }));
1209
+ } catch {
1210
+ return void 0;
1211
+ }
1180
1212
  }
1181
1213
  });
1182
1214
  if (timeoutMs > 0) {
@@ -1260,48 +1292,38 @@ var MantleCoreClient = class {
1260
1292
  if (credentials.accessToken !== void 0) {
1261
1293
  this.accessToken = credentials.accessToken;
1262
1294
  }
1295
+ if (credentials.accessTokenExpiresAt !== void 0) {
1296
+ this.accessTokenExpiresAt = credentials.accessTokenExpiresAt;
1297
+ }
1263
1298
  }
1264
- };
1265
-
1266
- // src/middleware/auth-refresh.ts
1267
- function createAuthRefreshMiddleware(options) {
1268
- const {
1269
- refreshToken,
1270
- updateAuth,
1271
- onRefreshSuccess,
1272
- onRefreshFailed,
1273
- maxRefreshAttempts = 1
1274
- } = options;
1275
- let refreshAttempts = 0;
1276
- return {
1277
- async onResponse({ request, response }) {
1278
- if (response.status !== 401) return void 0;
1279
- if (refreshAttempts >= maxRefreshAttempts) {
1280
- refreshAttempts = 0;
1281
- return void 0;
1282
- }
1283
- refreshAttempts++;
1299
+ /**
1300
+ * Check if the access token is expired (with a 30-second buffer).
1301
+ */
1302
+ isTokenExpired() {
1303
+ if (!this.accessTokenExpiresAt) return false;
1304
+ return this.accessTokenExpiresAt.getTime() - Date.now() <= 3e4;
1305
+ }
1306
+ /**
1307
+ * Execute a token refresh, deduplicating concurrent calls.
1308
+ * All concurrent requests will await the same in-flight refresh promise.
1309
+ */
1310
+ async doRefresh() {
1311
+ if (this.refreshPromise) return this.refreshPromise;
1312
+ this.refreshPromise = (async () => {
1284
1313
  try {
1285
- const newToken = await refreshToken();
1286
- updateAuth(newToken);
1287
- onRefreshSuccess?.(newToken);
1288
- refreshAttempts = 0;
1289
- const headers = new Headers(request.headers);
1290
- headers.set("Authorization", `Bearer ${newToken}`);
1291
- return fetch(new Request(request.url, {
1292
- method: request.method,
1293
- headers,
1294
- body: request.body,
1295
- signal: request.signal
1296
- }));
1297
- } catch (refreshError) {
1298
- refreshAttempts = 0;
1299
- onRefreshFailed?.(refreshError);
1300
- return void 0;
1314
+ const result = await this.refreshAccessToken();
1315
+ this.accessToken = result.accessToken;
1316
+ if (result.expiresAt) {
1317
+ this.accessTokenExpiresAt = result.expiresAt;
1318
+ }
1319
+ return result.accessToken;
1320
+ } finally {
1321
+ this.refreshPromise = void 0;
1301
1322
  }
1302
- }
1303
- };
1304
- }
1323
+ })();
1324
+ return this.refreshPromise;
1325
+ }
1326
+ };
1305
1327
 
1306
1328
  // src/middleware/rate-limit.ts
1307
1329
  var RateLimiter = class {
@@ -1468,6 +1490,5 @@ function createRateLimitMiddleware(options = {}) {
1468
1490
  UsageEventsResource,
1469
1491
  UsersResource,
1470
1492
  WebhooksResource,
1471
- createAuthRefreshMiddleware,
1472
1493
  createRateLimitMiddleware
1473
1494
  });
package/dist/index.mjs CHANGED
@@ -15,9 +15,10 @@ var MantleAPIError = class _MantleAPIError extends Error {
15
15
  }
16
16
  };
17
17
  var MantleAuthenticationError = class _MantleAuthenticationError extends MantleAPIError {
18
- constructor(message = "Authentication failed") {
18
+ constructor(message = "Authentication failed", isExpired = false) {
19
19
  super(message, 401);
20
20
  this.name = "MantleAuthenticationError";
21
+ this.isExpired = isExpired;
21
22
  Object.setPrototypeOf(this, _MantleAuthenticationError.prototype);
22
23
  }
23
24
  };
@@ -83,7 +84,10 @@ var BaseResource = class {
83
84
  const details = typeof err?.details === "string" ? err.details : void 0;
84
85
  switch (response.status) {
85
86
  case 401:
86
- return new MantleAuthenticationError(message);
87
+ return new MantleAuthenticationError(
88
+ message,
89
+ message.startsWith("token_expired")
90
+ );
87
91
  case 403:
88
92
  return new MantlePermissionError(message);
89
93
  case 404:
@@ -1079,6 +1083,8 @@ var MantleCoreClient = class {
1079
1083
  }
1080
1084
  this.apiKey = config.apiKey;
1081
1085
  this.accessToken = config.accessToken;
1086
+ this.accessTokenExpiresAt = config.accessTokenExpiresAt;
1087
+ this.refreshAccessToken = config.refreshAccessToken;
1082
1088
  const timeoutMs = config.timeout ?? 3e4;
1083
1089
  this._api = createClient({
1084
1090
  baseUrl: config.baseURL || "https://api.heymantle.com/v1",
@@ -1088,12 +1094,39 @@ var MantleCoreClient = class {
1088
1094
  ...config.fetch ? { fetch: config.fetch } : {}
1089
1095
  });
1090
1096
  this._api.use({
1091
- onRequest: ({ request }) => {
1097
+ onRequest: async ({ request }) => {
1098
+ if (this.refreshAccessToken && this.isTokenExpired()) {
1099
+ await this.doRefresh();
1100
+ }
1092
1101
  const token = this.accessToken || this.apiKey;
1093
1102
  if (token) {
1094
1103
  request.headers.set("Authorization", `Bearer ${token}`);
1095
1104
  }
1096
1105
  return request;
1106
+ },
1107
+ onResponse: async ({ request, response }) => {
1108
+ if (response.status !== 401 || !this.refreshAccessToken) return void 0;
1109
+ try {
1110
+ const body = await response.clone().json();
1111
+ const errorMsg = typeof body?.error === "string" ? body.error : "";
1112
+ if (errorMsg.startsWith("invalid_token") || errorMsg.startsWith("invalid_client")) {
1113
+ return void 0;
1114
+ }
1115
+ } catch {
1116
+ }
1117
+ try {
1118
+ const newToken = await this.doRefresh();
1119
+ const headers = new Headers(request.headers);
1120
+ headers.set("Authorization", `Bearer ${newToken}`);
1121
+ return fetch(new Request(request.url, {
1122
+ method: request.method,
1123
+ headers,
1124
+ body: request.body,
1125
+ signal: request.signal
1126
+ }));
1127
+ } catch {
1128
+ return void 0;
1129
+ }
1097
1130
  }
1098
1131
  });
1099
1132
  if (timeoutMs > 0) {
@@ -1177,48 +1210,38 @@ var MantleCoreClient = class {
1177
1210
  if (credentials.accessToken !== void 0) {
1178
1211
  this.accessToken = credentials.accessToken;
1179
1212
  }
1213
+ if (credentials.accessTokenExpiresAt !== void 0) {
1214
+ this.accessTokenExpiresAt = credentials.accessTokenExpiresAt;
1215
+ }
1180
1216
  }
1181
- };
1182
-
1183
- // src/middleware/auth-refresh.ts
1184
- function createAuthRefreshMiddleware(options) {
1185
- const {
1186
- refreshToken,
1187
- updateAuth,
1188
- onRefreshSuccess,
1189
- onRefreshFailed,
1190
- maxRefreshAttempts = 1
1191
- } = options;
1192
- let refreshAttempts = 0;
1193
- return {
1194
- async onResponse({ request, response }) {
1195
- if (response.status !== 401) return void 0;
1196
- if (refreshAttempts >= maxRefreshAttempts) {
1197
- refreshAttempts = 0;
1198
- return void 0;
1199
- }
1200
- refreshAttempts++;
1217
+ /**
1218
+ * Check if the access token is expired (with a 30-second buffer).
1219
+ */
1220
+ isTokenExpired() {
1221
+ if (!this.accessTokenExpiresAt) return false;
1222
+ return this.accessTokenExpiresAt.getTime() - Date.now() <= 3e4;
1223
+ }
1224
+ /**
1225
+ * Execute a token refresh, deduplicating concurrent calls.
1226
+ * All concurrent requests will await the same in-flight refresh promise.
1227
+ */
1228
+ async doRefresh() {
1229
+ if (this.refreshPromise) return this.refreshPromise;
1230
+ this.refreshPromise = (async () => {
1201
1231
  try {
1202
- const newToken = await refreshToken();
1203
- updateAuth(newToken);
1204
- onRefreshSuccess?.(newToken);
1205
- refreshAttempts = 0;
1206
- const headers = new Headers(request.headers);
1207
- headers.set("Authorization", `Bearer ${newToken}`);
1208
- return fetch(new Request(request.url, {
1209
- method: request.method,
1210
- headers,
1211
- body: request.body,
1212
- signal: request.signal
1213
- }));
1214
- } catch (refreshError) {
1215
- refreshAttempts = 0;
1216
- onRefreshFailed?.(refreshError);
1217
- return void 0;
1232
+ const result = await this.refreshAccessToken();
1233
+ this.accessToken = result.accessToken;
1234
+ if (result.expiresAt) {
1235
+ this.accessTokenExpiresAt = result.expiresAt;
1236
+ }
1237
+ return result.accessToken;
1238
+ } finally {
1239
+ this.refreshPromise = void 0;
1218
1240
  }
1219
- }
1220
- };
1221
- }
1241
+ })();
1242
+ return this.refreshPromise;
1243
+ }
1244
+ };
1222
1245
 
1223
1246
  // src/middleware/rate-limit.ts
1224
1247
  var RateLimiter = class {
@@ -1384,6 +1407,5 @@ export {
1384
1407
  UsageEventsResource,
1385
1408
  UsersResource,
1386
1409
  WebhooksResource,
1387
- createAuthRefreshMiddleware,
1388
1410
  createRateLimitMiddleware
1389
1411
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heymantle/core-api-client",
3
- "version": "0.3.4",
3
+ "version": "0.4.5",
4
4
  "description": "TypeScript SDK for the Mantle Core API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",