@feelflow/ffid-sdk 1.0.1 → 1.1.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 CHANGED
@@ -256,6 +256,23 @@ interface FFIDSubscription {
256
256
  }
257
257
  ```
258
258
 
259
+ ### OAuth userinfo の契約要約
260
+
261
+ token mode では SDK は `/api/v1/oauth/userinfo` を呼び出し、基本プロフィールに加えてサービス契約の要約を受け取ります。
262
+ この要約により、追加 API を呼ばずにプラン判定や UI 分岐を行えます。
263
+
264
+ ```ts
265
+ interface FFIDOAuthUserInfoSubscription {
266
+ status: 'trialing' | 'active' | 'past_due' | 'canceled' | 'paused' | null
267
+ planCode: string | null
268
+ seatModel: 'organization' | 'individual' | null
269
+ memberRole: 'owner' | 'admin' | 'member' | 'viewer' | null
270
+ organizationId: string | null
271
+ }
272
+ ```
273
+
274
+ `seatModel` はシートモデル識別用であり、organization と role は userinfo の解決済み組織文脈として扱います。
275
+
259
276
  ## 環境変数
260
277
 
261
278
  オプションで環境変数を使用してデフォルト設定を上書きできます:
@@ -135,6 +135,48 @@ function base64UrlEncode(buffer) {
135
135
  return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
136
136
  }
137
137
 
138
+ // src/client/oauth-userinfo.ts
139
+ var VALID_SUBSCRIPTION_STATUSES = ["trialing", "active", "past_due", "canceled", "paused"];
140
+ function isValidSubscriptionStatus(value) {
141
+ return VALID_SUBSCRIPTION_STATUSES.includes(value);
142
+ }
143
+ function normalizeUserinfo(raw) {
144
+ return {
145
+ sub: raw.sub,
146
+ email: raw.email,
147
+ name: raw.name,
148
+ picture: raw.picture,
149
+ organizationId: raw.organization_id ?? null,
150
+ subscription: raw.subscription ? {
151
+ status: raw.subscription.status ?? null,
152
+ planCode: raw.subscription.plan_code ?? null,
153
+ seatModel: raw.subscription.seat_model ?? null,
154
+ memberRole: raw.subscription.member_role ?? null,
155
+ organizationId: raw.subscription.organization_id ?? null
156
+ } : void 0
157
+ };
158
+ }
159
+ function mapUserinfoSubscriptionToSession(userinfo, serviceCode) {
160
+ const subscription = userinfo.subscription;
161
+ if (!subscription || !subscription.planCode || !isValidSubscriptionStatus(subscription.status)) {
162
+ return [];
163
+ }
164
+ return [
165
+ {
166
+ id: `userinfo:${serviceCode}`,
167
+ serviceCode,
168
+ serviceName: serviceCode,
169
+ planCode: subscription.planCode,
170
+ planName: subscription.planCode,
171
+ status: subscription.status,
172
+ currentPeriodEnd: null,
173
+ seatModel: subscription.seatModel ?? void 0,
174
+ memberRole: subscription.memberRole ?? void 0,
175
+ organizationId: subscription.organizationId
176
+ }
177
+ ];
178
+ }
179
+
138
180
  // src/client/ffid-client.ts
139
181
  var NO_CONTENT_STATUS = 204;
140
182
  var SESSION_ENDPOINT = "/api/v1/auth/session";
@@ -339,9 +381,9 @@ function createFFIDClient(config) {
339
381
  return refreshResult;
340
382
  }
341
383
  }
342
- let userinfo;
384
+ let rawUserinfo;
343
385
  try {
344
- userinfo = await response.json();
386
+ rawUserinfo = await response.json();
345
387
  } catch (parseError) {
346
388
  logger.error("Parse error:", parseError, "Status:", response.status);
347
389
  return {
@@ -352,7 +394,7 @@ function createFFIDClient(config) {
352
394
  };
353
395
  }
354
396
  if (!response.ok) {
355
- const errorBody = userinfo;
397
+ const errorBody = rawUserinfo;
356
398
  return {
357
399
  error: {
358
400
  code: errorBody.code ?? FFID_ERROR_CODES.UNKNOWN_ERROR,
@@ -360,6 +402,7 @@ function createFFIDClient(config) {
360
402
  }
361
403
  };
362
404
  }
405
+ const userinfo = normalizeUserinfo(rawUserinfo);
363
406
  const user = {
364
407
  id: userinfo.sub,
365
408
  email: userinfo.email ?? "",
@@ -373,7 +416,7 @@ function createFFIDClient(config) {
373
416
  data: {
374
417
  user,
375
418
  organizations: [],
376
- subscriptions: []
419
+ subscriptions: mapUserinfoSubscriptionToSession(userinfo, config.serviceCode)
377
420
  }
378
421
  };
379
422
  }
@@ -613,6 +656,10 @@ function createFFIDClient(config) {
613
656
  const redirect = redirectUrl ?? (typeof window !== "undefined" ? window.location.href : "");
614
657
  return `${baseUrl}/login?redirect=${encodeURIComponent(redirect)}&service=${encodeURIComponent(config.serviceCode)}`;
615
658
  }
659
+ function getSignupUrl(redirectUrl) {
660
+ const redirect = redirectUrl ?? (typeof window !== "undefined" ? window.location.href : "");
661
+ return `${baseUrl}/signup?redirect=${encodeURIComponent(redirect)}&service=${encodeURIComponent(config.serviceCode)}`;
662
+ }
616
663
  function createError(code, message) {
617
664
  return { code, message };
618
665
  }
@@ -621,6 +668,7 @@ function createFFIDClient(config) {
621
668
  signOut,
622
669
  redirectToLogin,
623
670
  getLoginUrl,
671
+ getSignupUrl,
624
672
  createError,
625
673
  exchangeCodeForTokens,
626
674
  refreshAccessToken,
@@ -898,6 +946,7 @@ function useFFIDClient() {
898
946
  // src/hooks/useFFID.ts
899
947
  function useFFID() {
900
948
  const context = useFFIDContext();
949
+ const client = useFFIDClient();
901
950
  return {
902
951
  user: context.user,
903
952
  organizations: context.organizations,
@@ -908,7 +957,9 @@ function useFFID() {
908
957
  login: context.login,
909
958
  logout: context.logout,
910
959
  switchOrganization: context.switchOrganization,
911
- refresh: context.refresh
960
+ refresh: context.refresh,
961
+ getLoginUrl: client.getLoginUrl,
962
+ getSignupUrl: client.getSignupUrl
912
963
  };
913
964
  }
914
965
  function FFIDLoginButton({
@@ -137,6 +137,48 @@ function base64UrlEncode(buffer) {
137
137
  return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
138
138
  }
139
139
 
140
+ // src/client/oauth-userinfo.ts
141
+ var VALID_SUBSCRIPTION_STATUSES = ["trialing", "active", "past_due", "canceled", "paused"];
142
+ function isValidSubscriptionStatus(value) {
143
+ return VALID_SUBSCRIPTION_STATUSES.includes(value);
144
+ }
145
+ function normalizeUserinfo(raw) {
146
+ return {
147
+ sub: raw.sub,
148
+ email: raw.email,
149
+ name: raw.name,
150
+ picture: raw.picture,
151
+ organizationId: raw.organization_id ?? null,
152
+ subscription: raw.subscription ? {
153
+ status: raw.subscription.status ?? null,
154
+ planCode: raw.subscription.plan_code ?? null,
155
+ seatModel: raw.subscription.seat_model ?? null,
156
+ memberRole: raw.subscription.member_role ?? null,
157
+ organizationId: raw.subscription.organization_id ?? null
158
+ } : void 0
159
+ };
160
+ }
161
+ function mapUserinfoSubscriptionToSession(userinfo, serviceCode) {
162
+ const subscription = userinfo.subscription;
163
+ if (!subscription || !subscription.planCode || !isValidSubscriptionStatus(subscription.status)) {
164
+ return [];
165
+ }
166
+ return [
167
+ {
168
+ id: `userinfo:${serviceCode}`,
169
+ serviceCode,
170
+ serviceName: serviceCode,
171
+ planCode: subscription.planCode,
172
+ planName: subscription.planCode,
173
+ status: subscription.status,
174
+ currentPeriodEnd: null,
175
+ seatModel: subscription.seatModel ?? void 0,
176
+ memberRole: subscription.memberRole ?? void 0,
177
+ organizationId: subscription.organizationId
178
+ }
179
+ ];
180
+ }
181
+
140
182
  // src/client/ffid-client.ts
141
183
  var NO_CONTENT_STATUS = 204;
142
184
  var SESSION_ENDPOINT = "/api/v1/auth/session";
@@ -341,9 +383,9 @@ function createFFIDClient(config) {
341
383
  return refreshResult;
342
384
  }
343
385
  }
344
- let userinfo;
386
+ let rawUserinfo;
345
387
  try {
346
- userinfo = await response.json();
388
+ rawUserinfo = await response.json();
347
389
  } catch (parseError) {
348
390
  logger.error("Parse error:", parseError, "Status:", response.status);
349
391
  return {
@@ -354,7 +396,7 @@ function createFFIDClient(config) {
354
396
  };
355
397
  }
356
398
  if (!response.ok) {
357
- const errorBody = userinfo;
399
+ const errorBody = rawUserinfo;
358
400
  return {
359
401
  error: {
360
402
  code: errorBody.code ?? FFID_ERROR_CODES.UNKNOWN_ERROR,
@@ -362,6 +404,7 @@ function createFFIDClient(config) {
362
404
  }
363
405
  };
364
406
  }
407
+ const userinfo = normalizeUserinfo(rawUserinfo);
365
408
  const user = {
366
409
  id: userinfo.sub,
367
410
  email: userinfo.email ?? "",
@@ -375,7 +418,7 @@ function createFFIDClient(config) {
375
418
  data: {
376
419
  user,
377
420
  organizations: [],
378
- subscriptions: []
421
+ subscriptions: mapUserinfoSubscriptionToSession(userinfo, config.serviceCode)
379
422
  }
380
423
  };
381
424
  }
@@ -615,6 +658,10 @@ function createFFIDClient(config) {
615
658
  const redirect = redirectUrl ?? (typeof window !== "undefined" ? window.location.href : "");
616
659
  return `${baseUrl}/login?redirect=${encodeURIComponent(redirect)}&service=${encodeURIComponent(config.serviceCode)}`;
617
660
  }
661
+ function getSignupUrl(redirectUrl) {
662
+ const redirect = redirectUrl ?? (typeof window !== "undefined" ? window.location.href : "");
663
+ return `${baseUrl}/signup?redirect=${encodeURIComponent(redirect)}&service=${encodeURIComponent(config.serviceCode)}`;
664
+ }
618
665
  function createError(code, message) {
619
666
  return { code, message };
620
667
  }
@@ -623,6 +670,7 @@ function createFFIDClient(config) {
623
670
  signOut,
624
671
  redirectToLogin,
625
672
  getLoginUrl,
673
+ getSignupUrl,
626
674
  createError,
627
675
  exchangeCodeForTokens,
628
676
  refreshAccessToken,
@@ -900,6 +948,7 @@ function useFFIDClient() {
900
948
  // src/hooks/useFFID.ts
901
949
  function useFFID() {
902
950
  const context = useFFIDContext();
951
+ const client = useFFIDClient();
903
952
  return {
904
953
  user: context.user,
905
954
  organizations: context.organizations,
@@ -910,7 +959,9 @@ function useFFID() {
910
959
  login: context.login,
911
960
  logout: context.logout,
912
961
  switchOrganization: context.switchOrganization,
913
- refresh: context.refresh
962
+ refresh: context.refresh,
963
+ getLoginUrl: client.getLoginUrl,
964
+ getSignupUrl: client.getSignupUrl
914
965
  };
915
966
  }
916
967
  function FFIDLoginButton({
@@ -1,30 +1,30 @@
1
1
  'use strict';
2
2
 
3
- var chunk53CYDXU3_cjs = require('../chunk-53CYDXU3.cjs');
3
+ var chunkTL6U5TJT_cjs = require('../chunk-TL6U5TJT.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "FFIDAnnouncementBadge", {
8
8
  enumerable: true,
9
- get: function () { return chunk53CYDXU3_cjs.FFIDAnnouncementBadge; }
9
+ get: function () { return chunkTL6U5TJT_cjs.FFIDAnnouncementBadge; }
10
10
  });
11
11
  Object.defineProperty(exports, "FFIDAnnouncementList", {
12
12
  enumerable: true,
13
- get: function () { return chunk53CYDXU3_cjs.FFIDAnnouncementList; }
13
+ get: function () { return chunkTL6U5TJT_cjs.FFIDAnnouncementList; }
14
14
  });
15
15
  Object.defineProperty(exports, "FFIDLoginButton", {
16
16
  enumerable: true,
17
- get: function () { return chunk53CYDXU3_cjs.FFIDLoginButton; }
17
+ get: function () { return chunkTL6U5TJT_cjs.FFIDLoginButton; }
18
18
  });
19
19
  Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
20
20
  enumerable: true,
21
- get: function () { return chunk53CYDXU3_cjs.FFIDOrganizationSwitcher; }
21
+ get: function () { return chunkTL6U5TJT_cjs.FFIDOrganizationSwitcher; }
22
22
  });
23
23
  Object.defineProperty(exports, "FFIDSubscriptionBadge", {
24
24
  enumerable: true,
25
- get: function () { return chunk53CYDXU3_cjs.FFIDSubscriptionBadge; }
25
+ get: function () { return chunkTL6U5TJT_cjs.FFIDSubscriptionBadge; }
26
26
  });
27
27
  Object.defineProperty(exports, "FFIDUserMenu", {
28
28
  enumerable: true,
29
- get: function () { return chunk53CYDXU3_cjs.FFIDUserMenu; }
29
+ get: function () { return chunkTL6U5TJT_cjs.FFIDUserMenu; }
30
30
  });
@@ -1,3 +1,3 @@
1
- export { k as FFIDAnnouncementBadge, C as FFIDAnnouncementBadgeClassNames, D as FFIDAnnouncementBadgeProps, l as FFIDAnnouncementList, E as FFIDAnnouncementListClassNames, G as FFIDAnnouncementListProps, s as FFIDLoginButton, H as FFIDLoginButtonProps, u as FFIDOrganizationSwitcher, I as FFIDOrganizationSwitcherClassNames, J as FFIDOrganizationSwitcherProps, x as FFIDSubscriptionBadge, K as FFIDSubscriptionBadgeClassNames, M as FFIDSubscriptionBadgeProps, y as FFIDUserMenu, N as FFIDUserMenuClassNames, O as FFIDUserMenuProps } from '../index-DKBSoAHg.cjs';
1
+ export { k as FFIDAnnouncementBadge, H as FFIDAnnouncementBadgeClassNames, I as FFIDAnnouncementBadgeProps, l as FFIDAnnouncementList, J as FFIDAnnouncementListClassNames, K as FFIDAnnouncementListProps, s as FFIDLoginButton, M as FFIDLoginButtonProps, x as FFIDOrganizationSwitcher, N as FFIDOrganizationSwitcherClassNames, O as FFIDOrganizationSwitcherProps, C as FFIDSubscriptionBadge, P as FFIDSubscriptionBadgeClassNames, Q as FFIDSubscriptionBadgeProps, D as FFIDUserMenu, R as FFIDUserMenuClassNames, S as FFIDUserMenuProps } from '../index-CyYHo3-R.cjs';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1,3 +1,3 @@
1
- export { k as FFIDAnnouncementBadge, C as FFIDAnnouncementBadgeClassNames, D as FFIDAnnouncementBadgeProps, l as FFIDAnnouncementList, E as FFIDAnnouncementListClassNames, G as FFIDAnnouncementListProps, s as FFIDLoginButton, H as FFIDLoginButtonProps, u as FFIDOrganizationSwitcher, I as FFIDOrganizationSwitcherClassNames, J as FFIDOrganizationSwitcherProps, x as FFIDSubscriptionBadge, K as FFIDSubscriptionBadgeClassNames, M as FFIDSubscriptionBadgeProps, y as FFIDUserMenu, N as FFIDUserMenuClassNames, O as FFIDUserMenuProps } from '../index-DKBSoAHg.js';
1
+ export { k as FFIDAnnouncementBadge, H as FFIDAnnouncementBadgeClassNames, I as FFIDAnnouncementBadgeProps, l as FFIDAnnouncementList, J as FFIDAnnouncementListClassNames, K as FFIDAnnouncementListProps, s as FFIDLoginButton, M as FFIDLoginButtonProps, x as FFIDOrganizationSwitcher, N as FFIDOrganizationSwitcherClassNames, O as FFIDOrganizationSwitcherProps, C as FFIDSubscriptionBadge, P as FFIDSubscriptionBadgeClassNames, Q as FFIDSubscriptionBadgeProps, D as FFIDUserMenu, R as FFIDUserMenuClassNames, S as FFIDUserMenuProps } from '../index-CyYHo3-R.js';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1 +1 @@
1
- export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-GAAFEPIY.js';
1
+ export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-K525KYQP.js';
@@ -9,6 +9,9 @@ import { ButtonHTMLAttributes, ReactNode, CSSProperties } from 'react';
9
9
  /**
10
10
  * User information from FFID
11
11
  */
12
+ type FFIDSeatModel = 'organization' | 'individual';
13
+ /** Userinfo member role for OAuth responses */
14
+ type FFIDOAuthUserInfoMemberRole = 'owner' | 'admin' | 'member' | 'viewer';
12
15
  interface FFIDUser {
13
16
  /** User ID (UUID) */
14
17
  id: string;
@@ -80,6 +83,29 @@ interface FFIDSubscription {
80
83
  status: 'trialing' | 'active' | 'past_due' | 'canceled' | 'paused';
81
84
  /** Current billing period end date */
82
85
  currentPeriodEnd: string | null;
86
+ /** Service seat model (available when sourced from OAuth userinfo) */
87
+ seatModel?: FFIDSeatModel | undefined;
88
+ /** Member role in the resolved organization context */
89
+ memberRole?: FFIDOAuthUserInfoMemberRole | undefined;
90
+ /** Organization ID used to resolve subscription access */
91
+ organizationId?: string | null | undefined;
92
+ }
93
+ /** OAuth userinfo subscription summary */
94
+ interface FFIDOAuthUserInfoSubscription {
95
+ status: 'trialing' | 'active' | 'past_due' | 'canceled' | 'paused' | null;
96
+ planCode: string | null;
97
+ seatModel: FFIDSeatModel | null;
98
+ memberRole: FFIDOAuthUserInfoMemberRole | null;
99
+ organizationId: string | null;
100
+ }
101
+ /** OAuth userinfo response exposed by FFID */
102
+ interface FFIDOAuthUserInfo {
103
+ sub: string;
104
+ email: string | null;
105
+ name: string | null;
106
+ picture: string | null;
107
+ organizationId?: string | null;
108
+ subscription?: FFIDOAuthUserInfoSubscription;
83
109
  }
84
110
  /**
85
111
  * SDK configuration options
@@ -577,4 +603,4 @@ interface FFIDAnnouncementListProps {
577
603
  */
578
604
  declare function FFIDAnnouncementList({ announcements, isLoading, className, classNames, style, formatDate, emptyMessage, loadingRender, renderItem, maxContentLines, }: FFIDAnnouncementListProps): react_jsx_runtime.JSX.Element;
579
605
 
580
- export { type AnnouncementListResponse as A, useFFIDAnnouncements as B, type FFIDAnnouncementBadgeClassNames as C, type FFIDAnnouncementBadgeProps as D, type FFIDAnnouncementListClassNames as E, type FFIDConfig as F, type FFIDAnnouncementListProps as G, type FFIDLoginButtonProps as H, type FFIDOrganizationSwitcherClassNames as I, type FFIDOrganizationSwitcherProps as J, type FFIDSubscriptionBadgeClassNames as K, type ListAnnouncementsOptions as L, type FFIDSubscriptionBadgeProps as M, type FFIDUserMenuClassNames as N, type FFIDUserMenuProps as O, type UseFFIDAnnouncementsOptions as U, type FFIDUser as a, type FFIDOrganization as b, type FFIDError as c, type FFIDSubscriptionContextValue as d, type FFIDAnnouncementsClientConfig as e, type FFIDAnnouncementsApiResponse as f, type FFIDAnnouncementsLogger as g, type Announcement as h, type AnnouncementStatus as i, type AnnouncementType as j, FFIDAnnouncementBadge as k, FFIDAnnouncementList as l, type FFIDAnnouncementsError as m, type FFIDAnnouncementsErrorCode as n, type FFIDAnnouncementsServerResponse as o, type FFIDApiResponse as p, type FFIDContextValue as q, type FFIDLogger as r, FFIDLoginButton as s, type FFIDOAuthTokenResponse as t, FFIDOrganizationSwitcher as u, type FFIDSessionResponse as v, type FFIDSubscription as w, FFIDSubscriptionBadge as x, FFIDUserMenu as y, type UseFFIDAnnouncementsReturn as z };
606
+ export { type AnnouncementListResponse as A, type FFIDSubscription as B, FFIDSubscriptionBadge as C, FFIDUserMenu as D, type UseFFIDAnnouncementsReturn as E, type FFIDConfig as F, useFFIDAnnouncements as G, type FFIDAnnouncementBadgeClassNames as H, type FFIDAnnouncementBadgeProps as I, type FFIDAnnouncementListClassNames as J, type FFIDAnnouncementListProps as K, type ListAnnouncementsOptions as L, type FFIDLoginButtonProps as M, type FFIDOrganizationSwitcherClassNames as N, type FFIDOrganizationSwitcherProps as O, type FFIDSubscriptionBadgeClassNames as P, type FFIDSubscriptionBadgeProps as Q, type FFIDUserMenuClassNames as R, type FFIDUserMenuProps as S, type UseFFIDAnnouncementsOptions as U, type FFIDUser as a, type FFIDOrganization as b, type FFIDError as c, type FFIDSubscriptionContextValue as d, type FFIDAnnouncementsClientConfig as e, type FFIDAnnouncementsApiResponse as f, type FFIDAnnouncementsLogger as g, type Announcement as h, type AnnouncementStatus as i, type AnnouncementType as j, FFIDAnnouncementBadge as k, FFIDAnnouncementList as l, type FFIDAnnouncementsError as m, type FFIDAnnouncementsErrorCode as n, type FFIDAnnouncementsServerResponse as o, type FFIDApiResponse as p, type FFIDContextValue as q, type FFIDLogger as r, FFIDLoginButton as s, type FFIDOAuthTokenResponse as t, type FFIDOAuthUserInfo as u, type FFIDOAuthUserInfoMemberRole as v, type FFIDOAuthUserInfoSubscription as w, FFIDOrganizationSwitcher as x, type FFIDSeatModel as y, type FFIDSessionResponse as z };
@@ -9,6 +9,9 @@ import { ButtonHTMLAttributes, ReactNode, CSSProperties } from 'react';
9
9
  /**
10
10
  * User information from FFID
11
11
  */
12
+ type FFIDSeatModel = 'organization' | 'individual';
13
+ /** Userinfo member role for OAuth responses */
14
+ type FFIDOAuthUserInfoMemberRole = 'owner' | 'admin' | 'member' | 'viewer';
12
15
  interface FFIDUser {
13
16
  /** User ID (UUID) */
14
17
  id: string;
@@ -80,6 +83,29 @@ interface FFIDSubscription {
80
83
  status: 'trialing' | 'active' | 'past_due' | 'canceled' | 'paused';
81
84
  /** Current billing period end date */
82
85
  currentPeriodEnd: string | null;
86
+ /** Service seat model (available when sourced from OAuth userinfo) */
87
+ seatModel?: FFIDSeatModel | undefined;
88
+ /** Member role in the resolved organization context */
89
+ memberRole?: FFIDOAuthUserInfoMemberRole | undefined;
90
+ /** Organization ID used to resolve subscription access */
91
+ organizationId?: string | null | undefined;
92
+ }
93
+ /** OAuth userinfo subscription summary */
94
+ interface FFIDOAuthUserInfoSubscription {
95
+ status: 'trialing' | 'active' | 'past_due' | 'canceled' | 'paused' | null;
96
+ planCode: string | null;
97
+ seatModel: FFIDSeatModel | null;
98
+ memberRole: FFIDOAuthUserInfoMemberRole | null;
99
+ organizationId: string | null;
100
+ }
101
+ /** OAuth userinfo response exposed by FFID */
102
+ interface FFIDOAuthUserInfo {
103
+ sub: string;
104
+ email: string | null;
105
+ name: string | null;
106
+ picture: string | null;
107
+ organizationId?: string | null;
108
+ subscription?: FFIDOAuthUserInfoSubscription;
83
109
  }
84
110
  /**
85
111
  * SDK configuration options
@@ -577,4 +603,4 @@ interface FFIDAnnouncementListProps {
577
603
  */
578
604
  declare function FFIDAnnouncementList({ announcements, isLoading, className, classNames, style, formatDate, emptyMessage, loadingRender, renderItem, maxContentLines, }: FFIDAnnouncementListProps): react_jsx_runtime.JSX.Element;
579
605
 
580
- export { type AnnouncementListResponse as A, useFFIDAnnouncements as B, type FFIDAnnouncementBadgeClassNames as C, type FFIDAnnouncementBadgeProps as D, type FFIDAnnouncementListClassNames as E, type FFIDConfig as F, type FFIDAnnouncementListProps as G, type FFIDLoginButtonProps as H, type FFIDOrganizationSwitcherClassNames as I, type FFIDOrganizationSwitcherProps as J, type FFIDSubscriptionBadgeClassNames as K, type ListAnnouncementsOptions as L, type FFIDSubscriptionBadgeProps as M, type FFIDUserMenuClassNames as N, type FFIDUserMenuProps as O, type UseFFIDAnnouncementsOptions as U, type FFIDUser as a, type FFIDOrganization as b, type FFIDError as c, type FFIDSubscriptionContextValue as d, type FFIDAnnouncementsClientConfig as e, type FFIDAnnouncementsApiResponse as f, type FFIDAnnouncementsLogger as g, type Announcement as h, type AnnouncementStatus as i, type AnnouncementType as j, FFIDAnnouncementBadge as k, FFIDAnnouncementList as l, type FFIDAnnouncementsError as m, type FFIDAnnouncementsErrorCode as n, type FFIDAnnouncementsServerResponse as o, type FFIDApiResponse as p, type FFIDContextValue as q, type FFIDLogger as r, FFIDLoginButton as s, type FFIDOAuthTokenResponse as t, FFIDOrganizationSwitcher as u, type FFIDSessionResponse as v, type FFIDSubscription as w, FFIDSubscriptionBadge as x, FFIDUserMenu as y, type UseFFIDAnnouncementsReturn as z };
606
+ export { type AnnouncementListResponse as A, type FFIDSubscription as B, FFIDSubscriptionBadge as C, FFIDUserMenu as D, type UseFFIDAnnouncementsReturn as E, type FFIDConfig as F, useFFIDAnnouncements as G, type FFIDAnnouncementBadgeClassNames as H, type FFIDAnnouncementBadgeProps as I, type FFIDAnnouncementListClassNames as J, type FFIDAnnouncementListProps as K, type ListAnnouncementsOptions as L, type FFIDLoginButtonProps as M, type FFIDOrganizationSwitcherClassNames as N, type FFIDOrganizationSwitcherProps as O, type FFIDSubscriptionBadgeClassNames as P, type FFIDSubscriptionBadgeProps as Q, type FFIDUserMenuClassNames as R, type FFIDUserMenuProps as S, type UseFFIDAnnouncementsOptions as U, type FFIDUser as a, type FFIDOrganization as b, type FFIDError as c, type FFIDSubscriptionContextValue as d, type FFIDAnnouncementsClientConfig as e, type FFIDAnnouncementsApiResponse as f, type FFIDAnnouncementsLogger as g, type Announcement as h, type AnnouncementStatus as i, type AnnouncementType as j, FFIDAnnouncementBadge as k, FFIDAnnouncementList as l, type FFIDAnnouncementsError as m, type FFIDAnnouncementsErrorCode as n, type FFIDAnnouncementsServerResponse as o, type FFIDApiResponse as p, type FFIDContextValue as q, type FFIDLogger as r, FFIDLoginButton as s, type FFIDOAuthTokenResponse as t, type FFIDOAuthUserInfo as u, type FFIDOAuthUserInfoMemberRole as v, type FFIDOAuthUserInfoSubscription as w, FFIDOrganizationSwitcher as x, type FFIDSeatModel as y, type FFIDSessionResponse as z };
package/dist/index.cjs CHANGED
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var chunk53CYDXU3_cjs = require('./chunk-53CYDXU3.cjs');
3
+ var chunkTL6U5TJT_cjs = require('./chunk-TL6U5TJT.cjs');
4
4
  var react = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
 
7
7
  function withFFIDAuth(Component, options = {}) {
8
8
  const WrappedComponent = (props) => {
9
- const { isLoading, isAuthenticated, login } = chunk53CYDXU3_cjs.useFFIDContext();
9
+ const { isLoading, isAuthenticated, login } = chunkTL6U5TJT_cjs.useFFIDContext();
10
10
  const hasRedirected = react.useRef(false);
11
11
  react.useEffect(() => {
12
12
  if (!isLoading && !isAuthenticated && options.redirectToLogin && !hasRedirected.current) {
@@ -31,78 +31,78 @@ function withFFIDAuth(Component, options = {}) {
31
31
 
32
32
  Object.defineProperty(exports, "DEFAULT_API_BASE_URL", {
33
33
  enumerable: true,
34
- get: function () { return chunk53CYDXU3_cjs.DEFAULT_API_BASE_URL; }
34
+ get: function () { return chunkTL6U5TJT_cjs.DEFAULT_API_BASE_URL; }
35
35
  });
36
36
  Object.defineProperty(exports, "FFIDAnnouncementBadge", {
37
37
  enumerable: true,
38
- get: function () { return chunk53CYDXU3_cjs.FFIDAnnouncementBadge; }
38
+ get: function () { return chunkTL6U5TJT_cjs.FFIDAnnouncementBadge; }
39
39
  });
40
40
  Object.defineProperty(exports, "FFIDAnnouncementList", {
41
41
  enumerable: true,
42
- get: function () { return chunk53CYDXU3_cjs.FFIDAnnouncementList; }
42
+ get: function () { return chunkTL6U5TJT_cjs.FFIDAnnouncementList; }
43
43
  });
44
44
  Object.defineProperty(exports, "FFIDLoginButton", {
45
45
  enumerable: true,
46
- get: function () { return chunk53CYDXU3_cjs.FFIDLoginButton; }
46
+ get: function () { return chunkTL6U5TJT_cjs.FFIDLoginButton; }
47
47
  });
48
48
  Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
49
49
  enumerable: true,
50
- get: function () { return chunk53CYDXU3_cjs.FFIDOrganizationSwitcher; }
50
+ get: function () { return chunkTL6U5TJT_cjs.FFIDOrganizationSwitcher; }
51
51
  });
52
52
  Object.defineProperty(exports, "FFIDProvider", {
53
53
  enumerable: true,
54
- get: function () { return chunk53CYDXU3_cjs.FFIDProvider; }
54
+ get: function () { return chunkTL6U5TJT_cjs.FFIDProvider; }
55
55
  });
56
56
  Object.defineProperty(exports, "FFIDSubscriptionBadge", {
57
57
  enumerable: true,
58
- get: function () { return chunk53CYDXU3_cjs.FFIDSubscriptionBadge; }
58
+ get: function () { return chunkTL6U5TJT_cjs.FFIDSubscriptionBadge; }
59
59
  });
60
60
  Object.defineProperty(exports, "FFIDUserMenu", {
61
61
  enumerable: true,
62
- get: function () { return chunk53CYDXU3_cjs.FFIDUserMenu; }
62
+ get: function () { return chunkTL6U5TJT_cjs.FFIDUserMenu; }
63
63
  });
64
64
  Object.defineProperty(exports, "FFID_ANNOUNCEMENTS_ERROR_CODES", {
65
65
  enumerable: true,
66
- get: function () { return chunk53CYDXU3_cjs.FFID_ANNOUNCEMENTS_ERROR_CODES; }
66
+ get: function () { return chunkTL6U5TJT_cjs.FFID_ANNOUNCEMENTS_ERROR_CODES; }
67
67
  });
68
68
  Object.defineProperty(exports, "createFFIDAnnouncementsClient", {
69
69
  enumerable: true,
70
- get: function () { return chunk53CYDXU3_cjs.createFFIDAnnouncementsClient; }
70
+ get: function () { return chunkTL6U5TJT_cjs.createFFIDAnnouncementsClient; }
71
71
  });
72
72
  Object.defineProperty(exports, "createTokenStore", {
73
73
  enumerable: true,
74
- get: function () { return chunk53CYDXU3_cjs.createTokenStore; }
74
+ get: function () { return chunkTL6U5TJT_cjs.createTokenStore; }
75
75
  });
76
76
  Object.defineProperty(exports, "generateCodeChallenge", {
77
77
  enumerable: true,
78
- get: function () { return chunk53CYDXU3_cjs.generateCodeChallenge; }
78
+ get: function () { return chunkTL6U5TJT_cjs.generateCodeChallenge; }
79
79
  });
80
80
  Object.defineProperty(exports, "generateCodeVerifier", {
81
81
  enumerable: true,
82
- get: function () { return chunk53CYDXU3_cjs.generateCodeVerifier; }
82
+ get: function () { return chunkTL6U5TJT_cjs.generateCodeVerifier; }
83
83
  });
84
84
  Object.defineProperty(exports, "retrieveCodeVerifier", {
85
85
  enumerable: true,
86
- get: function () { return chunk53CYDXU3_cjs.retrieveCodeVerifier; }
86
+ get: function () { return chunkTL6U5TJT_cjs.retrieveCodeVerifier; }
87
87
  });
88
88
  Object.defineProperty(exports, "storeCodeVerifier", {
89
89
  enumerable: true,
90
- get: function () { return chunk53CYDXU3_cjs.storeCodeVerifier; }
90
+ get: function () { return chunkTL6U5TJT_cjs.storeCodeVerifier; }
91
91
  });
92
92
  Object.defineProperty(exports, "useFFID", {
93
93
  enumerable: true,
94
- get: function () { return chunk53CYDXU3_cjs.useFFID; }
94
+ get: function () { return chunkTL6U5TJT_cjs.useFFID; }
95
95
  });
96
96
  Object.defineProperty(exports, "useFFIDAnnouncements", {
97
97
  enumerable: true,
98
- get: function () { return chunk53CYDXU3_cjs.useFFIDAnnouncements; }
98
+ get: function () { return chunkTL6U5TJT_cjs.useFFIDAnnouncements; }
99
99
  });
100
100
  Object.defineProperty(exports, "useSubscription", {
101
101
  enumerable: true,
102
- get: function () { return chunk53CYDXU3_cjs.useSubscription; }
102
+ get: function () { return chunkTL6U5TJT_cjs.useSubscription; }
103
103
  });
104
104
  Object.defineProperty(exports, "withSubscription", {
105
105
  enumerable: true,
106
- get: function () { return chunk53CYDXU3_cjs.withSubscription; }
106
+ get: function () { return chunkTL6U5TJT_cjs.withSubscription; }
107
107
  });
108
108
  exports.withFFIDAuth = withFFIDAuth;
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode, ComponentType, FC } from 'react';
3
- import { F as FFIDConfig, a as FFIDUser, b as FFIDOrganization, c as FFIDError, d as FFIDSubscriptionContextValue, e as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, f as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, g as FFIDAnnouncementsLogger } from './index-DKBSoAHg.cjs';
4
- export { h as Announcement, i as AnnouncementStatus, j as AnnouncementType, k as FFIDAnnouncementBadge, l as FFIDAnnouncementList, m as FFIDAnnouncementsError, n as FFIDAnnouncementsErrorCode, o as FFIDAnnouncementsServerResponse, p as FFIDApiResponse, q as FFIDContextValue, r as FFIDLogger, s as FFIDLoginButton, t as FFIDOAuthTokenResponse, u as FFIDOrganizationSwitcher, v as FFIDSessionResponse, w as FFIDSubscription, x as FFIDSubscriptionBadge, y as FFIDUserMenu, U as UseFFIDAnnouncementsOptions, z as UseFFIDAnnouncementsReturn, B as useFFIDAnnouncements } from './index-DKBSoAHg.cjs';
3
+ import { F as FFIDConfig, a as FFIDUser, b as FFIDOrganization, c as FFIDError, d as FFIDSubscriptionContextValue, e as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, f as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, g as FFIDAnnouncementsLogger } from './index-CyYHo3-R.cjs';
4
+ export { h as Announcement, i as AnnouncementStatus, j as AnnouncementType, k as FFIDAnnouncementBadge, l as FFIDAnnouncementList, m as FFIDAnnouncementsError, n as FFIDAnnouncementsErrorCode, o as FFIDAnnouncementsServerResponse, p as FFIDApiResponse, q as FFIDContextValue, r as FFIDLogger, s as FFIDLoginButton, t as FFIDOAuthTokenResponse, u as FFIDOAuthUserInfo, v as FFIDOAuthUserInfoMemberRole, w as FFIDOAuthUserInfoSubscription, x as FFIDOrganizationSwitcher, y as FFIDSeatModel, z as FFIDSessionResponse, B as FFIDSubscription, C as FFIDSubscriptionBadge, D as FFIDUserMenu, U as UseFFIDAnnouncementsOptions, E as UseFFIDAnnouncementsReturn, G as useFFIDAnnouncements } from './index-CyYHo3-R.cjs';
5
5
 
6
6
  /**
7
7
  * FFID SDK Shared Constants
@@ -127,6 +127,10 @@ interface UseFFIDReturn {
127
127
  switchOrganization: (organizationId: string) => void;
128
128
  /** Refresh session data */
129
129
  refresh: () => Promise<void>;
130
+ /** Get login URL with redirect parameter */
131
+ getLoginUrl: (redirectUrl?: string) => string;
132
+ /** Get signup URL with redirect parameter */
133
+ getSignupUrl: (redirectUrl?: string) => string;
130
134
  }
131
135
  /**
132
136
  * Hook to access FFID authentication and user data
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode, ComponentType, FC } from 'react';
3
- import { F as FFIDConfig, a as FFIDUser, b as FFIDOrganization, c as FFIDError, d as FFIDSubscriptionContextValue, e as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, f as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, g as FFIDAnnouncementsLogger } from './index-DKBSoAHg.js';
4
- export { h as Announcement, i as AnnouncementStatus, j as AnnouncementType, k as FFIDAnnouncementBadge, l as FFIDAnnouncementList, m as FFIDAnnouncementsError, n as FFIDAnnouncementsErrorCode, o as FFIDAnnouncementsServerResponse, p as FFIDApiResponse, q as FFIDContextValue, r as FFIDLogger, s as FFIDLoginButton, t as FFIDOAuthTokenResponse, u as FFIDOrganizationSwitcher, v as FFIDSessionResponse, w as FFIDSubscription, x as FFIDSubscriptionBadge, y as FFIDUserMenu, U as UseFFIDAnnouncementsOptions, z as UseFFIDAnnouncementsReturn, B as useFFIDAnnouncements } from './index-DKBSoAHg.js';
3
+ import { F as FFIDConfig, a as FFIDUser, b as FFIDOrganization, c as FFIDError, d as FFIDSubscriptionContextValue, e as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, f as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, g as FFIDAnnouncementsLogger } from './index-CyYHo3-R.js';
4
+ export { h as Announcement, i as AnnouncementStatus, j as AnnouncementType, k as FFIDAnnouncementBadge, l as FFIDAnnouncementList, m as FFIDAnnouncementsError, n as FFIDAnnouncementsErrorCode, o as FFIDAnnouncementsServerResponse, p as FFIDApiResponse, q as FFIDContextValue, r as FFIDLogger, s as FFIDLoginButton, t as FFIDOAuthTokenResponse, u as FFIDOAuthUserInfo, v as FFIDOAuthUserInfoMemberRole, w as FFIDOAuthUserInfoSubscription, x as FFIDOrganizationSwitcher, y as FFIDSeatModel, z as FFIDSessionResponse, B as FFIDSubscription, C as FFIDSubscriptionBadge, D as FFIDUserMenu, U as UseFFIDAnnouncementsOptions, E as UseFFIDAnnouncementsReturn, G as useFFIDAnnouncements } from './index-CyYHo3-R.js';
5
5
 
6
6
  /**
7
7
  * FFID SDK Shared Constants
@@ -127,6 +127,10 @@ interface UseFFIDReturn {
127
127
  switchOrganization: (organizationId: string) => void;
128
128
  /** Refresh session data */
129
129
  refresh: () => Promise<void>;
130
+ /** Get login URL with redirect parameter */
131
+ getLoginUrl: (redirectUrl?: string) => string;
132
+ /** Get signup URL with redirect parameter */
133
+ getSignupUrl: (redirectUrl?: string) => string;
130
134
  }
131
135
  /**
132
136
  * Hook to access FFID authentication and user data
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { useFFIDContext } from './chunk-GAAFEPIY.js';
2
- export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, createFFIDAnnouncementsClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-GAAFEPIY.js';
1
+ import { useFFIDContext } from './chunk-K525KYQP.js';
2
+ export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, createFFIDAnnouncementsClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-K525KYQP.js';
3
3
  import { useRef, useEffect } from 'react';
4
4
  import { jsx, Fragment } from 'react/jsx-runtime';
5
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feelflow/ffid-sdk",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "FeelFlow ID Platform SDK for React/Next.js applications",
5
5
  "keywords": [
6
6
  "feelflow",