@feelflow/ffid-sdk 2.18.0 → 2.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +152 -7
- package/dist/{chunk-IEYXT3LA.js → chunk-GCUVFSB2.js} +89 -9
- package/dist/{chunk-EK2W67BW.cjs → chunk-KNEZ5OUQ.cjs} +89 -8
- package/dist/components/index.cjs +8 -8
- package/dist/components/index.d.cts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +1 -1
- package/dist/ffid-client-Cjm_TKUc.d.cts +1123 -0
- package/dist/ffid-client-Cjm_TKUc.d.ts +1123 -0
- package/dist/{index--S6rLHjr.d.cts → index-0D2vYSLq.d.cts} +87 -2
- package/dist/{index--S6rLHjr.d.ts → index-0D2vYSLq.d.ts} +87 -2
- package/dist/index.cjs +62 -28
- package/dist/index.d.cts +181 -11
- package/dist/index.d.ts +181 -11
- package/dist/index.js +33 -4
- package/dist/server/index.cjs +1 -1
- package/dist/server/index.d.cts +3 -1123
- package/dist/server/index.d.ts +3 -1123
- package/dist/server/index.js +1 -1
- package/dist/server/test/index.cjs +105 -0
- package/dist/server/test/index.d.cts +125 -0
- package/dist/server/test/index.d.ts +125 -0
- package/dist/server/test/index.js +100 -0
- package/dist/webhooks/index.d.cts +71 -5
- package/dist/webhooks/index.d.ts +71 -5
- package/package.json +6 -1
|
@@ -22,6 +22,42 @@ interface FFIDCacheConfig {
|
|
|
22
22
|
ttl: number;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Subscription access-control types (Chain of Pacts / Issue #2443).
|
|
27
|
+
*
|
|
28
|
+
* Defines `EffectiveSubscriptionStatus` — the semantic status surfaced by
|
|
29
|
+
* `/api/v1/subscriptions/ext/check` for external services that need a single
|
|
30
|
+
* value to drive access-control decisions. Mirrors the server-side type in
|
|
31
|
+
* `src/lib/common/subscription-helpers.ts` so the FFID backend, SDK, and
|
|
32
|
+
* consuming services agree on the same vocabulary.
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* Semantic subscription status used for access-control decisions by external
|
|
36
|
+
* services.
|
|
37
|
+
*
|
|
38
|
+
* Unlike the raw DB `FFIDSubscriptionStatus` (which keeps the Stripe-aligned
|
|
39
|
+
* status machine, e.g. `past_due` / `incomplete` / `incomplete_expired`), this
|
|
40
|
+
* narrowed union flattens dunning-window vs. hard-block cases so callers can
|
|
41
|
+
* branch on a single value:
|
|
42
|
+
*
|
|
43
|
+
* - `active` — normal paying subscription; grant full access.
|
|
44
|
+
* - `past_due_grace` — payment failed but FFID is still retrying. Service
|
|
45
|
+
* SHOULD keep access and surface a recovery banner.
|
|
46
|
+
* - `blocked` — payment dunning exhausted (`past_due` over grace,
|
|
47
|
+
* `unpaid`, `incomplete_expired`, `paused`, `incomplete`). Deny access.
|
|
48
|
+
* - `canceled` — contract ended (voluntary or auto-cancel). Deny access;
|
|
49
|
+
* check the accompanying `reactivatable` flag before showing a restart CTA.
|
|
50
|
+
* - `trial_expired` — `status = 'trialing'` but the trial end is in the past.
|
|
51
|
+
* DB row is still `trialing`; deny access and prompt for a paid plan.
|
|
52
|
+
* - `expired` — `status = 'active'` but `current_period_end` is in the past.
|
|
53
|
+
* This is the FFID-internal runtime-expired case (see
|
|
54
|
+
* `getEffectiveSubscriptionStatus` on the server). Deny access.
|
|
55
|
+
*
|
|
56
|
+
* @see /api/v1/subscriptions/ext/check
|
|
57
|
+
* @see docs/03-implementation/EXPIRED_CONTRACT_HANDLING.md
|
|
58
|
+
*/
|
|
59
|
+
type EffectiveSubscriptionStatus = 'active' | 'past_due_grace' | 'blocked' | 'canceled' | 'trial_expired' | 'expired';
|
|
60
|
+
|
|
25
61
|
/**
|
|
26
62
|
* FFID SDK Type Definitions
|
|
27
63
|
*
|
|
@@ -284,10 +320,59 @@ interface FFIDSubscriptionContextValue {
|
|
|
284
320
|
isTrialExpired: boolean;
|
|
285
321
|
/** Whether subscription is canceled */
|
|
286
322
|
isCanceled: boolean;
|
|
323
|
+
/**
|
|
324
|
+
* Semantic access-control status for the current subscription.
|
|
325
|
+
*
|
|
326
|
+
* Always computed locally from the session response via
|
|
327
|
+
* `computeEffectiveStatusFromSession` (status + currentPeriodEnd + trialEnd).
|
|
328
|
+
* The session endpoint does not currently surface an authoritative
|
|
329
|
+
* effectiveStatus, so this is a best-effort approximation suitable for UI
|
|
330
|
+
* decisions that tolerate ~1 request worth of staleness.
|
|
331
|
+
*
|
|
332
|
+
* For authoritative decisions (e.g., paywall gates on billing-critical UI,
|
|
333
|
+
* grace-window banners that depend on `gracePeriodEndsAt`, or reactivation
|
|
334
|
+
* CTAs that depend on `reactivatable`), call the server-side
|
|
335
|
+
* `/api/v1/subscriptions/ext/check` endpoint directly — it returns a richer
|
|
336
|
+
* payload (`effectiveStatus`, `gracePeriodEndsAt`, `reactivatable`) computed
|
|
337
|
+
* against the live DB.
|
|
338
|
+
*
|
|
339
|
+
* `null` when there is no subscription for the current service.
|
|
340
|
+
*
|
|
341
|
+
* @see {@link EffectiveSubscriptionStatus}
|
|
342
|
+
*/
|
|
343
|
+
effectiveStatus: EffectiveSubscriptionStatus | null;
|
|
344
|
+
/**
|
|
345
|
+
* Whether the subscription is in an access-blocking terminal state
|
|
346
|
+
* (`blocked` | `expired` | `canceled` | `trial_expired`).
|
|
347
|
+
*/
|
|
348
|
+
isBlocked: boolean;
|
|
349
|
+
/**
|
|
350
|
+
* Whether the subscription is inside the payment-failure grace window
|
|
351
|
+
* (`past_due_grace`). Access is still granted by `hasAccess`, but UIs
|
|
352
|
+
* should surface a recovery banner.
|
|
353
|
+
*/
|
|
354
|
+
isGrace: boolean;
|
|
287
355
|
/** Check if user has specific plan */
|
|
288
356
|
hasPlan: (plans: string | string[]) => boolean;
|
|
289
|
-
/**
|
|
357
|
+
/**
|
|
358
|
+
* Whether the user currently has access.
|
|
359
|
+
*
|
|
360
|
+
* Post Chain-of-Pacts (Issue #2444): `true` when
|
|
361
|
+
* `effectiveStatus === 'active' || effectiveStatus === 'past_due_grace'`.
|
|
362
|
+
* Legacy consumers that need the pre-2444 semantics
|
|
363
|
+
* (`status === 'active' || status === 'trialing'`) can use
|
|
364
|
+
* `hasAccessLegacy()`.
|
|
365
|
+
*/
|
|
290
366
|
hasAccess: () => boolean;
|
|
367
|
+
/**
|
|
368
|
+
* Pre-2444 `hasAccess` semantics: `true` when the raw DB status is
|
|
369
|
+
* `active` or `trialing` (and, for trialing, the trial is not runtime-
|
|
370
|
+
* expired). Kept as a backwards-compatibility escape hatch so services
|
|
371
|
+
* that have not yet migrated to the effective-status model keep working.
|
|
372
|
+
*
|
|
373
|
+
* @deprecated Prefer `hasAccess()` or branch on `effectiveStatus` directly.
|
|
374
|
+
*/
|
|
375
|
+
hasAccessLegacy: () => boolean;
|
|
291
376
|
}
|
|
292
377
|
/**
|
|
293
378
|
* Logger interface for SDK debug output
|
|
@@ -1301,4 +1386,4 @@ interface FFIDInquiryFormPlaceholderContext {
|
|
|
1301
1386
|
}
|
|
1302
1387
|
declare function FFIDInquiryForm({ mode, prefill, organizations, preselectedOrganizationId, categories, termsVersion, privacyVersion, termsHref, privacyHref, turnstileToken, turnstileSlot, onSubmit, onChange, separateLegalCheckboxes, messagePlaceholder, requireCategorySelection, unstyled, classNames, locale, className, }: FFIDInquiryFormProps): react_jsx_runtime.JSX.Element;
|
|
1303
1388
|
|
|
1304
|
-
export { type
|
|
1389
|
+
export { type FFIDInquiryFormProps as $, type FFIDSubscription as A, type FFIDSubscriptionContextValue as B, type FFIDAnnouncementsClientConfig as C, type FFIDAnnouncementsApiResponse as D, type EffectiveSubscriptionStatus as E, type FFIDSubscriptionStatus as F, type AnnouncementListResponse as G, type FFIDAnnouncementsLogger as H, type Announcement as I, type AnnouncementStatus as J, type AnnouncementType as K, type ListAnnouncementsOptions as L, FFIDAnnouncementBadge as M, FFIDAnnouncementList as N, type FFIDAnnouncementsError as O, type FFIDAnnouncementsErrorCode as P, type FFIDAnnouncementsServerResponse as Q, type FFIDCacheConfig as R, type FFIDContextValue as S, type FFIDInquiryCategory as T, type FFIDInquiryCategorySite2026 as U, FFIDInquiryForm as V, type FFIDInquiryFormCategoryItem as W, type FFIDInquiryFormClassNames as X, type FFIDInquiryFormOrganization as Y, type FFIDInquiryFormPlaceholderContext as Z, type FFIDInquiryFormPrefill as _, type FFIDConfig as a, type FFIDInquiryFormSubmitData as a0, type FFIDInquiryFormSubmitResult as a1, type FFIDJwtClaims as a2, FFIDLoginButton as a3, type FFIDMemberStatus as a4, type FFIDOAuthTokenResponse as a5, type FFIDOAuthUserInfoMemberRole as a6, type FFIDOAuthUserInfoSubscription as a7, type FFIDOrganizationMember as a8, FFIDOrganizationSwitcher as a9, type FFIDRedirectErrorCode as aa, type FFIDSeatModel as ab, FFIDSubscriptionBadge as ac, type FFIDTokenIntrospectionResponse as ad, FFIDUserMenu as ae, FFID_INQUIRY_CATEGORIES as af, FFID_INQUIRY_CATEGORIES_SITE_2026 as ag, type UseFFIDAnnouncementsOptions as ah, type UseFFIDAnnouncementsReturn as ai, isFFIDInquiryCategorySite2026 as aj, useFFIDAnnouncements as ak, type FFIDAnnouncementBadgeClassNames as al, type FFIDAnnouncementBadgeProps as am, type FFIDAnnouncementListClassNames as an, type FFIDAnnouncementListProps as ao, type FFIDLoginButtonProps as ap, type FFIDOrganizationSwitcherClassNames as aq, type FFIDOrganizationSwitcherProps as ar, type FFIDSubscriptionBadgeClassNames as as, type FFIDSubscriptionBadgeProps as at, type FFIDUserMenuClassNames as au, type FFIDUserMenuProps as av, type FFIDApiResponse as b, type FFIDSessionResponse as c, type FFIDRedirectResult as d, type FFIDError as e, type FFIDSubscriptionCheckResponse as f, type FFIDListMembersResponse as g, type FFIDMemberRole as h, type FFIDUpdateMemberRoleResponse as i, type FFIDRemoveMemberResponse as j, type FFIDProfileCallOptions as k, type FFIDUserProfile as l, type FFIDUpdateUserProfileRequest as m, type FFIDCreateCheckoutParams as n, type FFIDCheckoutSessionResponse as o, type FFIDCreatePortalParams as p, type FFIDPortalSessionResponse as q, type FFIDVerifyAccessTokenOptions as r, type FFIDOAuthUserInfo as s, type FFIDInquiryCreateParams as t, type FFIDInquiryCreateResponse as u, type FFIDAuthMode as v, type FFIDLogger as w, type FFIDCacheAdapter as x, type FFIDUser as y, type FFIDOrganization as z };
|
|
@@ -22,6 +22,42 @@ interface FFIDCacheConfig {
|
|
|
22
22
|
ttl: number;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Subscription access-control types (Chain of Pacts / Issue #2443).
|
|
27
|
+
*
|
|
28
|
+
* Defines `EffectiveSubscriptionStatus` — the semantic status surfaced by
|
|
29
|
+
* `/api/v1/subscriptions/ext/check` for external services that need a single
|
|
30
|
+
* value to drive access-control decisions. Mirrors the server-side type in
|
|
31
|
+
* `src/lib/common/subscription-helpers.ts` so the FFID backend, SDK, and
|
|
32
|
+
* consuming services agree on the same vocabulary.
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* Semantic subscription status used for access-control decisions by external
|
|
36
|
+
* services.
|
|
37
|
+
*
|
|
38
|
+
* Unlike the raw DB `FFIDSubscriptionStatus` (which keeps the Stripe-aligned
|
|
39
|
+
* status machine, e.g. `past_due` / `incomplete` / `incomplete_expired`), this
|
|
40
|
+
* narrowed union flattens dunning-window vs. hard-block cases so callers can
|
|
41
|
+
* branch on a single value:
|
|
42
|
+
*
|
|
43
|
+
* - `active` — normal paying subscription; grant full access.
|
|
44
|
+
* - `past_due_grace` — payment failed but FFID is still retrying. Service
|
|
45
|
+
* SHOULD keep access and surface a recovery banner.
|
|
46
|
+
* - `blocked` — payment dunning exhausted (`past_due` over grace,
|
|
47
|
+
* `unpaid`, `incomplete_expired`, `paused`, `incomplete`). Deny access.
|
|
48
|
+
* - `canceled` — contract ended (voluntary or auto-cancel). Deny access;
|
|
49
|
+
* check the accompanying `reactivatable` flag before showing a restart CTA.
|
|
50
|
+
* - `trial_expired` — `status = 'trialing'` but the trial end is in the past.
|
|
51
|
+
* DB row is still `trialing`; deny access and prompt for a paid plan.
|
|
52
|
+
* - `expired` — `status = 'active'` but `current_period_end` is in the past.
|
|
53
|
+
* This is the FFID-internal runtime-expired case (see
|
|
54
|
+
* `getEffectiveSubscriptionStatus` on the server). Deny access.
|
|
55
|
+
*
|
|
56
|
+
* @see /api/v1/subscriptions/ext/check
|
|
57
|
+
* @see docs/03-implementation/EXPIRED_CONTRACT_HANDLING.md
|
|
58
|
+
*/
|
|
59
|
+
type EffectiveSubscriptionStatus = 'active' | 'past_due_grace' | 'blocked' | 'canceled' | 'trial_expired' | 'expired';
|
|
60
|
+
|
|
25
61
|
/**
|
|
26
62
|
* FFID SDK Type Definitions
|
|
27
63
|
*
|
|
@@ -284,10 +320,59 @@ interface FFIDSubscriptionContextValue {
|
|
|
284
320
|
isTrialExpired: boolean;
|
|
285
321
|
/** Whether subscription is canceled */
|
|
286
322
|
isCanceled: boolean;
|
|
323
|
+
/**
|
|
324
|
+
* Semantic access-control status for the current subscription.
|
|
325
|
+
*
|
|
326
|
+
* Always computed locally from the session response via
|
|
327
|
+
* `computeEffectiveStatusFromSession` (status + currentPeriodEnd + trialEnd).
|
|
328
|
+
* The session endpoint does not currently surface an authoritative
|
|
329
|
+
* effectiveStatus, so this is a best-effort approximation suitable for UI
|
|
330
|
+
* decisions that tolerate ~1 request worth of staleness.
|
|
331
|
+
*
|
|
332
|
+
* For authoritative decisions (e.g., paywall gates on billing-critical UI,
|
|
333
|
+
* grace-window banners that depend on `gracePeriodEndsAt`, or reactivation
|
|
334
|
+
* CTAs that depend on `reactivatable`), call the server-side
|
|
335
|
+
* `/api/v1/subscriptions/ext/check` endpoint directly — it returns a richer
|
|
336
|
+
* payload (`effectiveStatus`, `gracePeriodEndsAt`, `reactivatable`) computed
|
|
337
|
+
* against the live DB.
|
|
338
|
+
*
|
|
339
|
+
* `null` when there is no subscription for the current service.
|
|
340
|
+
*
|
|
341
|
+
* @see {@link EffectiveSubscriptionStatus}
|
|
342
|
+
*/
|
|
343
|
+
effectiveStatus: EffectiveSubscriptionStatus | null;
|
|
344
|
+
/**
|
|
345
|
+
* Whether the subscription is in an access-blocking terminal state
|
|
346
|
+
* (`blocked` | `expired` | `canceled` | `trial_expired`).
|
|
347
|
+
*/
|
|
348
|
+
isBlocked: boolean;
|
|
349
|
+
/**
|
|
350
|
+
* Whether the subscription is inside the payment-failure grace window
|
|
351
|
+
* (`past_due_grace`). Access is still granted by `hasAccess`, but UIs
|
|
352
|
+
* should surface a recovery banner.
|
|
353
|
+
*/
|
|
354
|
+
isGrace: boolean;
|
|
287
355
|
/** Check if user has specific plan */
|
|
288
356
|
hasPlan: (plans: string | string[]) => boolean;
|
|
289
|
-
/**
|
|
357
|
+
/**
|
|
358
|
+
* Whether the user currently has access.
|
|
359
|
+
*
|
|
360
|
+
* Post Chain-of-Pacts (Issue #2444): `true` when
|
|
361
|
+
* `effectiveStatus === 'active' || effectiveStatus === 'past_due_grace'`.
|
|
362
|
+
* Legacy consumers that need the pre-2444 semantics
|
|
363
|
+
* (`status === 'active' || status === 'trialing'`) can use
|
|
364
|
+
* `hasAccessLegacy()`.
|
|
365
|
+
*/
|
|
290
366
|
hasAccess: () => boolean;
|
|
367
|
+
/**
|
|
368
|
+
* Pre-2444 `hasAccess` semantics: `true` when the raw DB status is
|
|
369
|
+
* `active` or `trialing` (and, for trialing, the trial is not runtime-
|
|
370
|
+
* expired). Kept as a backwards-compatibility escape hatch so services
|
|
371
|
+
* that have not yet migrated to the effective-status model keep working.
|
|
372
|
+
*
|
|
373
|
+
* @deprecated Prefer `hasAccess()` or branch on `effectiveStatus` directly.
|
|
374
|
+
*/
|
|
375
|
+
hasAccessLegacy: () => boolean;
|
|
291
376
|
}
|
|
292
377
|
/**
|
|
293
378
|
* Logger interface for SDK debug output
|
|
@@ -1301,4 +1386,4 @@ interface FFIDInquiryFormPlaceholderContext {
|
|
|
1301
1386
|
}
|
|
1302
1387
|
declare function FFIDInquiryForm({ mode, prefill, organizations, preselectedOrganizationId, categories, termsVersion, privacyVersion, termsHref, privacyHref, turnstileToken, turnstileSlot, onSubmit, onChange, separateLegalCheckboxes, messagePlaceholder, requireCategorySelection, unstyled, classNames, locale, className, }: FFIDInquiryFormProps): react_jsx_runtime.JSX.Element;
|
|
1303
1388
|
|
|
1304
|
-
export { type
|
|
1389
|
+
export { type FFIDInquiryFormProps as $, type FFIDSubscription as A, type FFIDSubscriptionContextValue as B, type FFIDAnnouncementsClientConfig as C, type FFIDAnnouncementsApiResponse as D, type EffectiveSubscriptionStatus as E, type FFIDSubscriptionStatus as F, type AnnouncementListResponse as G, type FFIDAnnouncementsLogger as H, type Announcement as I, type AnnouncementStatus as J, type AnnouncementType as K, type ListAnnouncementsOptions as L, FFIDAnnouncementBadge as M, FFIDAnnouncementList as N, type FFIDAnnouncementsError as O, type FFIDAnnouncementsErrorCode as P, type FFIDAnnouncementsServerResponse as Q, type FFIDCacheConfig as R, type FFIDContextValue as S, type FFIDInquiryCategory as T, type FFIDInquiryCategorySite2026 as U, FFIDInquiryForm as V, type FFIDInquiryFormCategoryItem as W, type FFIDInquiryFormClassNames as X, type FFIDInquiryFormOrganization as Y, type FFIDInquiryFormPlaceholderContext as Z, type FFIDInquiryFormPrefill as _, type FFIDConfig as a, type FFIDInquiryFormSubmitData as a0, type FFIDInquiryFormSubmitResult as a1, type FFIDJwtClaims as a2, FFIDLoginButton as a3, type FFIDMemberStatus as a4, type FFIDOAuthTokenResponse as a5, type FFIDOAuthUserInfoMemberRole as a6, type FFIDOAuthUserInfoSubscription as a7, type FFIDOrganizationMember as a8, FFIDOrganizationSwitcher as a9, type FFIDRedirectErrorCode as aa, type FFIDSeatModel as ab, FFIDSubscriptionBadge as ac, type FFIDTokenIntrospectionResponse as ad, FFIDUserMenu as ae, FFID_INQUIRY_CATEGORIES as af, FFID_INQUIRY_CATEGORIES_SITE_2026 as ag, type UseFFIDAnnouncementsOptions as ah, type UseFFIDAnnouncementsReturn as ai, isFFIDInquiryCategorySite2026 as aj, useFFIDAnnouncements as ak, type FFIDAnnouncementBadgeClassNames as al, type FFIDAnnouncementBadgeProps as am, type FFIDAnnouncementListClassNames as an, type FFIDAnnouncementListProps as ao, type FFIDLoginButtonProps as ap, type FFIDOrganizationSwitcherClassNames as aq, type FFIDOrganizationSwitcherProps as ar, type FFIDSubscriptionBadgeClassNames as as, type FFIDSubscriptionBadgeProps as at, type FFIDUserMenuClassNames as au, type FFIDUserMenuProps as av, type FFIDApiResponse as b, type FFIDSessionResponse as c, type FFIDRedirectResult as d, type FFIDError as e, type FFIDSubscriptionCheckResponse as f, type FFIDListMembersResponse as g, type FFIDMemberRole as h, type FFIDUpdateMemberRoleResponse as i, type FFIDRemoveMemberResponse as j, type FFIDProfileCallOptions as k, type FFIDUserProfile as l, type FFIDUpdateUserProfileRequest as m, type FFIDCreateCheckoutParams as n, type FFIDCheckoutSessionResponse as o, type FFIDCreatePortalParams as p, type FFIDPortalSessionResponse as q, type FFIDVerifyAccessTokenOptions as r, type FFIDOAuthUserInfo as s, type FFIDInquiryCreateParams as t, type FFIDInquiryCreateResponse as u, type FFIDAuthMode as v, type FFIDLogger as w, type FFIDCacheAdapter as x, type FFIDUser as y, type FFIDOrganization as z };
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkKNEZ5OUQ_cjs = require('./chunk-KNEZ5OUQ.cjs');
|
|
4
4
|
var react = require('react');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
|
|
@@ -44,9 +44,38 @@ function createKVCacheAdapter(kv) {
|
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
|
+
function resolveRedirectUrl(redirectTo, status) {
|
|
48
|
+
return typeof redirectTo === "function" ? redirectTo(status) : redirectTo;
|
|
49
|
+
}
|
|
50
|
+
function defaultRedirect(url) {
|
|
51
|
+
if (typeof window === "undefined") return;
|
|
52
|
+
window.location.href = url;
|
|
53
|
+
}
|
|
54
|
+
function useRequireActiveSubscription(options) {
|
|
55
|
+
const { redirectTo, allowGrace = true, onRedirect } = options;
|
|
56
|
+
const { isLoading, error } = chunkKNEZ5OUQ_cjs.useFFIDContext();
|
|
57
|
+
const { effectiveStatus, isBlocked, isGrace } = chunkKNEZ5OUQ_cjs.useSubscription();
|
|
58
|
+
const hasFetchError = error !== null && effectiveStatus === null;
|
|
59
|
+
const shouldRedirect = !isLoading && !hasFetchError && (isBlocked || !allowGrace && isGrace || effectiveStatus === null);
|
|
60
|
+
react.useEffect(() => {
|
|
61
|
+
if (!shouldRedirect) return;
|
|
62
|
+
const triggeringStatus = effectiveStatus ?? "blocked";
|
|
63
|
+
const url = resolveRedirectUrl(redirectTo, triggeringStatus);
|
|
64
|
+
if (onRedirect) {
|
|
65
|
+
onRedirect(url);
|
|
66
|
+
} else {
|
|
67
|
+
defaultRedirect(url);
|
|
68
|
+
}
|
|
69
|
+
}, [shouldRedirect, effectiveStatus]);
|
|
70
|
+
return {
|
|
71
|
+
loading: isLoading,
|
|
72
|
+
effectiveStatus,
|
|
73
|
+
error
|
|
74
|
+
};
|
|
75
|
+
}
|
|
47
76
|
function withFFIDAuth(Component, options = {}) {
|
|
48
77
|
const WrappedComponent = (props) => {
|
|
49
|
-
const { isLoading, isAuthenticated, login } =
|
|
78
|
+
const { isLoading, isAuthenticated, login } = chunkKNEZ5OUQ_cjs.useFFIDContext();
|
|
50
79
|
const hasRedirected = react.useRef(false);
|
|
51
80
|
react.useEffect(() => {
|
|
52
81
|
if (!isLoading && !isAuthenticated && options.redirectToLogin && !hasRedirected.current) {
|
|
@@ -74,109 +103,114 @@ var FFID_NEWSLETTER_TYPES = ["inquiry_followup", "general"];
|
|
|
74
103
|
|
|
75
104
|
Object.defineProperty(exports, "DEFAULT_API_BASE_URL", {
|
|
76
105
|
enumerable: true,
|
|
77
|
-
get: function () { return
|
|
106
|
+
get: function () { return chunkKNEZ5OUQ_cjs.DEFAULT_API_BASE_URL; }
|
|
78
107
|
});
|
|
79
108
|
Object.defineProperty(exports, "FFIDAnnouncementBadge", {
|
|
80
109
|
enumerable: true,
|
|
81
|
-
get: function () { return
|
|
110
|
+
get: function () { return chunkKNEZ5OUQ_cjs.FFIDAnnouncementBadge; }
|
|
82
111
|
});
|
|
83
112
|
Object.defineProperty(exports, "FFIDAnnouncementList", {
|
|
84
113
|
enumerable: true,
|
|
85
|
-
get: function () { return
|
|
114
|
+
get: function () { return chunkKNEZ5OUQ_cjs.FFIDAnnouncementList; }
|
|
86
115
|
});
|
|
87
116
|
Object.defineProperty(exports, "FFIDInquiryForm", {
|
|
88
117
|
enumerable: true,
|
|
89
|
-
get: function () { return
|
|
118
|
+
get: function () { return chunkKNEZ5OUQ_cjs.FFIDInquiryForm; }
|
|
90
119
|
});
|
|
91
120
|
Object.defineProperty(exports, "FFIDLoginButton", {
|
|
92
121
|
enumerable: true,
|
|
93
|
-
get: function () { return
|
|
122
|
+
get: function () { return chunkKNEZ5OUQ_cjs.FFIDLoginButton; }
|
|
94
123
|
});
|
|
95
124
|
Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
|
|
96
125
|
enumerable: true,
|
|
97
|
-
get: function () { return
|
|
126
|
+
get: function () { return chunkKNEZ5OUQ_cjs.FFIDOrganizationSwitcher; }
|
|
98
127
|
});
|
|
99
128
|
Object.defineProperty(exports, "FFIDProvider", {
|
|
100
129
|
enumerable: true,
|
|
101
|
-
get: function () { return
|
|
130
|
+
get: function () { return chunkKNEZ5OUQ_cjs.FFIDProvider; }
|
|
102
131
|
});
|
|
103
132
|
Object.defineProperty(exports, "FFIDSDKError", {
|
|
104
133
|
enumerable: true,
|
|
105
|
-
get: function () { return
|
|
134
|
+
get: function () { return chunkKNEZ5OUQ_cjs.FFIDSDKError; }
|
|
106
135
|
});
|
|
107
136
|
Object.defineProperty(exports, "FFIDSubscriptionBadge", {
|
|
108
137
|
enumerable: true,
|
|
109
|
-
get: function () { return
|
|
138
|
+
get: function () { return chunkKNEZ5OUQ_cjs.FFIDSubscriptionBadge; }
|
|
110
139
|
});
|
|
111
140
|
Object.defineProperty(exports, "FFIDUserMenu", {
|
|
112
141
|
enumerable: true,
|
|
113
|
-
get: function () { return
|
|
142
|
+
get: function () { return chunkKNEZ5OUQ_cjs.FFIDUserMenu; }
|
|
114
143
|
});
|
|
115
144
|
Object.defineProperty(exports, "FFID_ANNOUNCEMENTS_ERROR_CODES", {
|
|
116
145
|
enumerable: true,
|
|
117
|
-
get: function () { return
|
|
146
|
+
get: function () { return chunkKNEZ5OUQ_cjs.FFID_ANNOUNCEMENTS_ERROR_CODES; }
|
|
118
147
|
});
|
|
119
148
|
Object.defineProperty(exports, "FFID_INQUIRY_CATEGORIES", {
|
|
120
149
|
enumerable: true,
|
|
121
|
-
get: function () { return
|
|
150
|
+
get: function () { return chunkKNEZ5OUQ_cjs.FFID_INQUIRY_CATEGORIES; }
|
|
122
151
|
});
|
|
123
152
|
Object.defineProperty(exports, "FFID_INQUIRY_CATEGORIES_SITE_2026", {
|
|
124
153
|
enumerable: true,
|
|
125
|
-
get: function () { return
|
|
154
|
+
get: function () { return chunkKNEZ5OUQ_cjs.FFID_INQUIRY_CATEGORIES_SITE_2026; }
|
|
155
|
+
});
|
|
156
|
+
Object.defineProperty(exports, "computeEffectiveStatusFromSession", {
|
|
157
|
+
enumerable: true,
|
|
158
|
+
get: function () { return chunkKNEZ5OUQ_cjs.computeEffectiveStatusFromSession; }
|
|
126
159
|
});
|
|
127
160
|
Object.defineProperty(exports, "createFFIDAnnouncementsClient", {
|
|
128
161
|
enumerable: true,
|
|
129
|
-
get: function () { return
|
|
162
|
+
get: function () { return chunkKNEZ5OUQ_cjs.createFFIDAnnouncementsClient; }
|
|
130
163
|
});
|
|
131
164
|
Object.defineProperty(exports, "createFFIDClient", {
|
|
132
165
|
enumerable: true,
|
|
133
|
-
get: function () { return
|
|
166
|
+
get: function () { return chunkKNEZ5OUQ_cjs.createFFIDClient; }
|
|
134
167
|
});
|
|
135
168
|
Object.defineProperty(exports, "createTokenStore", {
|
|
136
169
|
enumerable: true,
|
|
137
|
-
get: function () { return
|
|
170
|
+
get: function () { return chunkKNEZ5OUQ_cjs.createTokenStore; }
|
|
138
171
|
});
|
|
139
172
|
Object.defineProperty(exports, "generateCodeChallenge", {
|
|
140
173
|
enumerable: true,
|
|
141
|
-
get: function () { return
|
|
174
|
+
get: function () { return chunkKNEZ5OUQ_cjs.generateCodeChallenge; }
|
|
142
175
|
});
|
|
143
176
|
Object.defineProperty(exports, "generateCodeVerifier", {
|
|
144
177
|
enumerable: true,
|
|
145
|
-
get: function () { return
|
|
178
|
+
get: function () { return chunkKNEZ5OUQ_cjs.generateCodeVerifier; }
|
|
146
179
|
});
|
|
147
180
|
Object.defineProperty(exports, "isFFIDInquiryCategorySite2026", {
|
|
148
181
|
enumerable: true,
|
|
149
|
-
get: function () { return
|
|
182
|
+
get: function () { return chunkKNEZ5OUQ_cjs.isFFIDInquiryCategorySite2026; }
|
|
150
183
|
});
|
|
151
184
|
Object.defineProperty(exports, "normalizeRedirectUri", {
|
|
152
185
|
enumerable: true,
|
|
153
|
-
get: function () { return
|
|
186
|
+
get: function () { return chunkKNEZ5OUQ_cjs.normalizeRedirectUri; }
|
|
154
187
|
});
|
|
155
188
|
Object.defineProperty(exports, "retrieveCodeVerifier", {
|
|
156
189
|
enumerable: true,
|
|
157
|
-
get: function () { return
|
|
190
|
+
get: function () { return chunkKNEZ5OUQ_cjs.retrieveCodeVerifier; }
|
|
158
191
|
});
|
|
159
192
|
Object.defineProperty(exports, "storeCodeVerifier", {
|
|
160
193
|
enumerable: true,
|
|
161
|
-
get: function () { return
|
|
194
|
+
get: function () { return chunkKNEZ5OUQ_cjs.storeCodeVerifier; }
|
|
162
195
|
});
|
|
163
196
|
Object.defineProperty(exports, "useFFID", {
|
|
164
197
|
enumerable: true,
|
|
165
|
-
get: function () { return
|
|
198
|
+
get: function () { return chunkKNEZ5OUQ_cjs.useFFID; }
|
|
166
199
|
});
|
|
167
200
|
Object.defineProperty(exports, "useFFIDAnnouncements", {
|
|
168
201
|
enumerable: true,
|
|
169
|
-
get: function () { return
|
|
202
|
+
get: function () { return chunkKNEZ5OUQ_cjs.useFFIDAnnouncements; }
|
|
170
203
|
});
|
|
171
204
|
Object.defineProperty(exports, "useSubscription", {
|
|
172
205
|
enumerable: true,
|
|
173
|
-
get: function () { return
|
|
206
|
+
get: function () { return chunkKNEZ5OUQ_cjs.useSubscription; }
|
|
174
207
|
});
|
|
175
208
|
Object.defineProperty(exports, "withSubscription", {
|
|
176
209
|
enumerable: true,
|
|
177
|
-
get: function () { return
|
|
210
|
+
get: function () { return chunkKNEZ5OUQ_cjs.withSubscription; }
|
|
178
211
|
});
|
|
179
212
|
exports.FFID_NEWSLETTER_TYPES = FFID_NEWSLETTER_TYPES;
|
|
180
213
|
exports.createKVCacheAdapter = createKVCacheAdapter;
|
|
181
214
|
exports.createMemoryCacheAdapter = createMemoryCacheAdapter;
|
|
215
|
+
exports.useRequireActiveSubscription = useRequireActiveSubscription;
|
|
182
216
|
exports.withFFIDAuth = withFFIDAuth;
|