@feelflow/ffid-sdk 4.0.0 → 4.2.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 +31 -0
- package/dist/{chunk-XQL4YSTL.cjs → chunk-U4XDH7TI.cjs} +121 -1
- package/dist/{chunk-P35ULJLM.js → chunk-WI645CPU.js} +121 -1
- 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-ZcJhRbD6.d.ts → ffid-client-CKMGqqPi.d.cts} +90 -10
- package/dist/{ffid-client-ZcJhRbD6.d.cts → ffid-client-CUOFknXy.d.ts} +90 -10
- package/dist/{index-Cn8-3hgb.d.cts → index-DXgTH5vK.d.cts} +87 -11
- package/dist/{index-Cn8-3hgb.d.ts → index-DXgTH5vK.d.ts} +87 -11
- package/dist/index.cjs +32 -32
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +2 -2
- package/dist/server/index.cjs +121 -1
- package/dist/server/index.d.cts +3 -2
- package/dist/server/index.d.ts +3 -2
- package/dist/server/index.js +121 -1
- package/dist/server/test/index.d.cts +2 -1
- package/dist/server/test/index.d.ts +2 -1
- package/dist/types-5g_Bg6Ey.d.cts +37 -0
- package/dist/types-5g_Bg6Ey.d.ts +37 -0
- package/dist/webhooks/index.d.cts +65 -2
- package/dist/webhooks/index.d.ts +65 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -291,6 +291,37 @@ 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
|
+
|
|
294
325
|
### getProfile() / updateProfile()
|
|
295
326
|
|
|
296
327
|
ログイン中ユーザー自身のプロフィールを取得・更新するメソッド(`createFFIDClient` から呼び出し)。
|
|
@@ -808,7 +808,7 @@ function createProfileMethods(deps) {
|
|
|
808
808
|
}
|
|
809
809
|
|
|
810
810
|
// src/client/version-check.ts
|
|
811
|
-
var SDK_VERSION = "4.
|
|
811
|
+
var SDK_VERSION = "4.2.0";
|
|
812
812
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
813
813
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
814
814
|
function sdkHeaders() {
|
|
@@ -2224,6 +2224,73 @@ var FFID_ERROR_CODES = {
|
|
|
2224
2224
|
TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR"
|
|
2225
2225
|
};
|
|
2226
2226
|
var EXT_CHECK_ENDPOINT = "/api/v1/subscriptions/ext/check";
|
|
2227
|
+
var DEFAULT_ALLOW_GRACE = true;
|
|
2228
|
+
var DEFAULT_SERVICE_ACCESS_FAIL_POLICY = "failClosed";
|
|
2229
|
+
var SERVICE_ACCESS_DENIED_CODE = "SERVICE_ACCESS_DENIED";
|
|
2230
|
+
var ACCESS_GRANTING_EFFECTIVE_STATUSES = ["active", "past_due_grace"];
|
|
2231
|
+
var BLOCKING_EFFECTIVE_STATUSES = [
|
|
2232
|
+
"blocked",
|
|
2233
|
+
"canceled",
|
|
2234
|
+
"expired",
|
|
2235
|
+
"trial_expired"
|
|
2236
|
+
];
|
|
2237
|
+
function resolveServiceAccessDenialReason(params, allowGrace) {
|
|
2238
|
+
if (params.hasAccess) {
|
|
2239
|
+
return null;
|
|
2240
|
+
}
|
|
2241
|
+
if (params.effectiveStatus === null) {
|
|
2242
|
+
return "no_subscription";
|
|
2243
|
+
}
|
|
2244
|
+
if (params.isGrace && !allowGrace) {
|
|
2245
|
+
return "grace_disallowed";
|
|
2246
|
+
}
|
|
2247
|
+
if (params.effectiveStatus === "active" || params.effectiveStatus === "past_due_grace") {
|
|
2248
|
+
return "blocked";
|
|
2249
|
+
}
|
|
2250
|
+
return params.effectiveStatus;
|
|
2251
|
+
}
|
|
2252
|
+
function toServiceAccessDecision(response, allowGrace) {
|
|
2253
|
+
const effectiveStatus = response.effectiveStatus ?? null;
|
|
2254
|
+
const serverHasAccess = response.hasAccess ?? (effectiveStatus !== null && ACCESS_GRANTING_EFFECTIVE_STATUSES.includes(effectiveStatus));
|
|
2255
|
+
const isGrace = response.isGrace ?? effectiveStatus === "past_due_grace";
|
|
2256
|
+
const hasAccess = serverHasAccess && (allowGrace || !isGrace);
|
|
2257
|
+
const isBlocked = response.isBlocked ?? (effectiveStatus === null || effectiveStatus !== null && BLOCKING_EFFECTIVE_STATUSES.includes(effectiveStatus));
|
|
2258
|
+
return {
|
|
2259
|
+
hasAccess,
|
|
2260
|
+
effectiveStatus,
|
|
2261
|
+
isGrace,
|
|
2262
|
+
isBlocked: isBlocked || !hasAccess,
|
|
2263
|
+
allowGrace,
|
|
2264
|
+
failPolicy: DEFAULT_SERVICE_ACCESS_FAIL_POLICY,
|
|
2265
|
+
denialReason: resolveServiceAccessDenialReason({ effectiveStatus, hasAccess, isGrace }, allowGrace),
|
|
2266
|
+
organizationId: response.organizationId,
|
|
2267
|
+
subscriptionId: response.subscriptionId,
|
|
2268
|
+
status: response.status,
|
|
2269
|
+
planCode: response.planCode,
|
|
2270
|
+
currentPeriodEnd: response.currentPeriodEnd,
|
|
2271
|
+
gracePeriodEndsAt: response.gracePeriodEndsAt ?? null,
|
|
2272
|
+
reactivatable: response.reactivatable ?? false
|
|
2273
|
+
};
|
|
2274
|
+
}
|
|
2275
|
+
function failClosedServiceAccessDecision(params, error) {
|
|
2276
|
+
return {
|
|
2277
|
+
hasAccess: false,
|
|
2278
|
+
effectiveStatus: null,
|
|
2279
|
+
isGrace: false,
|
|
2280
|
+
isBlocked: true,
|
|
2281
|
+
allowGrace: params.allowGrace ?? DEFAULT_ALLOW_GRACE,
|
|
2282
|
+
failPolicy: DEFAULT_SERVICE_ACCESS_FAIL_POLICY,
|
|
2283
|
+
denialReason: "ffid_unreachable",
|
|
2284
|
+
organizationId: params.organizationId || null,
|
|
2285
|
+
subscriptionId: null,
|
|
2286
|
+
status: null,
|
|
2287
|
+
planCode: null,
|
|
2288
|
+
currentPeriodEnd: null,
|
|
2289
|
+
gracePeriodEndsAt: null,
|
|
2290
|
+
reactivatable: false,
|
|
2291
|
+
error
|
|
2292
|
+
};
|
|
2293
|
+
}
|
|
2227
2294
|
function resolveRedirectUri(raw, logger) {
|
|
2228
2295
|
if (raw === null) return null;
|
|
2229
2296
|
try {
|
|
@@ -2462,6 +2529,57 @@ function createFFIDClient(config) {
|
|
|
2462
2529
|
`${EXT_CHECK_ENDPOINT}?${query.toString()}`
|
|
2463
2530
|
);
|
|
2464
2531
|
}
|
|
2532
|
+
async function checkServiceAccess(params) {
|
|
2533
|
+
const failPolicy = params.failPolicy ?? DEFAULT_SERVICE_ACCESS_FAIL_POLICY;
|
|
2534
|
+
if (failPolicy !== DEFAULT_SERVICE_ACCESS_FAIL_POLICY) {
|
|
2535
|
+
return {
|
|
2536
|
+
error: createError(
|
|
2537
|
+
"VALIDATION_ERROR",
|
|
2538
|
+
`failPolicy \u306F ${DEFAULT_SERVICE_ACCESS_FAIL_POLICY} \u306E\u307F\u6307\u5B9A\u3067\u304D\u307E\u3059`
|
|
2539
|
+
)
|
|
2540
|
+
};
|
|
2541
|
+
}
|
|
2542
|
+
const subscriptionParams = {
|
|
2543
|
+
organizationId: params.organizationId
|
|
2544
|
+
};
|
|
2545
|
+
if (params.userId !== void 0) {
|
|
2546
|
+
subscriptionParams.userId = params.userId;
|
|
2547
|
+
}
|
|
2548
|
+
const subscriptionResult = await checkSubscription(subscriptionParams);
|
|
2549
|
+
if (subscriptionResult.error) {
|
|
2550
|
+
if (subscriptionResult.error.code === "VALIDATION_ERROR") {
|
|
2551
|
+
return { error: subscriptionResult.error };
|
|
2552
|
+
}
|
|
2553
|
+
return {
|
|
2554
|
+
data: failClosedServiceAccessDecision(params, subscriptionResult.error)
|
|
2555
|
+
};
|
|
2556
|
+
}
|
|
2557
|
+
return {
|
|
2558
|
+
data: toServiceAccessDecision(
|
|
2559
|
+
subscriptionResult.data,
|
|
2560
|
+
params.allowGrace ?? DEFAULT_ALLOW_GRACE
|
|
2561
|
+
)
|
|
2562
|
+
};
|
|
2563
|
+
}
|
|
2564
|
+
async function requireServiceAccess(params) {
|
|
2565
|
+
const result = await checkServiceAccess(params);
|
|
2566
|
+
if (result.error) {
|
|
2567
|
+
return result;
|
|
2568
|
+
}
|
|
2569
|
+
if (!result.data.hasAccess) {
|
|
2570
|
+
const error = createError(
|
|
2571
|
+
SERVICE_ACCESS_DENIED_CODE,
|
|
2572
|
+
`FFID service access denied: ${result.data.denialReason ?? "unknown"}`
|
|
2573
|
+
);
|
|
2574
|
+
if (result.data.error) {
|
|
2575
|
+
error.details = { cause: result.data.error };
|
|
2576
|
+
}
|
|
2577
|
+
return {
|
|
2578
|
+
error
|
|
2579
|
+
};
|
|
2580
|
+
}
|
|
2581
|
+
return result;
|
|
2582
|
+
}
|
|
2465
2583
|
const { createCheckoutSession, createPortalSession } = createBillingMethods({
|
|
2466
2584
|
fetchWithAuth,
|
|
2467
2585
|
createError
|
|
@@ -2560,6 +2678,8 @@ function createFFIDClient(config) {
|
|
|
2560
2678
|
exchangeCodeForTokens,
|
|
2561
2679
|
refreshAccessToken,
|
|
2562
2680
|
checkSubscription,
|
|
2681
|
+
checkServiceAccess,
|
|
2682
|
+
requireServiceAccess,
|
|
2563
2683
|
listMembers,
|
|
2564
2684
|
updateMemberRole,
|
|
2565
2685
|
removeMember,
|
|
@@ -806,7 +806,7 @@ function createProfileMethods(deps) {
|
|
|
806
806
|
}
|
|
807
807
|
|
|
808
808
|
// src/client/version-check.ts
|
|
809
|
-
var SDK_VERSION = "4.
|
|
809
|
+
var SDK_VERSION = "4.2.0";
|
|
810
810
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
811
811
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
812
812
|
function sdkHeaders() {
|
|
@@ -2222,6 +2222,73 @@ var FFID_ERROR_CODES = {
|
|
|
2222
2222
|
TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR"
|
|
2223
2223
|
};
|
|
2224
2224
|
var EXT_CHECK_ENDPOINT = "/api/v1/subscriptions/ext/check";
|
|
2225
|
+
var DEFAULT_ALLOW_GRACE = true;
|
|
2226
|
+
var DEFAULT_SERVICE_ACCESS_FAIL_POLICY = "failClosed";
|
|
2227
|
+
var SERVICE_ACCESS_DENIED_CODE = "SERVICE_ACCESS_DENIED";
|
|
2228
|
+
var ACCESS_GRANTING_EFFECTIVE_STATUSES = ["active", "past_due_grace"];
|
|
2229
|
+
var BLOCKING_EFFECTIVE_STATUSES = [
|
|
2230
|
+
"blocked",
|
|
2231
|
+
"canceled",
|
|
2232
|
+
"expired",
|
|
2233
|
+
"trial_expired"
|
|
2234
|
+
];
|
|
2235
|
+
function resolveServiceAccessDenialReason(params, allowGrace) {
|
|
2236
|
+
if (params.hasAccess) {
|
|
2237
|
+
return null;
|
|
2238
|
+
}
|
|
2239
|
+
if (params.effectiveStatus === null) {
|
|
2240
|
+
return "no_subscription";
|
|
2241
|
+
}
|
|
2242
|
+
if (params.isGrace && !allowGrace) {
|
|
2243
|
+
return "grace_disallowed";
|
|
2244
|
+
}
|
|
2245
|
+
if (params.effectiveStatus === "active" || params.effectiveStatus === "past_due_grace") {
|
|
2246
|
+
return "blocked";
|
|
2247
|
+
}
|
|
2248
|
+
return params.effectiveStatus;
|
|
2249
|
+
}
|
|
2250
|
+
function toServiceAccessDecision(response, allowGrace) {
|
|
2251
|
+
const effectiveStatus = response.effectiveStatus ?? null;
|
|
2252
|
+
const serverHasAccess = response.hasAccess ?? (effectiveStatus !== null && ACCESS_GRANTING_EFFECTIVE_STATUSES.includes(effectiveStatus));
|
|
2253
|
+
const isGrace = response.isGrace ?? effectiveStatus === "past_due_grace";
|
|
2254
|
+
const hasAccess = serverHasAccess && (allowGrace || !isGrace);
|
|
2255
|
+
const isBlocked = response.isBlocked ?? (effectiveStatus === null || effectiveStatus !== null && BLOCKING_EFFECTIVE_STATUSES.includes(effectiveStatus));
|
|
2256
|
+
return {
|
|
2257
|
+
hasAccess,
|
|
2258
|
+
effectiveStatus,
|
|
2259
|
+
isGrace,
|
|
2260
|
+
isBlocked: isBlocked || !hasAccess,
|
|
2261
|
+
allowGrace,
|
|
2262
|
+
failPolicy: DEFAULT_SERVICE_ACCESS_FAIL_POLICY,
|
|
2263
|
+
denialReason: resolveServiceAccessDenialReason({ effectiveStatus, hasAccess, isGrace }, allowGrace),
|
|
2264
|
+
organizationId: response.organizationId,
|
|
2265
|
+
subscriptionId: response.subscriptionId,
|
|
2266
|
+
status: response.status,
|
|
2267
|
+
planCode: response.planCode,
|
|
2268
|
+
currentPeriodEnd: response.currentPeriodEnd,
|
|
2269
|
+
gracePeriodEndsAt: response.gracePeriodEndsAt ?? null,
|
|
2270
|
+
reactivatable: response.reactivatable ?? false
|
|
2271
|
+
};
|
|
2272
|
+
}
|
|
2273
|
+
function failClosedServiceAccessDecision(params, error) {
|
|
2274
|
+
return {
|
|
2275
|
+
hasAccess: false,
|
|
2276
|
+
effectiveStatus: null,
|
|
2277
|
+
isGrace: false,
|
|
2278
|
+
isBlocked: true,
|
|
2279
|
+
allowGrace: params.allowGrace ?? DEFAULT_ALLOW_GRACE,
|
|
2280
|
+
failPolicy: DEFAULT_SERVICE_ACCESS_FAIL_POLICY,
|
|
2281
|
+
denialReason: "ffid_unreachable",
|
|
2282
|
+
organizationId: params.organizationId || null,
|
|
2283
|
+
subscriptionId: null,
|
|
2284
|
+
status: null,
|
|
2285
|
+
planCode: null,
|
|
2286
|
+
currentPeriodEnd: null,
|
|
2287
|
+
gracePeriodEndsAt: null,
|
|
2288
|
+
reactivatable: false,
|
|
2289
|
+
error
|
|
2290
|
+
};
|
|
2291
|
+
}
|
|
2225
2292
|
function resolveRedirectUri(raw, logger) {
|
|
2226
2293
|
if (raw === null) return null;
|
|
2227
2294
|
try {
|
|
@@ -2460,6 +2527,57 @@ function createFFIDClient(config) {
|
|
|
2460
2527
|
`${EXT_CHECK_ENDPOINT}?${query.toString()}`
|
|
2461
2528
|
);
|
|
2462
2529
|
}
|
|
2530
|
+
async function checkServiceAccess(params) {
|
|
2531
|
+
const failPolicy = params.failPolicy ?? DEFAULT_SERVICE_ACCESS_FAIL_POLICY;
|
|
2532
|
+
if (failPolicy !== DEFAULT_SERVICE_ACCESS_FAIL_POLICY) {
|
|
2533
|
+
return {
|
|
2534
|
+
error: createError(
|
|
2535
|
+
"VALIDATION_ERROR",
|
|
2536
|
+
`failPolicy \u306F ${DEFAULT_SERVICE_ACCESS_FAIL_POLICY} \u306E\u307F\u6307\u5B9A\u3067\u304D\u307E\u3059`
|
|
2537
|
+
)
|
|
2538
|
+
};
|
|
2539
|
+
}
|
|
2540
|
+
const subscriptionParams = {
|
|
2541
|
+
organizationId: params.organizationId
|
|
2542
|
+
};
|
|
2543
|
+
if (params.userId !== void 0) {
|
|
2544
|
+
subscriptionParams.userId = params.userId;
|
|
2545
|
+
}
|
|
2546
|
+
const subscriptionResult = await checkSubscription(subscriptionParams);
|
|
2547
|
+
if (subscriptionResult.error) {
|
|
2548
|
+
if (subscriptionResult.error.code === "VALIDATION_ERROR") {
|
|
2549
|
+
return { error: subscriptionResult.error };
|
|
2550
|
+
}
|
|
2551
|
+
return {
|
|
2552
|
+
data: failClosedServiceAccessDecision(params, subscriptionResult.error)
|
|
2553
|
+
};
|
|
2554
|
+
}
|
|
2555
|
+
return {
|
|
2556
|
+
data: toServiceAccessDecision(
|
|
2557
|
+
subscriptionResult.data,
|
|
2558
|
+
params.allowGrace ?? DEFAULT_ALLOW_GRACE
|
|
2559
|
+
)
|
|
2560
|
+
};
|
|
2561
|
+
}
|
|
2562
|
+
async function requireServiceAccess(params) {
|
|
2563
|
+
const result = await checkServiceAccess(params);
|
|
2564
|
+
if (result.error) {
|
|
2565
|
+
return result;
|
|
2566
|
+
}
|
|
2567
|
+
if (!result.data.hasAccess) {
|
|
2568
|
+
const error = createError(
|
|
2569
|
+
SERVICE_ACCESS_DENIED_CODE,
|
|
2570
|
+
`FFID service access denied: ${result.data.denialReason ?? "unknown"}`
|
|
2571
|
+
);
|
|
2572
|
+
if (result.data.error) {
|
|
2573
|
+
error.details = { cause: result.data.error };
|
|
2574
|
+
}
|
|
2575
|
+
return {
|
|
2576
|
+
error
|
|
2577
|
+
};
|
|
2578
|
+
}
|
|
2579
|
+
return result;
|
|
2580
|
+
}
|
|
2463
2581
|
const { createCheckoutSession, createPortalSession } = createBillingMethods({
|
|
2464
2582
|
fetchWithAuth,
|
|
2465
2583
|
createError
|
|
@@ -2558,6 +2676,8 @@ function createFFIDClient(config) {
|
|
|
2558
2676
|
exchangeCodeForTokens,
|
|
2559
2677
|
refreshAccessToken,
|
|
2560
2678
|
checkSubscription,
|
|
2679
|
+
checkServiceAccess,
|
|
2680
|
+
requireServiceAccess,
|
|
2561
2681
|
listMembers,
|
|
2562
2682
|
updateMemberRole,
|
|
2563
2683
|
removeMember,
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkU4XDH7TI_cjs = require('../chunk-U4XDH7TI.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 chunkU4XDH7TI_cjs.FFIDAnnouncementBadge; }
|
|
10
10
|
});
|
|
11
11
|
Object.defineProperty(exports, "FFIDAnnouncementList", {
|
|
12
12
|
enumerable: true,
|
|
13
|
-
get: function () { return
|
|
13
|
+
get: function () { return chunkU4XDH7TI_cjs.FFIDAnnouncementList; }
|
|
14
14
|
});
|
|
15
15
|
Object.defineProperty(exports, "FFIDInquiryForm", {
|
|
16
16
|
enumerable: true,
|
|
17
|
-
get: function () { return
|
|
17
|
+
get: function () { return chunkU4XDH7TI_cjs.FFIDInquiryForm; }
|
|
18
18
|
});
|
|
19
19
|
Object.defineProperty(exports, "FFIDLoginButton", {
|
|
20
20
|
enumerable: true,
|
|
21
|
-
get: function () { return
|
|
21
|
+
get: function () { return chunkU4XDH7TI_cjs.FFIDLoginButton; }
|
|
22
22
|
});
|
|
23
23
|
Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
|
|
24
24
|
enumerable: true,
|
|
25
|
-
get: function () { return
|
|
25
|
+
get: function () { return chunkU4XDH7TI_cjs.FFIDOrganizationSwitcher; }
|
|
26
26
|
});
|
|
27
27
|
Object.defineProperty(exports, "FFIDSubscriptionBadge", {
|
|
28
28
|
enumerable: true,
|
|
29
|
-
get: function () { return
|
|
29
|
+
get: function () { return chunkU4XDH7TI_cjs.FFIDSubscriptionBadge; }
|
|
30
30
|
});
|
|
31
31
|
Object.defineProperty(exports, "FFIDUserMenu", {
|
|
32
32
|
enumerable: true,
|
|
33
|
-
get: function () { return
|
|
33
|
+
get: function () { return chunkU4XDH7TI_cjs.FFIDUserMenu; }
|
|
34
34
|
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { P as FFIDAnnouncementBadge, ar as FFIDAnnouncementBadgeClassNames, as as FFIDAnnouncementBadgeProps, Q as FFIDAnnouncementList, at as FFIDAnnouncementListClassNames, au as FFIDAnnouncementListProps, Y as FFIDInquiryForm, Z as FFIDInquiryFormCategoryItem, _ as FFIDInquiryFormClassNames, $ as FFIDInquiryFormLegalLayout, a0 as FFIDInquiryFormOrganization, a1 as FFIDInquiryFormPlaceholderContext, a2 as FFIDInquiryFormPrefill, a3 as FFIDInquiryFormProps, a4 as FFIDInquiryFormSubmitData, a5 as FFIDInquiryFormSubmitResult, a7 as FFIDLoginButton, av as FFIDLoginButtonProps, ad as FFIDOrganizationSwitcher, aw as FFIDOrganizationSwitcherClassNames, ax as FFIDOrganizationSwitcherProps, ai as FFIDSubscriptionBadge, ay as FFIDSubscriptionBadgeClassNames, az as FFIDSubscriptionBadgeProps, ak as FFIDUserMenu, aA as FFIDUserMenuClassNames, aB as FFIDUserMenuProps } from '../index-DXgTH5vK.cjs';
|
|
2
2
|
import 'react/jsx-runtime';
|
|
3
3
|
import 'react';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { P as FFIDAnnouncementBadge, ar as FFIDAnnouncementBadgeClassNames, as as FFIDAnnouncementBadgeProps, Q as FFIDAnnouncementList, at as FFIDAnnouncementListClassNames, au as FFIDAnnouncementListProps, Y as FFIDInquiryForm, Z as FFIDInquiryFormCategoryItem, _ as FFIDInquiryFormClassNames, $ as FFIDInquiryFormLegalLayout, a0 as FFIDInquiryFormOrganization, a1 as FFIDInquiryFormPlaceholderContext, a2 as FFIDInquiryFormPrefill, a3 as FFIDInquiryFormProps, a4 as FFIDInquiryFormSubmitData, a5 as FFIDInquiryFormSubmitResult, a7 as FFIDLoginButton, av as FFIDLoginButtonProps, ad as FFIDOrganizationSwitcher, aw as FFIDOrganizationSwitcherClassNames, ax as FFIDOrganizationSwitcherProps, ai as FFIDSubscriptionBadge, ay as FFIDSubscriptionBadgeClassNames, az as FFIDSubscriptionBadgeProps, ak as FFIDUserMenu, aA as FFIDUserMenuClassNames, aB as FFIDUserMenuProps } from '../index-DXgTH5vK.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-WI645CPU.js';
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { E as EffectiveSubscriptionStatus } from './types-5g_Bg6Ey.cjs';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Inquiry types exposed by the FFID SDK.
|
|
3
5
|
*
|
|
@@ -183,6 +185,91 @@ interface FFIDCacheConfig {
|
|
|
183
185
|
ttl: number;
|
|
184
186
|
}
|
|
185
187
|
|
|
188
|
+
/**
|
|
189
|
+
* Canonical service-access types for subscription lifecycle decisions.
|
|
190
|
+
*/
|
|
191
|
+
|
|
192
|
+
/** Subscription status values matching the FFID platform's SubscriptionStatus type */
|
|
193
|
+
type FFIDSubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'canceled' | 'pending_invoice' | 'paused' | 'incomplete' | 'incomplete_expired' | 'unpaid';
|
|
194
|
+
interface FFIDSubscriptionCheckResponse {
|
|
195
|
+
hasActiveSubscription: boolean;
|
|
196
|
+
/**
|
|
197
|
+
* Canonical access decision returned by FFID's `/subscriptions/ext/check`.
|
|
198
|
+
*
|
|
199
|
+
* This is the server-side source of truth for service gates. Consumers
|
|
200
|
+
* should not recompute access from `currentPeriodEnd`, `past_due_since`, or
|
|
201
|
+
* local payment timestamps.
|
|
202
|
+
*/
|
|
203
|
+
hasAccess?: boolean;
|
|
204
|
+
/** True when `effectiveStatus === 'past_due_grace'`. */
|
|
205
|
+
isGrace?: boolean;
|
|
206
|
+
/** True when FFID's canonical effective status denies service access. */
|
|
207
|
+
isBlocked?: boolean;
|
|
208
|
+
organizationId: string | null;
|
|
209
|
+
subscriptionId: string | null;
|
|
210
|
+
status: FFIDSubscriptionStatus | null;
|
|
211
|
+
planCode: string | null;
|
|
212
|
+
currentPeriodEnd: string | null;
|
|
213
|
+
/**
|
|
214
|
+
* Semantic FFID access-control status. `null` means the organization has no
|
|
215
|
+
* subscription row for this service.
|
|
216
|
+
*/
|
|
217
|
+
effectiveStatus?: EffectiveSubscriptionStatus | null;
|
|
218
|
+
/**
|
|
219
|
+
* ISO timestamp at which `past_due_grace` flips to `blocked`; null outside
|
|
220
|
+
* the grace window.
|
|
221
|
+
*/
|
|
222
|
+
gracePeriodEndsAt?: string | null;
|
|
223
|
+
/** Whether a canceled subscription can be resumed via a re-subscription flow. */
|
|
224
|
+
reactivatable?: boolean;
|
|
225
|
+
}
|
|
226
|
+
type FFIDServiceAccessFailPolicy = 'failClosed';
|
|
227
|
+
type FFIDServiceAccessDenialReason = 'no_subscription' | 'grace_disallowed' | 'blocked' | 'canceled' | 'expired' | 'trial_expired' | 'ffid_unreachable';
|
|
228
|
+
interface FFIDCheckServiceAccessParams {
|
|
229
|
+
userId?: string;
|
|
230
|
+
organizationId: string;
|
|
231
|
+
/**
|
|
232
|
+
* Whether `past_due_grace` should keep access open.
|
|
233
|
+
*
|
|
234
|
+
* @default true
|
|
235
|
+
*/
|
|
236
|
+
allowGrace?: boolean;
|
|
237
|
+
/**
|
|
238
|
+
* Error policy when FFID cannot return a canonical decision.
|
|
239
|
+
*
|
|
240
|
+
* Currently only `failClosed` is supported: network/server/parse failures
|
|
241
|
+
* become `hasAccess=false` decisions with `denialReason='ffid_unreachable'`
|
|
242
|
+
* and the root cause in `decision.error`. Treat `hasAccess` as the gate.
|
|
243
|
+
*/
|
|
244
|
+
failPolicy?: FFIDServiceAccessFailPolicy;
|
|
245
|
+
}
|
|
246
|
+
interface FFIDServiceAccessError {
|
|
247
|
+
code: string;
|
|
248
|
+
message: string;
|
|
249
|
+
details?: unknown;
|
|
250
|
+
}
|
|
251
|
+
interface FFIDServiceAccessDecision {
|
|
252
|
+
hasAccess: boolean;
|
|
253
|
+
effectiveStatus: EffectiveSubscriptionStatus | null;
|
|
254
|
+
isGrace: boolean;
|
|
255
|
+
isBlocked: boolean;
|
|
256
|
+
allowGrace: boolean;
|
|
257
|
+
failPolicy: FFIDServiceAccessFailPolicy;
|
|
258
|
+
denialReason: FFIDServiceAccessDenialReason | null;
|
|
259
|
+
organizationId: string | null;
|
|
260
|
+
subscriptionId: string | null;
|
|
261
|
+
status: FFIDSubscriptionStatus | null;
|
|
262
|
+
planCode: string | null;
|
|
263
|
+
currentPeriodEnd: string | null;
|
|
264
|
+
gracePeriodEndsAt: string | null;
|
|
265
|
+
reactivatable: boolean;
|
|
266
|
+
/**
|
|
267
|
+
* Present when the decision was produced by the SDK fail-closed policy
|
|
268
|
+
* rather than by a successful FFID response.
|
|
269
|
+
*/
|
|
270
|
+
error?: FFIDServiceAccessError;
|
|
271
|
+
}
|
|
272
|
+
|
|
186
273
|
/** Billing interval for subscriptions */
|
|
187
274
|
type FFIDBillingInterval = 'monthly' | 'yearly';
|
|
188
275
|
/**
|
|
@@ -736,16 +823,7 @@ type FFIDApiResponse<T> = {
|
|
|
736
823
|
data?: undefined;
|
|
737
824
|
error: FFIDError;
|
|
738
825
|
};
|
|
739
|
-
|
|
740
|
-
type FFIDSubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'canceled' | 'pending_invoice' | 'paused' | 'incomplete' | 'incomplete_expired' | 'unpaid';
|
|
741
|
-
interface FFIDSubscriptionCheckResponse {
|
|
742
|
-
hasActiveSubscription: boolean;
|
|
743
|
-
organizationId: string | null;
|
|
744
|
-
subscriptionId: string | null;
|
|
745
|
-
status: FFIDSubscriptionStatus | null;
|
|
746
|
-
planCode: string | null;
|
|
747
|
-
currentPeriodEnd: string | null;
|
|
748
|
-
}
|
|
826
|
+
|
|
749
827
|
/**
|
|
750
828
|
* Checkout session response from billing checkout endpoint
|
|
751
829
|
*/
|
|
@@ -1140,6 +1218,8 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
1140
1218
|
userId?: string;
|
|
1141
1219
|
organizationId: string;
|
|
1142
1220
|
}) => Promise<FFIDApiResponse<FFIDSubscriptionCheckResponse>>;
|
|
1221
|
+
checkServiceAccess: (params: FFIDCheckServiceAccessParams) => Promise<FFIDApiResponse<FFIDServiceAccessDecision>>;
|
|
1222
|
+
requireServiceAccess: (params: FFIDCheckServiceAccessParams) => Promise<FFIDApiResponse<FFIDServiceAccessDecision>>;
|
|
1143
1223
|
listMembers: (params: {
|
|
1144
1224
|
organizationId: string;
|
|
1145
1225
|
}) => Promise<FFIDApiResponse<FFIDListMembersResponse>>;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { E as EffectiveSubscriptionStatus } from './types-5g_Bg6Ey.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Inquiry types exposed by the FFID SDK.
|
|
3
5
|
*
|
|
@@ -183,6 +185,91 @@ interface FFIDCacheConfig {
|
|
|
183
185
|
ttl: number;
|
|
184
186
|
}
|
|
185
187
|
|
|
188
|
+
/**
|
|
189
|
+
* Canonical service-access types for subscription lifecycle decisions.
|
|
190
|
+
*/
|
|
191
|
+
|
|
192
|
+
/** Subscription status values matching the FFID platform's SubscriptionStatus type */
|
|
193
|
+
type FFIDSubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'canceled' | 'pending_invoice' | 'paused' | 'incomplete' | 'incomplete_expired' | 'unpaid';
|
|
194
|
+
interface FFIDSubscriptionCheckResponse {
|
|
195
|
+
hasActiveSubscription: boolean;
|
|
196
|
+
/**
|
|
197
|
+
* Canonical access decision returned by FFID's `/subscriptions/ext/check`.
|
|
198
|
+
*
|
|
199
|
+
* This is the server-side source of truth for service gates. Consumers
|
|
200
|
+
* should not recompute access from `currentPeriodEnd`, `past_due_since`, or
|
|
201
|
+
* local payment timestamps.
|
|
202
|
+
*/
|
|
203
|
+
hasAccess?: boolean;
|
|
204
|
+
/** True when `effectiveStatus === 'past_due_grace'`. */
|
|
205
|
+
isGrace?: boolean;
|
|
206
|
+
/** True when FFID's canonical effective status denies service access. */
|
|
207
|
+
isBlocked?: boolean;
|
|
208
|
+
organizationId: string | null;
|
|
209
|
+
subscriptionId: string | null;
|
|
210
|
+
status: FFIDSubscriptionStatus | null;
|
|
211
|
+
planCode: string | null;
|
|
212
|
+
currentPeriodEnd: string | null;
|
|
213
|
+
/**
|
|
214
|
+
* Semantic FFID access-control status. `null` means the organization has no
|
|
215
|
+
* subscription row for this service.
|
|
216
|
+
*/
|
|
217
|
+
effectiveStatus?: EffectiveSubscriptionStatus | null;
|
|
218
|
+
/**
|
|
219
|
+
* ISO timestamp at which `past_due_grace` flips to `blocked`; null outside
|
|
220
|
+
* the grace window.
|
|
221
|
+
*/
|
|
222
|
+
gracePeriodEndsAt?: string | null;
|
|
223
|
+
/** Whether a canceled subscription can be resumed via a re-subscription flow. */
|
|
224
|
+
reactivatable?: boolean;
|
|
225
|
+
}
|
|
226
|
+
type FFIDServiceAccessFailPolicy = 'failClosed';
|
|
227
|
+
type FFIDServiceAccessDenialReason = 'no_subscription' | 'grace_disallowed' | 'blocked' | 'canceled' | 'expired' | 'trial_expired' | 'ffid_unreachable';
|
|
228
|
+
interface FFIDCheckServiceAccessParams {
|
|
229
|
+
userId?: string;
|
|
230
|
+
organizationId: string;
|
|
231
|
+
/**
|
|
232
|
+
* Whether `past_due_grace` should keep access open.
|
|
233
|
+
*
|
|
234
|
+
* @default true
|
|
235
|
+
*/
|
|
236
|
+
allowGrace?: boolean;
|
|
237
|
+
/**
|
|
238
|
+
* Error policy when FFID cannot return a canonical decision.
|
|
239
|
+
*
|
|
240
|
+
* Currently only `failClosed` is supported: network/server/parse failures
|
|
241
|
+
* become `hasAccess=false` decisions with `denialReason='ffid_unreachable'`
|
|
242
|
+
* and the root cause in `decision.error`. Treat `hasAccess` as the gate.
|
|
243
|
+
*/
|
|
244
|
+
failPolicy?: FFIDServiceAccessFailPolicy;
|
|
245
|
+
}
|
|
246
|
+
interface FFIDServiceAccessError {
|
|
247
|
+
code: string;
|
|
248
|
+
message: string;
|
|
249
|
+
details?: unknown;
|
|
250
|
+
}
|
|
251
|
+
interface FFIDServiceAccessDecision {
|
|
252
|
+
hasAccess: boolean;
|
|
253
|
+
effectiveStatus: EffectiveSubscriptionStatus | null;
|
|
254
|
+
isGrace: boolean;
|
|
255
|
+
isBlocked: boolean;
|
|
256
|
+
allowGrace: boolean;
|
|
257
|
+
failPolicy: FFIDServiceAccessFailPolicy;
|
|
258
|
+
denialReason: FFIDServiceAccessDenialReason | null;
|
|
259
|
+
organizationId: string | null;
|
|
260
|
+
subscriptionId: string | null;
|
|
261
|
+
status: FFIDSubscriptionStatus | null;
|
|
262
|
+
planCode: string | null;
|
|
263
|
+
currentPeriodEnd: string | null;
|
|
264
|
+
gracePeriodEndsAt: string | null;
|
|
265
|
+
reactivatable: boolean;
|
|
266
|
+
/**
|
|
267
|
+
* Present when the decision was produced by the SDK fail-closed policy
|
|
268
|
+
* rather than by a successful FFID response.
|
|
269
|
+
*/
|
|
270
|
+
error?: FFIDServiceAccessError;
|
|
271
|
+
}
|
|
272
|
+
|
|
186
273
|
/** Billing interval for subscriptions */
|
|
187
274
|
type FFIDBillingInterval = 'monthly' | 'yearly';
|
|
188
275
|
/**
|
|
@@ -736,16 +823,7 @@ type FFIDApiResponse<T> = {
|
|
|
736
823
|
data?: undefined;
|
|
737
824
|
error: FFIDError;
|
|
738
825
|
};
|
|
739
|
-
|
|
740
|
-
type FFIDSubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'canceled' | 'pending_invoice' | 'paused' | 'incomplete' | 'incomplete_expired' | 'unpaid';
|
|
741
|
-
interface FFIDSubscriptionCheckResponse {
|
|
742
|
-
hasActiveSubscription: boolean;
|
|
743
|
-
organizationId: string | null;
|
|
744
|
-
subscriptionId: string | null;
|
|
745
|
-
status: FFIDSubscriptionStatus | null;
|
|
746
|
-
planCode: string | null;
|
|
747
|
-
currentPeriodEnd: string | null;
|
|
748
|
-
}
|
|
826
|
+
|
|
749
827
|
/**
|
|
750
828
|
* Checkout session response from billing checkout endpoint
|
|
751
829
|
*/
|
|
@@ -1140,6 +1218,8 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
1140
1218
|
userId?: string;
|
|
1141
1219
|
organizationId: string;
|
|
1142
1220
|
}) => Promise<FFIDApiResponse<FFIDSubscriptionCheckResponse>>;
|
|
1221
|
+
checkServiceAccess: (params: FFIDCheckServiceAccessParams) => Promise<FFIDApiResponse<FFIDServiceAccessDecision>>;
|
|
1222
|
+
requireServiceAccess: (params: FFIDCheckServiceAccessParams) => Promise<FFIDApiResponse<FFIDServiceAccessDecision>>;
|
|
1143
1223
|
listMembers: (params: {
|
|
1144
1224
|
organizationId: string;
|
|
1145
1225
|
}) => Promise<FFIDApiResponse<FFIDListMembersResponse>>;
|