@feelflow/ffid-sdk 1.14.0 → 1.18.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.
@@ -113,6 +113,10 @@ function normalizeUserinfo(raw) {
113
113
  email: raw.email,
114
114
  name: raw.name,
115
115
  picture: raw.picture,
116
+ companyName: raw.company_name ?? null,
117
+ department: raw.department ?? null,
118
+ position: raw.position ?? null,
119
+ phoneNumber: raw.phone_number ?? null,
116
120
  organizationId: raw.organization_id ?? null,
117
121
  subscription: raw.subscription ? {
118
122
  subscriptionId: raw.subscription.subscription_id ?? null,
@@ -120,7 +124,8 @@ function normalizeUserinfo(raw) {
120
124
  planCode: raw.subscription.plan_code ?? null,
121
125
  seatModel: raw.subscription.seat_model ?? null,
122
126
  memberRole: raw.subscription.member_role ?? null,
123
- organizationId: raw.subscription.organization_id ?? null
127
+ organizationId: raw.subscription.organization_id ?? null,
128
+ hasSeatAssignment: raw.subscription.has_seat_assignment ?? false
124
129
  } : void 0
125
130
  };
126
131
  }
@@ -138,6 +143,7 @@ function mapUserinfoSubscriptionToSession(userinfo, serviceCode) {
138
143
  planName: subscription.planCode,
139
144
  status: subscription.status,
140
145
  currentPeriodEnd: null,
146
+ trialEnd: null,
141
147
  seatModel: subscription.seatModel ?? void 0,
142
148
  memberRole: subscription.memberRole ?? void 0,
143
149
  organizationId: subscription.organizationId
@@ -345,6 +351,10 @@ function createVerifyAccessToken(deps) {
345
351
  email: introspectResponse.email ?? null,
346
352
  name: introspectResponse.name ?? null,
347
353
  picture: introspectResponse.picture ?? null,
354
+ company_name: introspectResponse.company_name ?? null,
355
+ department: introspectResponse.department ?? null,
356
+ position: introspectResponse.position ?? null,
357
+ phone_number: introspectResponse.phone_number ?? null,
348
358
  organization_id: introspectResponse.organization_id ?? null
349
359
  };
350
360
  const raw = introspectResponse.subscription ? {
@@ -355,7 +365,8 @@ function createVerifyAccessToken(deps) {
355
365
  plan_code: introspectResponse.subscription.plan_code,
356
366
  seat_model: introspectResponse.subscription.seat_model,
357
367
  member_role: introspectResponse.subscription.member_role,
358
- organization_id: introspectResponse.subscription.organization_id
368
+ organization_id: introspectResponse.subscription.organization_id,
369
+ has_seat_assignment: introspectResponse.subscription.has_seat_assignment ?? false
359
370
  }
360
371
  } : base;
361
372
  const userinfo = normalizeUserinfo(raw);
@@ -436,8 +447,60 @@ function createBillingMethods(deps) {
436
447
  return { createCheckoutSession, createPortalSession };
437
448
  }
438
449
 
450
+ // src/client/members-methods.ts
451
+ var EXT_MEMBERS_ENDPOINT = "/api/v1/organizations/ext/members";
452
+ function createMembersMethods(deps) {
453
+ const { fetchWithAuth, createError, serviceCode } = deps;
454
+ function buildQuery(organizationId) {
455
+ return new URLSearchParams({ organizationId, serviceCode }).toString();
456
+ }
457
+ async function listMembers(params) {
458
+ if (!params.organizationId) {
459
+ return {
460
+ error: createError("VALIDATION_ERROR", "organizationId \u306F\u5FC5\u9808\u3067\u3059")
461
+ };
462
+ }
463
+ return fetchWithAuth(
464
+ `${EXT_MEMBERS_ENDPOINT}?${buildQuery(params.organizationId)}`
465
+ );
466
+ }
467
+ async function updateMemberRole(params) {
468
+ if (!params.organizationId || !params.userId) {
469
+ return {
470
+ error: createError("VALIDATION_ERROR", "organizationId \u3068 userId \u306F\u5FC5\u9808\u3067\u3059")
471
+ };
472
+ }
473
+ if (!params.role) {
474
+ return {
475
+ error: createError("VALIDATION_ERROR", "role \u306F\u5FC5\u9808\u3067\u3059")
476
+ };
477
+ }
478
+ return fetchWithAuth(
479
+ `${EXT_MEMBERS_ENDPOINT}/${encodeURIComponent(params.userId)}?${buildQuery(params.organizationId)}`,
480
+ {
481
+ method: "PUT",
482
+ body: JSON.stringify({ role: params.role })
483
+ }
484
+ );
485
+ }
486
+ async function removeMember(params) {
487
+ if (!params.organizationId || !params.userId) {
488
+ return {
489
+ error: createError("VALIDATION_ERROR", "organizationId \u3068 userId \u306F\u5FC5\u9808\u3067\u3059")
490
+ };
491
+ }
492
+ return fetchWithAuth(
493
+ `${EXT_MEMBERS_ENDPOINT}/${encodeURIComponent(params.userId)}?${buildQuery(params.organizationId)}`,
494
+ {
495
+ method: "DELETE"
496
+ }
497
+ );
498
+ }
499
+ return { listMembers, updateMemberRole, removeMember };
500
+ }
501
+
439
502
  // src/client/version-check.ts
440
- var SDK_VERSION = "1.14.0";
503
+ var SDK_VERSION = "1.18.0";
441
504
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
442
505
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
443
506
  function sdkHeaders() {
@@ -963,7 +1026,11 @@ function createRedirectMethods(deps) {
963
1026
  resolvedRedirectUri,
964
1027
  logger
965
1028
  } = deps;
966
- async function redirectToAuthorize() {
1029
+ async function redirectToAuthorize(options) {
1030
+ if (typeof window === "undefined") {
1031
+ logger.warn("SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093");
1032
+ return { success: false, error: "SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093" };
1033
+ }
967
1034
  const verifier = generateCodeVerifier();
968
1035
  storeCodeVerifier(verifier, logger);
969
1036
  let challenge;
@@ -984,6 +1051,14 @@ function createRedirectMethods(deps) {
984
1051
  code_challenge: challenge,
985
1052
  code_challenge_method: "S256"
986
1053
  });
1054
+ if (options?.organizationId !== void 0) {
1055
+ const trimmedOrgId = options.organizationId.trim();
1056
+ if (!trimmedOrgId) {
1057
+ logger.error("organizationId \u304C\u7A7A\u6587\u5B57\u3067\u3059");
1058
+ return { success: false, error: "organizationId \u306F\u7A7A\u306B\u3067\u304D\u307E\u305B\u3093" };
1059
+ }
1060
+ params.set("organization_id", trimmedOrgId);
1061
+ }
987
1062
  const authorizeUrl = `${baseUrl}${OAUTH_AUTHORIZE_ENDPOINT}?${params.toString()}`;
988
1063
  logger.debug("Redirecting to authorize:", authorizeUrl);
989
1064
  window.location.href = authorizeUrl;
@@ -1471,7 +1546,7 @@ function createFFIDClient(config) {
1471
1546
  }
1472
1547
  return signOutCookie();
1473
1548
  }
1474
- const { redirectToLogin, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout } = createRedirectMethods({
1549
+ const { redirectToLogin, redirectToAuthorize, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout } = createRedirectMethods({
1475
1550
  authMode,
1476
1551
  baseUrl,
1477
1552
  clientId,
@@ -1498,6 +1573,11 @@ function createFFIDClient(config) {
1498
1573
  fetchWithAuth,
1499
1574
  createError
1500
1575
  });
1576
+ const { listMembers, updateMemberRole, removeMember } = createMembersMethods({
1577
+ fetchWithAuth,
1578
+ createError,
1579
+ serviceCode: config.serviceCode
1580
+ });
1501
1581
  const {
1502
1582
  requestPasswordReset,
1503
1583
  verifyPasswordResetToken,
@@ -1532,6 +1612,7 @@ function createFFIDClient(config) {
1532
1612
  getSession,
1533
1613
  signOut,
1534
1614
  redirectToLogin,
1615
+ redirectToAuthorize,
1535
1616
  redirectToLogout,
1536
1617
  getLoginUrl,
1537
1618
  getLogoutUrl,
@@ -1540,6 +1621,9 @@ function createFFIDClient(config) {
1540
1621
  exchangeCodeForTokens,
1541
1622
  refreshAccessToken,
1542
1623
  checkSubscription,
1624
+ listMembers,
1625
+ updateMemberRole,
1626
+ removeMember,
1543
1627
  createCheckoutSession,
1544
1628
  createPortalSession,
1545
1629
  verifyAccessToken,
@@ -1687,11 +1771,7 @@ function FFIDProvider({
1687
1771
  const switchOrganization = react.useCallback(
1688
1772
  (organizationId) => {
1689
1773
  const org = organizations.find((o) => o.id === organizationId);
1690
- if (org) {
1691
- setCurrentOrganizationId(organizationId);
1692
- setError(null);
1693
- client.logger.debug("Switched organization:", org.name);
1694
- } else {
1774
+ if (!org) {
1695
1775
  client.logger.debug("Organization not found:", organizationId);
1696
1776
  const ffidError = client.createError(
1697
1777
  "ORGANIZATION_NOT_FOUND",
@@ -1699,6 +1779,33 @@ function FFIDProvider({
1699
1779
  );
1700
1780
  setError(ffidError);
1701
1781
  onErrorRef.current?.(ffidError);
1782
+ return;
1783
+ }
1784
+ if (client.authMode === "token") {
1785
+ client.logger.debug("Switching organization via re-authorization:", org.name);
1786
+ client.redirectToAuthorize({ organizationId }).then((result) => {
1787
+ if (!result.success) {
1788
+ client.logger.error("\u7D44\u7E54\u5207\u308A\u66FF\u3048\u306E\u518D\u8A8D\u8A3C\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", result.error);
1789
+ const ffidError = client.createError(
1790
+ "ORGANIZATION_SWITCH_ERROR",
1791
+ result.error
1792
+ );
1793
+ setError(ffidError);
1794
+ onErrorRef.current?.(ffidError);
1795
+ }
1796
+ }).catch((err) => {
1797
+ client.logger.error("\u7D44\u7E54\u5207\u308A\u66FF\u3048\u306E\u518D\u8A8D\u8A3C\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", err);
1798
+ const ffidError = client.createError(
1799
+ "ORGANIZATION_SWITCH_ERROR",
1800
+ err instanceof Error ? err.message : "\u7D44\u7E54\u5207\u308A\u66FF\u3048\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
1801
+ );
1802
+ setError(ffidError);
1803
+ onErrorRef.current?.(ffidError);
1804
+ });
1805
+ } else {
1806
+ setCurrentOrganizationId(organizationId);
1807
+ setError(null);
1808
+ client.logger.debug("Switched organization:", org.name);
1702
1809
  }
1703
1810
  },
1704
1811
  [organizations, client]
@@ -2229,6 +2336,12 @@ function useSubscription() {
2229
2336
  const isActive = subscription?.status === "active";
2230
2337
  const isTrialing = subscription?.status === "trialing";
2231
2338
  const isCanceled = subscription?.status === "canceled";
2339
+ const isTrialExpired = react.useMemo(() => {
2340
+ if (!isTrialing) return false;
2341
+ const relevantEnd = subscription?.trialEnd ?? subscription?.currentPeriodEnd;
2342
+ if (!relevantEnd) return false;
2343
+ return new Date(relevantEnd).getTime() < Date.now();
2344
+ }, [isTrialing, subscription?.trialEnd, subscription?.currentPeriodEnd]);
2232
2345
  const hasPlan = react.useCallback(
2233
2346
  (plans) => {
2234
2347
  if (!planCode) return false;
@@ -2238,13 +2351,15 @@ function useSubscription() {
2238
2351
  [planCode]
2239
2352
  );
2240
2353
  const hasAccess = react.useCallback(() => {
2354
+ if (isTrialExpired) return false;
2241
2355
  return isActive || isTrialing;
2242
- }, [isActive, isTrialing]);
2356
+ }, [isActive, isTrialing, isTrialExpired]);
2243
2357
  return {
2244
2358
  subscription,
2245
2359
  planCode,
2246
2360
  isActive,
2247
2361
  isTrialing,
2362
+ isTrialExpired,
2248
2363
  isCanceled,
2249
2364
  hasPlan,
2250
2365
  hasAccess
@@ -111,6 +111,10 @@ function normalizeUserinfo(raw) {
111
111
  email: raw.email,
112
112
  name: raw.name,
113
113
  picture: raw.picture,
114
+ companyName: raw.company_name ?? null,
115
+ department: raw.department ?? null,
116
+ position: raw.position ?? null,
117
+ phoneNumber: raw.phone_number ?? null,
114
118
  organizationId: raw.organization_id ?? null,
115
119
  subscription: raw.subscription ? {
116
120
  subscriptionId: raw.subscription.subscription_id ?? null,
@@ -118,7 +122,8 @@ function normalizeUserinfo(raw) {
118
122
  planCode: raw.subscription.plan_code ?? null,
119
123
  seatModel: raw.subscription.seat_model ?? null,
120
124
  memberRole: raw.subscription.member_role ?? null,
121
- organizationId: raw.subscription.organization_id ?? null
125
+ organizationId: raw.subscription.organization_id ?? null,
126
+ hasSeatAssignment: raw.subscription.has_seat_assignment ?? false
122
127
  } : void 0
123
128
  };
124
129
  }
@@ -136,6 +141,7 @@ function mapUserinfoSubscriptionToSession(userinfo, serviceCode) {
136
141
  planName: subscription.planCode,
137
142
  status: subscription.status,
138
143
  currentPeriodEnd: null,
144
+ trialEnd: null,
139
145
  seatModel: subscription.seatModel ?? void 0,
140
146
  memberRole: subscription.memberRole ?? void 0,
141
147
  organizationId: subscription.organizationId
@@ -343,6 +349,10 @@ function createVerifyAccessToken(deps) {
343
349
  email: introspectResponse.email ?? null,
344
350
  name: introspectResponse.name ?? null,
345
351
  picture: introspectResponse.picture ?? null,
352
+ company_name: introspectResponse.company_name ?? null,
353
+ department: introspectResponse.department ?? null,
354
+ position: introspectResponse.position ?? null,
355
+ phone_number: introspectResponse.phone_number ?? null,
346
356
  organization_id: introspectResponse.organization_id ?? null
347
357
  };
348
358
  const raw = introspectResponse.subscription ? {
@@ -353,7 +363,8 @@ function createVerifyAccessToken(deps) {
353
363
  plan_code: introspectResponse.subscription.plan_code,
354
364
  seat_model: introspectResponse.subscription.seat_model,
355
365
  member_role: introspectResponse.subscription.member_role,
356
- organization_id: introspectResponse.subscription.organization_id
366
+ organization_id: introspectResponse.subscription.organization_id,
367
+ has_seat_assignment: introspectResponse.subscription.has_seat_assignment ?? false
357
368
  }
358
369
  } : base;
359
370
  const userinfo = normalizeUserinfo(raw);
@@ -434,8 +445,60 @@ function createBillingMethods(deps) {
434
445
  return { createCheckoutSession, createPortalSession };
435
446
  }
436
447
 
448
+ // src/client/members-methods.ts
449
+ var EXT_MEMBERS_ENDPOINT = "/api/v1/organizations/ext/members";
450
+ function createMembersMethods(deps) {
451
+ const { fetchWithAuth, createError, serviceCode } = deps;
452
+ function buildQuery(organizationId) {
453
+ return new URLSearchParams({ organizationId, serviceCode }).toString();
454
+ }
455
+ async function listMembers(params) {
456
+ if (!params.organizationId) {
457
+ return {
458
+ error: createError("VALIDATION_ERROR", "organizationId \u306F\u5FC5\u9808\u3067\u3059")
459
+ };
460
+ }
461
+ return fetchWithAuth(
462
+ `${EXT_MEMBERS_ENDPOINT}?${buildQuery(params.organizationId)}`
463
+ );
464
+ }
465
+ async function updateMemberRole(params) {
466
+ if (!params.organizationId || !params.userId) {
467
+ return {
468
+ error: createError("VALIDATION_ERROR", "organizationId \u3068 userId \u306F\u5FC5\u9808\u3067\u3059")
469
+ };
470
+ }
471
+ if (!params.role) {
472
+ return {
473
+ error: createError("VALIDATION_ERROR", "role \u306F\u5FC5\u9808\u3067\u3059")
474
+ };
475
+ }
476
+ return fetchWithAuth(
477
+ `${EXT_MEMBERS_ENDPOINT}/${encodeURIComponent(params.userId)}?${buildQuery(params.organizationId)}`,
478
+ {
479
+ method: "PUT",
480
+ body: JSON.stringify({ role: params.role })
481
+ }
482
+ );
483
+ }
484
+ async function removeMember(params) {
485
+ if (!params.organizationId || !params.userId) {
486
+ return {
487
+ error: createError("VALIDATION_ERROR", "organizationId \u3068 userId \u306F\u5FC5\u9808\u3067\u3059")
488
+ };
489
+ }
490
+ return fetchWithAuth(
491
+ `${EXT_MEMBERS_ENDPOINT}/${encodeURIComponent(params.userId)}?${buildQuery(params.organizationId)}`,
492
+ {
493
+ method: "DELETE"
494
+ }
495
+ );
496
+ }
497
+ return { listMembers, updateMemberRole, removeMember };
498
+ }
499
+
437
500
  // src/client/version-check.ts
438
- var SDK_VERSION = "1.14.0";
501
+ var SDK_VERSION = "1.18.0";
439
502
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
440
503
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
441
504
  function sdkHeaders() {
@@ -961,7 +1024,11 @@ function createRedirectMethods(deps) {
961
1024
  resolvedRedirectUri,
962
1025
  logger
963
1026
  } = deps;
964
- async function redirectToAuthorize() {
1027
+ async function redirectToAuthorize(options) {
1028
+ if (typeof window === "undefined") {
1029
+ logger.warn("SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093");
1030
+ return { success: false, error: "SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093" };
1031
+ }
965
1032
  const verifier = generateCodeVerifier();
966
1033
  storeCodeVerifier(verifier, logger);
967
1034
  let challenge;
@@ -982,6 +1049,14 @@ function createRedirectMethods(deps) {
982
1049
  code_challenge: challenge,
983
1050
  code_challenge_method: "S256"
984
1051
  });
1052
+ if (options?.organizationId !== void 0) {
1053
+ const trimmedOrgId = options.organizationId.trim();
1054
+ if (!trimmedOrgId) {
1055
+ logger.error("organizationId \u304C\u7A7A\u6587\u5B57\u3067\u3059");
1056
+ return { success: false, error: "organizationId \u306F\u7A7A\u306B\u3067\u304D\u307E\u305B\u3093" };
1057
+ }
1058
+ params.set("organization_id", trimmedOrgId);
1059
+ }
985
1060
  const authorizeUrl = `${baseUrl}${OAUTH_AUTHORIZE_ENDPOINT}?${params.toString()}`;
986
1061
  logger.debug("Redirecting to authorize:", authorizeUrl);
987
1062
  window.location.href = authorizeUrl;
@@ -1469,7 +1544,7 @@ function createFFIDClient(config) {
1469
1544
  }
1470
1545
  return signOutCookie();
1471
1546
  }
1472
- const { redirectToLogin, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout } = createRedirectMethods({
1547
+ const { redirectToLogin, redirectToAuthorize, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout } = createRedirectMethods({
1473
1548
  authMode,
1474
1549
  baseUrl,
1475
1550
  clientId,
@@ -1496,6 +1571,11 @@ function createFFIDClient(config) {
1496
1571
  fetchWithAuth,
1497
1572
  createError
1498
1573
  });
1574
+ const { listMembers, updateMemberRole, removeMember } = createMembersMethods({
1575
+ fetchWithAuth,
1576
+ createError,
1577
+ serviceCode: config.serviceCode
1578
+ });
1499
1579
  const {
1500
1580
  requestPasswordReset,
1501
1581
  verifyPasswordResetToken,
@@ -1530,6 +1610,7 @@ function createFFIDClient(config) {
1530
1610
  getSession,
1531
1611
  signOut,
1532
1612
  redirectToLogin,
1613
+ redirectToAuthorize,
1533
1614
  redirectToLogout,
1534
1615
  getLoginUrl,
1535
1616
  getLogoutUrl,
@@ -1538,6 +1619,9 @@ function createFFIDClient(config) {
1538
1619
  exchangeCodeForTokens,
1539
1620
  refreshAccessToken,
1540
1621
  checkSubscription,
1622
+ listMembers,
1623
+ updateMemberRole,
1624
+ removeMember,
1541
1625
  createCheckoutSession,
1542
1626
  createPortalSession,
1543
1627
  verifyAccessToken,
@@ -1685,11 +1769,7 @@ function FFIDProvider({
1685
1769
  const switchOrganization = useCallback(
1686
1770
  (organizationId) => {
1687
1771
  const org = organizations.find((o) => o.id === organizationId);
1688
- if (org) {
1689
- setCurrentOrganizationId(organizationId);
1690
- setError(null);
1691
- client.logger.debug("Switched organization:", org.name);
1692
- } else {
1772
+ if (!org) {
1693
1773
  client.logger.debug("Organization not found:", organizationId);
1694
1774
  const ffidError = client.createError(
1695
1775
  "ORGANIZATION_NOT_FOUND",
@@ -1697,6 +1777,33 @@ function FFIDProvider({
1697
1777
  );
1698
1778
  setError(ffidError);
1699
1779
  onErrorRef.current?.(ffidError);
1780
+ return;
1781
+ }
1782
+ if (client.authMode === "token") {
1783
+ client.logger.debug("Switching organization via re-authorization:", org.name);
1784
+ client.redirectToAuthorize({ organizationId }).then((result) => {
1785
+ if (!result.success) {
1786
+ client.logger.error("\u7D44\u7E54\u5207\u308A\u66FF\u3048\u306E\u518D\u8A8D\u8A3C\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", result.error);
1787
+ const ffidError = client.createError(
1788
+ "ORGANIZATION_SWITCH_ERROR",
1789
+ result.error
1790
+ );
1791
+ setError(ffidError);
1792
+ onErrorRef.current?.(ffidError);
1793
+ }
1794
+ }).catch((err) => {
1795
+ client.logger.error("\u7D44\u7E54\u5207\u308A\u66FF\u3048\u306E\u518D\u8A8D\u8A3C\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", err);
1796
+ const ffidError = client.createError(
1797
+ "ORGANIZATION_SWITCH_ERROR",
1798
+ err instanceof Error ? err.message : "\u7D44\u7E54\u5207\u308A\u66FF\u3048\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
1799
+ );
1800
+ setError(ffidError);
1801
+ onErrorRef.current?.(ffidError);
1802
+ });
1803
+ } else {
1804
+ setCurrentOrganizationId(organizationId);
1805
+ setError(null);
1806
+ client.logger.debug("Switched organization:", org.name);
1700
1807
  }
1701
1808
  },
1702
1809
  [organizations, client]
@@ -2227,6 +2334,12 @@ function useSubscription() {
2227
2334
  const isActive = subscription?.status === "active";
2228
2335
  const isTrialing = subscription?.status === "trialing";
2229
2336
  const isCanceled = subscription?.status === "canceled";
2337
+ const isTrialExpired = useMemo(() => {
2338
+ if (!isTrialing) return false;
2339
+ const relevantEnd = subscription?.trialEnd ?? subscription?.currentPeriodEnd;
2340
+ if (!relevantEnd) return false;
2341
+ return new Date(relevantEnd).getTime() < Date.now();
2342
+ }, [isTrialing, subscription?.trialEnd, subscription?.currentPeriodEnd]);
2230
2343
  const hasPlan = useCallback(
2231
2344
  (plans) => {
2232
2345
  if (!planCode) return false;
@@ -2236,13 +2349,15 @@ function useSubscription() {
2236
2349
  [planCode]
2237
2350
  );
2238
2351
  const hasAccess = useCallback(() => {
2352
+ if (isTrialExpired) return false;
2239
2353
  return isActive || isTrialing;
2240
- }, [isActive, isTrialing]);
2354
+ }, [isActive, isTrialing, isTrialExpired]);
2241
2355
  return {
2242
2356
  subscription,
2243
2357
  planCode,
2244
2358
  isActive,
2245
2359
  isTrialing,
2360
+ isTrialExpired,
2246
2361
  isCanceled,
2247
2362
  hasPlan,
2248
2363
  hasAccess
@@ -1,30 +1,30 @@
1
1
  'use strict';
2
2
 
3
- var chunkTMUFELR5_cjs = require('../chunk-TMUFELR5.cjs');
3
+ var chunkTHHBQAFX_cjs = require('../chunk-THHBQAFX.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "FFIDAnnouncementBadge", {
8
8
  enumerable: true,
9
- get: function () { return chunkTMUFELR5_cjs.FFIDAnnouncementBadge; }
9
+ get: function () { return chunkTHHBQAFX_cjs.FFIDAnnouncementBadge; }
10
10
  });
11
11
  Object.defineProperty(exports, "FFIDAnnouncementList", {
12
12
  enumerable: true,
13
- get: function () { return chunkTMUFELR5_cjs.FFIDAnnouncementList; }
13
+ get: function () { return chunkTHHBQAFX_cjs.FFIDAnnouncementList; }
14
14
  });
15
15
  Object.defineProperty(exports, "FFIDLoginButton", {
16
16
  enumerable: true,
17
- get: function () { return chunkTMUFELR5_cjs.FFIDLoginButton; }
17
+ get: function () { return chunkTHHBQAFX_cjs.FFIDLoginButton; }
18
18
  });
19
19
  Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
20
20
  enumerable: true,
21
- get: function () { return chunkTMUFELR5_cjs.FFIDOrganizationSwitcher; }
21
+ get: function () { return chunkTHHBQAFX_cjs.FFIDOrganizationSwitcher; }
22
22
  });
23
23
  Object.defineProperty(exports, "FFIDSubscriptionBadge", {
24
24
  enumerable: true,
25
- get: function () { return chunkTMUFELR5_cjs.FFIDSubscriptionBadge; }
25
+ get: function () { return chunkTHHBQAFX_cjs.FFIDSubscriptionBadge; }
26
26
  });
27
27
  Object.defineProperty(exports, "FFIDUserMenu", {
28
28
  enumerable: true,
29
- get: function () { return chunkTMUFELR5_cjs.FFIDUserMenu; }
29
+ get: function () { return chunkTHHBQAFX_cjs.FFIDUserMenu; }
30
30
  });
@@ -1,3 +1,3 @@
1
- export { y as FFIDAnnouncementBadge, W as FFIDAnnouncementBadgeClassNames, X as FFIDAnnouncementBadgeProps, z as FFIDAnnouncementList, Y as FFIDAnnouncementListClassNames, Z as FFIDAnnouncementListProps, I as FFIDLoginButton, _ as FFIDLoginButtonProps, N as FFIDOrganizationSwitcher, $ as FFIDOrganizationSwitcherClassNames, a0 as FFIDOrganizationSwitcherProps, P as FFIDSubscriptionBadge, a1 as FFIDSubscriptionBadgeClassNames, a2 as FFIDSubscriptionBadgeProps, S as FFIDUserMenu, a3 as FFIDUserMenuClassNames, a4 as FFIDUserMenuProps } from '../index-DU-lFo9B.cjs';
1
+ export { D as FFIDAnnouncementBadge, a0 as FFIDAnnouncementBadgeClassNames, a1 as FFIDAnnouncementBadgeProps, E as FFIDAnnouncementList, a2 as FFIDAnnouncementListClassNames, a3 as FFIDAnnouncementListProps, N as FFIDLoginButton, a4 as FFIDLoginButtonProps, T as FFIDOrganizationSwitcher, a5 as FFIDOrganizationSwitcherClassNames, a6 as FFIDOrganizationSwitcherProps, V as FFIDSubscriptionBadge, a7 as FFIDSubscriptionBadgeClassNames, a8 as FFIDSubscriptionBadgeProps, Y as FFIDUserMenu, a9 as FFIDUserMenuClassNames, aa as FFIDUserMenuProps } from '../index-BHh-uxYS.cjs';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1,3 +1,3 @@
1
- export { y as FFIDAnnouncementBadge, W as FFIDAnnouncementBadgeClassNames, X as FFIDAnnouncementBadgeProps, z as FFIDAnnouncementList, Y as FFIDAnnouncementListClassNames, Z as FFIDAnnouncementListProps, I as FFIDLoginButton, _ as FFIDLoginButtonProps, N as FFIDOrganizationSwitcher, $ as FFIDOrganizationSwitcherClassNames, a0 as FFIDOrganizationSwitcherProps, P as FFIDSubscriptionBadge, a1 as FFIDSubscriptionBadgeClassNames, a2 as FFIDSubscriptionBadgeProps, S as FFIDUserMenu, a3 as FFIDUserMenuClassNames, a4 as FFIDUserMenuProps } from '../index-DU-lFo9B.js';
1
+ export { D as FFIDAnnouncementBadge, a0 as FFIDAnnouncementBadgeClassNames, a1 as FFIDAnnouncementBadgeProps, E as FFIDAnnouncementList, a2 as FFIDAnnouncementListClassNames, a3 as FFIDAnnouncementListProps, N as FFIDLoginButton, a4 as FFIDLoginButtonProps, T as FFIDOrganizationSwitcher, a5 as FFIDOrganizationSwitcherClassNames, a6 as FFIDOrganizationSwitcherProps, V as FFIDSubscriptionBadge, a7 as FFIDSubscriptionBadgeClassNames, a8 as FFIDSubscriptionBadgeProps, Y as FFIDUserMenu, a9 as FFIDUserMenuClassNames, aa as FFIDUserMenuProps } from '../index-BHh-uxYS.js';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1 +1 @@
1
- export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-WJI7D5C7.js';
1
+ export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-ZJIZTYXQ.js';