@feelflow/ffid-sdk 2.5.2 → 2.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.cts CHANGED
@@ -94,6 +94,11 @@ declare function retrieveCodeVerifier(logger?: PKCELogger): string | null;
94
94
 
95
95
  /** Billing interval for subscriptions */
96
96
  type FFIDBillingInterval = 'monthly' | 'yearly';
97
+ /**
98
+ * Supported currencies for billing responses.
99
+ * Mirrors the platform's `SupportedCurrency` enum (`jpy` = zero-decimal Japanese Yen, `usd` = US Dollar).
100
+ */
101
+ type FFIDSupportedCurrency = 'jpy' | 'usd';
97
102
  /** Service information returned by plans endpoint */
98
103
  interface FFIDServiceInfo {
99
104
  id: string;
@@ -285,27 +290,56 @@ interface FFIDPlanChangeLineItem {
285
290
  description: string;
286
291
  amount: number;
287
292
  }
293
+ /** Fields shared by every plan-change preview variant (internal; consumers use `FFIDPlanChangePreview`) */
294
+ interface FFIDPlanChangePreviewBase {
295
+ /** Discriminant for preview response variants (reserved for future unions with e.g. seat-change previews) */
296
+ type: 'plan-change';
297
+ /** Current plan display info. `price` is the total for the current quantity (unitPrice × quantity), not per-seat. */
298
+ currentPlan: {
299
+ name: string;
300
+ price: number;
301
+ };
302
+ /** New plan display info. `price` is the total for the effective quantity (unitPrice × quantity), not per-seat. */
303
+ newPlan: {
304
+ name: string;
305
+ price: number;
306
+ };
307
+ billingInterval: FFIDBillingInterval;
308
+ isUpgrade: boolean;
309
+ /** Full amount of the next billing cycle at the new plan's standard price. Never overwritten by Stripe proration data. */
310
+ nextInvoiceAmount: number;
311
+ nextInvoiceDate: string | null;
312
+ currency: FFIDSupportedCurrency;
313
+ /** true when amounts are estimated from local prices (no Stripe proration data) */
314
+ isEstimate: boolean;
315
+ /** Reason why `isEstimate` is true. Only meaningful when `isEstimate === true`. */
316
+ estimateReason?: 'no_stripe_data' | 'custom_pricing' | 'stripe_error';
317
+ lineItems: FFIDPlanChangeLineItem[];
318
+ }
319
+ /**
320
+ * Plan change proration preview.
321
+ *
322
+ * `willApplyAtPeriodEnd` is a discriminant that constrains related fields at the type level:
323
+ * - `true`: period-end-deferred downgrade. `proratedAmount` is always 0; `effectiveDate` mirrors
324
+ * the subscription's `currentPeriodEnd` (may be `null` when the subscription has no active
325
+ * billing cycle yet — e.g. a pre-Stripe trial or a subscription whose billing cycle is unset).
326
+ * - `false`: immediate change. `effectiveDate` is always `null`; `proratedAmount` is the live
327
+ * (possibly Stripe-refined) day-basis difference.
328
+ */
329
+ type FFIDPlanChangePreview = FFIDPlanChangePreviewBase & ({
330
+ willApplyAtPeriodEnd: true;
331
+ effectiveDate: string | null;
332
+ /** 0 on period-end-deferred changes; charge happens at the next invoice */
333
+ proratedAmount: 0;
334
+ } | {
335
+ willApplyAtPeriodEnd: false;
336
+ effectiveDate: null;
337
+ /** Prorated difference charged within the current billing period */
338
+ proratedAmount: number;
339
+ });
288
340
  /** Response from plan change preview endpoint */
289
341
  interface FFIDPlanChangePreviewResponse {
290
- preview: {
291
- currentPlan: {
292
- name: string;
293
- price: number;
294
- };
295
- newPlan: {
296
- name: string;
297
- price: number;
298
- };
299
- billingInterval: FFIDBillingInterval;
300
- isUpgrade: boolean;
301
- proratedAmount: number;
302
- nextInvoiceAmount: number;
303
- nextInvoiceDate: string | null;
304
- currency: string;
305
- isEstimate: boolean;
306
- estimateReason?: string;
307
- lineItems: FFIDPlanChangeLineItem[];
308
- };
342
+ preview: FFIDPlanChangePreview;
309
343
  }
310
344
 
311
345
  /** OTP / magic link methods - sendOtp / verifyOtp */
@@ -441,6 +475,12 @@ declare function createFFIDClient(config: FFIDConfig): {
441
475
  accessToken: string;
442
476
  refreshToken: string;
443
477
  }) => Promise<FFIDApiResponse<FFIDOtpVerifyResponse>>;
478
+ /** Newsletter methods (subscribe / confirm / unsubscribe) */
479
+ newsletter: {
480
+ subscribe: (params: FFIDNewsletterSubscribeParams) => Promise<FFIDApiResponse<FFIDNewsletterSubscribeResponse>>;
481
+ confirm: (params: FFIDNewsletterConfirmParams) => Promise<FFIDApiResponse<FFIDNewsletterConfirmResponse>>;
482
+ unsubscribe: (params: FFIDNewsletterUnsubscribeParams) => Promise<FFIDApiResponse<FFIDNewsletterUnsubscribeResponse>>;
483
+ };
444
484
  /** Token store (token mode only) */
445
485
  tokenStore: TokenStore;
446
486
  /** Resolved auth mode */
@@ -729,4 +769,64 @@ declare function createFFIDAnnouncementsClient(config?: FFIDAnnouncementsClientC
729
769
  /** Type of the FFID Announcements client */
730
770
  type FFIDAnnouncementsClient = ReturnType<typeof createFFIDAnnouncementsClient>;
731
771
 
732
- export { AnnouncementListResponse, type ContractWizardFlowType, type ContractWizardResubscribeOptions, type ContractWizardSubscribeOptions, type ContractWizardSubscriptionOptions, DEFAULT_API_BASE_URL, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDBillingInterval, FFIDCacheAdapter, type FFIDCancelPendingDowngradeResponse, type FFIDCancelSubscriptionParams, type FFIDCancelSubscriptionResponse, type FFIDChangePlanParams, type FFIDChangePlanResponse, FFIDCheckoutSessionResponse, type FFIDClient, FFIDConfig, FFIDCreateCheckoutParams, FFIDCreatePortalParams, FFIDError, FFIDListMembersResponse, type FFIDListPlansResponse, FFIDLogger, FFIDMemberRole, FFIDOAuthUserInfo, FFIDOrganization, type FFIDOtpSendResponse, type FFIDOtpVerifyResponse, type FFIDPasswordResetConfirmResponse, type FFIDPasswordResetResponse, type FFIDPasswordResetVerifyResponse, type FFIDPlanChangeLineItem, type FFIDPlanChangePreviewResponse, type FFIDPlanInfo, FFIDPortalSessionResponse, type FFIDPreviewPlanChangeParams, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, FFIDRemoveMemberResponse, type FFIDResetSessionResponse, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, FFIDUpdateMemberRoleResponse, FFIDUser, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, type KVNamespaceLike, ListAnnouncementsOptions, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, retrieveCodeVerifier, storeCodeVerifier, useFFID, useSubscription, withFFIDAuth, withSubscription };
772
+ /**
773
+ * Newsletter types exposed by the FFID SDK.
774
+ *
775
+ * 2-layer newsletter model (#2078):
776
+ * - `inquiry_followup`: 問い合わせフォローアップ (Type A)
777
+ * - `general`: 定期ニュースレター (Type B)
778
+ *
779
+ * FFID account holders' preferences live in `user_marketing_preferences`;
780
+ * anonymous subscribers live in `newsletter_subscribers` with double
781
+ * opt-in required.
782
+ */
783
+ declare const FFID_NEWSLETTER_TYPES: readonly ["inquiry_followup", "general"];
784
+ type FFIDNewsletterType = (typeof FFID_NEWSLETTER_TYPES)[number];
785
+ interface FFIDNewsletterSubscribeParams {
786
+ /** Subscriber email address */
787
+ email: string;
788
+ /** One or more newsletter types to opt in to */
789
+ types: FFIDNewsletterType[];
790
+ /** Origin string recorded on the subscriber row (e.g. your service code) */
791
+ source: string;
792
+ /** ISO 639-1 locale (e.g. 'ja', 'en') */
793
+ locale?: string;
794
+ }
795
+ interface FFIDNewsletterSubscribeResponse {
796
+ ok: true;
797
+ /** True when a double opt-in confirmation email was sent */
798
+ requiresConfirmation: boolean;
799
+ /** True when the email matched an existing FFID account; the caller
800
+ * must sign in to update preferences. Preferences are NOT modified. */
801
+ requiresSignIn: boolean;
802
+ }
803
+ interface FFIDNewsletterConfirmParams {
804
+ /** Confirmation token received in the double opt-in email */
805
+ token: string;
806
+ }
807
+ interface FFIDNewsletterConfirmResponse {
808
+ ok: true;
809
+ }
810
+ interface FFIDNewsletterUnsubscribeParams {
811
+ /** Unsubscribe token received in the newsletter footer / List-Unsubscribe header */
812
+ token: string;
813
+ }
814
+ interface FFIDNewsletterUnsubscribeResponse {
815
+ ok: true;
816
+ }
817
+
818
+ /** Newsletter methods - subscribe / confirm / unsubscribe */
819
+
820
+ interface NewsletterMethodsDeps {
821
+ fetchWithAuth: <T>(endpoint: string, options?: RequestInit) => Promise<FFIDApiResponse<T>>;
822
+ baseUrl: string;
823
+ createError: (code: string, message: string) => FFIDError;
824
+ }
825
+ declare function createNewsletterMethods(deps: NewsletterMethodsDeps): {
826
+ subscribe: (params: FFIDNewsletterSubscribeParams) => Promise<FFIDApiResponse<FFIDNewsletterSubscribeResponse>>;
827
+ confirm: (params: FFIDNewsletterConfirmParams) => Promise<FFIDApiResponse<FFIDNewsletterConfirmResponse>>;
828
+ unsubscribe: (params: FFIDNewsletterUnsubscribeParams) => Promise<FFIDApiResponse<FFIDNewsletterUnsubscribeResponse>>;
829
+ };
830
+ type FFIDNewsletterClient = ReturnType<typeof createNewsletterMethods>;
831
+
832
+ export { AnnouncementListResponse, type ContractWizardFlowType, type ContractWizardResubscribeOptions, type ContractWizardSubscribeOptions, type ContractWizardSubscriptionOptions, DEFAULT_API_BASE_URL, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDBillingInterval, FFIDCacheAdapter, type FFIDCancelPendingDowngradeResponse, type FFIDCancelSubscriptionParams, type FFIDCancelSubscriptionResponse, type FFIDChangePlanParams, type FFIDChangePlanResponse, FFIDCheckoutSessionResponse, type FFIDClient, FFIDConfig, FFIDCreateCheckoutParams, FFIDCreatePortalParams, FFIDError, FFIDListMembersResponse, type FFIDListPlansResponse, FFIDLogger, FFIDMemberRole, type FFIDNewsletterClient, type FFIDNewsletterConfirmParams, type FFIDNewsletterConfirmResponse, type FFIDNewsletterSubscribeParams, type FFIDNewsletterSubscribeResponse, type FFIDNewsletterType, type FFIDNewsletterUnsubscribeParams, type FFIDNewsletterUnsubscribeResponse, FFIDOAuthUserInfo, FFIDOrganization, type FFIDOtpSendResponse, type FFIDOtpVerifyResponse, type FFIDPasswordResetConfirmResponse, type FFIDPasswordResetResponse, type FFIDPasswordResetVerifyResponse, type FFIDPlanChangeLineItem, type FFIDPlanChangePreview, type FFIDPlanChangePreviewResponse, type FFIDPlanInfo, FFIDPortalSessionResponse, type FFIDPreviewPlanChangeParams, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, FFIDRemoveMemberResponse, type FFIDResetSessionResponse, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, type FFIDSupportedCurrency, FFIDUpdateMemberRoleResponse, FFIDUser, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_NEWSLETTER_TYPES, type KVNamespaceLike, ListAnnouncementsOptions, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, retrieveCodeVerifier, storeCodeVerifier, useFFID, useSubscription, withFFIDAuth, withSubscription };
package/dist/index.d.ts CHANGED
@@ -94,6 +94,11 @@ declare function retrieveCodeVerifier(logger?: PKCELogger): string | null;
94
94
 
95
95
  /** Billing interval for subscriptions */
96
96
  type FFIDBillingInterval = 'monthly' | 'yearly';
97
+ /**
98
+ * Supported currencies for billing responses.
99
+ * Mirrors the platform's `SupportedCurrency` enum (`jpy` = zero-decimal Japanese Yen, `usd` = US Dollar).
100
+ */
101
+ type FFIDSupportedCurrency = 'jpy' | 'usd';
97
102
  /** Service information returned by plans endpoint */
98
103
  interface FFIDServiceInfo {
99
104
  id: string;
@@ -285,27 +290,56 @@ interface FFIDPlanChangeLineItem {
285
290
  description: string;
286
291
  amount: number;
287
292
  }
293
+ /** Fields shared by every plan-change preview variant (internal; consumers use `FFIDPlanChangePreview`) */
294
+ interface FFIDPlanChangePreviewBase {
295
+ /** Discriminant for preview response variants (reserved for future unions with e.g. seat-change previews) */
296
+ type: 'plan-change';
297
+ /** Current plan display info. `price` is the total for the current quantity (unitPrice × quantity), not per-seat. */
298
+ currentPlan: {
299
+ name: string;
300
+ price: number;
301
+ };
302
+ /** New plan display info. `price` is the total for the effective quantity (unitPrice × quantity), not per-seat. */
303
+ newPlan: {
304
+ name: string;
305
+ price: number;
306
+ };
307
+ billingInterval: FFIDBillingInterval;
308
+ isUpgrade: boolean;
309
+ /** Full amount of the next billing cycle at the new plan's standard price. Never overwritten by Stripe proration data. */
310
+ nextInvoiceAmount: number;
311
+ nextInvoiceDate: string | null;
312
+ currency: FFIDSupportedCurrency;
313
+ /** true when amounts are estimated from local prices (no Stripe proration data) */
314
+ isEstimate: boolean;
315
+ /** Reason why `isEstimate` is true. Only meaningful when `isEstimate === true`. */
316
+ estimateReason?: 'no_stripe_data' | 'custom_pricing' | 'stripe_error';
317
+ lineItems: FFIDPlanChangeLineItem[];
318
+ }
319
+ /**
320
+ * Plan change proration preview.
321
+ *
322
+ * `willApplyAtPeriodEnd` is a discriminant that constrains related fields at the type level:
323
+ * - `true`: period-end-deferred downgrade. `proratedAmount` is always 0; `effectiveDate` mirrors
324
+ * the subscription's `currentPeriodEnd` (may be `null` when the subscription has no active
325
+ * billing cycle yet — e.g. a pre-Stripe trial or a subscription whose billing cycle is unset).
326
+ * - `false`: immediate change. `effectiveDate` is always `null`; `proratedAmount` is the live
327
+ * (possibly Stripe-refined) day-basis difference.
328
+ */
329
+ type FFIDPlanChangePreview = FFIDPlanChangePreviewBase & ({
330
+ willApplyAtPeriodEnd: true;
331
+ effectiveDate: string | null;
332
+ /** 0 on period-end-deferred changes; charge happens at the next invoice */
333
+ proratedAmount: 0;
334
+ } | {
335
+ willApplyAtPeriodEnd: false;
336
+ effectiveDate: null;
337
+ /** Prorated difference charged within the current billing period */
338
+ proratedAmount: number;
339
+ });
288
340
  /** Response from plan change preview endpoint */
289
341
  interface FFIDPlanChangePreviewResponse {
290
- preview: {
291
- currentPlan: {
292
- name: string;
293
- price: number;
294
- };
295
- newPlan: {
296
- name: string;
297
- price: number;
298
- };
299
- billingInterval: FFIDBillingInterval;
300
- isUpgrade: boolean;
301
- proratedAmount: number;
302
- nextInvoiceAmount: number;
303
- nextInvoiceDate: string | null;
304
- currency: string;
305
- isEstimate: boolean;
306
- estimateReason?: string;
307
- lineItems: FFIDPlanChangeLineItem[];
308
- };
342
+ preview: FFIDPlanChangePreview;
309
343
  }
310
344
 
311
345
  /** OTP / magic link methods - sendOtp / verifyOtp */
@@ -441,6 +475,12 @@ declare function createFFIDClient(config: FFIDConfig): {
441
475
  accessToken: string;
442
476
  refreshToken: string;
443
477
  }) => Promise<FFIDApiResponse<FFIDOtpVerifyResponse>>;
478
+ /** Newsletter methods (subscribe / confirm / unsubscribe) */
479
+ newsletter: {
480
+ subscribe: (params: FFIDNewsletterSubscribeParams) => Promise<FFIDApiResponse<FFIDNewsletterSubscribeResponse>>;
481
+ confirm: (params: FFIDNewsletterConfirmParams) => Promise<FFIDApiResponse<FFIDNewsletterConfirmResponse>>;
482
+ unsubscribe: (params: FFIDNewsletterUnsubscribeParams) => Promise<FFIDApiResponse<FFIDNewsletterUnsubscribeResponse>>;
483
+ };
444
484
  /** Token store (token mode only) */
445
485
  tokenStore: TokenStore;
446
486
  /** Resolved auth mode */
@@ -729,4 +769,64 @@ declare function createFFIDAnnouncementsClient(config?: FFIDAnnouncementsClientC
729
769
  /** Type of the FFID Announcements client */
730
770
  type FFIDAnnouncementsClient = ReturnType<typeof createFFIDAnnouncementsClient>;
731
771
 
732
- export { AnnouncementListResponse, type ContractWizardFlowType, type ContractWizardResubscribeOptions, type ContractWizardSubscribeOptions, type ContractWizardSubscriptionOptions, DEFAULT_API_BASE_URL, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDBillingInterval, FFIDCacheAdapter, type FFIDCancelPendingDowngradeResponse, type FFIDCancelSubscriptionParams, type FFIDCancelSubscriptionResponse, type FFIDChangePlanParams, type FFIDChangePlanResponse, FFIDCheckoutSessionResponse, type FFIDClient, FFIDConfig, FFIDCreateCheckoutParams, FFIDCreatePortalParams, FFIDError, FFIDListMembersResponse, type FFIDListPlansResponse, FFIDLogger, FFIDMemberRole, FFIDOAuthUserInfo, FFIDOrganization, type FFIDOtpSendResponse, type FFIDOtpVerifyResponse, type FFIDPasswordResetConfirmResponse, type FFIDPasswordResetResponse, type FFIDPasswordResetVerifyResponse, type FFIDPlanChangeLineItem, type FFIDPlanChangePreviewResponse, type FFIDPlanInfo, FFIDPortalSessionResponse, type FFIDPreviewPlanChangeParams, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, FFIDRemoveMemberResponse, type FFIDResetSessionResponse, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, FFIDUpdateMemberRoleResponse, FFIDUser, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, type KVNamespaceLike, ListAnnouncementsOptions, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, retrieveCodeVerifier, storeCodeVerifier, useFFID, useSubscription, withFFIDAuth, withSubscription };
772
+ /**
773
+ * Newsletter types exposed by the FFID SDK.
774
+ *
775
+ * 2-layer newsletter model (#2078):
776
+ * - `inquiry_followup`: 問い合わせフォローアップ (Type A)
777
+ * - `general`: 定期ニュースレター (Type B)
778
+ *
779
+ * FFID account holders' preferences live in `user_marketing_preferences`;
780
+ * anonymous subscribers live in `newsletter_subscribers` with double
781
+ * opt-in required.
782
+ */
783
+ declare const FFID_NEWSLETTER_TYPES: readonly ["inquiry_followup", "general"];
784
+ type FFIDNewsletterType = (typeof FFID_NEWSLETTER_TYPES)[number];
785
+ interface FFIDNewsletterSubscribeParams {
786
+ /** Subscriber email address */
787
+ email: string;
788
+ /** One or more newsletter types to opt in to */
789
+ types: FFIDNewsletterType[];
790
+ /** Origin string recorded on the subscriber row (e.g. your service code) */
791
+ source: string;
792
+ /** ISO 639-1 locale (e.g. 'ja', 'en') */
793
+ locale?: string;
794
+ }
795
+ interface FFIDNewsletterSubscribeResponse {
796
+ ok: true;
797
+ /** True when a double opt-in confirmation email was sent */
798
+ requiresConfirmation: boolean;
799
+ /** True when the email matched an existing FFID account; the caller
800
+ * must sign in to update preferences. Preferences are NOT modified. */
801
+ requiresSignIn: boolean;
802
+ }
803
+ interface FFIDNewsletterConfirmParams {
804
+ /** Confirmation token received in the double opt-in email */
805
+ token: string;
806
+ }
807
+ interface FFIDNewsletterConfirmResponse {
808
+ ok: true;
809
+ }
810
+ interface FFIDNewsletterUnsubscribeParams {
811
+ /** Unsubscribe token received in the newsletter footer / List-Unsubscribe header */
812
+ token: string;
813
+ }
814
+ interface FFIDNewsletterUnsubscribeResponse {
815
+ ok: true;
816
+ }
817
+
818
+ /** Newsletter methods - subscribe / confirm / unsubscribe */
819
+
820
+ interface NewsletterMethodsDeps {
821
+ fetchWithAuth: <T>(endpoint: string, options?: RequestInit) => Promise<FFIDApiResponse<T>>;
822
+ baseUrl: string;
823
+ createError: (code: string, message: string) => FFIDError;
824
+ }
825
+ declare function createNewsletterMethods(deps: NewsletterMethodsDeps): {
826
+ subscribe: (params: FFIDNewsletterSubscribeParams) => Promise<FFIDApiResponse<FFIDNewsletterSubscribeResponse>>;
827
+ confirm: (params: FFIDNewsletterConfirmParams) => Promise<FFIDApiResponse<FFIDNewsletterConfirmResponse>>;
828
+ unsubscribe: (params: FFIDNewsletterUnsubscribeParams) => Promise<FFIDApiResponse<FFIDNewsletterUnsubscribeResponse>>;
829
+ };
830
+ type FFIDNewsletterClient = ReturnType<typeof createNewsletterMethods>;
831
+
832
+ export { AnnouncementListResponse, type ContractWizardFlowType, type ContractWizardResubscribeOptions, type ContractWizardSubscribeOptions, type ContractWizardSubscriptionOptions, DEFAULT_API_BASE_URL, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDBillingInterval, FFIDCacheAdapter, type FFIDCancelPendingDowngradeResponse, type FFIDCancelSubscriptionParams, type FFIDCancelSubscriptionResponse, type FFIDChangePlanParams, type FFIDChangePlanResponse, FFIDCheckoutSessionResponse, type FFIDClient, FFIDConfig, FFIDCreateCheckoutParams, FFIDCreatePortalParams, FFIDError, FFIDListMembersResponse, type FFIDListPlansResponse, FFIDLogger, FFIDMemberRole, type FFIDNewsletterClient, type FFIDNewsletterConfirmParams, type FFIDNewsletterConfirmResponse, type FFIDNewsletterSubscribeParams, type FFIDNewsletterSubscribeResponse, type FFIDNewsletterType, type FFIDNewsletterUnsubscribeParams, type FFIDNewsletterUnsubscribeResponse, FFIDOAuthUserInfo, FFIDOrganization, type FFIDOtpSendResponse, type FFIDOtpVerifyResponse, type FFIDPasswordResetConfirmResponse, type FFIDPasswordResetResponse, type FFIDPasswordResetVerifyResponse, type FFIDPlanChangeLineItem, type FFIDPlanChangePreview, type FFIDPlanChangePreviewResponse, type FFIDPlanInfo, FFIDPortalSessionResponse, type FFIDPreviewPlanChangeParams, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, FFIDRemoveMemberResponse, type FFIDResetSessionResponse, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, type FFIDSupportedCurrency, FFIDUpdateMemberRoleResponse, FFIDUser, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_NEWSLETTER_TYPES, type KVNamespaceLike, ListAnnouncementsOptions, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, retrieveCodeVerifier, storeCodeVerifier, useFFID, useSubscription, withFFIDAuth, withSubscription };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { useFFIDContext } from './chunk-DKWGMLCB.js';
2
- export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-DKWGMLCB.js';
1
+ import { useFFIDContext } from './chunk-YQPG6Z7W.js';
2
+ export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-YQPG6Z7W.js';
3
3
  import { useRef, useEffect } from 'react';
4
4
  import { jsx, Fragment } from 'react/jsx-runtime';
5
5
 
@@ -68,4 +68,7 @@ function withFFIDAuth(Component, options = {}) {
68
68
  return WrappedComponent;
69
69
  }
70
70
 
71
- export { createKVCacheAdapter, createMemoryCacheAdapter, withFFIDAuth };
71
+ // src/newsletter/types.ts
72
+ var FFID_NEWSLETTER_TYPES = ["inquiry_followup", "general"];
73
+
74
+ export { FFID_NEWSLETTER_TYPES, createKVCacheAdapter, createMemoryCacheAdapter, withFFIDAuth };
@@ -99,9 +99,15 @@ function createTokenStore(storageType) {
99
99
  }
100
100
 
101
101
  // src/client/oauth-userinfo.ts
102
- var VALID_SUBSCRIPTION_STATUSES = ["trialing", "active", "past_due", "canceled", "paused"];
103
- function isValidSubscriptionStatus(value) {
104
- return VALID_SUBSCRIPTION_STATUSES.includes(value);
102
+ var SESSION_ELIGIBLE_SUBSCRIPTION_STATUSES = [
103
+ "trialing",
104
+ "active",
105
+ "past_due",
106
+ "canceled",
107
+ "paused"
108
+ ];
109
+ function isSessionEligibleSubscriptionStatus(value) {
110
+ return typeof value === "string" && SESSION_ELIGIBLE_SUBSCRIPTION_STATUSES.includes(value);
105
111
  }
106
112
  function normalizeUserinfo(raw) {
107
113
  return {
@@ -127,7 +133,7 @@ function normalizeUserinfo(raw) {
127
133
  }
128
134
  function mapUserinfoSubscriptionToSession(userinfo, serviceCode) {
129
135
  const subscription = userinfo.subscription;
130
- if (!subscription || !subscription.planCode || !isValidSubscriptionStatus(subscription.status)) {
136
+ if (!subscription || !subscription.planCode || !isSessionEligibleSubscriptionStatus(subscription.status)) {
131
137
  return [];
132
138
  }
133
139
  return [
@@ -611,7 +617,7 @@ function createMembersMethods(deps) {
611
617
  }
612
618
 
613
619
  // src/client/version-check.ts
614
- var SDK_VERSION = "2.5.2";
620
+ var SDK_VERSION = "2.7.0";
615
621
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
616
622
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
617
623
  function sdkHeaders() {
@@ -1542,6 +1548,118 @@ function createContractWizardMethods(deps) {
1542
1548
  };
1543
1549
  }
1544
1550
 
1551
+ // src/newsletter/ffid-newsletter-client.ts
1552
+ var EXT_SUBSCRIBE_ENDPOINT2 = "/api/v1/ext/newsletter/subscribe";
1553
+ var CONFIRM_ENDPOINT = "/api/newsletter/confirm";
1554
+ var UNSUBSCRIBE_ENDPOINT = "/api/newsletter/unsubscribe";
1555
+ function trimOrEmpty(s) {
1556
+ return typeof s === "string" ? s.trim() : "";
1557
+ }
1558
+ async function postPublic(url, init, opts) {
1559
+ let response;
1560
+ try {
1561
+ response = await fetch(url, init);
1562
+ } catch (err) {
1563
+ return {
1564
+ error: opts.createError(
1565
+ "NETWORK_ERROR",
1566
+ err instanceof Error ? err.message : "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"
1567
+ )
1568
+ };
1569
+ }
1570
+ if (!response.ok) {
1571
+ try {
1572
+ const body = await response.json();
1573
+ if (body?.error?.code || body?.error?.message) {
1574
+ return {
1575
+ error: opts.createError(
1576
+ body.error.code ?? "UNKNOWN_ERROR",
1577
+ body.error.message ?? `${opts.fallbackMessage} (status: ${response.status})`
1578
+ )
1579
+ };
1580
+ }
1581
+ } catch {
1582
+ }
1583
+ return {
1584
+ error: opts.createError(
1585
+ "NETWORK_ERROR",
1586
+ `${opts.fallbackMessage} (status: ${response.status})`
1587
+ )
1588
+ };
1589
+ }
1590
+ return { data: opts.success };
1591
+ }
1592
+ function createNewsletterMethods(deps) {
1593
+ const { fetchWithAuth, baseUrl, createError } = deps;
1594
+ async function subscribe(params) {
1595
+ const email = trimOrEmpty(params.email);
1596
+ const source = trimOrEmpty(params.source);
1597
+ if (!email) {
1598
+ return { error: createError("VALIDATION_ERROR", "email \u306F\u5FC5\u9808\u3067\u3059") };
1599
+ }
1600
+ if (!source) {
1601
+ return { error: createError("VALIDATION_ERROR", "source \u306F\u5FC5\u9808\u3067\u3059") };
1602
+ }
1603
+ if (!Array.isArray(params.types) || params.types.length === 0) {
1604
+ return {
1605
+ error: createError(
1606
+ "VALIDATION_ERROR",
1607
+ "types \u306B\u306F1\u3064\u4EE5\u4E0A\u306E newsletter \u7A2E\u5225\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044"
1608
+ )
1609
+ };
1610
+ }
1611
+ return fetchWithAuth(
1612
+ EXT_SUBSCRIBE_ENDPOINT2,
1613
+ {
1614
+ method: "POST",
1615
+ body: JSON.stringify({
1616
+ email,
1617
+ types: params.types,
1618
+ source,
1619
+ locale: params.locale
1620
+ })
1621
+ }
1622
+ );
1623
+ }
1624
+ async function confirm(params) {
1625
+ const token = trimOrEmpty(params.token);
1626
+ if (!token) {
1627
+ return { error: createError("VALIDATION_ERROR", "token \u306F\u5FC5\u9808\u3067\u3059") };
1628
+ }
1629
+ return postPublic(
1630
+ `${baseUrl}${CONFIRM_ENDPOINT}`,
1631
+ {
1632
+ method: "POST",
1633
+ headers: { "Content-Type": "application/json" },
1634
+ body: JSON.stringify({ token })
1635
+ },
1636
+ {
1637
+ success: { ok: true },
1638
+ createError,
1639
+ fallbackMessage: "\u78BA\u8A8D\u30EA\u30AF\u30A8\u30B9\u30C8\u304C\u5931\u6557\u3057\u307E\u3057\u305F"
1640
+ }
1641
+ );
1642
+ }
1643
+ async function unsubscribe(params) {
1644
+ const token = trimOrEmpty(params.token);
1645
+ if (!token) {
1646
+ return { error: createError("VALIDATION_ERROR", "token \u306F\u5FC5\u9808\u3067\u3059") };
1647
+ }
1648
+ const url = new URL(`${baseUrl}${UNSUBSCRIBE_ENDPOINT}`);
1649
+ url.searchParams.set("token", token);
1650
+ return postPublic(
1651
+ url.toString(),
1652
+ { method: "POST" },
1653
+ {
1654
+ success: { ok: true },
1655
+ createError,
1656
+ fallbackMessage: "\u89E3\u9664\u30EA\u30AF\u30A8\u30B9\u30C8\u304C\u5931\u6557\u3057\u307E\u3057\u305F"
1657
+ }
1658
+ );
1659
+ }
1660
+ return { subscribe, confirm, unsubscribe };
1661
+ }
1662
+
1545
1663
  // src/client/ffid-client.ts
1546
1664
  var UNAUTHORIZED_STATUS2 = 401;
1547
1665
  var SDK_LOG_PREFIX = "[FFID SDK]";
@@ -1817,6 +1935,11 @@ function createFFIDClient(config) {
1817
1935
  createError,
1818
1936
  errorCodes: FFID_ERROR_CODES
1819
1937
  });
1938
+ const newsletter = createNewsletterMethods({
1939
+ fetchWithAuth,
1940
+ baseUrl,
1941
+ createError
1942
+ });
1820
1943
  const verifyAccessToken = createVerifyAccessToken({
1821
1944
  authMode,
1822
1945
  baseUrl,
@@ -1871,6 +1994,8 @@ function createFFIDClient(config) {
1871
1994
  confirmPasswordReset,
1872
1995
  sendOtp,
1873
1996
  verifyOtp,
1997
+ /** Newsletter methods (subscribe / confirm / unsubscribe) */
1998
+ newsletter,
1874
1999
  /** Token store (token mode only) */
1875
2000
  tokenStore,
1876
2001
  /** Resolved auth mode */