@feelflow/ffid-sdk 4.1.0 → 4.3.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
@@ -291,6 +291,72 @@ export default function Layout({ children }: { children: React.ReactNode }) {
291
291
 
292
292
  **詳細な実装レシピ**(middleware、Express、UI 分岐、Webhook 受信、fixture API を使ったテスト、`EffectiveSubscriptionStatus` 別の UI 推奨動作まで) → [docs/03-implementation/EXPIRED_CONTRACT_HANDLING.md](https://github.com/feel-flow/feelflow-id-platform/blob/develop/docs/03-implementation/EXPIRED_CONTRACT_HANDLING.md)
293
293
 
294
+ ### Server-side service access decision
295
+
296
+ API route / middleware では `checkServiceAccess()` を使う。FFID の `/api/v1/subscriptions/ext/check` が返す canonical decision をそのまま受け取り、外部サービス側で `past_due_since + 7d`、`current_period_end + 7d`、`payment_failed_at + 7d` のような lifecycle date math を再実装しない。
297
+
298
+ ```ts
299
+ import { createFFIDClient } from '@feelflow/ffid-sdk'
300
+
301
+ const ffid = createFFIDClient({
302
+ serviceCode: 'flow-board-ai',
303
+ scope: '',
304
+ authMode: 'service-key',
305
+ serviceApiKey: process.env.FFID_SERVICE_API_KEY!,
306
+ })
307
+
308
+ const { data: access, error } = await ffid.checkServiceAccess({
309
+ userId,
310
+ organizationId,
311
+ allowGrace: true,
312
+ })
313
+
314
+ if (error || !access?.hasAccess) {
315
+ return Response.redirect('/contract-required')
316
+ }
317
+ ```
318
+
319
+ - `checkServiceAccess()` は **`data.hasAccess` が唯一の gate**。`result.error` は入力 validation など SDK が decision を作れない場合にだけ返る。
320
+ - `hasAccess`: FFID が決めた canonical access decision。`allowGrace=false` のときだけ SDK 側で `past_due_grace` を deny に変換する。
321
+ - `effectiveStatus`: `active` / `past_due_grace` / `blocked` / `canceled` / `trial_expired` / `expired`。
322
+ - `gracePeriodEndsAt`: `past_due_grace` が `blocked` に変わる時刻。表示・警告用であり、アクセス判定の source of truth にしない。
323
+ - `failPolicy`: 現在は `failClosed` 固定。FFID に到達できない、または canonical decision を取得できない場合は `result.error` ではなく `data.hasAccess=false` / `denialReason='ffid_unreachable'` / `data.error` を返す。呼び出し側は `result.error` だけで通過判定しない。
324
+
325
+ ### Organization member management
326
+
327
+ `organization:read` / `organization:write` scope を持つ service-key または token で、組織メンバーの参照・追加・ロール変更・削除ができます。
328
+
329
+ ```ts
330
+ import { createFFIDClient } from '@feelflow/ffid-sdk/server'
331
+
332
+ const ffid = createFFIDClient({
333
+ serviceCode: 'flow-board-ai',
334
+ scope: '',
335
+ authMode: 'service-key',
336
+ serviceApiKey: process.env.FFID_SERVICE_API_KEY!,
337
+ })
338
+
339
+ const addResult = await ffid.addMember({
340
+ organizationId,
341
+ email: 'new-member@example.com',
342
+ role: 'member',
343
+ })
344
+
345
+ if (addResult.error) {
346
+ throw new Error(addResult.error.message)
347
+ }
348
+
349
+ await ffid.updateMemberRole({
350
+ organizationId,
351
+ userId: addResult.data.member.userId,
352
+ role: 'admin',
353
+ })
354
+ ```
355
+
356
+ - `addMember` は既存 FFID ユーザーを active member として追加します。招待メール送信や token 発行は行いません。
357
+ - `role` は `admin` / `member` / `viewer` のみ指定可能です。`owner` は追加・昇格 API では扱いません。
358
+ - agency client と同じ呼び味が必要な場合は `ffid.addMember(organizationId, { email, role })` も使えます。
359
+
294
360
  ### getProfile() / updateProfile()
295
361
 
296
362
  ログイン中ユーザー自身のプロフィールを取得・更新するメソッド(`createFFIDClient` から呼び出し)。
@@ -708,6 +708,7 @@ function createSubscriptionMethods(deps) {
708
708
  var EXT_MEMBERS_ENDPOINT = "/api/v1/organizations/ext/members";
709
709
  function createMembersMethods(deps) {
710
710
  const { fetchWithAuth, createError, serviceCode } = deps;
711
+ const assignableRoles = /* @__PURE__ */ new Set(["admin", "member", "viewer"]);
711
712
  function buildQuery(organizationId) {
712
713
  return new URLSearchParams({ organizationId, serviceCode }).toString();
713
714
  }
@@ -721,6 +722,37 @@ function createMembersMethods(deps) {
721
722
  `${EXT_MEMBERS_ENDPOINT}?${buildQuery(params.organizationId)}`
722
723
  );
723
724
  }
725
+ function normalizeAddMemberArgs(paramsOrOrganizationId, data) {
726
+ if (typeof paramsOrOrganizationId === "string") {
727
+ const params = {
728
+ organizationId: paramsOrOrganizationId,
729
+ email: data?.email ?? ""
730
+ };
731
+ if (data?.role !== void 0) params.role = data.role;
732
+ return params;
733
+ }
734
+ return paramsOrOrganizationId;
735
+ }
736
+ async function addMember(paramsOrOrganizationId, data) {
737
+ const params = normalizeAddMemberArgs(paramsOrOrganizationId, data);
738
+ if (!params.organizationId || !params.email) {
739
+ return {
740
+ error: createError("VALIDATION_ERROR", "organizationId \u3068 email \u306F\u5FC5\u9808\u3067\u3059")
741
+ };
742
+ }
743
+ if (params.role !== void 0 && !assignableRoles.has(params.role)) {
744
+ return {
745
+ error: createError("VALIDATION_ERROR", "role \u306F admin\u3001member\u3001viewer \u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044")
746
+ };
747
+ }
748
+ return fetchWithAuth(
749
+ `${EXT_MEMBERS_ENDPOINT}?${buildQuery(params.organizationId)}`,
750
+ {
751
+ method: "POST",
752
+ body: JSON.stringify({ email: params.email, role: params.role })
753
+ }
754
+ );
755
+ }
724
756
  async function updateMemberRole(params) {
725
757
  if (!params.organizationId || !params.userId) {
726
758
  return {
@@ -753,7 +785,7 @@ function createMembersMethods(deps) {
753
785
  }
754
786
  );
755
787
  }
756
- return { listMembers, updateMemberRole, removeMember };
788
+ return { listMembers, addMember, updateMemberRole, removeMember };
757
789
  }
758
790
 
759
791
  // src/client/profile-methods.ts
@@ -806,7 +838,7 @@ function createProfileMethods(deps) {
806
838
  }
807
839
 
808
840
  // src/client/version-check.ts
809
- var SDK_VERSION = "4.1.0";
841
+ var SDK_VERSION = "4.3.0";
810
842
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
811
843
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
812
844
  function sdkHeaders() {
@@ -2222,6 +2254,73 @@ var FFID_ERROR_CODES = {
2222
2254
  TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR"
2223
2255
  };
2224
2256
  var EXT_CHECK_ENDPOINT = "/api/v1/subscriptions/ext/check";
2257
+ var DEFAULT_ALLOW_GRACE = true;
2258
+ var DEFAULT_SERVICE_ACCESS_FAIL_POLICY = "failClosed";
2259
+ var SERVICE_ACCESS_DENIED_CODE = "SERVICE_ACCESS_DENIED";
2260
+ var ACCESS_GRANTING_EFFECTIVE_STATUSES = ["active", "past_due_grace"];
2261
+ var BLOCKING_EFFECTIVE_STATUSES = [
2262
+ "blocked",
2263
+ "canceled",
2264
+ "expired",
2265
+ "trial_expired"
2266
+ ];
2267
+ function resolveServiceAccessDenialReason(params, allowGrace) {
2268
+ if (params.hasAccess) {
2269
+ return null;
2270
+ }
2271
+ if (params.effectiveStatus === null) {
2272
+ return "no_subscription";
2273
+ }
2274
+ if (params.isGrace && !allowGrace) {
2275
+ return "grace_disallowed";
2276
+ }
2277
+ if (params.effectiveStatus === "active" || params.effectiveStatus === "past_due_grace") {
2278
+ return "blocked";
2279
+ }
2280
+ return params.effectiveStatus;
2281
+ }
2282
+ function toServiceAccessDecision(response, allowGrace) {
2283
+ const effectiveStatus = response.effectiveStatus ?? null;
2284
+ const serverHasAccess = response.hasAccess ?? (effectiveStatus !== null && ACCESS_GRANTING_EFFECTIVE_STATUSES.includes(effectiveStatus));
2285
+ const isGrace = response.isGrace ?? effectiveStatus === "past_due_grace";
2286
+ const hasAccess = serverHasAccess && (allowGrace || !isGrace);
2287
+ const isBlocked = response.isBlocked ?? (effectiveStatus === null || effectiveStatus !== null && BLOCKING_EFFECTIVE_STATUSES.includes(effectiveStatus));
2288
+ return {
2289
+ hasAccess,
2290
+ effectiveStatus,
2291
+ isGrace,
2292
+ isBlocked: isBlocked || !hasAccess,
2293
+ allowGrace,
2294
+ failPolicy: DEFAULT_SERVICE_ACCESS_FAIL_POLICY,
2295
+ denialReason: resolveServiceAccessDenialReason({ effectiveStatus, hasAccess, isGrace }, allowGrace),
2296
+ organizationId: response.organizationId,
2297
+ subscriptionId: response.subscriptionId,
2298
+ status: response.status,
2299
+ planCode: response.planCode,
2300
+ currentPeriodEnd: response.currentPeriodEnd,
2301
+ gracePeriodEndsAt: response.gracePeriodEndsAt ?? null,
2302
+ reactivatable: response.reactivatable ?? false
2303
+ };
2304
+ }
2305
+ function failClosedServiceAccessDecision(params, error) {
2306
+ return {
2307
+ hasAccess: false,
2308
+ effectiveStatus: null,
2309
+ isGrace: false,
2310
+ isBlocked: true,
2311
+ allowGrace: params.allowGrace ?? DEFAULT_ALLOW_GRACE,
2312
+ failPolicy: DEFAULT_SERVICE_ACCESS_FAIL_POLICY,
2313
+ denialReason: "ffid_unreachable",
2314
+ organizationId: params.organizationId || null,
2315
+ subscriptionId: null,
2316
+ status: null,
2317
+ planCode: null,
2318
+ currentPeriodEnd: null,
2319
+ gracePeriodEndsAt: null,
2320
+ reactivatable: false,
2321
+ error
2322
+ };
2323
+ }
2225
2324
  function resolveRedirectUri(raw, logger) {
2226
2325
  if (raw === null) return null;
2227
2326
  try {
@@ -2460,6 +2559,57 @@ function createFFIDClient(config) {
2460
2559
  `${EXT_CHECK_ENDPOINT}?${query.toString()}`
2461
2560
  );
2462
2561
  }
2562
+ async function checkServiceAccess(params) {
2563
+ const failPolicy = params.failPolicy ?? DEFAULT_SERVICE_ACCESS_FAIL_POLICY;
2564
+ if (failPolicy !== DEFAULT_SERVICE_ACCESS_FAIL_POLICY) {
2565
+ return {
2566
+ error: createError(
2567
+ "VALIDATION_ERROR",
2568
+ `failPolicy \u306F ${DEFAULT_SERVICE_ACCESS_FAIL_POLICY} \u306E\u307F\u6307\u5B9A\u3067\u304D\u307E\u3059`
2569
+ )
2570
+ };
2571
+ }
2572
+ const subscriptionParams = {
2573
+ organizationId: params.organizationId
2574
+ };
2575
+ if (params.userId !== void 0) {
2576
+ subscriptionParams.userId = params.userId;
2577
+ }
2578
+ const subscriptionResult = await checkSubscription(subscriptionParams);
2579
+ if (subscriptionResult.error) {
2580
+ if (subscriptionResult.error.code === "VALIDATION_ERROR") {
2581
+ return { error: subscriptionResult.error };
2582
+ }
2583
+ return {
2584
+ data: failClosedServiceAccessDecision(params, subscriptionResult.error)
2585
+ };
2586
+ }
2587
+ return {
2588
+ data: toServiceAccessDecision(
2589
+ subscriptionResult.data,
2590
+ params.allowGrace ?? DEFAULT_ALLOW_GRACE
2591
+ )
2592
+ };
2593
+ }
2594
+ async function requireServiceAccess(params) {
2595
+ const result = await checkServiceAccess(params);
2596
+ if (result.error) {
2597
+ return result;
2598
+ }
2599
+ if (!result.data.hasAccess) {
2600
+ const error = createError(
2601
+ SERVICE_ACCESS_DENIED_CODE,
2602
+ `FFID service access denied: ${result.data.denialReason ?? "unknown"}`
2603
+ );
2604
+ if (result.data.error) {
2605
+ error.details = { cause: result.data.error };
2606
+ }
2607
+ return {
2608
+ error
2609
+ };
2610
+ }
2611
+ return result;
2612
+ }
2463
2613
  const { createCheckoutSession, createPortalSession } = createBillingMethods({
2464
2614
  fetchWithAuth,
2465
2615
  createError
@@ -2477,7 +2627,7 @@ function createFFIDClient(config) {
2477
2627
  fetchWithAuth,
2478
2628
  createError
2479
2629
  });
2480
- const { listMembers, updateMemberRole, removeMember } = createMembersMethods({
2630
+ const { listMembers, addMember, updateMemberRole, removeMember } = createMembersMethods({
2481
2631
  fetchWithAuth,
2482
2632
  createError,
2483
2633
  serviceCode: config.serviceCode
@@ -2558,7 +2708,10 @@ function createFFIDClient(config) {
2558
2708
  exchangeCodeForTokens,
2559
2709
  refreshAccessToken,
2560
2710
  checkSubscription,
2711
+ checkServiceAccess,
2712
+ requireServiceAccess,
2561
2713
  listMembers,
2714
+ addMember,
2562
2715
  updateMemberRole,
2563
2716
  removeMember,
2564
2717
  getProfile,
@@ -710,6 +710,7 @@ function createSubscriptionMethods(deps) {
710
710
  var EXT_MEMBERS_ENDPOINT = "/api/v1/organizations/ext/members";
711
711
  function createMembersMethods(deps) {
712
712
  const { fetchWithAuth, createError, serviceCode } = deps;
713
+ const assignableRoles = /* @__PURE__ */ new Set(["admin", "member", "viewer"]);
713
714
  function buildQuery(organizationId) {
714
715
  return new URLSearchParams({ organizationId, serviceCode }).toString();
715
716
  }
@@ -723,6 +724,37 @@ function createMembersMethods(deps) {
723
724
  `${EXT_MEMBERS_ENDPOINT}?${buildQuery(params.organizationId)}`
724
725
  );
725
726
  }
727
+ function normalizeAddMemberArgs(paramsOrOrganizationId, data) {
728
+ if (typeof paramsOrOrganizationId === "string") {
729
+ const params = {
730
+ organizationId: paramsOrOrganizationId,
731
+ email: data?.email ?? ""
732
+ };
733
+ if (data?.role !== void 0) params.role = data.role;
734
+ return params;
735
+ }
736
+ return paramsOrOrganizationId;
737
+ }
738
+ async function addMember(paramsOrOrganizationId, data) {
739
+ const params = normalizeAddMemberArgs(paramsOrOrganizationId, data);
740
+ if (!params.organizationId || !params.email) {
741
+ return {
742
+ error: createError("VALIDATION_ERROR", "organizationId \u3068 email \u306F\u5FC5\u9808\u3067\u3059")
743
+ };
744
+ }
745
+ if (params.role !== void 0 && !assignableRoles.has(params.role)) {
746
+ return {
747
+ error: createError("VALIDATION_ERROR", "role \u306F admin\u3001member\u3001viewer \u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044")
748
+ };
749
+ }
750
+ return fetchWithAuth(
751
+ `${EXT_MEMBERS_ENDPOINT}?${buildQuery(params.organizationId)}`,
752
+ {
753
+ method: "POST",
754
+ body: JSON.stringify({ email: params.email, role: params.role })
755
+ }
756
+ );
757
+ }
726
758
  async function updateMemberRole(params) {
727
759
  if (!params.organizationId || !params.userId) {
728
760
  return {
@@ -755,7 +787,7 @@ function createMembersMethods(deps) {
755
787
  }
756
788
  );
757
789
  }
758
- return { listMembers, updateMemberRole, removeMember };
790
+ return { listMembers, addMember, updateMemberRole, removeMember };
759
791
  }
760
792
 
761
793
  // src/client/profile-methods.ts
@@ -808,7 +840,7 @@ function createProfileMethods(deps) {
808
840
  }
809
841
 
810
842
  // src/client/version-check.ts
811
- var SDK_VERSION = "4.1.0";
843
+ var SDK_VERSION = "4.3.0";
812
844
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
813
845
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
814
846
  function sdkHeaders() {
@@ -2224,6 +2256,73 @@ var FFID_ERROR_CODES = {
2224
2256
  TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR"
2225
2257
  };
2226
2258
  var EXT_CHECK_ENDPOINT = "/api/v1/subscriptions/ext/check";
2259
+ var DEFAULT_ALLOW_GRACE = true;
2260
+ var DEFAULT_SERVICE_ACCESS_FAIL_POLICY = "failClosed";
2261
+ var SERVICE_ACCESS_DENIED_CODE = "SERVICE_ACCESS_DENIED";
2262
+ var ACCESS_GRANTING_EFFECTIVE_STATUSES = ["active", "past_due_grace"];
2263
+ var BLOCKING_EFFECTIVE_STATUSES = [
2264
+ "blocked",
2265
+ "canceled",
2266
+ "expired",
2267
+ "trial_expired"
2268
+ ];
2269
+ function resolveServiceAccessDenialReason(params, allowGrace) {
2270
+ if (params.hasAccess) {
2271
+ return null;
2272
+ }
2273
+ if (params.effectiveStatus === null) {
2274
+ return "no_subscription";
2275
+ }
2276
+ if (params.isGrace && !allowGrace) {
2277
+ return "grace_disallowed";
2278
+ }
2279
+ if (params.effectiveStatus === "active" || params.effectiveStatus === "past_due_grace") {
2280
+ return "blocked";
2281
+ }
2282
+ return params.effectiveStatus;
2283
+ }
2284
+ function toServiceAccessDecision(response, allowGrace) {
2285
+ const effectiveStatus = response.effectiveStatus ?? null;
2286
+ const serverHasAccess = response.hasAccess ?? (effectiveStatus !== null && ACCESS_GRANTING_EFFECTIVE_STATUSES.includes(effectiveStatus));
2287
+ const isGrace = response.isGrace ?? effectiveStatus === "past_due_grace";
2288
+ const hasAccess = serverHasAccess && (allowGrace || !isGrace);
2289
+ const isBlocked = response.isBlocked ?? (effectiveStatus === null || effectiveStatus !== null && BLOCKING_EFFECTIVE_STATUSES.includes(effectiveStatus));
2290
+ return {
2291
+ hasAccess,
2292
+ effectiveStatus,
2293
+ isGrace,
2294
+ isBlocked: isBlocked || !hasAccess,
2295
+ allowGrace,
2296
+ failPolicy: DEFAULT_SERVICE_ACCESS_FAIL_POLICY,
2297
+ denialReason: resolveServiceAccessDenialReason({ effectiveStatus, hasAccess, isGrace }, allowGrace),
2298
+ organizationId: response.organizationId,
2299
+ subscriptionId: response.subscriptionId,
2300
+ status: response.status,
2301
+ planCode: response.planCode,
2302
+ currentPeriodEnd: response.currentPeriodEnd,
2303
+ gracePeriodEndsAt: response.gracePeriodEndsAt ?? null,
2304
+ reactivatable: response.reactivatable ?? false
2305
+ };
2306
+ }
2307
+ function failClosedServiceAccessDecision(params, error) {
2308
+ return {
2309
+ hasAccess: false,
2310
+ effectiveStatus: null,
2311
+ isGrace: false,
2312
+ isBlocked: true,
2313
+ allowGrace: params.allowGrace ?? DEFAULT_ALLOW_GRACE,
2314
+ failPolicy: DEFAULT_SERVICE_ACCESS_FAIL_POLICY,
2315
+ denialReason: "ffid_unreachable",
2316
+ organizationId: params.organizationId || null,
2317
+ subscriptionId: null,
2318
+ status: null,
2319
+ planCode: null,
2320
+ currentPeriodEnd: null,
2321
+ gracePeriodEndsAt: null,
2322
+ reactivatable: false,
2323
+ error
2324
+ };
2325
+ }
2227
2326
  function resolveRedirectUri(raw, logger) {
2228
2327
  if (raw === null) return null;
2229
2328
  try {
@@ -2462,6 +2561,57 @@ function createFFIDClient(config) {
2462
2561
  `${EXT_CHECK_ENDPOINT}?${query.toString()}`
2463
2562
  );
2464
2563
  }
2564
+ async function checkServiceAccess(params) {
2565
+ const failPolicy = params.failPolicy ?? DEFAULT_SERVICE_ACCESS_FAIL_POLICY;
2566
+ if (failPolicy !== DEFAULT_SERVICE_ACCESS_FAIL_POLICY) {
2567
+ return {
2568
+ error: createError(
2569
+ "VALIDATION_ERROR",
2570
+ `failPolicy \u306F ${DEFAULT_SERVICE_ACCESS_FAIL_POLICY} \u306E\u307F\u6307\u5B9A\u3067\u304D\u307E\u3059`
2571
+ )
2572
+ };
2573
+ }
2574
+ const subscriptionParams = {
2575
+ organizationId: params.organizationId
2576
+ };
2577
+ if (params.userId !== void 0) {
2578
+ subscriptionParams.userId = params.userId;
2579
+ }
2580
+ const subscriptionResult = await checkSubscription(subscriptionParams);
2581
+ if (subscriptionResult.error) {
2582
+ if (subscriptionResult.error.code === "VALIDATION_ERROR") {
2583
+ return { error: subscriptionResult.error };
2584
+ }
2585
+ return {
2586
+ data: failClosedServiceAccessDecision(params, subscriptionResult.error)
2587
+ };
2588
+ }
2589
+ return {
2590
+ data: toServiceAccessDecision(
2591
+ subscriptionResult.data,
2592
+ params.allowGrace ?? DEFAULT_ALLOW_GRACE
2593
+ )
2594
+ };
2595
+ }
2596
+ async function requireServiceAccess(params) {
2597
+ const result = await checkServiceAccess(params);
2598
+ if (result.error) {
2599
+ return result;
2600
+ }
2601
+ if (!result.data.hasAccess) {
2602
+ const error = createError(
2603
+ SERVICE_ACCESS_DENIED_CODE,
2604
+ `FFID service access denied: ${result.data.denialReason ?? "unknown"}`
2605
+ );
2606
+ if (result.data.error) {
2607
+ error.details = { cause: result.data.error };
2608
+ }
2609
+ return {
2610
+ error
2611
+ };
2612
+ }
2613
+ return result;
2614
+ }
2465
2615
  const { createCheckoutSession, createPortalSession } = createBillingMethods({
2466
2616
  fetchWithAuth,
2467
2617
  createError
@@ -2479,7 +2629,7 @@ function createFFIDClient(config) {
2479
2629
  fetchWithAuth,
2480
2630
  createError
2481
2631
  });
2482
- const { listMembers, updateMemberRole, removeMember } = createMembersMethods({
2632
+ const { listMembers, addMember, updateMemberRole, removeMember } = createMembersMethods({
2483
2633
  fetchWithAuth,
2484
2634
  createError,
2485
2635
  serviceCode: config.serviceCode
@@ -2560,7 +2710,10 @@ function createFFIDClient(config) {
2560
2710
  exchangeCodeForTokens,
2561
2711
  refreshAccessToken,
2562
2712
  checkSubscription,
2713
+ checkServiceAccess,
2714
+ requireServiceAccess,
2563
2715
  listMembers,
2716
+ addMember,
2564
2717
  updateMemberRole,
2565
2718
  removeMember,
2566
2719
  getProfile,
@@ -1,34 +1,34 @@
1
1
  'use strict';
2
2
 
3
- var chunkOYCNHBMG_cjs = require('../chunk-OYCNHBMG.cjs');
3
+ var chunk5MO7G2JW_cjs = require('../chunk-5MO7G2JW.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "FFIDAnnouncementBadge", {
8
8
  enumerable: true,
9
- get: function () { return chunkOYCNHBMG_cjs.FFIDAnnouncementBadge; }
9
+ get: function () { return chunk5MO7G2JW_cjs.FFIDAnnouncementBadge; }
10
10
  });
11
11
  Object.defineProperty(exports, "FFIDAnnouncementList", {
12
12
  enumerable: true,
13
- get: function () { return chunkOYCNHBMG_cjs.FFIDAnnouncementList; }
13
+ get: function () { return chunk5MO7G2JW_cjs.FFIDAnnouncementList; }
14
14
  });
15
15
  Object.defineProperty(exports, "FFIDInquiryForm", {
16
16
  enumerable: true,
17
- get: function () { return chunkOYCNHBMG_cjs.FFIDInquiryForm; }
17
+ get: function () { return chunk5MO7G2JW_cjs.FFIDInquiryForm; }
18
18
  });
19
19
  Object.defineProperty(exports, "FFIDLoginButton", {
20
20
  enumerable: true,
21
- get: function () { return chunkOYCNHBMG_cjs.FFIDLoginButton; }
21
+ get: function () { return chunk5MO7G2JW_cjs.FFIDLoginButton; }
22
22
  });
23
23
  Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
24
24
  enumerable: true,
25
- get: function () { return chunkOYCNHBMG_cjs.FFIDOrganizationSwitcher; }
25
+ get: function () { return chunk5MO7G2JW_cjs.FFIDOrganizationSwitcher; }
26
26
  });
27
27
  Object.defineProperty(exports, "FFIDSubscriptionBadge", {
28
28
  enumerable: true,
29
- get: function () { return chunkOYCNHBMG_cjs.FFIDSubscriptionBadge; }
29
+ get: function () { return chunk5MO7G2JW_cjs.FFIDSubscriptionBadge; }
30
30
  });
31
31
  Object.defineProperty(exports, "FFIDUserMenu", {
32
32
  enumerable: true,
33
- get: function () { return chunkOYCNHBMG_cjs.FFIDUserMenu; }
33
+ get: function () { return chunk5MO7G2JW_cjs.FFIDUserMenu; }
34
34
  });
@@ -1,3 +1,3 @@
1
- export { N as FFIDAnnouncementBadge, an as FFIDAnnouncementBadgeClassNames, ao as FFIDAnnouncementBadgeProps, O as FFIDAnnouncementList, ap as FFIDAnnouncementListClassNames, aq as FFIDAnnouncementListProps, W as FFIDInquiryForm, X as FFIDInquiryFormCategoryItem, Y as FFIDInquiryFormClassNames, Z as FFIDInquiryFormLegalLayout, _ as FFIDInquiryFormOrganization, $ as FFIDInquiryFormPlaceholderContext, a0 as FFIDInquiryFormPrefill, a1 as FFIDInquiryFormProps, a2 as FFIDInquiryFormSubmitData, a3 as FFIDInquiryFormSubmitResult, a5 as FFIDLoginButton, ar as FFIDLoginButtonProps, ab as FFIDOrganizationSwitcher, as as FFIDOrganizationSwitcherClassNames, at as FFIDOrganizationSwitcherProps, ae as FFIDSubscriptionBadge, au as FFIDSubscriptionBadgeClassNames, av as FFIDSubscriptionBadgeProps, ag as FFIDUserMenu, aw as FFIDUserMenuClassNames, ax as FFIDUserMenuProps } from '../index-Cn8-3hgb.cjs';
1
+ export { S as FFIDAnnouncementBadge, av as FFIDAnnouncementBadgeClassNames, aw as FFIDAnnouncementBadgeProps, T as FFIDAnnouncementList, ax as FFIDAnnouncementListClassNames, ay as FFIDAnnouncementListProps, a0 as FFIDInquiryForm, a1 as FFIDInquiryFormCategoryItem, a2 as FFIDInquiryFormClassNames, a3 as FFIDInquiryFormLegalLayout, a4 as FFIDInquiryFormOrganization, a5 as FFIDInquiryFormPlaceholderContext, a6 as FFIDInquiryFormPrefill, a7 as FFIDInquiryFormProps, a8 as FFIDInquiryFormSubmitData, a9 as FFIDInquiryFormSubmitResult, ab as FFIDLoginButton, az as FFIDLoginButtonProps, ah as FFIDOrganizationSwitcher, aA as FFIDOrganizationSwitcherClassNames, aB as FFIDOrganizationSwitcherProps, am as FFIDSubscriptionBadge, aC as FFIDSubscriptionBadgeClassNames, aD as FFIDSubscriptionBadgeProps, ao as FFIDUserMenu, aE as FFIDUserMenuClassNames, aF as FFIDUserMenuProps } from '../index-CInGR4I9.cjs';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1,3 +1,3 @@
1
- export { N as FFIDAnnouncementBadge, an as FFIDAnnouncementBadgeClassNames, ao as FFIDAnnouncementBadgeProps, O as FFIDAnnouncementList, ap as FFIDAnnouncementListClassNames, aq as FFIDAnnouncementListProps, W as FFIDInquiryForm, X as FFIDInquiryFormCategoryItem, Y as FFIDInquiryFormClassNames, Z as FFIDInquiryFormLegalLayout, _ as FFIDInquiryFormOrganization, $ as FFIDInquiryFormPlaceholderContext, a0 as FFIDInquiryFormPrefill, a1 as FFIDInquiryFormProps, a2 as FFIDInquiryFormSubmitData, a3 as FFIDInquiryFormSubmitResult, a5 as FFIDLoginButton, ar as FFIDLoginButtonProps, ab as FFIDOrganizationSwitcher, as as FFIDOrganizationSwitcherClassNames, at as FFIDOrganizationSwitcherProps, ae as FFIDSubscriptionBadge, au as FFIDSubscriptionBadgeClassNames, av as FFIDSubscriptionBadgeProps, ag as FFIDUserMenu, aw as FFIDUserMenuClassNames, ax as FFIDUserMenuProps } from '../index-Cn8-3hgb.js';
1
+ export { S as FFIDAnnouncementBadge, av as FFIDAnnouncementBadgeClassNames, aw as FFIDAnnouncementBadgeProps, T as FFIDAnnouncementList, ax as FFIDAnnouncementListClassNames, ay as FFIDAnnouncementListProps, a0 as FFIDInquiryForm, a1 as FFIDInquiryFormCategoryItem, a2 as FFIDInquiryFormClassNames, a3 as FFIDInquiryFormLegalLayout, a4 as FFIDInquiryFormOrganization, a5 as FFIDInquiryFormPlaceholderContext, a6 as FFIDInquiryFormPrefill, a7 as FFIDInquiryFormProps, a8 as FFIDInquiryFormSubmitData, a9 as FFIDInquiryFormSubmitResult, ab as FFIDLoginButton, az as FFIDLoginButtonProps, ah as FFIDOrganizationSwitcher, aA as FFIDOrganizationSwitcherClassNames, aB as FFIDOrganizationSwitcherProps, am as FFIDSubscriptionBadge, aC as FFIDSubscriptionBadgeClassNames, aD as FFIDSubscriptionBadgeProps, ao as FFIDUserMenu, aE as FFIDUserMenuClassNames, aF as FFIDUserMenuProps } from '../index-CInGR4I9.js';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1 +1 @@
1
- export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-P7HSNT4U.js';
1
+ export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-35UOD62N.js';