@feelflow/ffid-sdk 2.5.2 → 2.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.
@@ -101,9 +101,15 @@ function createTokenStore(storageType) {
101
101
  }
102
102
 
103
103
  // src/client/oauth-userinfo.ts
104
- var VALID_SUBSCRIPTION_STATUSES = ["trialing", "active", "past_due", "canceled", "paused"];
105
- function isValidSubscriptionStatus(value) {
106
- return VALID_SUBSCRIPTION_STATUSES.includes(value);
104
+ var SESSION_ELIGIBLE_SUBSCRIPTION_STATUSES = [
105
+ "trialing",
106
+ "active",
107
+ "past_due",
108
+ "canceled",
109
+ "paused"
110
+ ];
111
+ function isSessionEligibleSubscriptionStatus(value) {
112
+ return typeof value === "string" && SESSION_ELIGIBLE_SUBSCRIPTION_STATUSES.includes(value);
107
113
  }
108
114
  function normalizeUserinfo(raw) {
109
115
  return {
@@ -129,7 +135,7 @@ function normalizeUserinfo(raw) {
129
135
  }
130
136
  function mapUserinfoSubscriptionToSession(userinfo, serviceCode) {
131
137
  const subscription = userinfo.subscription;
132
- if (!subscription || !subscription.planCode || !isValidSubscriptionStatus(subscription.status)) {
138
+ if (!subscription || !subscription.planCode || !isSessionEligibleSubscriptionStatus(subscription.status)) {
133
139
  return [];
134
140
  }
135
141
  return [
@@ -613,7 +619,7 @@ function createMembersMethods(deps) {
613
619
  }
614
620
 
615
621
  // src/client/version-check.ts
616
- var SDK_VERSION = "2.5.2";
622
+ var SDK_VERSION = "2.6.0";
617
623
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
618
624
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
619
625
  function sdkHeaders() {
@@ -103,9 +103,15 @@ function createTokenStore(storageType) {
103
103
  }
104
104
 
105
105
  // src/client/oauth-userinfo.ts
106
- var VALID_SUBSCRIPTION_STATUSES = ["trialing", "active", "past_due", "canceled", "paused"];
107
- function isValidSubscriptionStatus(value) {
108
- return VALID_SUBSCRIPTION_STATUSES.includes(value);
106
+ var SESSION_ELIGIBLE_SUBSCRIPTION_STATUSES = [
107
+ "trialing",
108
+ "active",
109
+ "past_due",
110
+ "canceled",
111
+ "paused"
112
+ ];
113
+ function isSessionEligibleSubscriptionStatus(value) {
114
+ return typeof value === "string" && SESSION_ELIGIBLE_SUBSCRIPTION_STATUSES.includes(value);
109
115
  }
110
116
  function normalizeUserinfo(raw) {
111
117
  return {
@@ -131,7 +137,7 @@ function normalizeUserinfo(raw) {
131
137
  }
132
138
  function mapUserinfoSubscriptionToSession(userinfo, serviceCode) {
133
139
  const subscription = userinfo.subscription;
134
- if (!subscription || !subscription.planCode || !isValidSubscriptionStatus(subscription.status)) {
140
+ if (!subscription || !subscription.planCode || !isSessionEligibleSubscriptionStatus(subscription.status)) {
135
141
  return [];
136
142
  }
137
143
  return [
@@ -615,7 +621,7 @@ function createMembersMethods(deps) {
615
621
  }
616
622
 
617
623
  // src/client/version-check.ts
618
- var SDK_VERSION = "2.5.2";
624
+ var SDK_VERSION = "2.6.0";
619
625
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
620
626
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
621
627
  function sdkHeaders() {
@@ -1,30 +1,30 @@
1
1
  'use strict';
2
2
 
3
- var chunkZBBRUQGX_cjs = require('../chunk-ZBBRUQGX.cjs');
3
+ var chunkZORI5YFR_cjs = require('../chunk-ZORI5YFR.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "FFIDAnnouncementBadge", {
8
8
  enumerable: true,
9
- get: function () { return chunkZBBRUQGX_cjs.FFIDAnnouncementBadge; }
9
+ get: function () { return chunkZORI5YFR_cjs.FFIDAnnouncementBadge; }
10
10
  });
11
11
  Object.defineProperty(exports, "FFIDAnnouncementList", {
12
12
  enumerable: true,
13
- get: function () { return chunkZBBRUQGX_cjs.FFIDAnnouncementList; }
13
+ get: function () { return chunkZORI5YFR_cjs.FFIDAnnouncementList; }
14
14
  });
15
15
  Object.defineProperty(exports, "FFIDLoginButton", {
16
16
  enumerable: true,
17
- get: function () { return chunkZBBRUQGX_cjs.FFIDLoginButton; }
17
+ get: function () { return chunkZORI5YFR_cjs.FFIDLoginButton; }
18
18
  });
19
19
  Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
20
20
  enumerable: true,
21
- get: function () { return chunkZBBRUQGX_cjs.FFIDOrganizationSwitcher; }
21
+ get: function () { return chunkZORI5YFR_cjs.FFIDOrganizationSwitcher; }
22
22
  });
23
23
  Object.defineProperty(exports, "FFIDSubscriptionBadge", {
24
24
  enumerable: true,
25
- get: function () { return chunkZBBRUQGX_cjs.FFIDSubscriptionBadge; }
25
+ get: function () { return chunkZORI5YFR_cjs.FFIDSubscriptionBadge; }
26
26
  });
27
27
  Object.defineProperty(exports, "FFIDUserMenu", {
28
28
  enumerable: true,
29
- get: function () { return chunkZBBRUQGX_cjs.FFIDUserMenu; }
29
+ get: function () { return chunkZORI5YFR_cjs.FFIDUserMenu; }
30
30
  });
@@ -1 +1 @@
1
- export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-DKWGMLCB.js';
1
+ export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-7FEWA2P2.js';
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkZBBRUQGX_cjs = require('./chunk-ZBBRUQGX.cjs');
3
+ var chunkZORI5YFR_cjs = require('./chunk-ZORI5YFR.cjs');
4
4
  var react = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
 
@@ -46,7 +46,7 @@ function createKVCacheAdapter(kv) {
46
46
  }
47
47
  function withFFIDAuth(Component, options = {}) {
48
48
  const WrappedComponent = (props) => {
49
- const { isLoading, isAuthenticated, login } = chunkZBBRUQGX_cjs.useFFIDContext();
49
+ const { isLoading, isAuthenticated, login } = chunkZORI5YFR_cjs.useFFIDContext();
50
50
  const hasRedirected = react.useRef(false);
51
51
  react.useEffect(() => {
52
52
  if (!isLoading && !isAuthenticated && options.redirectToLogin && !hasRedirected.current) {
@@ -71,83 +71,83 @@ function withFFIDAuth(Component, options = {}) {
71
71
 
72
72
  Object.defineProperty(exports, "DEFAULT_API_BASE_URL", {
73
73
  enumerable: true,
74
- get: function () { return chunkZBBRUQGX_cjs.DEFAULT_API_BASE_URL; }
74
+ get: function () { return chunkZORI5YFR_cjs.DEFAULT_API_BASE_URL; }
75
75
  });
76
76
  Object.defineProperty(exports, "FFIDAnnouncementBadge", {
77
77
  enumerable: true,
78
- get: function () { return chunkZBBRUQGX_cjs.FFIDAnnouncementBadge; }
78
+ get: function () { return chunkZORI5YFR_cjs.FFIDAnnouncementBadge; }
79
79
  });
80
80
  Object.defineProperty(exports, "FFIDAnnouncementList", {
81
81
  enumerable: true,
82
- get: function () { return chunkZBBRUQGX_cjs.FFIDAnnouncementList; }
82
+ get: function () { return chunkZORI5YFR_cjs.FFIDAnnouncementList; }
83
83
  });
84
84
  Object.defineProperty(exports, "FFIDLoginButton", {
85
85
  enumerable: true,
86
- get: function () { return chunkZBBRUQGX_cjs.FFIDLoginButton; }
86
+ get: function () { return chunkZORI5YFR_cjs.FFIDLoginButton; }
87
87
  });
88
88
  Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
89
89
  enumerable: true,
90
- get: function () { return chunkZBBRUQGX_cjs.FFIDOrganizationSwitcher; }
90
+ get: function () { return chunkZORI5YFR_cjs.FFIDOrganizationSwitcher; }
91
91
  });
92
92
  Object.defineProperty(exports, "FFIDProvider", {
93
93
  enumerable: true,
94
- get: function () { return chunkZBBRUQGX_cjs.FFIDProvider; }
94
+ get: function () { return chunkZORI5YFR_cjs.FFIDProvider; }
95
95
  });
96
96
  Object.defineProperty(exports, "FFIDSubscriptionBadge", {
97
97
  enumerable: true,
98
- get: function () { return chunkZBBRUQGX_cjs.FFIDSubscriptionBadge; }
98
+ get: function () { return chunkZORI5YFR_cjs.FFIDSubscriptionBadge; }
99
99
  });
100
100
  Object.defineProperty(exports, "FFIDUserMenu", {
101
101
  enumerable: true,
102
- get: function () { return chunkZBBRUQGX_cjs.FFIDUserMenu; }
102
+ get: function () { return chunkZORI5YFR_cjs.FFIDUserMenu; }
103
103
  });
104
104
  Object.defineProperty(exports, "FFID_ANNOUNCEMENTS_ERROR_CODES", {
105
105
  enumerable: true,
106
- get: function () { return chunkZBBRUQGX_cjs.FFID_ANNOUNCEMENTS_ERROR_CODES; }
106
+ get: function () { return chunkZORI5YFR_cjs.FFID_ANNOUNCEMENTS_ERROR_CODES; }
107
107
  });
108
108
  Object.defineProperty(exports, "createFFIDAnnouncementsClient", {
109
109
  enumerable: true,
110
- get: function () { return chunkZBBRUQGX_cjs.createFFIDAnnouncementsClient; }
110
+ get: function () { return chunkZORI5YFR_cjs.createFFIDAnnouncementsClient; }
111
111
  });
112
112
  Object.defineProperty(exports, "createFFIDClient", {
113
113
  enumerable: true,
114
- get: function () { return chunkZBBRUQGX_cjs.createFFIDClient; }
114
+ get: function () { return chunkZORI5YFR_cjs.createFFIDClient; }
115
115
  });
116
116
  Object.defineProperty(exports, "createTokenStore", {
117
117
  enumerable: true,
118
- get: function () { return chunkZBBRUQGX_cjs.createTokenStore; }
118
+ get: function () { return chunkZORI5YFR_cjs.createTokenStore; }
119
119
  });
120
120
  Object.defineProperty(exports, "generateCodeChallenge", {
121
121
  enumerable: true,
122
- get: function () { return chunkZBBRUQGX_cjs.generateCodeChallenge; }
122
+ get: function () { return chunkZORI5YFR_cjs.generateCodeChallenge; }
123
123
  });
124
124
  Object.defineProperty(exports, "generateCodeVerifier", {
125
125
  enumerable: true,
126
- get: function () { return chunkZBBRUQGX_cjs.generateCodeVerifier; }
126
+ get: function () { return chunkZORI5YFR_cjs.generateCodeVerifier; }
127
127
  });
128
128
  Object.defineProperty(exports, "retrieveCodeVerifier", {
129
129
  enumerable: true,
130
- get: function () { return chunkZBBRUQGX_cjs.retrieveCodeVerifier; }
130
+ get: function () { return chunkZORI5YFR_cjs.retrieveCodeVerifier; }
131
131
  });
132
132
  Object.defineProperty(exports, "storeCodeVerifier", {
133
133
  enumerable: true,
134
- get: function () { return chunkZBBRUQGX_cjs.storeCodeVerifier; }
134
+ get: function () { return chunkZORI5YFR_cjs.storeCodeVerifier; }
135
135
  });
136
136
  Object.defineProperty(exports, "useFFID", {
137
137
  enumerable: true,
138
- get: function () { return chunkZBBRUQGX_cjs.useFFID; }
138
+ get: function () { return chunkZORI5YFR_cjs.useFFID; }
139
139
  });
140
140
  Object.defineProperty(exports, "useFFIDAnnouncements", {
141
141
  enumerable: true,
142
- get: function () { return chunkZBBRUQGX_cjs.useFFIDAnnouncements; }
142
+ get: function () { return chunkZORI5YFR_cjs.useFFIDAnnouncements; }
143
143
  });
144
144
  Object.defineProperty(exports, "useSubscription", {
145
145
  enumerable: true,
146
- get: function () { return chunkZBBRUQGX_cjs.useSubscription; }
146
+ get: function () { return chunkZORI5YFR_cjs.useSubscription; }
147
147
  });
148
148
  Object.defineProperty(exports, "withSubscription", {
149
149
  enumerable: true,
150
- get: function () { return chunkZBBRUQGX_cjs.withSubscription; }
150
+ get: function () { return chunkZORI5YFR_cjs.withSubscription; }
151
151
  });
152
152
  exports.createKVCacheAdapter = createKVCacheAdapter;
153
153
  exports.createMemoryCacheAdapter = createMemoryCacheAdapter;
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 */
@@ -729,4 +763,4 @@ declare function createFFIDAnnouncementsClient(config?: FFIDAnnouncementsClientC
729
763
  /** Type of the FFID Announcements client */
730
764
  type FFIDAnnouncementsClient = ReturnType<typeof createFFIDAnnouncementsClient>;
731
765
 
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 };
766
+ 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 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, 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 */
@@ -729,4 +763,4 @@ declare function createFFIDAnnouncementsClient(config?: FFIDAnnouncementsClientC
729
763
  /** Type of the FFID Announcements client */
730
764
  type FFIDAnnouncementsClient = ReturnType<typeof createFFIDAnnouncementsClient>;
731
765
 
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 };
766
+ 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 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, 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-7FEWA2P2.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-7FEWA2P2.js';
3
3
  import { useRef, useEffect } from 'react';
4
4
  import { jsx, Fragment } from 'react/jsx-runtime';
5
5
 
@@ -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.6.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() {
@@ -23,6 +23,11 @@ interface FFIDCacheConfig {
23
23
 
24
24
  /** Billing interval for subscriptions */
25
25
  type FFIDBillingInterval = 'monthly' | 'yearly';
26
+ /**
27
+ * Supported currencies for billing responses.
28
+ * Mirrors the platform's `SupportedCurrency` enum (`jpy` = zero-decimal Japanese Yen, `usd` = US Dollar).
29
+ */
30
+ type FFIDSupportedCurrency = 'jpy' | 'usd';
26
31
  /** Service information returned by plans endpoint */
27
32
  interface FFIDServiceInfo {
28
33
  id: string;
@@ -214,27 +219,56 @@ interface FFIDPlanChangeLineItem {
214
219
  description: string;
215
220
  amount: number;
216
221
  }
222
+ /** Fields shared by every plan-change preview variant (internal; consumers use `FFIDPlanChangePreview`) */
223
+ interface FFIDPlanChangePreviewBase {
224
+ /** Discriminant for preview response variants (reserved for future unions with e.g. seat-change previews) */
225
+ type: 'plan-change';
226
+ /** Current plan display info. `price` is the total for the current quantity (unitPrice × quantity), not per-seat. */
227
+ currentPlan: {
228
+ name: string;
229
+ price: number;
230
+ };
231
+ /** New plan display info. `price` is the total for the effective quantity (unitPrice × quantity), not per-seat. */
232
+ newPlan: {
233
+ name: string;
234
+ price: number;
235
+ };
236
+ billingInterval: FFIDBillingInterval;
237
+ isUpgrade: boolean;
238
+ /** Full amount of the next billing cycle at the new plan's standard price. Never overwritten by Stripe proration data. */
239
+ nextInvoiceAmount: number;
240
+ nextInvoiceDate: string | null;
241
+ currency: FFIDSupportedCurrency;
242
+ /** true when amounts are estimated from local prices (no Stripe proration data) */
243
+ isEstimate: boolean;
244
+ /** Reason why `isEstimate` is true. Only meaningful when `isEstimate === true`. */
245
+ estimateReason?: 'no_stripe_data' | 'custom_pricing' | 'stripe_error';
246
+ lineItems: FFIDPlanChangeLineItem[];
247
+ }
248
+ /**
249
+ * Plan change proration preview.
250
+ *
251
+ * `willApplyAtPeriodEnd` is a discriminant that constrains related fields at the type level:
252
+ * - `true`: period-end-deferred downgrade. `proratedAmount` is always 0; `effectiveDate` mirrors
253
+ * the subscription's `currentPeriodEnd` (may be `null` when the subscription has no active
254
+ * billing cycle yet — e.g. a pre-Stripe trial or a subscription whose billing cycle is unset).
255
+ * - `false`: immediate change. `effectiveDate` is always `null`; `proratedAmount` is the live
256
+ * (possibly Stripe-refined) day-basis difference.
257
+ */
258
+ type FFIDPlanChangePreview = FFIDPlanChangePreviewBase & ({
259
+ willApplyAtPeriodEnd: true;
260
+ effectiveDate: string | null;
261
+ /** 0 on period-end-deferred changes; charge happens at the next invoice */
262
+ proratedAmount: 0;
263
+ } | {
264
+ willApplyAtPeriodEnd: false;
265
+ effectiveDate: null;
266
+ /** Prorated difference charged within the current billing period */
267
+ proratedAmount: number;
268
+ });
217
269
  /** Response from plan change preview endpoint */
218
270
  interface FFIDPlanChangePreviewResponse {
219
- preview: {
220
- currentPlan: {
221
- name: string;
222
- price: number;
223
- };
224
- newPlan: {
225
- name: string;
226
- price: number;
227
- };
228
- billingInterval: FFIDBillingInterval;
229
- isUpgrade: boolean;
230
- proratedAmount: number;
231
- nextInvoiceAmount: number;
232
- nextInvoiceDate: string | null;
233
- currency: string;
234
- isEstimate: boolean;
235
- estimateReason?: string;
236
- lineItems: FFIDPlanChangeLineItem[];
237
- };
271
+ preview: FFIDPlanChangePreview;
238
272
  }
239
273
 
240
274
  /**
@@ -23,6 +23,11 @@ interface FFIDCacheConfig {
23
23
 
24
24
  /** Billing interval for subscriptions */
25
25
  type FFIDBillingInterval = 'monthly' | 'yearly';
26
+ /**
27
+ * Supported currencies for billing responses.
28
+ * Mirrors the platform's `SupportedCurrency` enum (`jpy` = zero-decimal Japanese Yen, `usd` = US Dollar).
29
+ */
30
+ type FFIDSupportedCurrency = 'jpy' | 'usd';
26
31
  /** Service information returned by plans endpoint */
27
32
  interface FFIDServiceInfo {
28
33
  id: string;
@@ -214,27 +219,56 @@ interface FFIDPlanChangeLineItem {
214
219
  description: string;
215
220
  amount: number;
216
221
  }
222
+ /** Fields shared by every plan-change preview variant (internal; consumers use `FFIDPlanChangePreview`) */
223
+ interface FFIDPlanChangePreviewBase {
224
+ /** Discriminant for preview response variants (reserved for future unions with e.g. seat-change previews) */
225
+ type: 'plan-change';
226
+ /** Current plan display info. `price` is the total for the current quantity (unitPrice × quantity), not per-seat. */
227
+ currentPlan: {
228
+ name: string;
229
+ price: number;
230
+ };
231
+ /** New plan display info. `price` is the total for the effective quantity (unitPrice × quantity), not per-seat. */
232
+ newPlan: {
233
+ name: string;
234
+ price: number;
235
+ };
236
+ billingInterval: FFIDBillingInterval;
237
+ isUpgrade: boolean;
238
+ /** Full amount of the next billing cycle at the new plan's standard price. Never overwritten by Stripe proration data. */
239
+ nextInvoiceAmount: number;
240
+ nextInvoiceDate: string | null;
241
+ currency: FFIDSupportedCurrency;
242
+ /** true when amounts are estimated from local prices (no Stripe proration data) */
243
+ isEstimate: boolean;
244
+ /** Reason why `isEstimate` is true. Only meaningful when `isEstimate === true`. */
245
+ estimateReason?: 'no_stripe_data' | 'custom_pricing' | 'stripe_error';
246
+ lineItems: FFIDPlanChangeLineItem[];
247
+ }
248
+ /**
249
+ * Plan change proration preview.
250
+ *
251
+ * `willApplyAtPeriodEnd` is a discriminant that constrains related fields at the type level:
252
+ * - `true`: period-end-deferred downgrade. `proratedAmount` is always 0; `effectiveDate` mirrors
253
+ * the subscription's `currentPeriodEnd` (may be `null` when the subscription has no active
254
+ * billing cycle yet — e.g. a pre-Stripe trial or a subscription whose billing cycle is unset).
255
+ * - `false`: immediate change. `effectiveDate` is always `null`; `proratedAmount` is the live
256
+ * (possibly Stripe-refined) day-basis difference.
257
+ */
258
+ type FFIDPlanChangePreview = FFIDPlanChangePreviewBase & ({
259
+ willApplyAtPeriodEnd: true;
260
+ effectiveDate: string | null;
261
+ /** 0 on period-end-deferred changes; charge happens at the next invoice */
262
+ proratedAmount: 0;
263
+ } | {
264
+ willApplyAtPeriodEnd: false;
265
+ effectiveDate: null;
266
+ /** Prorated difference charged within the current billing period */
267
+ proratedAmount: number;
268
+ });
217
269
  /** Response from plan change preview endpoint */
218
270
  interface FFIDPlanChangePreviewResponse {
219
- preview: {
220
- currentPlan: {
221
- name: string;
222
- price: number;
223
- };
224
- newPlan: {
225
- name: string;
226
- price: number;
227
- };
228
- billingInterval: FFIDBillingInterval;
229
- isUpgrade: boolean;
230
- proratedAmount: number;
231
- nextInvoiceAmount: number;
232
- nextInvoiceDate: string | null;
233
- currency: string;
234
- isEstimate: boolean;
235
- estimateReason?: string;
236
- lineItems: FFIDPlanChangeLineItem[];
237
- };
271
+ preview: FFIDPlanChangePreview;
238
272
  }
239
273
 
240
274
  /**
@@ -98,9 +98,15 @@ function createTokenStore(storageType) {
98
98
  }
99
99
 
100
100
  // src/client/oauth-userinfo.ts
101
- var VALID_SUBSCRIPTION_STATUSES = ["trialing", "active", "past_due", "canceled", "paused"];
102
- function isValidSubscriptionStatus(value) {
103
- return VALID_SUBSCRIPTION_STATUSES.includes(value);
101
+ var SESSION_ELIGIBLE_SUBSCRIPTION_STATUSES = [
102
+ "trialing",
103
+ "active",
104
+ "past_due",
105
+ "canceled",
106
+ "paused"
107
+ ];
108
+ function isSessionEligibleSubscriptionStatus(value) {
109
+ return typeof value === "string" && SESSION_ELIGIBLE_SUBSCRIPTION_STATUSES.includes(value);
104
110
  }
105
111
  function normalizeUserinfo(raw) {
106
112
  return {
@@ -126,7 +132,7 @@ function normalizeUserinfo(raw) {
126
132
  }
127
133
  function mapUserinfoSubscriptionToSession(userinfo, serviceCode) {
128
134
  const subscription = userinfo.subscription;
129
- if (!subscription || !subscription.planCode || !isValidSubscriptionStatus(subscription.status)) {
135
+ if (!subscription || !subscription.planCode || !isSessionEligibleSubscriptionStatus(subscription.status)) {
130
136
  return [];
131
137
  }
132
138
  return [
@@ -610,7 +616,7 @@ function createMembersMethods(deps) {
610
616
  }
611
617
 
612
618
  // src/client/version-check.ts
613
- var SDK_VERSION = "2.5.2";
619
+ var SDK_VERSION = "2.6.0";
614
620
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
615
621
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
616
622
  function sdkHeaders() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feelflow/ffid-sdk",
3
- "version": "2.5.2",
3
+ "version": "2.6.0",
4
4
  "description": "FeelFlow ID Platform SDK for React/Next.js applications",
5
5
  "keywords": [
6
6
  "feelflow",
@@ -97,6 +97,7 @@
97
97
  "devDependencies": {
98
98
  "@testing-library/jest-dom": "^6.0.0",
99
99
  "@testing-library/react": "^16.0.0",
100
+ "@types/node": "^22.19.17",
100
101
  "@types/react": "^19.0.0",
101
102
  "@types/react-dom": "^19.0.0",
102
103
  "@typescript-eslint/eslint-plugin": "^8.58.0",