@feelflow/ffid-sdk 2.17.1 → 2.19.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 +70 -7
- package/dist/{chunk-DERFBYBZ.cjs → chunk-BBXUZS4U.cjs} +195 -13
- package/dist/{chunk-FGTRPNSW.js → chunk-SXYB5QM3.js} +195 -14
- 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/{index-Cv1qXIl1.d.cts → index-0D2vYSLq.d.cts} +107 -3
- package/dist/{index-Cv1qXIl1.d.ts → index-0D2vYSLq.d.ts} +107 -3
- 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 +120 -6
- package/dist/server/index.d.cts +20 -1
- package/dist/server/index.d.ts +20 -1
- package/dist/server/index.js +120 -6
- package/dist/webhooks/index.d.cts +71 -5
- package/dist/webhooks/index.d.ts +71 -5
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDListMembersResponse, h as FFIDMemberRole, i as FFIDUpdateMemberRoleResponse, j as FFIDRemoveMemberResponse, k as FFIDProfileCallOptions, l as FFIDUserProfile, m as FFIDUpdateUserProfileRequest, n as FFIDCreateCheckoutParams, o as FFIDCheckoutSessionResponse, p as FFIDCreatePortalParams, q as FFIDPortalSessionResponse, r as FFIDVerifyAccessTokenOptions, s as FFIDOAuthUserInfo, t as FFIDInquiryCreateParams, u as FFIDInquiryCreateResponse, v as FFIDAuthMode, w as FFIDLogger, x as FFIDCacheAdapter, y as FFIDUser, z as FFIDOrganization, A as FFIDSubscription, B as FFIDSubscriptionContextValue, C as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, D as FFIDAnnouncementsApiResponse,
|
|
2
|
-
export {
|
|
1
|
+
import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDListMembersResponse, h as FFIDMemberRole, i as FFIDUpdateMemberRoleResponse, j as FFIDRemoveMemberResponse, k as FFIDProfileCallOptions, l as FFIDUserProfile, m as FFIDUpdateUserProfileRequest, n as FFIDCreateCheckoutParams, o as FFIDCheckoutSessionResponse, p as FFIDCreatePortalParams, q as FFIDPortalSessionResponse, r as FFIDVerifyAccessTokenOptions, s as FFIDOAuthUserInfo, t as FFIDInquiryCreateParams, u as FFIDInquiryCreateResponse, v as FFIDAuthMode, w as FFIDLogger, x as FFIDCacheAdapter, y as FFIDUser, z as FFIDOrganization, A as FFIDSubscription, B as FFIDSubscriptionContextValue, E as EffectiveSubscriptionStatus, C as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, D as FFIDAnnouncementsApiResponse, G as AnnouncementListResponse, H as FFIDAnnouncementsLogger } from './index-0D2vYSLq.cjs';
|
|
2
|
+
export { I as Announcement, J as AnnouncementStatus, K as AnnouncementType, M as FFIDAnnouncementBadge, N as FFIDAnnouncementList, O as FFIDAnnouncementsError, P as FFIDAnnouncementsErrorCode, Q as FFIDAnnouncementsServerResponse, R as FFIDCacheConfig, S as FFIDContextValue, T as FFIDInquiryCategory, U as FFIDInquiryCategorySite2026, V as FFIDInquiryForm, W as FFIDInquiryFormCategoryItem, X as FFIDInquiryFormClassNames, Y as FFIDInquiryFormOrganization, Z as FFIDInquiryFormPlaceholderContext, _ as FFIDInquiryFormPrefill, $ as FFIDInquiryFormProps, a0 as FFIDInquiryFormSubmitData, a1 as FFIDInquiryFormSubmitResult, a2 as FFIDJwtClaims, a3 as FFIDLoginButton, a4 as FFIDMemberStatus, a5 as FFIDOAuthTokenResponse, a6 as FFIDOAuthUserInfoMemberRole, a7 as FFIDOAuthUserInfoSubscription, a8 as FFIDOrganizationMember, a9 as FFIDOrganizationSwitcher, aa as FFIDRedirectErrorCode, ab as FFIDSeatModel, ac as FFIDSubscriptionBadge, ad as FFIDTokenIntrospectionResponse, ae as FFIDUserMenu, af as FFID_INQUIRY_CATEGORIES, ag as FFID_INQUIRY_CATEGORIES_SITE_2026, ah as UseFFIDAnnouncementsOptions, ai as UseFFIDAnnouncementsReturn, aj as isFFIDInquiryCategorySite2026, ak as useFFIDAnnouncements } from './index-0D2vYSLq.cjs';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import { ReactNode, ComponentType, FC } from 'react';
|
|
5
5
|
|
|
@@ -698,36 +698,47 @@ declare function useFFID(): UseFFIDReturn;
|
|
|
698
698
|
/**
|
|
699
699
|
* useSubscription Hook
|
|
700
700
|
*
|
|
701
|
-
* Access subscription/contract information for the current service
|
|
701
|
+
* Access subscription/contract information for the current service.
|
|
702
|
+
*
|
|
703
|
+
* Post Chain-of-Pacts (Issue #2444) the hook exposes a semantic
|
|
704
|
+
* `effectiveStatus` alongside the raw booleans so callers can branch on a
|
|
705
|
+
* single access-control value instead of re-deriving `past_due_grace` vs.
|
|
706
|
+
* `blocked` in every component. See
|
|
707
|
+
* `docs/03-implementation/EXPIRED_CONTRACT_HANDLING.md` for the full recipe.
|
|
702
708
|
*
|
|
703
709
|
* @example
|
|
704
710
|
* ```tsx
|
|
705
711
|
* import { useSubscription } from '@feelflow/ffid-sdk'
|
|
706
712
|
*
|
|
707
713
|
* function PremiumFeature() {
|
|
708
|
-
* const {
|
|
714
|
+
* const { effectiveStatus, hasAccess, isGrace, hasPlan } = useSubscription()
|
|
709
715
|
*
|
|
710
|
-
* if (!
|
|
711
|
-
* return <div
|
|
716
|
+
* if (!hasAccess()) {
|
|
717
|
+
* return <div>契約が必要です(状態: {effectiveStatus})</div>
|
|
712
718
|
* }
|
|
713
719
|
*
|
|
714
720
|
* if (!hasPlan(['pro', 'enterprise'])) {
|
|
715
721
|
* return <div>プロプラン以上が必要です</div>
|
|
716
722
|
* }
|
|
717
723
|
*
|
|
718
|
-
* return
|
|
724
|
+
* return (
|
|
725
|
+
* <>
|
|
726
|
+
* {isGrace && <PaymentFailedBanner />}
|
|
727
|
+
* <PremiumContent />
|
|
728
|
+
* </>
|
|
729
|
+
* )
|
|
719
730
|
* }
|
|
720
731
|
* ```
|
|
721
732
|
*/
|
|
722
733
|
|
|
723
734
|
/**
|
|
724
|
-
* Hook to access subscription information
|
|
735
|
+
* Hook to access subscription information.
|
|
725
736
|
*
|
|
726
|
-
* Must be used within FFIDProvider
|
|
737
|
+
* Must be used within `FFIDProvider`.
|
|
727
738
|
*/
|
|
728
739
|
declare function useSubscription(): FFIDSubscriptionContextValue;
|
|
729
740
|
/**
|
|
730
|
-
* HOC to require subscription for a component
|
|
741
|
+
* HOC to require subscription for a component.
|
|
731
742
|
*
|
|
732
743
|
* @example
|
|
733
744
|
* ```tsx
|
|
@@ -749,6 +760,89 @@ interface WithSubscriptionOptions {
|
|
|
749
760
|
}
|
|
750
761
|
declare function withSubscription<P extends object>(Component: ComponentType<P>, options?: WithSubscriptionOptions): FC<P>;
|
|
751
762
|
|
|
763
|
+
/**
|
|
764
|
+
* Options accepted by {@link useRequireActiveSubscription}.
|
|
765
|
+
*/
|
|
766
|
+
interface UseRequireActiveSubscriptionOptions {
|
|
767
|
+
/**
|
|
768
|
+
* Destination to redirect to when the subscription is blocked.
|
|
769
|
+
*
|
|
770
|
+
* - `string` — used verbatim.
|
|
771
|
+
* - `(status) => string` — invoked with the triggering
|
|
772
|
+
* {@link EffectiveSubscriptionStatus} so callers can route
|
|
773
|
+
* `canceled` to a different landing page than `blocked`, etc.
|
|
774
|
+
*/
|
|
775
|
+
redirectTo: string | ((status: EffectiveSubscriptionStatus) => string);
|
|
776
|
+
/**
|
|
777
|
+
* Whether to treat `past_due_grace` as "still allowed".
|
|
778
|
+
* Defaults to `true` — matches the canonical FFID behaviour of showing
|
|
779
|
+
* a warning banner while Stripe retries the invoice. Flip to `false` to
|
|
780
|
+
* treat any non-`active` state as a hard block.
|
|
781
|
+
*/
|
|
782
|
+
allowGrace?: boolean;
|
|
783
|
+
/**
|
|
784
|
+
* Side effect that performs the actual navigation. Receives the resolved
|
|
785
|
+
* URL (after running `redirectTo` against the effective status) and is
|
|
786
|
+
* only ever called in the browser. When omitted the hook falls back to
|
|
787
|
+
* `window.location.href = url` — convenient for pages that do not use a
|
|
788
|
+
* router.
|
|
789
|
+
*/
|
|
790
|
+
onRedirect?: (url: string) => void;
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Return value of {@link useRequireActiveSubscription}.
|
|
794
|
+
*/
|
|
795
|
+
interface UseRequireActiveSubscriptionReturn {
|
|
796
|
+
/**
|
|
797
|
+
* `true` while the FFID session is still being fetched. Consumers should
|
|
798
|
+
* render a loading state until this turns `false` to avoid rendering
|
|
799
|
+
* protected UI behind the upcoming redirect.
|
|
800
|
+
*/
|
|
801
|
+
loading: boolean;
|
|
802
|
+
/**
|
|
803
|
+
* The effective subscription status that drove the guard decision.
|
|
804
|
+
* `null` when there is no subscription for the current service (the hook
|
|
805
|
+
* will then trigger a redirect on the first non-loading render).
|
|
806
|
+
*/
|
|
807
|
+
effectiveStatus: EffectiveSubscriptionStatus | null;
|
|
808
|
+
/**
|
|
809
|
+
* Surfaces the FFID context error (session fetch failure, token exchange
|
|
810
|
+
* error, etc.) so callers can render a retry surface instead of redirecting
|
|
811
|
+
* through the "contract required" flow. When `error` is non-null **and**
|
|
812
|
+
* `effectiveStatus === null`, the hook intentionally skips the redirect
|
|
813
|
+
* side effect — the subscription-less state is indistinguishable from a
|
|
814
|
+
* transient fetch failure, so routing the user to a hard paywall would
|
|
815
|
+
* punish an intermittent network blip. Callers that want to force a
|
|
816
|
+
* redirect anyway can invoke `onRedirect` manually after inspecting
|
|
817
|
+
* `error`.
|
|
818
|
+
*/
|
|
819
|
+
error: FFIDError | null;
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Guard a React tree against expired / blocked / cancelled subscriptions.
|
|
823
|
+
*
|
|
824
|
+
* The hook does nothing while the FFID provider is still loading, then —
|
|
825
|
+
* on the next render — evaluates `effectiveStatus` and fires the configured
|
|
826
|
+
* redirect when the subscription is in a blocking state. Returning
|
|
827
|
+
* `{ loading, effectiveStatus, error }` lets the caller render a skeleton /
|
|
828
|
+
* null placeholder during the transition rather than flashing protected
|
|
829
|
+
* content, and surface a retry affordance when the FFID fetch itself failed.
|
|
830
|
+
*
|
|
831
|
+
* **Error surface (S-H3)**: when the FFID context is in an error state AND
|
|
832
|
+
* there is no subscription (`effectiveStatus === null`), the hook
|
|
833
|
+
* intentionally **does not redirect**. A network blip should not send the
|
|
834
|
+
* user to the "contract required" page — the consumer is expected to
|
|
835
|
+
* inspect `error` and render a retry UI, or call `onRedirect` manually if
|
|
836
|
+
* a forced redirect is still appropriate.
|
|
837
|
+
*
|
|
838
|
+
* The redirect effect runs at most once per resolved status (tracked via
|
|
839
|
+
* React's dependency array) so consumers do not need to memoise
|
|
840
|
+
* `redirectTo` / `onRedirect` for correctness. Subsequent status changes
|
|
841
|
+
* (e.g. the user reactivates their contract in another tab and the session
|
|
842
|
+
* refreshes to `active`) naturally cancel the pending redirect.
|
|
843
|
+
*/
|
|
844
|
+
declare function useRequireActiveSubscription(options: UseRequireActiveSubscriptionOptions): UseRequireActiveSubscriptionReturn;
|
|
845
|
+
|
|
752
846
|
/**
|
|
753
847
|
* withFFIDAuth HOC
|
|
754
848
|
*
|
|
@@ -811,6 +905,82 @@ interface WithFFIDAuthOptions {
|
|
|
811
905
|
*/
|
|
812
906
|
declare function withFFIDAuth<P extends object>(Component: ComponentType<P>, options?: WithFFIDAuthOptions): FC<P>;
|
|
813
907
|
|
|
908
|
+
/**
|
|
909
|
+
* Local fallback for `EffectiveSubscriptionStatus`.
|
|
910
|
+
*
|
|
911
|
+
* The canonical value is produced by the FFID backend on
|
|
912
|
+
* `/api/v1/subscriptions/ext/check`. This helper exists to cover cases where
|
|
913
|
+
* the SDK only has the fields carried by the OAuth session response
|
|
914
|
+
* (`status`, `currentPeriodEnd`, `trialEnd`) — for example in `useSubscription`
|
|
915
|
+
* which reads from the React context, not from `/ext/check`.
|
|
916
|
+
*
|
|
917
|
+
* The mapping intentionally mirrors `getEffectiveSubscriptionStatus` /
|
|
918
|
+
* `EffectiveSubscriptionStatus` in `src/lib/common/subscription-helpers.ts`.
|
|
919
|
+
* When the server ships the authoritative `effectiveStatus`, callers should
|
|
920
|
+
* prefer it over this local approximation.
|
|
921
|
+
*
|
|
922
|
+
* Limitations (documented so callers can reason about accuracy):
|
|
923
|
+
*
|
|
924
|
+
* - **`past_due` is resolved via a 7-day grace window** anchored on
|
|
925
|
+
* `pastDueSince` (when supplied) or `currentPeriodEnd` (best-effort
|
|
926
|
+
* fallback — Stripe flips `past_due` at/around period end). Within the
|
|
927
|
+
* window the status is `past_due_grace`; past the window it flips to
|
|
928
|
+
* `blocked`. When both timestamps are missing (or unparseable) the
|
|
929
|
+
* function fails closed to `blocked`. The grace window length is
|
|
930
|
+
* duplicated from the FFID backend constant of the same name — see
|
|
931
|
+
* {@link PAST_DUE_GRACE_PERIOD_DAYS} for the sync invariant.
|
|
932
|
+
* - **`paused` / `incomplete` are mapped to `active` (fail-open).** Matches
|
|
933
|
+
* the FFID backend `computeEffectiveStatus` (`src/lib/common/subscription-
|
|
934
|
+
* helpers.ts`) which keeps access live for these transient intents — the
|
|
935
|
+
* server has richer context (Stripe webhook order, seat assignment state)
|
|
936
|
+
* so it fails open, and the SDK aligns to avoid the consumer seeing a
|
|
937
|
+
* different verdict than `/ext/check`.
|
|
938
|
+
* - **`pending_invoice` is mapped to `active`.** This is a transient state
|
|
939
|
+
* between invoice finalisation and payment, and FFID keeps access live for
|
|
940
|
+
* the organisation during that window.
|
|
941
|
+
*/
|
|
942
|
+
|
|
943
|
+
/**
|
|
944
|
+
* Inputs required to approximate `EffectiveSubscriptionStatus` from session
|
|
945
|
+
* data alone. Kept as a small record so unit tests do not need to build full
|
|
946
|
+
* `FFIDSubscription` objects.
|
|
947
|
+
*/
|
|
948
|
+
interface ComputeEffectiveStatusInput {
|
|
949
|
+
/** Raw DB status as reported by FFID. */
|
|
950
|
+
status: FFIDSubscriptionStatus;
|
|
951
|
+
/** ISO 8601 timestamp of the current billing period end, or `null` for seatless / free plans. */
|
|
952
|
+
currentPeriodEnd: string | null;
|
|
953
|
+
/** ISO 8601 timestamp of the trial end, or `null` if not on a trial. */
|
|
954
|
+
trialEnd: string | null;
|
|
955
|
+
/**
|
|
956
|
+
* ISO 8601 timestamp of when the subscription first entered `past_due`.
|
|
957
|
+
*
|
|
958
|
+
* Carried alongside the session response when available (currently not
|
|
959
|
+
* emitted — see TODO in `useSubscription` that tracks the session API
|
|
960
|
+
* extension). When absent, the compute helper falls back to
|
|
961
|
+
* `currentPeriodEnd` as a best-effort proxy (Stripe flips `past_due` at /
|
|
962
|
+
* near period end, so the proxy is within ~1 dunning retry cycle). When
|
|
963
|
+
* both timestamps are missing or unparseable the helper fails closed to
|
|
964
|
+
* `blocked`.
|
|
965
|
+
*/
|
|
966
|
+
pastDueSince?: string | null | undefined;
|
|
967
|
+
}
|
|
968
|
+
/**
|
|
969
|
+
* Compute an `EffectiveSubscriptionStatus` from the fields available in the
|
|
970
|
+
* session response. Designed as a pure function so it can be reused by
|
|
971
|
+
* `useSubscription` and by any caller that needs a best-effort access-control
|
|
972
|
+
* decision without waiting for an `/ext/check` round-trip.
|
|
973
|
+
*
|
|
974
|
+
* Callers SHOULD prefer the `effectiveStatus` returned by the FFID server
|
|
975
|
+
* (`/api/v1/subscriptions/ext/check`) when available — it has access to grace
|
|
976
|
+
* window information (`graceUntil`) that the SDK cannot see.
|
|
977
|
+
*
|
|
978
|
+
* @param input - Session-level subscription fields.
|
|
979
|
+
* @param nowMs - Override for "now", injected for deterministic tests.
|
|
980
|
+
* Defaults to `Date.now()`.
|
|
981
|
+
*/
|
|
982
|
+
declare function computeEffectiveStatusFromSession(input: ComputeEffectiveStatusInput, nowMs?: number): EffectiveSubscriptionStatus;
|
|
983
|
+
|
|
814
984
|
/**
|
|
815
985
|
* FFID Announcements API Client
|
|
816
986
|
*
|
|
@@ -937,4 +1107,4 @@ declare function createInquiryMethods(deps: InquiryMethodsDeps): {
|
|
|
937
1107
|
};
|
|
938
1108
|
type FFIDInquiryClient = ReturnType<typeof createInquiryMethods>;
|
|
939
1109
|
|
|
940
|
-
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, type FFIDInquiryClient, FFIDInquiryCreateParams, FFIDInquiryCreateResponse, 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, type FFIDPreviewSeatChangeParams, FFIDProfileCallOptions, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, FFIDRemoveMemberResponse, type FFIDResetSessionResponse, FFIDSDKError, type FFIDSeatChangeLineItem, type FFIDSeatChangePreview, type FFIDSeatChangePreviewResponse, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, type FFIDSupportedCurrency, FFIDUpdateMemberRoleResponse, FFIDUpdateUserProfileRequest, FFIDUser, FFIDUserProfile, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_NEWSLETTER_TYPES, type KVNamespaceLike, ListAnnouncementsOptions, type NormalizeRedirectUriResult, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useSubscription, withFFIDAuth, withSubscription };
|
|
1110
|
+
export { AnnouncementListResponse, type ComputeEffectiveStatusInput, type ContractWizardFlowType, type ContractWizardResubscribeOptions, type ContractWizardSubscribeOptions, type ContractWizardSubscriptionOptions, DEFAULT_API_BASE_URL, EffectiveSubscriptionStatus, 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, type FFIDInquiryClient, FFIDInquiryCreateParams, FFIDInquiryCreateResponse, 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, type FFIDPreviewSeatChangeParams, FFIDProfileCallOptions, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, FFIDRemoveMemberResponse, type FFIDResetSessionResponse, FFIDSDKError, type FFIDSeatChangeLineItem, type FFIDSeatChangePreview, type FFIDSeatChangePreviewResponse, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, type FFIDSupportedCurrency, FFIDUpdateMemberRoleResponse, FFIDUpdateUserProfileRequest, FFIDUser, FFIDUserProfile, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_NEWSLETTER_TYPES, type KVNamespaceLike, ListAnnouncementsOptions, type NormalizeRedirectUriResult, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type UseRequireActiveSubscriptionOptions, type UseRequireActiveSubscriptionReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, computeEffectiveStatusFromSession, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useRequireActiveSubscription, useSubscription, withFFIDAuth, withSubscription };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDListMembersResponse, h as FFIDMemberRole, i as FFIDUpdateMemberRoleResponse, j as FFIDRemoveMemberResponse, k as FFIDProfileCallOptions, l as FFIDUserProfile, m as FFIDUpdateUserProfileRequest, n as FFIDCreateCheckoutParams, o as FFIDCheckoutSessionResponse, p as FFIDCreatePortalParams, q as FFIDPortalSessionResponse, r as FFIDVerifyAccessTokenOptions, s as FFIDOAuthUserInfo, t as FFIDInquiryCreateParams, u as FFIDInquiryCreateResponse, v as FFIDAuthMode, w as FFIDLogger, x as FFIDCacheAdapter, y as FFIDUser, z as FFIDOrganization, A as FFIDSubscription, B as FFIDSubscriptionContextValue, C as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, D as FFIDAnnouncementsApiResponse,
|
|
2
|
-
export {
|
|
1
|
+
import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDListMembersResponse, h as FFIDMemberRole, i as FFIDUpdateMemberRoleResponse, j as FFIDRemoveMemberResponse, k as FFIDProfileCallOptions, l as FFIDUserProfile, m as FFIDUpdateUserProfileRequest, n as FFIDCreateCheckoutParams, o as FFIDCheckoutSessionResponse, p as FFIDCreatePortalParams, q as FFIDPortalSessionResponse, r as FFIDVerifyAccessTokenOptions, s as FFIDOAuthUserInfo, t as FFIDInquiryCreateParams, u as FFIDInquiryCreateResponse, v as FFIDAuthMode, w as FFIDLogger, x as FFIDCacheAdapter, y as FFIDUser, z as FFIDOrganization, A as FFIDSubscription, B as FFIDSubscriptionContextValue, E as EffectiveSubscriptionStatus, C as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, D as FFIDAnnouncementsApiResponse, G as AnnouncementListResponse, H as FFIDAnnouncementsLogger } from './index-0D2vYSLq.js';
|
|
2
|
+
export { I as Announcement, J as AnnouncementStatus, K as AnnouncementType, M as FFIDAnnouncementBadge, N as FFIDAnnouncementList, O as FFIDAnnouncementsError, P as FFIDAnnouncementsErrorCode, Q as FFIDAnnouncementsServerResponse, R as FFIDCacheConfig, S as FFIDContextValue, T as FFIDInquiryCategory, U as FFIDInquiryCategorySite2026, V as FFIDInquiryForm, W as FFIDInquiryFormCategoryItem, X as FFIDInquiryFormClassNames, Y as FFIDInquiryFormOrganization, Z as FFIDInquiryFormPlaceholderContext, _ as FFIDInquiryFormPrefill, $ as FFIDInquiryFormProps, a0 as FFIDInquiryFormSubmitData, a1 as FFIDInquiryFormSubmitResult, a2 as FFIDJwtClaims, a3 as FFIDLoginButton, a4 as FFIDMemberStatus, a5 as FFIDOAuthTokenResponse, a6 as FFIDOAuthUserInfoMemberRole, a7 as FFIDOAuthUserInfoSubscription, a8 as FFIDOrganizationMember, a9 as FFIDOrganizationSwitcher, aa as FFIDRedirectErrorCode, ab as FFIDSeatModel, ac as FFIDSubscriptionBadge, ad as FFIDTokenIntrospectionResponse, ae as FFIDUserMenu, af as FFID_INQUIRY_CATEGORIES, ag as FFID_INQUIRY_CATEGORIES_SITE_2026, ah as UseFFIDAnnouncementsOptions, ai as UseFFIDAnnouncementsReturn, aj as isFFIDInquiryCategorySite2026, ak as useFFIDAnnouncements } from './index-0D2vYSLq.js';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import { ReactNode, ComponentType, FC } from 'react';
|
|
5
5
|
|
|
@@ -698,36 +698,47 @@ declare function useFFID(): UseFFIDReturn;
|
|
|
698
698
|
/**
|
|
699
699
|
* useSubscription Hook
|
|
700
700
|
*
|
|
701
|
-
* Access subscription/contract information for the current service
|
|
701
|
+
* Access subscription/contract information for the current service.
|
|
702
|
+
*
|
|
703
|
+
* Post Chain-of-Pacts (Issue #2444) the hook exposes a semantic
|
|
704
|
+
* `effectiveStatus` alongside the raw booleans so callers can branch on a
|
|
705
|
+
* single access-control value instead of re-deriving `past_due_grace` vs.
|
|
706
|
+
* `blocked` in every component. See
|
|
707
|
+
* `docs/03-implementation/EXPIRED_CONTRACT_HANDLING.md` for the full recipe.
|
|
702
708
|
*
|
|
703
709
|
* @example
|
|
704
710
|
* ```tsx
|
|
705
711
|
* import { useSubscription } from '@feelflow/ffid-sdk'
|
|
706
712
|
*
|
|
707
713
|
* function PremiumFeature() {
|
|
708
|
-
* const {
|
|
714
|
+
* const { effectiveStatus, hasAccess, isGrace, hasPlan } = useSubscription()
|
|
709
715
|
*
|
|
710
|
-
* if (!
|
|
711
|
-
* return <div
|
|
716
|
+
* if (!hasAccess()) {
|
|
717
|
+
* return <div>契約が必要です(状態: {effectiveStatus})</div>
|
|
712
718
|
* }
|
|
713
719
|
*
|
|
714
720
|
* if (!hasPlan(['pro', 'enterprise'])) {
|
|
715
721
|
* return <div>プロプラン以上が必要です</div>
|
|
716
722
|
* }
|
|
717
723
|
*
|
|
718
|
-
* return
|
|
724
|
+
* return (
|
|
725
|
+
* <>
|
|
726
|
+
* {isGrace && <PaymentFailedBanner />}
|
|
727
|
+
* <PremiumContent />
|
|
728
|
+
* </>
|
|
729
|
+
* )
|
|
719
730
|
* }
|
|
720
731
|
* ```
|
|
721
732
|
*/
|
|
722
733
|
|
|
723
734
|
/**
|
|
724
|
-
* Hook to access subscription information
|
|
735
|
+
* Hook to access subscription information.
|
|
725
736
|
*
|
|
726
|
-
* Must be used within FFIDProvider
|
|
737
|
+
* Must be used within `FFIDProvider`.
|
|
727
738
|
*/
|
|
728
739
|
declare function useSubscription(): FFIDSubscriptionContextValue;
|
|
729
740
|
/**
|
|
730
|
-
* HOC to require subscription for a component
|
|
741
|
+
* HOC to require subscription for a component.
|
|
731
742
|
*
|
|
732
743
|
* @example
|
|
733
744
|
* ```tsx
|
|
@@ -749,6 +760,89 @@ interface WithSubscriptionOptions {
|
|
|
749
760
|
}
|
|
750
761
|
declare function withSubscription<P extends object>(Component: ComponentType<P>, options?: WithSubscriptionOptions): FC<P>;
|
|
751
762
|
|
|
763
|
+
/**
|
|
764
|
+
* Options accepted by {@link useRequireActiveSubscription}.
|
|
765
|
+
*/
|
|
766
|
+
interface UseRequireActiveSubscriptionOptions {
|
|
767
|
+
/**
|
|
768
|
+
* Destination to redirect to when the subscription is blocked.
|
|
769
|
+
*
|
|
770
|
+
* - `string` — used verbatim.
|
|
771
|
+
* - `(status) => string` — invoked with the triggering
|
|
772
|
+
* {@link EffectiveSubscriptionStatus} so callers can route
|
|
773
|
+
* `canceled` to a different landing page than `blocked`, etc.
|
|
774
|
+
*/
|
|
775
|
+
redirectTo: string | ((status: EffectiveSubscriptionStatus) => string);
|
|
776
|
+
/**
|
|
777
|
+
* Whether to treat `past_due_grace` as "still allowed".
|
|
778
|
+
* Defaults to `true` — matches the canonical FFID behaviour of showing
|
|
779
|
+
* a warning banner while Stripe retries the invoice. Flip to `false` to
|
|
780
|
+
* treat any non-`active` state as a hard block.
|
|
781
|
+
*/
|
|
782
|
+
allowGrace?: boolean;
|
|
783
|
+
/**
|
|
784
|
+
* Side effect that performs the actual navigation. Receives the resolved
|
|
785
|
+
* URL (after running `redirectTo` against the effective status) and is
|
|
786
|
+
* only ever called in the browser. When omitted the hook falls back to
|
|
787
|
+
* `window.location.href = url` — convenient for pages that do not use a
|
|
788
|
+
* router.
|
|
789
|
+
*/
|
|
790
|
+
onRedirect?: (url: string) => void;
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Return value of {@link useRequireActiveSubscription}.
|
|
794
|
+
*/
|
|
795
|
+
interface UseRequireActiveSubscriptionReturn {
|
|
796
|
+
/**
|
|
797
|
+
* `true` while the FFID session is still being fetched. Consumers should
|
|
798
|
+
* render a loading state until this turns `false` to avoid rendering
|
|
799
|
+
* protected UI behind the upcoming redirect.
|
|
800
|
+
*/
|
|
801
|
+
loading: boolean;
|
|
802
|
+
/**
|
|
803
|
+
* The effective subscription status that drove the guard decision.
|
|
804
|
+
* `null` when there is no subscription for the current service (the hook
|
|
805
|
+
* will then trigger a redirect on the first non-loading render).
|
|
806
|
+
*/
|
|
807
|
+
effectiveStatus: EffectiveSubscriptionStatus | null;
|
|
808
|
+
/**
|
|
809
|
+
* Surfaces the FFID context error (session fetch failure, token exchange
|
|
810
|
+
* error, etc.) so callers can render a retry surface instead of redirecting
|
|
811
|
+
* through the "contract required" flow. When `error` is non-null **and**
|
|
812
|
+
* `effectiveStatus === null`, the hook intentionally skips the redirect
|
|
813
|
+
* side effect — the subscription-less state is indistinguishable from a
|
|
814
|
+
* transient fetch failure, so routing the user to a hard paywall would
|
|
815
|
+
* punish an intermittent network blip. Callers that want to force a
|
|
816
|
+
* redirect anyway can invoke `onRedirect` manually after inspecting
|
|
817
|
+
* `error`.
|
|
818
|
+
*/
|
|
819
|
+
error: FFIDError | null;
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Guard a React tree against expired / blocked / cancelled subscriptions.
|
|
823
|
+
*
|
|
824
|
+
* The hook does nothing while the FFID provider is still loading, then —
|
|
825
|
+
* on the next render — evaluates `effectiveStatus` and fires the configured
|
|
826
|
+
* redirect when the subscription is in a blocking state. Returning
|
|
827
|
+
* `{ loading, effectiveStatus, error }` lets the caller render a skeleton /
|
|
828
|
+
* null placeholder during the transition rather than flashing protected
|
|
829
|
+
* content, and surface a retry affordance when the FFID fetch itself failed.
|
|
830
|
+
*
|
|
831
|
+
* **Error surface (S-H3)**: when the FFID context is in an error state AND
|
|
832
|
+
* there is no subscription (`effectiveStatus === null`), the hook
|
|
833
|
+
* intentionally **does not redirect**. A network blip should not send the
|
|
834
|
+
* user to the "contract required" page — the consumer is expected to
|
|
835
|
+
* inspect `error` and render a retry UI, or call `onRedirect` manually if
|
|
836
|
+
* a forced redirect is still appropriate.
|
|
837
|
+
*
|
|
838
|
+
* The redirect effect runs at most once per resolved status (tracked via
|
|
839
|
+
* React's dependency array) so consumers do not need to memoise
|
|
840
|
+
* `redirectTo` / `onRedirect` for correctness. Subsequent status changes
|
|
841
|
+
* (e.g. the user reactivates their contract in another tab and the session
|
|
842
|
+
* refreshes to `active`) naturally cancel the pending redirect.
|
|
843
|
+
*/
|
|
844
|
+
declare function useRequireActiveSubscription(options: UseRequireActiveSubscriptionOptions): UseRequireActiveSubscriptionReturn;
|
|
845
|
+
|
|
752
846
|
/**
|
|
753
847
|
* withFFIDAuth HOC
|
|
754
848
|
*
|
|
@@ -811,6 +905,82 @@ interface WithFFIDAuthOptions {
|
|
|
811
905
|
*/
|
|
812
906
|
declare function withFFIDAuth<P extends object>(Component: ComponentType<P>, options?: WithFFIDAuthOptions): FC<P>;
|
|
813
907
|
|
|
908
|
+
/**
|
|
909
|
+
* Local fallback for `EffectiveSubscriptionStatus`.
|
|
910
|
+
*
|
|
911
|
+
* The canonical value is produced by the FFID backend on
|
|
912
|
+
* `/api/v1/subscriptions/ext/check`. This helper exists to cover cases where
|
|
913
|
+
* the SDK only has the fields carried by the OAuth session response
|
|
914
|
+
* (`status`, `currentPeriodEnd`, `trialEnd`) — for example in `useSubscription`
|
|
915
|
+
* which reads from the React context, not from `/ext/check`.
|
|
916
|
+
*
|
|
917
|
+
* The mapping intentionally mirrors `getEffectiveSubscriptionStatus` /
|
|
918
|
+
* `EffectiveSubscriptionStatus` in `src/lib/common/subscription-helpers.ts`.
|
|
919
|
+
* When the server ships the authoritative `effectiveStatus`, callers should
|
|
920
|
+
* prefer it over this local approximation.
|
|
921
|
+
*
|
|
922
|
+
* Limitations (documented so callers can reason about accuracy):
|
|
923
|
+
*
|
|
924
|
+
* - **`past_due` is resolved via a 7-day grace window** anchored on
|
|
925
|
+
* `pastDueSince` (when supplied) or `currentPeriodEnd` (best-effort
|
|
926
|
+
* fallback — Stripe flips `past_due` at/around period end). Within the
|
|
927
|
+
* window the status is `past_due_grace`; past the window it flips to
|
|
928
|
+
* `blocked`. When both timestamps are missing (or unparseable) the
|
|
929
|
+
* function fails closed to `blocked`. The grace window length is
|
|
930
|
+
* duplicated from the FFID backend constant of the same name — see
|
|
931
|
+
* {@link PAST_DUE_GRACE_PERIOD_DAYS} for the sync invariant.
|
|
932
|
+
* - **`paused` / `incomplete` are mapped to `active` (fail-open).** Matches
|
|
933
|
+
* the FFID backend `computeEffectiveStatus` (`src/lib/common/subscription-
|
|
934
|
+
* helpers.ts`) which keeps access live for these transient intents — the
|
|
935
|
+
* server has richer context (Stripe webhook order, seat assignment state)
|
|
936
|
+
* so it fails open, and the SDK aligns to avoid the consumer seeing a
|
|
937
|
+
* different verdict than `/ext/check`.
|
|
938
|
+
* - **`pending_invoice` is mapped to `active`.** This is a transient state
|
|
939
|
+
* between invoice finalisation and payment, and FFID keeps access live for
|
|
940
|
+
* the organisation during that window.
|
|
941
|
+
*/
|
|
942
|
+
|
|
943
|
+
/**
|
|
944
|
+
* Inputs required to approximate `EffectiveSubscriptionStatus` from session
|
|
945
|
+
* data alone. Kept as a small record so unit tests do not need to build full
|
|
946
|
+
* `FFIDSubscription` objects.
|
|
947
|
+
*/
|
|
948
|
+
interface ComputeEffectiveStatusInput {
|
|
949
|
+
/** Raw DB status as reported by FFID. */
|
|
950
|
+
status: FFIDSubscriptionStatus;
|
|
951
|
+
/** ISO 8601 timestamp of the current billing period end, or `null` for seatless / free plans. */
|
|
952
|
+
currentPeriodEnd: string | null;
|
|
953
|
+
/** ISO 8601 timestamp of the trial end, or `null` if not on a trial. */
|
|
954
|
+
trialEnd: string | null;
|
|
955
|
+
/**
|
|
956
|
+
* ISO 8601 timestamp of when the subscription first entered `past_due`.
|
|
957
|
+
*
|
|
958
|
+
* Carried alongside the session response when available (currently not
|
|
959
|
+
* emitted — see TODO in `useSubscription` that tracks the session API
|
|
960
|
+
* extension). When absent, the compute helper falls back to
|
|
961
|
+
* `currentPeriodEnd` as a best-effort proxy (Stripe flips `past_due` at /
|
|
962
|
+
* near period end, so the proxy is within ~1 dunning retry cycle). When
|
|
963
|
+
* both timestamps are missing or unparseable the helper fails closed to
|
|
964
|
+
* `blocked`.
|
|
965
|
+
*/
|
|
966
|
+
pastDueSince?: string | null | undefined;
|
|
967
|
+
}
|
|
968
|
+
/**
|
|
969
|
+
* Compute an `EffectiveSubscriptionStatus` from the fields available in the
|
|
970
|
+
* session response. Designed as a pure function so it can be reused by
|
|
971
|
+
* `useSubscription` and by any caller that needs a best-effort access-control
|
|
972
|
+
* decision without waiting for an `/ext/check` round-trip.
|
|
973
|
+
*
|
|
974
|
+
* Callers SHOULD prefer the `effectiveStatus` returned by the FFID server
|
|
975
|
+
* (`/api/v1/subscriptions/ext/check`) when available — it has access to grace
|
|
976
|
+
* window information (`graceUntil`) that the SDK cannot see.
|
|
977
|
+
*
|
|
978
|
+
* @param input - Session-level subscription fields.
|
|
979
|
+
* @param nowMs - Override for "now", injected for deterministic tests.
|
|
980
|
+
* Defaults to `Date.now()`.
|
|
981
|
+
*/
|
|
982
|
+
declare function computeEffectiveStatusFromSession(input: ComputeEffectiveStatusInput, nowMs?: number): EffectiveSubscriptionStatus;
|
|
983
|
+
|
|
814
984
|
/**
|
|
815
985
|
* FFID Announcements API Client
|
|
816
986
|
*
|
|
@@ -937,4 +1107,4 @@ declare function createInquiryMethods(deps: InquiryMethodsDeps): {
|
|
|
937
1107
|
};
|
|
938
1108
|
type FFIDInquiryClient = ReturnType<typeof createInquiryMethods>;
|
|
939
1109
|
|
|
940
|
-
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, type FFIDInquiryClient, FFIDInquiryCreateParams, FFIDInquiryCreateResponse, 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, type FFIDPreviewSeatChangeParams, FFIDProfileCallOptions, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, FFIDRemoveMemberResponse, type FFIDResetSessionResponse, FFIDSDKError, type FFIDSeatChangeLineItem, type FFIDSeatChangePreview, type FFIDSeatChangePreviewResponse, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, type FFIDSupportedCurrency, FFIDUpdateMemberRoleResponse, FFIDUpdateUserProfileRequest, FFIDUser, FFIDUserProfile, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_NEWSLETTER_TYPES, type KVNamespaceLike, ListAnnouncementsOptions, type NormalizeRedirectUriResult, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useSubscription, withFFIDAuth, withSubscription };
|
|
1110
|
+
export { AnnouncementListResponse, type ComputeEffectiveStatusInput, type ContractWizardFlowType, type ContractWizardResubscribeOptions, type ContractWizardSubscribeOptions, type ContractWizardSubscriptionOptions, DEFAULT_API_BASE_URL, EffectiveSubscriptionStatus, 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, type FFIDInquiryClient, FFIDInquiryCreateParams, FFIDInquiryCreateResponse, 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, type FFIDPreviewSeatChangeParams, FFIDProfileCallOptions, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, FFIDRemoveMemberResponse, type FFIDResetSessionResponse, FFIDSDKError, type FFIDSeatChangeLineItem, type FFIDSeatChangePreview, type FFIDSeatChangePreviewResponse, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, type FFIDSupportedCurrency, FFIDUpdateMemberRoleResponse, FFIDUpdateUserProfileRequest, FFIDUser, FFIDUserProfile, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_NEWSLETTER_TYPES, type KVNamespaceLike, ListAnnouncementsOptions, type NormalizeRedirectUriResult, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type UseRequireActiveSubscriptionOptions, type UseRequireActiveSubscriptionReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, computeEffectiveStatusFromSession, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useRequireActiveSubscription, useSubscription, withFFIDAuth, withSubscription };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useFFIDContext } from './chunk-
|
|
2
|
-
export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSDKError, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_INQUIRY_CATEGORIES, FFID_INQUIRY_CATEGORIES_SITE_2026, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, isFFIDInquiryCategorySite2026, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-
|
|
3
|
-
import {
|
|
1
|
+
import { useFFIDContext, useSubscription } from './chunk-SXYB5QM3.js';
|
|
2
|
+
export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSDKError, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_INQUIRY_CATEGORIES, FFID_INQUIRY_CATEGORIES_SITE_2026, computeEffectiveStatusFromSession, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, isFFIDInquiryCategorySite2026, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-SXYB5QM3.js';
|
|
3
|
+
import { useEffect, useRef } from 'react';
|
|
4
4
|
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
// src/client/cache/memory-cache-adapter.ts
|
|
@@ -43,6 +43,35 @@ function createKVCacheAdapter(kv) {
|
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
|
+
function resolveRedirectUrl(redirectTo, status) {
|
|
47
|
+
return typeof redirectTo === "function" ? redirectTo(status) : redirectTo;
|
|
48
|
+
}
|
|
49
|
+
function defaultRedirect(url) {
|
|
50
|
+
if (typeof window === "undefined") return;
|
|
51
|
+
window.location.href = url;
|
|
52
|
+
}
|
|
53
|
+
function useRequireActiveSubscription(options) {
|
|
54
|
+
const { redirectTo, allowGrace = true, onRedirect } = options;
|
|
55
|
+
const { isLoading, error } = useFFIDContext();
|
|
56
|
+
const { effectiveStatus, isBlocked, isGrace } = useSubscription();
|
|
57
|
+
const hasFetchError = error !== null && effectiveStatus === null;
|
|
58
|
+
const shouldRedirect = !isLoading && !hasFetchError && (isBlocked || !allowGrace && isGrace || effectiveStatus === null);
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (!shouldRedirect) return;
|
|
61
|
+
const triggeringStatus = effectiveStatus ?? "blocked";
|
|
62
|
+
const url = resolveRedirectUrl(redirectTo, triggeringStatus);
|
|
63
|
+
if (onRedirect) {
|
|
64
|
+
onRedirect(url);
|
|
65
|
+
} else {
|
|
66
|
+
defaultRedirect(url);
|
|
67
|
+
}
|
|
68
|
+
}, [shouldRedirect, effectiveStatus]);
|
|
69
|
+
return {
|
|
70
|
+
loading: isLoading,
|
|
71
|
+
effectiveStatus,
|
|
72
|
+
error
|
|
73
|
+
};
|
|
74
|
+
}
|
|
46
75
|
function withFFIDAuth(Component, options = {}) {
|
|
47
76
|
const WrappedComponent = (props) => {
|
|
48
77
|
const { isLoading, isAuthenticated, login } = useFFIDContext();
|
|
@@ -71,4 +100,4 @@ function withFFIDAuth(Component, options = {}) {
|
|
|
71
100
|
// src/newsletter/types.ts
|
|
72
101
|
var FFID_NEWSLETTER_TYPES = ["inquiry_followup", "general"];
|
|
73
102
|
|
|
74
|
-
export { FFID_NEWSLETTER_TYPES, createKVCacheAdapter, createMemoryCacheAdapter, withFFIDAuth };
|
|
103
|
+
export { FFID_NEWSLETTER_TYPES, createKVCacheAdapter, createMemoryCacheAdapter, useRequireActiveSubscription, withFFIDAuth };
|