@feelflow/ffid-sdk 10.1.0 → 11.0.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 +16 -0
- package/dist/agency/index.d.cts +23 -1
- package/dist/agency/index.d.ts +23 -1
- package/dist/{chunk-ITSQIAO5.js → chunk-QORWLPWG.js} +52 -5
- package/dist/{chunk-VHOIA25Y.cjs → chunk-VR3QR64A.cjs} +52 -5
- package/dist/components/index.cjs +8 -8
- package/dist/components/index.d.cts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +1 -1
- package/dist/{ffid-client-DUbQLYTN.d.ts → ffid-client-By_vcKYu.d.ts} +30 -9
- package/dist/{ffid-client-qcfCWLfs.d.cts → ffid-client-C3A8L9uW.d.cts} +30 -9
- package/dist/{index-CWGoIgYL.d.cts → index-BknVfXhZ.d.cts} +19 -8
- package/dist/{index-CWGoIgYL.d.ts → index-BknVfXhZ.d.ts} +19 -8
- package/dist/index.cjs +91 -91
- package/dist/index.d.cts +21 -3
- package/dist/index.d.ts +21 -3
- package/dist/index.js +2 -2
- package/dist/server/index.cjs +51 -5
- package/dist/server/index.d.cts +2 -2
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +51 -5
- package/dist/server/test/index.d.cts +1 -1
- package/dist/server/test/index.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -481,6 +481,10 @@ await ffid.updateMemberRole({
|
|
|
481
481
|
- `addMember` は既存 FFID ユーザーを active member として追加します。招待メール送信や token 発行は行いません。
|
|
482
482
|
- `role` は `admin` / `member` / `viewer` のみ指定可能です。`owner` は追加・昇格 API では扱いません。
|
|
483
483
|
- agency client と同じ呼び味が必要な場合は `ffid.addMember(organizationId, { email, role })` も使えます。
|
|
484
|
+
- 未登録の人を招待する(招待メールと受諾リンクを FFID が送る)ときは `inviteMember({ organizationId, email, role, inviterUserId })` を使います。`inviterUserId` は、サービスで招待を操作した人の FFID ユーザー ID です。FFID の「保留中の招待」と招待メールに、その人が招待者として出ます。
|
|
485
|
+
- service-key モードでは `inviterUserId` を渡してください。その人が対象の組織の owner / admin でなければ 403 `FORBIDDEN`(`details.reason: 'inviter_not_organization_admin'`)で、招待は作られません。省略すると従来どおり組織の owner が招待者になり、メールの招待者名は `service:<serviceCode>` です。
|
|
486
|
+
- token モードでは省略します(ログイン中の利用者が招待者になります)。別の人の ID を渡すと 400 `VALIDATION_ERROR` です。
|
|
487
|
+
- `inviterUserId` は「誰を招待者として記録するか」の指定で、招待できる範囲は増えません。FFID が確かめるのは「招待できる立場か」までなので、実際に操作した本人の ID だけを渡してください。
|
|
484
488
|
|
|
485
489
|
### Organization profile / public logo wall
|
|
486
490
|
|
|
@@ -950,6 +954,18 @@ SDK の `package.json` で `react` / `react-dom` は `optional: true` に設定
|
|
|
950
954
|
}
|
|
951
955
|
```
|
|
952
956
|
|
|
957
|
+
## サーバー側のアクセストークン検証の照会障害(SDK 11)
|
|
958
|
+
|
|
959
|
+
`verifyAccessToken()` の introspect 照会(JWT検証後の `includeProfile: true` を含む)が
|
|
960
|
+
HTTP429 / 5xx を返す場合は、本文のエラーコードやJSONの可否によらず
|
|
961
|
+
`NETWORK_ERROR` と `details.status` を返します。SDKの診断ログにはHTTPステータスだけを
|
|
962
|
+
記録し、上流本文・アクセストークンをコピーしません。自動再試行は行いません。
|
|
963
|
+
|
|
964
|
+
連携先は、この照会障害を本人の認証不正と区別し、利用は拒否したうえで一時的な利用不可
|
|
965
|
+
(例: HTTP503)として案内してください。HTTP200の `active: false` は引き続き
|
|
966
|
+
`TOKEN_VERIFICATION_ERROR`、HTTP400 / 401 / 403の明示エラーコードは従来どおり保持します。
|
|
967
|
+
このメソッドによる本人確認とは別に、契約の利用可否と本人のactiveな席を確認する必要があります。
|
|
968
|
+
|
|
953
969
|
## E2E テストモード(`@feelflow/ffid-sdk/server/test`)
|
|
954
970
|
|
|
955
971
|
> **⚠️ SECURITY NOTICE** — テストモードは Bearer トークン検証を **意図的にバイパス** する仕組みです。本番環境で誤って有効化すると、登録されたバイパストークンを持つ任意のリクエストが認証通過します。
|
package/dist/agency/index.d.cts
CHANGED
|
@@ -124,6 +124,20 @@ interface FFIDProvisionOrganizationRequest {
|
|
|
124
124
|
slug?: string;
|
|
125
125
|
/** 請求先メールアドレス */
|
|
126
126
|
billingEmail?: string;
|
|
127
|
+
/**
|
|
128
|
+
* 冪等キー(1〜255 文字の表示可能な ASCII。空白不可)。
|
|
129
|
+
*
|
|
130
|
+
* 指定すると、同じ代理店・同じキーの再送(24 時間以内)は**組織を作らずに**
|
|
131
|
+
* 初回の結果を返す。タイムアウトや `PARSE_ERROR` で応答を受け取れなかったときは、
|
|
132
|
+
* **同じキーのまま**再送すれば二重作成にならない。申込番号など、作りたい組織 1 つに
|
|
133
|
+
* 1 つ対応する値を使う。
|
|
134
|
+
*
|
|
135
|
+
* - 同じキーで内容(`name` / `ownerEmail` / `slug` / `billingEmail`)が違うと 422
|
|
136
|
+
* `IDEMPOTENCY_KEY_REUSED`(別の組織を作るなら別のキーを使う)
|
|
137
|
+
* - 省略すると従来どおり毎回作成する
|
|
138
|
+
* - HTTP では `Idempotency-Key` ヘッダーでも渡せる(本文と両方に入れる場合は同じ値)
|
|
139
|
+
*/
|
|
140
|
+
idempotencyKey?: string;
|
|
127
141
|
}
|
|
128
142
|
/** 案内メールの送信結果。組織作成の成否とは独立している。 */
|
|
129
143
|
type FFIDWelcomeEmailOutcome = 'sent' | 'failed';
|
|
@@ -453,9 +467,17 @@ interface FFIDAgencyServerClient {
|
|
|
453
467
|
* そのほか:
|
|
454
468
|
* - スコープ不足 / 代理店が停止中 → `FORBIDDEN`(403)
|
|
455
469
|
* - slug が既存組織と衝突 → `ORGANIZATION_SLUG_CONFLICT`(409、組織は作成されない)
|
|
470
|
+
* - slug が予約語(`admin` / `api` / `login` など)→ `ORGANIZATION_SLUG_RESERVED`
|
|
471
|
+
* (400、組織は作成されない。別の値を指定する)
|
|
472
|
+
* - `ownerEmail` の既存アカウントが停止・削除済み → `OWNER_ACCOUNT_UNAVAILABLE`
|
|
473
|
+
* (422、**組織は作成されない**。別のメールアドレスを指定する)
|
|
456
474
|
* - 認証段階の一時障害 → `SERVICE_UNAVAILABLE`(503、**安全に再試行できる**)
|
|
457
475
|
* - `PARSE_ERROR` / `NETWORK_ERROR` — **組織が作成された可能性がある**。
|
|
458
|
-
*
|
|
476
|
+
* `idempotencyKey` を付けていれば**同じキーで**再送してよい(作成済みなら
|
|
477
|
+
* 初回の結果が返り、組織は増えない。#5165)。付けていない場合は再試行の前に
|
|
478
|
+
* 組織一覧を確認すること
|
|
479
|
+
* - 同じ `idempotencyKey` で内容が違う → `IDEMPOTENCY_KEY_REUSED`(422)
|
|
480
|
+
* - `idempotencyKey` の形式不正 → `INVALID_IDEMPOTENCY_KEY`(400)
|
|
459
481
|
*/
|
|
460
482
|
provisionCustomerOrganization(data: FFIDProvisionOrganizationRequest): Promise<FFIDAgencyServerClientResponse<FFIDProvisionedOrganization>>;
|
|
461
483
|
}
|
package/dist/agency/index.d.ts
CHANGED
|
@@ -124,6 +124,20 @@ interface FFIDProvisionOrganizationRequest {
|
|
|
124
124
|
slug?: string;
|
|
125
125
|
/** 請求先メールアドレス */
|
|
126
126
|
billingEmail?: string;
|
|
127
|
+
/**
|
|
128
|
+
* 冪等キー(1〜255 文字の表示可能な ASCII。空白不可)。
|
|
129
|
+
*
|
|
130
|
+
* 指定すると、同じ代理店・同じキーの再送(24 時間以内)は**組織を作らずに**
|
|
131
|
+
* 初回の結果を返す。タイムアウトや `PARSE_ERROR` で応答を受け取れなかったときは、
|
|
132
|
+
* **同じキーのまま**再送すれば二重作成にならない。申込番号など、作りたい組織 1 つに
|
|
133
|
+
* 1 つ対応する値を使う。
|
|
134
|
+
*
|
|
135
|
+
* - 同じキーで内容(`name` / `ownerEmail` / `slug` / `billingEmail`)が違うと 422
|
|
136
|
+
* `IDEMPOTENCY_KEY_REUSED`(別の組織を作るなら別のキーを使う)
|
|
137
|
+
* - 省略すると従来どおり毎回作成する
|
|
138
|
+
* - HTTP では `Idempotency-Key` ヘッダーでも渡せる(本文と両方に入れる場合は同じ値)
|
|
139
|
+
*/
|
|
140
|
+
idempotencyKey?: string;
|
|
127
141
|
}
|
|
128
142
|
/** 案内メールの送信結果。組織作成の成否とは独立している。 */
|
|
129
143
|
type FFIDWelcomeEmailOutcome = 'sent' | 'failed';
|
|
@@ -453,9 +467,17 @@ interface FFIDAgencyServerClient {
|
|
|
453
467
|
* そのほか:
|
|
454
468
|
* - スコープ不足 / 代理店が停止中 → `FORBIDDEN`(403)
|
|
455
469
|
* - slug が既存組織と衝突 → `ORGANIZATION_SLUG_CONFLICT`(409、組織は作成されない)
|
|
470
|
+
* - slug が予約語(`admin` / `api` / `login` など)→ `ORGANIZATION_SLUG_RESERVED`
|
|
471
|
+
* (400、組織は作成されない。別の値を指定する)
|
|
472
|
+
* - `ownerEmail` の既存アカウントが停止・削除済み → `OWNER_ACCOUNT_UNAVAILABLE`
|
|
473
|
+
* (422、**組織は作成されない**。別のメールアドレスを指定する)
|
|
456
474
|
* - 認証段階の一時障害 → `SERVICE_UNAVAILABLE`(503、**安全に再試行できる**)
|
|
457
475
|
* - `PARSE_ERROR` / `NETWORK_ERROR` — **組織が作成された可能性がある**。
|
|
458
|
-
*
|
|
476
|
+
* `idempotencyKey` を付けていれば**同じキーで**再送してよい(作成済みなら
|
|
477
|
+
* 初回の結果が返り、組織は増えない。#5165)。付けていない場合は再試行の前に
|
|
478
|
+
* 組織一覧を確認すること
|
|
479
|
+
* - 同じ `idempotencyKey` で内容が違う → `IDEMPOTENCY_KEY_REUSED`(422)
|
|
480
|
+
* - `idempotencyKey` の形式不正 → `INVALID_IDEMPOTENCY_KEY`(400)
|
|
459
481
|
*/
|
|
460
482
|
provisionCustomerOrganization(data: FFIDProvisionOrganizationRequest): Promise<FFIDAgencyServerClientResponse<FFIDProvisionedOrganization>>;
|
|
461
483
|
}
|
|
@@ -308,6 +308,9 @@ var OAUTH_INTROSPECT_ENDPOINT = "/api/v1/oauth/introspect";
|
|
|
308
308
|
var CACHE_KEY_PREFIX = "ffid:introspect:";
|
|
309
309
|
var HEX_BASE = 16;
|
|
310
310
|
var HEX_BYTE_WIDTH = 2;
|
|
311
|
+
var HTTP_TOO_MANY_REQUESTS = 429;
|
|
312
|
+
var HTTP_SERVER_ERROR_MIN = 500;
|
|
313
|
+
var HTTP_SERVER_ERROR_LIMIT = 600;
|
|
311
314
|
function createVerifyAccessToken(deps) {
|
|
312
315
|
const { authMode, baseUrl, serviceCode, serviceApiKey, verifyStrategy, logger, createError, errorCodes, cache, timeout } = deps;
|
|
313
316
|
let jwtVerify2 = null;
|
|
@@ -362,6 +365,16 @@ function createVerifyAccessToken(deps) {
|
|
|
362
365
|
}
|
|
363
366
|
return verifyViaIntrospect(accessToken);
|
|
364
367
|
}
|
|
368
|
+
function introspectionUnavailable(status) {
|
|
369
|
+
logger.error("Token introspection unavailable", { status });
|
|
370
|
+
return {
|
|
371
|
+
error: {
|
|
372
|
+
code: errorCodes.NETWORK_ERROR,
|
|
373
|
+
message: `\u30C8\u30FC\u30AF\u30F3\u691C\u8A3C\u30B5\u30FC\u30D3\u30B9\u304C\u4E00\u6642\u7684\u306B\u5229\u7528\u3067\u304D\u307E\u305B\u3093 (status: ${status})`,
|
|
374
|
+
details: { status }
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
}
|
|
365
378
|
async function verifyViaIntrospect(accessToken, cacheKeySuffix) {
|
|
366
379
|
if (!serviceApiKey) {
|
|
367
380
|
return {
|
|
@@ -419,10 +432,12 @@ function createVerifyAccessToken(deps) {
|
|
|
419
432
|
}
|
|
420
433
|
};
|
|
421
434
|
}
|
|
435
|
+
const upstreamUnavailable = response.status === HTTP_TOO_MANY_REQUESTS || response.status >= HTTP_SERVER_ERROR_MIN && response.status < HTTP_SERVER_ERROR_LIMIT;
|
|
422
436
|
let introspectResponse;
|
|
423
437
|
try {
|
|
424
438
|
introspectResponse = await response.json();
|
|
425
439
|
} catch (parseError) {
|
|
440
|
+
if (upstreamUnavailable) return introspectionUnavailable(response.status);
|
|
426
441
|
logger.error("Parse error during token verification:", parseError);
|
|
427
442
|
return {
|
|
428
443
|
error: {
|
|
@@ -431,6 +446,7 @@ function createVerifyAccessToken(deps) {
|
|
|
431
446
|
}
|
|
432
447
|
};
|
|
433
448
|
}
|
|
449
|
+
if (upstreamUnavailable) return introspectionUnavailable(response.status);
|
|
434
450
|
if (!response.ok) {
|
|
435
451
|
const errorBody = introspectResponse;
|
|
436
452
|
return {
|
|
@@ -1374,7 +1390,7 @@ var FFID_ORGANIZATION_PROFILE_ERROR_CODES = {
|
|
|
1374
1390
|
};
|
|
1375
1391
|
|
|
1376
1392
|
// src/client/version-check.ts
|
|
1377
|
-
var SDK_VERSION = "
|
|
1393
|
+
var SDK_VERSION = "11.0.0";
|
|
1378
1394
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
1379
1395
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
1380
1396
|
function sdkHeaders() {
|
|
@@ -1942,7 +1958,7 @@ function createInviteMethods(deps) {
|
|
|
1942
1958
|
}).toString();
|
|
1943
1959
|
return fetchWithAuth(`${EXT_INVITE_ENDPOINT}?${query}`, {
|
|
1944
1960
|
method: "POST",
|
|
1945
|
-
body: JSON.stringify({ email: params.email, role: params.role })
|
|
1961
|
+
body: JSON.stringify({ email: params.email, role: params.role, inviterUserId: params.inviterUserId })
|
|
1946
1962
|
});
|
|
1947
1963
|
}
|
|
1948
1964
|
return { inviteMember };
|
|
@@ -2245,6 +2261,25 @@ function createOAuthTokenMethods(deps) {
|
|
|
2245
2261
|
return { exchangeCodeForTokens, refreshAccessToken, signOutToken };
|
|
2246
2262
|
}
|
|
2247
2263
|
|
|
2264
|
+
// src/client/request-timeout.ts
|
|
2265
|
+
function withRequestTimeout(options, timeout) {
|
|
2266
|
+
if (timeout === void 0 || options.signal?.aborted) return options;
|
|
2267
|
+
const deadline = AbortSignal.timeout(timeout);
|
|
2268
|
+
if (!options.signal) return { ...options, signal: deadline };
|
|
2269
|
+
const callerSignal = options.signal;
|
|
2270
|
+
const controller = new AbortController();
|
|
2271
|
+
const abortFromCaller = () => abort(callerSignal.reason);
|
|
2272
|
+
const abortFromDeadline = () => abort(deadline.reason);
|
|
2273
|
+
function abort(reason) {
|
|
2274
|
+
callerSignal.removeEventListener("abort", abortFromCaller);
|
|
2275
|
+
deadline.removeEventListener("abort", abortFromDeadline);
|
|
2276
|
+
controller.abort(reason);
|
|
2277
|
+
}
|
|
2278
|
+
callerSignal.addEventListener("abort", abortFromCaller, { once: true });
|
|
2279
|
+
deadline.addEventListener("abort", abortFromDeadline, { once: true });
|
|
2280
|
+
return { ...options, signal: controller.signal };
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2248
2283
|
// src/client/session.ts
|
|
2249
2284
|
var SESSION_ENDPOINT = "/api/v1/auth/session";
|
|
2250
2285
|
var LOGOUT_ENDPOINT = "/api/v1/auth/signout";
|
|
@@ -3979,6 +4014,7 @@ function toServiceAccessDecision(response, allowGrace) {
|
|
|
3979
4014
|
const isBlocked = response.isBlocked ?? (effectiveStatus === null || effectiveStatus !== null && BLOCKING_EFFECTIVE_STATUSES.includes(effectiveStatus));
|
|
3980
4015
|
return {
|
|
3981
4016
|
hasAccess,
|
|
4017
|
+
...response.seatAssigned !== void 0 ? { seatAssigned: response.seatAssigned } : {},
|
|
3982
4018
|
effectiveStatus,
|
|
3983
4019
|
isGrace,
|
|
3984
4020
|
isBlocked: isBlocked || !hasAccess,
|
|
@@ -4046,6 +4082,7 @@ var FFID_SUBSCRIPTION_ERROR_CODES = {
|
|
|
4046
4082
|
var FFID_CREDITS_ERROR_CODES = {
|
|
4047
4083
|
CREDITS_INSUFFICIENT: "CREDITS_INSUFFICIENT",
|
|
4048
4084
|
CREDITS_IDEMPOTENCY_CONFLICT: "CREDITS_IDEMPOTENCY_CONFLICT",
|
|
4085
|
+
CREDITS_TURN_CANCELLED: "CREDITS_TURN_CANCELLED",
|
|
4049
4086
|
CREDITS_NOT_APPLICABLE: "CREDITS_NOT_APPLICABLE",
|
|
4050
4087
|
CREDITS_BALANCE_CAP_EXCEEDED: "CREDITS_BALANCE_CAP_EXCEEDED",
|
|
4051
4088
|
SEAT_BILLING_NOT_APPLICABLE: "SEAT_BILLING_NOT_APPLICABLE",
|
|
@@ -4210,9 +4247,10 @@ function createFFIDClient(config) {
|
|
|
4210
4247
|
async function fetchWithAuth(endpoint, options = {}, authOverride) {
|
|
4211
4248
|
const url = `${baseUrl}${endpoint}`;
|
|
4212
4249
|
logger.debug("Fetching:", url);
|
|
4213
|
-
|
|
4250
|
+
let fetchOptions = buildFetchOptions(options, authOverride);
|
|
4214
4251
|
let response;
|
|
4215
4252
|
try {
|
|
4253
|
+
fetchOptions = withRequestTimeout(fetchOptions, timeout);
|
|
4216
4254
|
response = await fetch(url, fetchOptions);
|
|
4217
4255
|
} catch (error) {
|
|
4218
4256
|
logger.error("Network error:", error);
|
|
@@ -4227,9 +4265,9 @@ function createFFIDClient(config) {
|
|
|
4227
4265
|
const refreshResult = await refreshAccessToken();
|
|
4228
4266
|
if (!refreshResult.error) {
|
|
4229
4267
|
logger.debug("Token refreshed, retrying request");
|
|
4230
|
-
const retryOptions = buildFetchOptions(options);
|
|
4231
4268
|
try {
|
|
4232
|
-
|
|
4269
|
+
fetchOptions = withRequestTimeout(buildFetchOptions(options), timeout);
|
|
4270
|
+
response = await fetch(url, fetchOptions);
|
|
4233
4271
|
} catch (retryError) {
|
|
4234
4272
|
logger.error("Network error on retry:", retryError);
|
|
4235
4273
|
return {
|
|
@@ -4248,6 +4286,15 @@ function createFFIDClient(config) {
|
|
|
4248
4286
|
try {
|
|
4249
4287
|
raw = await response.json();
|
|
4250
4288
|
} catch (parseError) {
|
|
4289
|
+
if (fetchOptions.signal?.aborted) {
|
|
4290
|
+
logger.error("Response body aborted:", parseError);
|
|
4291
|
+
return {
|
|
4292
|
+
error: {
|
|
4293
|
+
code: FFID_ERROR_CODES.NETWORK_ERROR,
|
|
4294
|
+
message: "\u30EC\u30B9\u30DD\u30F3\u30B9\u306E\u53D7\u4FE1\u304C\u4E2D\u65AD\u3055\u308C\u307E\u3057\u305F"
|
|
4295
|
+
}
|
|
4296
|
+
};
|
|
4297
|
+
}
|
|
4251
4298
|
logger.error("Parse error:", parseError, "Status:", response.status);
|
|
4252
4299
|
return {
|
|
4253
4300
|
error: {
|
|
@@ -310,6 +310,9 @@ var OAUTH_INTROSPECT_ENDPOINT = "/api/v1/oauth/introspect";
|
|
|
310
310
|
var CACHE_KEY_PREFIX = "ffid:introspect:";
|
|
311
311
|
var HEX_BASE = 16;
|
|
312
312
|
var HEX_BYTE_WIDTH = 2;
|
|
313
|
+
var HTTP_TOO_MANY_REQUESTS = 429;
|
|
314
|
+
var HTTP_SERVER_ERROR_MIN = 500;
|
|
315
|
+
var HTTP_SERVER_ERROR_LIMIT = 600;
|
|
313
316
|
function createVerifyAccessToken(deps) {
|
|
314
317
|
const { authMode, baseUrl, serviceCode, serviceApiKey, verifyStrategy, logger, createError, errorCodes, cache, timeout } = deps;
|
|
315
318
|
let jwtVerify2 = null;
|
|
@@ -364,6 +367,16 @@ function createVerifyAccessToken(deps) {
|
|
|
364
367
|
}
|
|
365
368
|
return verifyViaIntrospect(accessToken);
|
|
366
369
|
}
|
|
370
|
+
function introspectionUnavailable(status) {
|
|
371
|
+
logger.error("Token introspection unavailable", { status });
|
|
372
|
+
return {
|
|
373
|
+
error: {
|
|
374
|
+
code: errorCodes.NETWORK_ERROR,
|
|
375
|
+
message: `\u30C8\u30FC\u30AF\u30F3\u691C\u8A3C\u30B5\u30FC\u30D3\u30B9\u304C\u4E00\u6642\u7684\u306B\u5229\u7528\u3067\u304D\u307E\u305B\u3093 (status: ${status})`,
|
|
376
|
+
details: { status }
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
}
|
|
367
380
|
async function verifyViaIntrospect(accessToken, cacheKeySuffix) {
|
|
368
381
|
if (!serviceApiKey) {
|
|
369
382
|
return {
|
|
@@ -421,10 +434,12 @@ function createVerifyAccessToken(deps) {
|
|
|
421
434
|
}
|
|
422
435
|
};
|
|
423
436
|
}
|
|
437
|
+
const upstreamUnavailable = response.status === HTTP_TOO_MANY_REQUESTS || response.status >= HTTP_SERVER_ERROR_MIN && response.status < HTTP_SERVER_ERROR_LIMIT;
|
|
424
438
|
let introspectResponse;
|
|
425
439
|
try {
|
|
426
440
|
introspectResponse = await response.json();
|
|
427
441
|
} catch (parseError) {
|
|
442
|
+
if (upstreamUnavailable) return introspectionUnavailable(response.status);
|
|
428
443
|
logger.error("Parse error during token verification:", parseError);
|
|
429
444
|
return {
|
|
430
445
|
error: {
|
|
@@ -433,6 +448,7 @@ function createVerifyAccessToken(deps) {
|
|
|
433
448
|
}
|
|
434
449
|
};
|
|
435
450
|
}
|
|
451
|
+
if (upstreamUnavailable) return introspectionUnavailable(response.status);
|
|
436
452
|
if (!response.ok) {
|
|
437
453
|
const errorBody = introspectResponse;
|
|
438
454
|
return {
|
|
@@ -1376,7 +1392,7 @@ var FFID_ORGANIZATION_PROFILE_ERROR_CODES = {
|
|
|
1376
1392
|
};
|
|
1377
1393
|
|
|
1378
1394
|
// src/client/version-check.ts
|
|
1379
|
-
var SDK_VERSION = "
|
|
1395
|
+
var SDK_VERSION = "11.0.0";
|
|
1380
1396
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
1381
1397
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
1382
1398
|
function sdkHeaders() {
|
|
@@ -1944,7 +1960,7 @@ function createInviteMethods(deps) {
|
|
|
1944
1960
|
}).toString();
|
|
1945
1961
|
return fetchWithAuth(`${EXT_INVITE_ENDPOINT}?${query}`, {
|
|
1946
1962
|
method: "POST",
|
|
1947
|
-
body: JSON.stringify({ email: params.email, role: params.role })
|
|
1963
|
+
body: JSON.stringify({ email: params.email, role: params.role, inviterUserId: params.inviterUserId })
|
|
1948
1964
|
});
|
|
1949
1965
|
}
|
|
1950
1966
|
return { inviteMember };
|
|
@@ -2247,6 +2263,25 @@ function createOAuthTokenMethods(deps) {
|
|
|
2247
2263
|
return { exchangeCodeForTokens, refreshAccessToken, signOutToken };
|
|
2248
2264
|
}
|
|
2249
2265
|
|
|
2266
|
+
// src/client/request-timeout.ts
|
|
2267
|
+
function withRequestTimeout(options, timeout) {
|
|
2268
|
+
if (timeout === void 0 || options.signal?.aborted) return options;
|
|
2269
|
+
const deadline = AbortSignal.timeout(timeout);
|
|
2270
|
+
if (!options.signal) return { ...options, signal: deadline };
|
|
2271
|
+
const callerSignal = options.signal;
|
|
2272
|
+
const controller = new AbortController();
|
|
2273
|
+
const abortFromCaller = () => abort(callerSignal.reason);
|
|
2274
|
+
const abortFromDeadline = () => abort(deadline.reason);
|
|
2275
|
+
function abort(reason) {
|
|
2276
|
+
callerSignal.removeEventListener("abort", abortFromCaller);
|
|
2277
|
+
deadline.removeEventListener("abort", abortFromDeadline);
|
|
2278
|
+
controller.abort(reason);
|
|
2279
|
+
}
|
|
2280
|
+
callerSignal.addEventListener("abort", abortFromCaller, { once: true });
|
|
2281
|
+
deadline.addEventListener("abort", abortFromDeadline, { once: true });
|
|
2282
|
+
return { ...options, signal: controller.signal };
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2250
2285
|
// src/client/session.ts
|
|
2251
2286
|
var SESSION_ENDPOINT = "/api/v1/auth/session";
|
|
2252
2287
|
var LOGOUT_ENDPOINT = "/api/v1/auth/signout";
|
|
@@ -3981,6 +4016,7 @@ function toServiceAccessDecision(response, allowGrace) {
|
|
|
3981
4016
|
const isBlocked = response.isBlocked ?? (effectiveStatus === null || effectiveStatus !== null && BLOCKING_EFFECTIVE_STATUSES.includes(effectiveStatus));
|
|
3982
4017
|
return {
|
|
3983
4018
|
hasAccess,
|
|
4019
|
+
...response.seatAssigned !== void 0 ? { seatAssigned: response.seatAssigned } : {},
|
|
3984
4020
|
effectiveStatus,
|
|
3985
4021
|
isGrace,
|
|
3986
4022
|
isBlocked: isBlocked || !hasAccess,
|
|
@@ -4048,6 +4084,7 @@ var FFID_SUBSCRIPTION_ERROR_CODES = {
|
|
|
4048
4084
|
var FFID_CREDITS_ERROR_CODES = {
|
|
4049
4085
|
CREDITS_INSUFFICIENT: "CREDITS_INSUFFICIENT",
|
|
4050
4086
|
CREDITS_IDEMPOTENCY_CONFLICT: "CREDITS_IDEMPOTENCY_CONFLICT",
|
|
4087
|
+
CREDITS_TURN_CANCELLED: "CREDITS_TURN_CANCELLED",
|
|
4051
4088
|
CREDITS_NOT_APPLICABLE: "CREDITS_NOT_APPLICABLE",
|
|
4052
4089
|
CREDITS_BALANCE_CAP_EXCEEDED: "CREDITS_BALANCE_CAP_EXCEEDED",
|
|
4053
4090
|
SEAT_BILLING_NOT_APPLICABLE: "SEAT_BILLING_NOT_APPLICABLE",
|
|
@@ -4212,9 +4249,10 @@ function createFFIDClient(config) {
|
|
|
4212
4249
|
async function fetchWithAuth(endpoint, options = {}, authOverride) {
|
|
4213
4250
|
const url = `${baseUrl}${endpoint}`;
|
|
4214
4251
|
logger.debug("Fetching:", url);
|
|
4215
|
-
|
|
4252
|
+
let fetchOptions = buildFetchOptions(options, authOverride);
|
|
4216
4253
|
let response;
|
|
4217
4254
|
try {
|
|
4255
|
+
fetchOptions = withRequestTimeout(fetchOptions, timeout);
|
|
4218
4256
|
response = await fetch(url, fetchOptions);
|
|
4219
4257
|
} catch (error) {
|
|
4220
4258
|
logger.error("Network error:", error);
|
|
@@ -4229,9 +4267,9 @@ function createFFIDClient(config) {
|
|
|
4229
4267
|
const refreshResult = await refreshAccessToken();
|
|
4230
4268
|
if (!refreshResult.error) {
|
|
4231
4269
|
logger.debug("Token refreshed, retrying request");
|
|
4232
|
-
const retryOptions = buildFetchOptions(options);
|
|
4233
4270
|
try {
|
|
4234
|
-
|
|
4271
|
+
fetchOptions = withRequestTimeout(buildFetchOptions(options), timeout);
|
|
4272
|
+
response = await fetch(url, fetchOptions);
|
|
4235
4273
|
} catch (retryError) {
|
|
4236
4274
|
logger.error("Network error on retry:", retryError);
|
|
4237
4275
|
return {
|
|
@@ -4250,6 +4288,15 @@ function createFFIDClient(config) {
|
|
|
4250
4288
|
try {
|
|
4251
4289
|
raw = await response.json();
|
|
4252
4290
|
} catch (parseError) {
|
|
4291
|
+
if (fetchOptions.signal?.aborted) {
|
|
4292
|
+
logger.error("Response body aborted:", parseError);
|
|
4293
|
+
return {
|
|
4294
|
+
error: {
|
|
4295
|
+
code: FFID_ERROR_CODES.NETWORK_ERROR,
|
|
4296
|
+
message: "\u30EC\u30B9\u30DD\u30F3\u30B9\u306E\u53D7\u4FE1\u304C\u4E2D\u65AD\u3055\u308C\u307E\u3057\u305F"
|
|
4297
|
+
}
|
|
4298
|
+
};
|
|
4299
|
+
}
|
|
4253
4300
|
logger.error("Parse error:", parseError, "Status:", response.status);
|
|
4254
4301
|
return {
|
|
4255
4302
|
error: {
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkVR3QR64A_cjs = require('../chunk-VR3QR64A.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
Object.defineProperty(exports, "FFIDAnnouncementBadge", {
|
|
8
8
|
enumerable: true,
|
|
9
|
-
get: function () { return
|
|
9
|
+
get: function () { return chunkVR3QR64A_cjs.FFIDAnnouncementBadge; }
|
|
10
10
|
});
|
|
11
11
|
Object.defineProperty(exports, "FFIDAnnouncementList", {
|
|
12
12
|
enumerable: true,
|
|
13
|
-
get: function () { return
|
|
13
|
+
get: function () { return chunkVR3QR64A_cjs.FFIDAnnouncementList; }
|
|
14
14
|
});
|
|
15
15
|
Object.defineProperty(exports, "FFIDInquiryForm", {
|
|
16
16
|
enumerable: true,
|
|
17
|
-
get: function () { return
|
|
17
|
+
get: function () { return chunkVR3QR64A_cjs.FFIDInquiryForm; }
|
|
18
18
|
});
|
|
19
19
|
Object.defineProperty(exports, "FFIDLoginButton", {
|
|
20
20
|
enumerable: true,
|
|
21
|
-
get: function () { return
|
|
21
|
+
get: function () { return chunkVR3QR64A_cjs.FFIDLoginButton; }
|
|
22
22
|
});
|
|
23
23
|
Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
|
|
24
24
|
enumerable: true,
|
|
25
|
-
get: function () { return
|
|
25
|
+
get: function () { return chunkVR3QR64A_cjs.FFIDOrganizationSwitcher; }
|
|
26
26
|
});
|
|
27
27
|
Object.defineProperty(exports, "FFIDSubscriptionBadge", {
|
|
28
28
|
enumerable: true,
|
|
29
|
-
get: function () { return
|
|
29
|
+
get: function () { return chunkVR3QR64A_cjs.FFIDSubscriptionBadge; }
|
|
30
30
|
});
|
|
31
31
|
Object.defineProperty(exports, "FFIDUserMenu", {
|
|
32
32
|
enumerable: true,
|
|
33
|
-
get: function () { return
|
|
33
|
+
get: function () { return chunkVR3QR64A_cjs.FFIDUserMenu; }
|
|
34
34
|
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { a8 as FFIDAnnouncementBadge, bk as FFIDAnnouncementBadgeClassNames, bl as FFIDAnnouncementBadgeProps, a9 as FFIDAnnouncementList, bm as FFIDAnnouncementListClassNames, bn as FFIDAnnouncementListProps, ar as FFIDInquiryForm, as as FFIDInquiryFormCategoryItem, at as FFIDInquiryFormClassNames, au as FFIDInquiryFormLegalLayout, av as FFIDInquiryFormOrganization, aw as FFIDInquiryFormPlaceholderContext, ax as FFIDInquiryFormPrefill, ay as FFIDInquiryFormProps, az as FFIDInquiryFormSubmitData, aA as FFIDInquiryFormSubmitResult, aC as FFIDLoginButton, bo as FFIDLoginButtonProps, aE as FFIDOrganizationSwitcher, bp as FFIDOrganizationSwitcherClassNames, bq as FFIDOrganizationSwitcherProps, aS as FFIDSubscriptionBadge, br as FFIDSubscriptionBadgeClassNames, bs as FFIDSubscriptionBadgeProps, aW as FFIDUserMenu, bt as FFIDUserMenuClassNames, bu as FFIDUserMenuProps } from '../index-
|
|
1
|
+
export { a8 as FFIDAnnouncementBadge, bk as FFIDAnnouncementBadgeClassNames, bl as FFIDAnnouncementBadgeProps, a9 as FFIDAnnouncementList, bm as FFIDAnnouncementListClassNames, bn as FFIDAnnouncementListProps, ar as FFIDInquiryForm, as as FFIDInquiryFormCategoryItem, at as FFIDInquiryFormClassNames, au as FFIDInquiryFormLegalLayout, av as FFIDInquiryFormOrganization, aw as FFIDInquiryFormPlaceholderContext, ax as FFIDInquiryFormPrefill, ay as FFIDInquiryFormProps, az as FFIDInquiryFormSubmitData, aA as FFIDInquiryFormSubmitResult, aC as FFIDLoginButton, bo as FFIDLoginButtonProps, aE as FFIDOrganizationSwitcher, bp as FFIDOrganizationSwitcherClassNames, bq as FFIDOrganizationSwitcherProps, aS as FFIDSubscriptionBadge, br as FFIDSubscriptionBadgeClassNames, bs as FFIDSubscriptionBadgeProps, aW as FFIDUserMenu, bt as FFIDUserMenuClassNames, bu as FFIDUserMenuProps } from '../index-BknVfXhZ.cjs';
|
|
2
2
|
import 'react/jsx-runtime';
|
|
3
3
|
import 'react';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { a8 as FFIDAnnouncementBadge, bk as FFIDAnnouncementBadgeClassNames, bl as FFIDAnnouncementBadgeProps, a9 as FFIDAnnouncementList, bm as FFIDAnnouncementListClassNames, bn as FFIDAnnouncementListProps, ar as FFIDInquiryForm, as as FFIDInquiryFormCategoryItem, at as FFIDInquiryFormClassNames, au as FFIDInquiryFormLegalLayout, av as FFIDInquiryFormOrganization, aw as FFIDInquiryFormPlaceholderContext, ax as FFIDInquiryFormPrefill, ay as FFIDInquiryFormProps, az as FFIDInquiryFormSubmitData, aA as FFIDInquiryFormSubmitResult, aC as FFIDLoginButton, bo as FFIDLoginButtonProps, aE as FFIDOrganizationSwitcher, bp as FFIDOrganizationSwitcherClassNames, bq as FFIDOrganizationSwitcherProps, aS as FFIDSubscriptionBadge, br as FFIDSubscriptionBadgeClassNames, bs as FFIDSubscriptionBadgeProps, aW as FFIDUserMenu, bt as FFIDUserMenuClassNames, bu as FFIDUserMenuProps } from '../index-
|
|
1
|
+
export { a8 as FFIDAnnouncementBadge, bk as FFIDAnnouncementBadgeClassNames, bl as FFIDAnnouncementBadgeProps, a9 as FFIDAnnouncementList, bm as FFIDAnnouncementListClassNames, bn as FFIDAnnouncementListProps, ar as FFIDInquiryForm, as as FFIDInquiryFormCategoryItem, at as FFIDInquiryFormClassNames, au as FFIDInquiryFormLegalLayout, av as FFIDInquiryFormOrganization, aw as FFIDInquiryFormPlaceholderContext, ax as FFIDInquiryFormPrefill, ay as FFIDInquiryFormProps, az as FFIDInquiryFormSubmitData, aA as FFIDInquiryFormSubmitResult, aC as FFIDLoginButton, bo as FFIDLoginButtonProps, aE as FFIDOrganizationSwitcher, bp as FFIDOrganizationSwitcherClassNames, bq as FFIDOrganizationSwitcherProps, aS as FFIDSubscriptionBadge, br as FFIDSubscriptionBadgeClassNames, bs as FFIDSubscriptionBadgeProps, aW as FFIDUserMenu, bt as FFIDUserMenuClassNames, bu as FFIDUserMenuProps } from '../index-BknVfXhZ.js';
|
|
2
2
|
import 'react/jsx-runtime';
|
|
3
3
|
import 'react';
|
package/dist/components/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-
|
|
1
|
+
export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-QORWLPWG.js';
|
|
@@ -961,12 +961,19 @@ interface FFIDBuyCreditsUrlParams {
|
|
|
961
961
|
type FFIDSubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'canceled' | 'pending_invoice' | 'paused' | 'incomplete' | 'incomplete_expired' | 'unpaid';
|
|
962
962
|
interface FFIDSubscriptionCheckResponse {
|
|
963
963
|
hasActiveSubscription: boolean;
|
|
964
|
+
/**
|
|
965
|
+
* Active seat for the requested user; null for organization-only checks.
|
|
966
|
+
* Older servers omit this field. User access requires hasAccess AND
|
|
967
|
+
* seatAssigned === true; an omitted/null value is not proof of a seat.
|
|
968
|
+
*/
|
|
969
|
+
seatAssigned?: boolean | null;
|
|
964
970
|
/**
|
|
965
971
|
* Canonical access decision returned by FFID's `/subscriptions/ext/check`.
|
|
966
972
|
*
|
|
967
973
|
* This is the server-side source of truth for service gates. Consumers
|
|
968
974
|
* should not recompute access from `currentPeriodEnd`, `past_due_since`, or
|
|
969
975
|
* local payment timestamps.
|
|
976
|
+
* This is contract access; user access also requires seatAssigned === true.
|
|
970
977
|
*/
|
|
971
978
|
hasAccess?: boolean;
|
|
972
979
|
/** True when `effectiveStatus === 'past_due_grace'`. */
|
|
@@ -996,9 +1003,11 @@ interface FFIDSubscriptionCheckResponse {
|
|
|
996
1003
|
*/
|
|
997
1004
|
pricingModel?: FFIDPricingModel | null;
|
|
998
1005
|
/**
|
|
999
|
-
* Credit balance summary — flat plans only (10.0.0). `null` for per_seat, for
|
|
1000
|
-
*
|
|
1001
|
-
*
|
|
1006
|
+
* Credit balance summary — paid flat plans only (10.0.0). `null` for per_seat, for a
|
|
1007
|
+
* `free` plan (flat on the unified ladder since #6547, but outside credits — consume /
|
|
1008
|
+
* balance return 409 `CREDITS_NOT_APPLICABLE`), for no subscription, **and** when FFID
|
|
1009
|
+
* could not read the ledger, so `null` does not mean "not flat" (use `pricingModel`).
|
|
1010
|
+
* Never affects `hasAccess`.
|
|
1002
1011
|
*/
|
|
1003
1012
|
credits?: FFIDSubscriptionCheckCredits | null;
|
|
1004
1013
|
/**
|
|
@@ -1045,7 +1054,10 @@ interface FFIDServiceAccessError {
|
|
|
1045
1054
|
details?: unknown;
|
|
1046
1055
|
}
|
|
1047
1056
|
interface FFIDServiceAccessDecision {
|
|
1057
|
+
/** Contract access; user access also requires seatAssigned === true. */
|
|
1048
1058
|
hasAccess: boolean;
|
|
1059
|
+
/** User's active seat, passed through when returned. Gate user access with === true. */
|
|
1060
|
+
seatAssigned?: boolean | null;
|
|
1049
1061
|
effectiveStatus: EffectiveSubscriptionStatus | null;
|
|
1050
1062
|
isGrace: boolean;
|
|
1051
1063
|
isBlocked: boolean;
|
|
@@ -1210,9 +1222,18 @@ interface FFIDAddMemberRequest {
|
|
|
1210
1222
|
interface FFIDAddMemberParams extends FFIDAddMemberRequest {
|
|
1211
1223
|
organizationId: string;
|
|
1212
1224
|
}
|
|
1225
|
+
/** Seat assignment outcome after membership creation; membership exists in every case. */
|
|
1226
|
+
type FFIDMemberSeatAssignmentResult = 'assigned' | 'not_applicable' | 'member_limit_reached' | 'failed';
|
|
1213
1227
|
/** Response from addMember (ext) */
|
|
1214
1228
|
interface FFIDAddMemberResponse {
|
|
1215
1229
|
member: FFIDOrganizationMember;
|
|
1230
|
+
/**
|
|
1231
|
+
* Membership creation can succeed even when seat assignment fails.
|
|
1232
|
+
* Omitted by older servers. `not_applicable`/undefined do not prove an active seat.
|
|
1233
|
+
* Check the authenticated user's hasAccess and seatAssigned before granting access;
|
|
1234
|
+
* do not automatically restore a removed seat on a duplicate-member retry.
|
|
1235
|
+
*/
|
|
1236
|
+
seatAssignment?: FFIDMemberSeatAssignmentResult;
|
|
1216
1237
|
}
|
|
1217
1238
|
/** Response from updateMemberRole (ext) */
|
|
1218
1239
|
interface FFIDUpdateMemberRoleResponse {
|
|
@@ -2431,11 +2452,10 @@ interface FFIDConfig {
|
|
|
2431
2452
|
*/
|
|
2432
2453
|
cache?: FFIDCacheConfig | undefined;
|
|
2433
2454
|
/**
|
|
2434
|
-
*
|
|
2435
|
-
* token verification
|
|
2436
|
-
*
|
|
2437
|
-
*
|
|
2438
|
-
* surfaced through the normal error path (e.g. `NETWORK_ERROR`).
|
|
2455
|
+
* Per-HTTP timeout (ms): shared JSON APIs (e.g. checkSubscription/getProfile),
|
|
2456
|
+
* token verification/introspection, token OAuth exchange/refresh/revoke; also FFIDProvider.timeout.
|
|
2457
|
+
* Shared JSON includes body and preserves signals; refresh/retry have separate deadlines.
|
|
2458
|
+
* Excludes token getSession, cookie signOut, public/newsletter/inquiry; not a method deadline.
|
|
2439
2459
|
* @default undefined (no timeout, uses fetch default)
|
|
2440
2460
|
*/
|
|
2441
2461
|
timeout?: number | undefined;
|
|
@@ -2801,6 +2821,7 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
2801
2821
|
organizationId: string;
|
|
2802
2822
|
email: string;
|
|
2803
2823
|
role?: FFIDAssignableMemberRole;
|
|
2824
|
+
inviterUserId?: string;
|
|
2804
2825
|
}) => Promise<FFIDApiResponse<FFIDInviteMemberResponse>>;
|
|
2805
2826
|
leaveOrganization: (params: FFIDLeaveOrganizationParams) => Promise<FFIDApiResponse<FFIDLeaveOrganizationResponse>>;
|
|
2806
2827
|
getAnalyticsConfig: (serviceCode: string, options?: FFIDProfileCallOptions) => Promise<FFIDApiResponse<FFIDAnalyticsConfig>>;
|
|
@@ -2887,4 +2908,4 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
2887
2908
|
/** Type of the FFID client */
|
|
2888
2909
|
type FFIDClient = ReturnType<typeof createFFIDClient>;
|
|
2889
2910
|
|
|
2890
|
-
export { type
|
|
2911
|
+
export { type FFIDProvisionUserResponse as $, type FFIDMemberSeatAssignmentResult as A, type FFIDOrganization as B, type FFIDOrganizationLogoUploadResponse as C, type FFIDOrganizationMember as D, type FFIDOrganizationProfile as E, type FFIDError as F, type FFIDOrganizationProfileErrorCode as G, type FFIDOrganizationProfileResponse as H, type FFIDOtpSendResponse as I, type FFIDOtpVerifyResponse as J, type FFIDPasswordResetConfirmResponse as K, type FFIDPasswordResetResponse as L, type FFIDPasswordResetVerifyResponse as M, type FFIDProfileCallOptions as N, type FFIDProvisionMemberPlan as O, type FFIDProvisionMemberPlanStatus as P, type FFIDProvisionMemberResult as Q, type FFIDProvisionMemberStatus as R, type FFIDProvisionOrganizationDryRun as S, type FFIDProvisionOrganizationMemberInput as T, type FFIDProvisionOrganizationOutcome as U, type FFIDProvisionOrganizationParams as V, type FFIDProvisionOrganizationResponse as W, type FFIDProvisionUserDryRun as X, type FFIDProvisionUserOutcome as Y, type FFIDProvisionUserParams as Z, type FFIDProvisionUserProfileInput as _, type FFIDLogger as a, type FFIDProvisionedOrganization as a0, type FFIDProvisionedUser as a1, type FFIDPublishedPlan as a2, type FFIDRemoveMemberResponse as a3, type FFIDResetSessionResponse as a4, type FFIDSubscription as a5, type FFIDUpdateMemberRoleResponse as a6, type FFIDUpdateUserProfileRequest as a7, type FFIDUploadOrganizationLogoParams as a8, type FFIDUpsertOrganizationProfileParams as a9, type FFIDUpsertOrganizationProfileRequest as aa, type FFIDUser as ab, type FFIDUserProfile as ac, FFID_ALLOWED_ORGANIZATION_LOGO_MIME_TYPES as ad, FFID_CATALOG_ENVIRONMENTS as ae, FFID_CATALOG_PUBLICATION_STATUSES as af, FFID_COMPANY_SIZE_CODES as ag, FFID_INDUSTRY_CODES as ah, FFID_MAX_ORGANIZATION_LOGO_FILE_SIZE_BYTES as ai, FFID_MAX_ORGANIZATION_LOGO_FILE_SIZE_MB as aj, FFID_ORGANIZATION_PROFILE_ERROR_CODES as ak, type TokenData as al, type TokenStore as am, createFFIDClient as an, createTokenStore as ao, type FFIDCacheAdapter as b, type FFIDVerifyAccessTokenOptions as c, type FFIDApiResponse as d, type FFIDOAuthUserInfo as e, type FFIDCatalogEnvironment as f, type FFIDBillingInterval as g, type FFIDTaxBehavior as h, type FFIDPublishedCatalog as i, type FFIDAddMemberParams as j, type FFIDAddMemberRequest as k, type FFIDAddMemberResponse as l, type FFIDAllowedLogoMimeType as m, type FFIDAssignableMemberRole as n, type FFIDCacheConfig as o, type FFIDCatalogPublication as p, type FFIDCatalogPublicationStatus as q, type FFIDClient as r, type FFIDCompanySizeCode as s, type FFIDConfig as t, type FFIDIndustryCode as u, type FFIDListMembersResponse as v, type FFIDListingConsentInput as w, type FFIDLogoWallEntry as x, type FFIDLogoWallResponse as y, type FFIDMemberRole as z };
|