@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.
@@ -109,6 +109,10 @@ function normalizeUserinfo(raw) {
109
109
  email: raw.email,
110
110
  name: raw.name,
111
111
  picture: raw.picture,
112
+ companyName: raw.company_name ?? null,
113
+ department: raw.department ?? null,
114
+ position: raw.position ?? null,
115
+ phoneNumber: raw.phone_number ?? null,
112
116
  organizationId: raw.organization_id ?? null,
113
117
  subscription: raw.subscription ? {
114
118
  subscriptionId: raw.subscription.subscription_id ?? null,
@@ -116,7 +120,8 @@ function normalizeUserinfo(raw) {
116
120
  planCode: raw.subscription.plan_code ?? null,
117
121
  seatModel: raw.subscription.seat_model ?? null,
118
122
  memberRole: raw.subscription.member_role ?? null,
119
- organizationId: raw.subscription.organization_id ?? null
123
+ organizationId: raw.subscription.organization_id ?? null,
124
+ hasSeatAssignment: raw.subscription.has_seat_assignment ?? false
120
125
  } : void 0
121
126
  };
122
127
  }
@@ -134,6 +139,7 @@ function mapUserinfoSubscriptionToSession(userinfo, serviceCode) {
134
139
  planName: subscription.planCode,
135
140
  status: subscription.status,
136
141
  currentPeriodEnd: null,
142
+ trialEnd: null,
137
143
  seatModel: subscription.seatModel ?? void 0,
138
144
  memberRole: subscription.memberRole ?? void 0,
139
145
  organizationId: subscription.organizationId
@@ -341,6 +347,10 @@ function createVerifyAccessToken(deps) {
341
347
  email: introspectResponse.email ?? null,
342
348
  name: introspectResponse.name ?? null,
343
349
  picture: introspectResponse.picture ?? null,
350
+ company_name: introspectResponse.company_name ?? null,
351
+ department: introspectResponse.department ?? null,
352
+ position: introspectResponse.position ?? null,
353
+ phone_number: introspectResponse.phone_number ?? null,
344
354
  organization_id: introspectResponse.organization_id ?? null
345
355
  };
346
356
  const raw = introspectResponse.subscription ? {
@@ -351,7 +361,8 @@ function createVerifyAccessToken(deps) {
351
361
  plan_code: introspectResponse.subscription.plan_code,
352
362
  seat_model: introspectResponse.subscription.seat_model,
353
363
  member_role: introspectResponse.subscription.member_role,
354
- organization_id: introspectResponse.subscription.organization_id
364
+ organization_id: introspectResponse.subscription.organization_id,
365
+ has_seat_assignment: introspectResponse.subscription.has_seat_assignment ?? false
355
366
  }
356
367
  } : base;
357
368
  const userinfo = normalizeUserinfo(raw);
@@ -432,8 +443,60 @@ function createBillingMethods(deps) {
432
443
  return { createCheckoutSession, createPortalSession };
433
444
  }
434
445
 
446
+ // src/client/members-methods.ts
447
+ var EXT_MEMBERS_ENDPOINT = "/api/v1/organizations/ext/members";
448
+ function createMembersMethods(deps) {
449
+ const { fetchWithAuth, createError, serviceCode } = deps;
450
+ function buildQuery(organizationId) {
451
+ return new URLSearchParams({ organizationId, serviceCode }).toString();
452
+ }
453
+ async function listMembers(params) {
454
+ if (!params.organizationId) {
455
+ return {
456
+ error: createError("VALIDATION_ERROR", "organizationId \u306F\u5FC5\u9808\u3067\u3059")
457
+ };
458
+ }
459
+ return fetchWithAuth(
460
+ `${EXT_MEMBERS_ENDPOINT}?${buildQuery(params.organizationId)}`
461
+ );
462
+ }
463
+ async function updateMemberRole(params) {
464
+ if (!params.organizationId || !params.userId) {
465
+ return {
466
+ error: createError("VALIDATION_ERROR", "organizationId \u3068 userId \u306F\u5FC5\u9808\u3067\u3059")
467
+ };
468
+ }
469
+ if (!params.role) {
470
+ return {
471
+ error: createError("VALIDATION_ERROR", "role \u306F\u5FC5\u9808\u3067\u3059")
472
+ };
473
+ }
474
+ return fetchWithAuth(
475
+ `${EXT_MEMBERS_ENDPOINT}/${encodeURIComponent(params.userId)}?${buildQuery(params.organizationId)}`,
476
+ {
477
+ method: "PUT",
478
+ body: JSON.stringify({ role: params.role })
479
+ }
480
+ );
481
+ }
482
+ async function removeMember(params) {
483
+ if (!params.organizationId || !params.userId) {
484
+ return {
485
+ error: createError("VALIDATION_ERROR", "organizationId \u3068 userId \u306F\u5FC5\u9808\u3067\u3059")
486
+ };
487
+ }
488
+ return fetchWithAuth(
489
+ `${EXT_MEMBERS_ENDPOINT}/${encodeURIComponent(params.userId)}?${buildQuery(params.organizationId)}`,
490
+ {
491
+ method: "DELETE"
492
+ }
493
+ );
494
+ }
495
+ return { listMembers, updateMemberRole, removeMember };
496
+ }
497
+
435
498
  // src/client/version-check.ts
436
- var SDK_VERSION = "1.14.0";
499
+ var SDK_VERSION = "1.18.0";
437
500
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
438
501
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
439
502
  function sdkHeaders() {
@@ -946,7 +1009,11 @@ function createRedirectMethods(deps) {
946
1009
  resolvedRedirectUri,
947
1010
  logger
948
1011
  } = deps;
949
- async function redirectToAuthorize() {
1012
+ async function redirectToAuthorize(options) {
1013
+ if (typeof window === "undefined") {
1014
+ logger.warn("SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093");
1015
+ return { success: false, error: "SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093" };
1016
+ }
950
1017
  const verifier = generateCodeVerifier();
951
1018
  storeCodeVerifier(verifier, logger);
952
1019
  let challenge;
@@ -967,6 +1034,14 @@ function createRedirectMethods(deps) {
967
1034
  code_challenge: challenge,
968
1035
  code_challenge_method: "S256"
969
1036
  });
1037
+ if (options?.organizationId !== void 0) {
1038
+ const trimmedOrgId = options.organizationId.trim();
1039
+ if (!trimmedOrgId) {
1040
+ logger.error("organizationId \u304C\u7A7A\u6587\u5B57\u3067\u3059");
1041
+ return { success: false, error: "organizationId \u306F\u7A7A\u306B\u3067\u304D\u307E\u305B\u3093" };
1042
+ }
1043
+ params.set("organization_id", trimmedOrgId);
1044
+ }
970
1045
  const authorizeUrl = `${baseUrl}${OAUTH_AUTHORIZE_ENDPOINT}?${params.toString()}`;
971
1046
  logger.debug("Redirecting to authorize:", authorizeUrl);
972
1047
  window.location.href = authorizeUrl;
@@ -1454,7 +1529,7 @@ function createFFIDClient(config) {
1454
1529
  }
1455
1530
  return signOutCookie();
1456
1531
  }
1457
- const { redirectToLogin, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout } = createRedirectMethods({
1532
+ const { redirectToLogin, redirectToAuthorize, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout } = createRedirectMethods({
1458
1533
  authMode,
1459
1534
  baseUrl,
1460
1535
  clientId,
@@ -1481,6 +1556,11 @@ function createFFIDClient(config) {
1481
1556
  fetchWithAuth,
1482
1557
  createError
1483
1558
  });
1559
+ const { listMembers, updateMemberRole, removeMember } = createMembersMethods({
1560
+ fetchWithAuth,
1561
+ createError,
1562
+ serviceCode: config.serviceCode
1563
+ });
1484
1564
  const {
1485
1565
  requestPasswordReset,
1486
1566
  verifyPasswordResetToken,
@@ -1515,6 +1595,7 @@ function createFFIDClient(config) {
1515
1595
  getSession,
1516
1596
  signOut,
1517
1597
  redirectToLogin,
1598
+ redirectToAuthorize,
1518
1599
  redirectToLogout,
1519
1600
  getLoginUrl,
1520
1601
  getLogoutUrl,
@@ -1523,6 +1604,9 @@ function createFFIDClient(config) {
1523
1604
  exchangeCodeForTokens,
1524
1605
  refreshAccessToken,
1525
1606
  checkSubscription,
1607
+ listMembers,
1608
+ updateMemberRole,
1609
+ removeMember,
1526
1610
  createCheckoutSession,
1527
1611
  createPortalSession,
1528
1612
  verifyAccessToken,
@@ -106,6 +106,8 @@ interface FFIDSubscription {
106
106
  status: 'trialing' | 'active' | 'past_due' | 'canceled' | 'paused';
107
107
  /** Current billing period end date */
108
108
  currentPeriodEnd: string | null;
109
+ /** Trial end date (null if not a trial or no trial_end set) */
110
+ trialEnd: string | null;
109
111
  /** Service seat model (available when sourced from OAuth userinfo) */
110
112
  seatModel?: FFIDSeatModel | undefined;
111
113
  /** Member role in the resolved organization context */
@@ -121,6 +123,7 @@ interface FFIDOAuthUserInfoSubscription {
121
123
  seatModel: FFIDSeatModel | null;
122
124
  memberRole: FFIDOAuthUserInfoMemberRole | null;
123
125
  organizationId: string | null;
126
+ hasSeatAssignment: boolean | null;
124
127
  }
125
128
  /** OAuth userinfo response exposed by FFID */
126
129
  interface FFIDOAuthUserInfo {
@@ -128,6 +131,10 @@ interface FFIDOAuthUserInfo {
128
131
  email: string | null;
129
132
  name: string | null;
130
133
  picture: string | null;
134
+ companyName?: string | null | undefined;
135
+ department?: string | null | undefined;
136
+ position?: string | null | undefined;
137
+ phoneNumber?: string | null | undefined;
131
138
  organizationId?: string | null | undefined;
132
139
  subscription?: FFIDOAuthUserInfoSubscription | undefined;
133
140
  }
@@ -301,6 +308,44 @@ interface FFIDCreatePortalParams {
301
308
  /** URL to redirect when user exits the portal */
302
309
  returnUrl: string;
303
310
  }
311
+ /** Member role in an organization */
312
+ type FFIDMemberRole = 'owner' | 'admin' | 'member' | 'viewer';
313
+ /** Member status in an organization */
314
+ type FFIDMemberStatus = 'active' | 'invited' | 'suspended';
315
+ /** Organization member returned by the ext members API */
316
+ interface FFIDOrganizationMember {
317
+ /** User ID (UUID) */
318
+ userId: string;
319
+ /** Email address */
320
+ email: string;
321
+ /** Display name */
322
+ displayName: string | null;
323
+ /** Avatar URL */
324
+ avatarUrl: string | null;
325
+ /** Role in the organization */
326
+ role: FFIDMemberRole;
327
+ /** Membership status */
328
+ status: FFIDMemberStatus;
329
+ /** When the user joined */
330
+ joinedAt: string | null;
331
+ /** When the user was invited */
332
+ invitedAt: string | null;
333
+ /** Last sign-in timestamp */
334
+ lastSignInAt: string | null;
335
+ }
336
+ /** Response from listMembers (ext) */
337
+ interface FFIDListMembersResponse {
338
+ organizationId: string;
339
+ members: FFIDOrganizationMember[];
340
+ }
341
+ /** Response from updateMemberRole (ext) */
342
+ interface FFIDUpdateMemberRoleResponse {
343
+ member: FFIDOrganizationMember;
344
+ }
345
+ /** Response from removeMember (ext) */
346
+ interface FFIDRemoveMemberResponse {
347
+ message: string;
348
+ }
304
349
  /**
305
350
  * Result of a redirect operation (redirectToLogin / redirectToAuthorize / redirectToLogout)
306
351
  *
@@ -351,6 +396,14 @@ type FFIDResetSessionResponse = FFIDPasswordResetResponse;
351
396
  /** Response from confirmPasswordReset */
352
397
  type FFIDPasswordResetConfirmResponse = FFIDPasswordResetResponse;
353
398
 
399
+ /** Redirect and URL generation - redirectToLogin / redirectToAuthorize / redirectToLogout / getLoginUrl / getSignupUrl / getLogoutUrl */
400
+
401
+ /** Options for redirectToAuthorize */
402
+ interface RedirectToAuthorizeOptions {
403
+ /** Target organization ID — triggers org-scoped OAuth re-authorization */
404
+ organizationId?: string;
405
+ }
406
+
354
407
  /**
355
408
  * Token Store
356
409
  *
@@ -397,6 +450,7 @@ declare function createFFIDClient(config: FFIDConfig): {
397
450
  getSession: () => Promise<FFIDApiResponse<FFIDSessionResponse>>;
398
451
  signOut: () => Promise<FFIDApiResponse<void>>;
399
452
  redirectToLogin: () => Promise<FFIDRedirectResult>;
453
+ redirectToAuthorize: (options?: RedirectToAuthorizeOptions) => Promise<FFIDRedirectResult>;
400
454
  redirectToLogout: (postLogoutRedirectUri?: string) => FFIDRedirectResult;
401
455
  getLoginUrl: (redirectUrl?: string) => string;
402
456
  getLogoutUrl: (postLogoutRedirectUri?: string) => string;
@@ -408,6 +462,18 @@ declare function createFFIDClient(config: FFIDConfig): {
408
462
  userId: string;
409
463
  organizationId: string;
410
464
  }) => Promise<FFIDApiResponse<FFIDSubscriptionCheckResponse>>;
465
+ listMembers: (params: {
466
+ organizationId: string;
467
+ }) => Promise<FFIDApiResponse<FFIDListMembersResponse>>;
468
+ updateMemberRole: (params: {
469
+ organizationId: string;
470
+ userId: string;
471
+ role: FFIDMemberRole;
472
+ }) => Promise<FFIDApiResponse<FFIDUpdateMemberRoleResponse>>;
473
+ removeMember: (params: {
474
+ organizationId: string;
475
+ userId: string;
476
+ }) => Promise<FFIDApiResponse<FFIDRemoveMemberResponse>>;
411
477
  createCheckoutSession: (params: FFIDCreateCheckoutParams) => Promise<FFIDApiResponse<FFIDCheckoutSessionResponse>>;
412
478
  createPortalSession: (params: FFIDCreatePortalParams) => Promise<FFIDApiResponse<FFIDPortalSessionResponse>>;
413
479
  verifyAccessToken: (accessToken: string, options?: FFIDVerifyAccessTokenOptions) => Promise<FFIDApiResponse<FFIDOAuthUserInfo>>;
@@ -106,6 +106,8 @@ interface FFIDSubscription {
106
106
  status: 'trialing' | 'active' | 'past_due' | 'canceled' | 'paused';
107
107
  /** Current billing period end date */
108
108
  currentPeriodEnd: string | null;
109
+ /** Trial end date (null if not a trial or no trial_end set) */
110
+ trialEnd: string | null;
109
111
  /** Service seat model (available when sourced from OAuth userinfo) */
110
112
  seatModel?: FFIDSeatModel | undefined;
111
113
  /** Member role in the resolved organization context */
@@ -121,6 +123,7 @@ interface FFIDOAuthUserInfoSubscription {
121
123
  seatModel: FFIDSeatModel | null;
122
124
  memberRole: FFIDOAuthUserInfoMemberRole | null;
123
125
  organizationId: string | null;
126
+ hasSeatAssignment: boolean | null;
124
127
  }
125
128
  /** OAuth userinfo response exposed by FFID */
126
129
  interface FFIDOAuthUserInfo {
@@ -128,6 +131,10 @@ interface FFIDOAuthUserInfo {
128
131
  email: string | null;
129
132
  name: string | null;
130
133
  picture: string | null;
134
+ companyName?: string | null | undefined;
135
+ department?: string | null | undefined;
136
+ position?: string | null | undefined;
137
+ phoneNumber?: string | null | undefined;
131
138
  organizationId?: string | null | undefined;
132
139
  subscription?: FFIDOAuthUserInfoSubscription | undefined;
133
140
  }
@@ -301,6 +308,44 @@ interface FFIDCreatePortalParams {
301
308
  /** URL to redirect when user exits the portal */
302
309
  returnUrl: string;
303
310
  }
311
+ /** Member role in an organization */
312
+ type FFIDMemberRole = 'owner' | 'admin' | 'member' | 'viewer';
313
+ /** Member status in an organization */
314
+ type FFIDMemberStatus = 'active' | 'invited' | 'suspended';
315
+ /** Organization member returned by the ext members API */
316
+ interface FFIDOrganizationMember {
317
+ /** User ID (UUID) */
318
+ userId: string;
319
+ /** Email address */
320
+ email: string;
321
+ /** Display name */
322
+ displayName: string | null;
323
+ /** Avatar URL */
324
+ avatarUrl: string | null;
325
+ /** Role in the organization */
326
+ role: FFIDMemberRole;
327
+ /** Membership status */
328
+ status: FFIDMemberStatus;
329
+ /** When the user joined */
330
+ joinedAt: string | null;
331
+ /** When the user was invited */
332
+ invitedAt: string | null;
333
+ /** Last sign-in timestamp */
334
+ lastSignInAt: string | null;
335
+ }
336
+ /** Response from listMembers (ext) */
337
+ interface FFIDListMembersResponse {
338
+ organizationId: string;
339
+ members: FFIDOrganizationMember[];
340
+ }
341
+ /** Response from updateMemberRole (ext) */
342
+ interface FFIDUpdateMemberRoleResponse {
343
+ member: FFIDOrganizationMember;
344
+ }
345
+ /** Response from removeMember (ext) */
346
+ interface FFIDRemoveMemberResponse {
347
+ message: string;
348
+ }
304
349
  /**
305
350
  * Result of a redirect operation (redirectToLogin / redirectToAuthorize / redirectToLogout)
306
351
  *
@@ -351,6 +396,14 @@ type FFIDResetSessionResponse = FFIDPasswordResetResponse;
351
396
  /** Response from confirmPasswordReset */
352
397
  type FFIDPasswordResetConfirmResponse = FFIDPasswordResetResponse;
353
398
 
399
+ /** Redirect and URL generation - redirectToLogin / redirectToAuthorize / redirectToLogout / getLoginUrl / getSignupUrl / getLogoutUrl */
400
+
401
+ /** Options for redirectToAuthorize */
402
+ interface RedirectToAuthorizeOptions {
403
+ /** Target organization ID — triggers org-scoped OAuth re-authorization */
404
+ organizationId?: string;
405
+ }
406
+
354
407
  /**
355
408
  * Token Store
356
409
  *
@@ -397,6 +450,7 @@ declare function createFFIDClient(config: FFIDConfig): {
397
450
  getSession: () => Promise<FFIDApiResponse<FFIDSessionResponse>>;
398
451
  signOut: () => Promise<FFIDApiResponse<void>>;
399
452
  redirectToLogin: () => Promise<FFIDRedirectResult>;
453
+ redirectToAuthorize: (options?: RedirectToAuthorizeOptions) => Promise<FFIDRedirectResult>;
400
454
  redirectToLogout: (postLogoutRedirectUri?: string) => FFIDRedirectResult;
401
455
  getLoginUrl: (redirectUrl?: string) => string;
402
456
  getLogoutUrl: (postLogoutRedirectUri?: string) => string;
@@ -408,6 +462,18 @@ declare function createFFIDClient(config: FFIDConfig): {
408
462
  userId: string;
409
463
  organizationId: string;
410
464
  }) => Promise<FFIDApiResponse<FFIDSubscriptionCheckResponse>>;
465
+ listMembers: (params: {
466
+ organizationId: string;
467
+ }) => Promise<FFIDApiResponse<FFIDListMembersResponse>>;
468
+ updateMemberRole: (params: {
469
+ organizationId: string;
470
+ userId: string;
471
+ role: FFIDMemberRole;
472
+ }) => Promise<FFIDApiResponse<FFIDUpdateMemberRoleResponse>>;
473
+ removeMember: (params: {
474
+ organizationId: string;
475
+ userId: string;
476
+ }) => Promise<FFIDApiResponse<FFIDRemoveMemberResponse>>;
411
477
  createCheckoutSession: (params: FFIDCreateCheckoutParams) => Promise<FFIDApiResponse<FFIDCheckoutSessionResponse>>;
412
478
  createPortalSession: (params: FFIDCreatePortalParams) => Promise<FFIDApiResponse<FFIDPortalSessionResponse>>;
413
479
  verifyAccessToken: (accessToken: string, options?: FFIDVerifyAccessTokenOptions) => Promise<FFIDApiResponse<FFIDOAuthUserInfo>>;
@@ -108,6 +108,10 @@ function normalizeUserinfo(raw) {
108
108
  email: raw.email,
109
109
  name: raw.name,
110
110
  picture: raw.picture,
111
+ companyName: raw.company_name ?? null,
112
+ department: raw.department ?? null,
113
+ position: raw.position ?? null,
114
+ phoneNumber: raw.phone_number ?? null,
111
115
  organizationId: raw.organization_id ?? null,
112
116
  subscription: raw.subscription ? {
113
117
  subscriptionId: raw.subscription.subscription_id ?? null,
@@ -115,7 +119,8 @@ function normalizeUserinfo(raw) {
115
119
  planCode: raw.subscription.plan_code ?? null,
116
120
  seatModel: raw.subscription.seat_model ?? null,
117
121
  memberRole: raw.subscription.member_role ?? null,
118
- organizationId: raw.subscription.organization_id ?? null
122
+ organizationId: raw.subscription.organization_id ?? null,
123
+ hasSeatAssignment: raw.subscription.has_seat_assignment ?? false
119
124
  } : void 0
120
125
  };
121
126
  }
@@ -133,6 +138,7 @@ function mapUserinfoSubscriptionToSession(userinfo, serviceCode) {
133
138
  planName: subscription.planCode,
134
139
  status: subscription.status,
135
140
  currentPeriodEnd: null,
141
+ trialEnd: null,
136
142
  seatModel: subscription.seatModel ?? void 0,
137
143
  memberRole: subscription.memberRole ?? void 0,
138
144
  organizationId: subscription.organizationId
@@ -340,6 +346,10 @@ function createVerifyAccessToken(deps) {
340
346
  email: introspectResponse.email ?? null,
341
347
  name: introspectResponse.name ?? null,
342
348
  picture: introspectResponse.picture ?? null,
349
+ company_name: introspectResponse.company_name ?? null,
350
+ department: introspectResponse.department ?? null,
351
+ position: introspectResponse.position ?? null,
352
+ phone_number: introspectResponse.phone_number ?? null,
343
353
  organization_id: introspectResponse.organization_id ?? null
344
354
  };
345
355
  const raw = introspectResponse.subscription ? {
@@ -350,7 +360,8 @@ function createVerifyAccessToken(deps) {
350
360
  plan_code: introspectResponse.subscription.plan_code,
351
361
  seat_model: introspectResponse.subscription.seat_model,
352
362
  member_role: introspectResponse.subscription.member_role,
353
- organization_id: introspectResponse.subscription.organization_id
363
+ organization_id: introspectResponse.subscription.organization_id,
364
+ has_seat_assignment: introspectResponse.subscription.has_seat_assignment ?? false
354
365
  }
355
366
  } : base;
356
367
  const userinfo = normalizeUserinfo(raw);
@@ -431,8 +442,60 @@ function createBillingMethods(deps) {
431
442
  return { createCheckoutSession, createPortalSession };
432
443
  }
433
444
 
445
+ // src/client/members-methods.ts
446
+ var EXT_MEMBERS_ENDPOINT = "/api/v1/organizations/ext/members";
447
+ function createMembersMethods(deps) {
448
+ const { fetchWithAuth, createError, serviceCode } = deps;
449
+ function buildQuery(organizationId) {
450
+ return new URLSearchParams({ organizationId, serviceCode }).toString();
451
+ }
452
+ async function listMembers(params) {
453
+ if (!params.organizationId) {
454
+ return {
455
+ error: createError("VALIDATION_ERROR", "organizationId \u306F\u5FC5\u9808\u3067\u3059")
456
+ };
457
+ }
458
+ return fetchWithAuth(
459
+ `${EXT_MEMBERS_ENDPOINT}?${buildQuery(params.organizationId)}`
460
+ );
461
+ }
462
+ async function updateMemberRole(params) {
463
+ if (!params.organizationId || !params.userId) {
464
+ return {
465
+ error: createError("VALIDATION_ERROR", "organizationId \u3068 userId \u306F\u5FC5\u9808\u3067\u3059")
466
+ };
467
+ }
468
+ if (!params.role) {
469
+ return {
470
+ error: createError("VALIDATION_ERROR", "role \u306F\u5FC5\u9808\u3067\u3059")
471
+ };
472
+ }
473
+ return fetchWithAuth(
474
+ `${EXT_MEMBERS_ENDPOINT}/${encodeURIComponent(params.userId)}?${buildQuery(params.organizationId)}`,
475
+ {
476
+ method: "PUT",
477
+ body: JSON.stringify({ role: params.role })
478
+ }
479
+ );
480
+ }
481
+ async function removeMember(params) {
482
+ if (!params.organizationId || !params.userId) {
483
+ return {
484
+ error: createError("VALIDATION_ERROR", "organizationId \u3068 userId \u306F\u5FC5\u9808\u3067\u3059")
485
+ };
486
+ }
487
+ return fetchWithAuth(
488
+ `${EXT_MEMBERS_ENDPOINT}/${encodeURIComponent(params.userId)}?${buildQuery(params.organizationId)}`,
489
+ {
490
+ method: "DELETE"
491
+ }
492
+ );
493
+ }
494
+ return { listMembers, updateMemberRole, removeMember };
495
+ }
496
+
434
497
  // src/client/version-check.ts
435
- var SDK_VERSION = "1.14.0";
498
+ var SDK_VERSION = "1.18.0";
436
499
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
437
500
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
438
501
  function sdkHeaders() {
@@ -945,7 +1008,11 @@ function createRedirectMethods(deps) {
945
1008
  resolvedRedirectUri,
946
1009
  logger
947
1010
  } = deps;
948
- async function redirectToAuthorize() {
1011
+ async function redirectToAuthorize(options) {
1012
+ if (typeof window === "undefined") {
1013
+ logger.warn("SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093");
1014
+ return { success: false, error: "SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093" };
1015
+ }
949
1016
  const verifier = generateCodeVerifier();
950
1017
  storeCodeVerifier(verifier, logger);
951
1018
  let challenge;
@@ -966,6 +1033,14 @@ function createRedirectMethods(deps) {
966
1033
  code_challenge: challenge,
967
1034
  code_challenge_method: "S256"
968
1035
  });
1036
+ if (options?.organizationId !== void 0) {
1037
+ const trimmedOrgId = options.organizationId.trim();
1038
+ if (!trimmedOrgId) {
1039
+ logger.error("organizationId \u304C\u7A7A\u6587\u5B57\u3067\u3059");
1040
+ return { success: false, error: "organizationId \u306F\u7A7A\u306B\u3067\u304D\u307E\u305B\u3093" };
1041
+ }
1042
+ params.set("organization_id", trimmedOrgId);
1043
+ }
969
1044
  const authorizeUrl = `${baseUrl}${OAUTH_AUTHORIZE_ENDPOINT}?${params.toString()}`;
970
1045
  logger.debug("Redirecting to authorize:", authorizeUrl);
971
1046
  window.location.href = authorizeUrl;
@@ -1453,7 +1528,7 @@ function createFFIDClient(config) {
1453
1528
  }
1454
1529
  return signOutCookie();
1455
1530
  }
1456
- const { redirectToLogin, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout } = createRedirectMethods({
1531
+ const { redirectToLogin, redirectToAuthorize, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout } = createRedirectMethods({
1457
1532
  authMode,
1458
1533
  baseUrl,
1459
1534
  clientId,
@@ -1480,6 +1555,11 @@ function createFFIDClient(config) {
1480
1555
  fetchWithAuth,
1481
1556
  createError
1482
1557
  });
1558
+ const { listMembers, updateMemberRole, removeMember } = createMembersMethods({
1559
+ fetchWithAuth,
1560
+ createError,
1561
+ serviceCode: config.serviceCode
1562
+ });
1483
1563
  const {
1484
1564
  requestPasswordReset,
1485
1565
  verifyPasswordResetToken,
@@ -1514,6 +1594,7 @@ function createFFIDClient(config) {
1514
1594
  getSession,
1515
1595
  signOut,
1516
1596
  redirectToLogin,
1597
+ redirectToAuthorize,
1517
1598
  redirectToLogout,
1518
1599
  getLoginUrl,
1519
1600
  getLogoutUrl,
@@ -1522,6 +1603,9 @@ function createFFIDClient(config) {
1522
1603
  exchangeCodeForTokens,
1523
1604
  refreshAccessToken,
1524
1605
  checkSubscription,
1606
+ listMembers,
1607
+ updateMemberRole,
1608
+ removeMember,
1525
1609
  createCheckoutSession,
1526
1610
  createPortalSession,
1527
1611
  verifyAccessToken,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feelflow/ffid-sdk",
3
- "version": "1.14.0",
3
+ "version": "1.18.0",
4
4
  "description": "FeelFlow ID Platform SDK for React/Next.js applications",
5
5
  "keywords": [
6
6
  "feelflow",