@feelflow/ffid-sdk 2.11.0 → 2.12.1
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/dist/{chunk-BEHDXUB2.cjs → chunk-DJPOGNAO.cjs} +185 -5
- package/dist/{chunk-2OAFWUEL.js → chunk-MDBV4WY3.js} +184 -6
- package/dist/components/index.cjs +8 -8
- package/dist/components/index.js +1 -1
- package/dist/index.cjs +32 -24
- package/dist/index.d.cts +89 -1
- package/dist/index.d.ts +89 -1
- package/dist/index.js +2 -2
- package/dist/server/index.cjs +183 -5
- package/dist/server/index.d.cts +57 -0
- package/dist/server/index.d.ts +57 -0
- package/dist/server/index.js +183 -5
- package/package.json +1 -1
|
@@ -457,9 +457,118 @@ function createBillingMethods(deps) {
|
|
|
457
457
|
var EXT_PLANS_ENDPOINT = "/api/v1/subscriptions/ext/plans";
|
|
458
458
|
var EXT_SUBSCRIPTION_ENDPOINT = "/api/v1/subscriptions/ext";
|
|
459
459
|
var EXT_SUBSCRIBE_ENDPOINT = "/api/v1/subscriptions/ext/subscribe";
|
|
460
|
+
var FFIDSDKError = class extends Error {
|
|
461
|
+
code;
|
|
462
|
+
constructor(code, message) {
|
|
463
|
+
super(message);
|
|
464
|
+
this.name = "FFIDSDKError";
|
|
465
|
+
this.code = code;
|
|
466
|
+
}
|
|
467
|
+
};
|
|
460
468
|
function isBlankString(value) {
|
|
461
469
|
return typeof value !== "string" || value.trim() === "";
|
|
462
470
|
}
|
|
471
|
+
var MALFORMED_PREVIEW_CODE = "MALFORMED_PLAN_CHANGE_PREVIEW";
|
|
472
|
+
var MALFORMED_SEAT_PREVIEW_CODE = "MALFORMED_SEAT_CHANGE_PREVIEW";
|
|
473
|
+
var SEAT_ESTIMATE_REASONS = /* @__PURE__ */ new Set(["no_stripe_data", "custom_pricing", "stripe_error"]);
|
|
474
|
+
function validatePlanChangePreview(preview) {
|
|
475
|
+
if (preview === null || typeof preview !== "object") {
|
|
476
|
+
throw new FFIDSDKError(
|
|
477
|
+
MALFORMED_PREVIEW_CODE,
|
|
478
|
+
"SDK: server returned malformed PlanChangePreview \u2014 expected object, got " + (preview === null ? "null" : typeof preview)
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
const p = preview;
|
|
482
|
+
const flag = p.willApplyAtPeriodEnd;
|
|
483
|
+
if (typeof flag !== "boolean") {
|
|
484
|
+
throw new FFIDSDKError(
|
|
485
|
+
MALFORMED_PREVIEW_CODE,
|
|
486
|
+
`SDK: server returned malformed PlanChangePreview \u2014 willApplyAtPeriodEnd must be boolean (got ${typeof flag})`
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
const { proratedAmount, effectiveDate } = p;
|
|
490
|
+
if (flag === true) {
|
|
491
|
+
if (proratedAmount !== 0) {
|
|
492
|
+
throw new FFIDSDKError(
|
|
493
|
+
MALFORMED_PREVIEW_CODE,
|
|
494
|
+
`SDK: server returned malformed PlanChangePreview \u2014 willApplyAtPeriodEnd=true requires proratedAmount=0 (got ${JSON.stringify(proratedAmount)})`
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
if (effectiveDate !== null && typeof effectiveDate !== "string") {
|
|
498
|
+
throw new FFIDSDKError(
|
|
499
|
+
MALFORMED_PREVIEW_CODE,
|
|
500
|
+
`SDK: server returned malformed PlanChangePreview \u2014 willApplyAtPeriodEnd=true requires effectiveDate to be string or null (got ${typeof effectiveDate})`
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
if (effectiveDate !== null) {
|
|
506
|
+
throw new FFIDSDKError(
|
|
507
|
+
MALFORMED_PREVIEW_CODE,
|
|
508
|
+
`SDK: server returned malformed PlanChangePreview \u2014 willApplyAtPeriodEnd=false requires effectiveDate=null (got ${JSON.stringify(effectiveDate)})`
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
if (typeof proratedAmount !== "number") {
|
|
512
|
+
throw new FFIDSDKError(
|
|
513
|
+
MALFORMED_PREVIEW_CODE,
|
|
514
|
+
`SDK: server returned malformed PlanChangePreview \u2014 willApplyAtPeriodEnd=false requires proratedAmount to be a number (got ${typeof proratedAmount})`
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
function validateSeatChangePreview(preview) {
|
|
519
|
+
if (preview === null || typeof preview !== "object") {
|
|
520
|
+
throw new FFIDSDKError(
|
|
521
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
522
|
+
"SDK: server returned malformed SeatChangePreview \u2014 expected object, got " + (preview === null ? "null" : typeof preview)
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
const p = preview;
|
|
526
|
+
if (p.type !== "seat-change") {
|
|
527
|
+
throw new FFIDSDKError(
|
|
528
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
529
|
+
`SDK: server returned malformed SeatChangePreview \u2014 type must be 'seat-change' (got ${JSON.stringify(p.type)})`
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
const numericFields = [
|
|
533
|
+
"currentQuantity",
|
|
534
|
+
"newQuantity",
|
|
535
|
+
"unitPrice",
|
|
536
|
+
"proratedAmount",
|
|
537
|
+
"nextInvoiceAmount"
|
|
538
|
+
];
|
|
539
|
+
for (const key of numericFields) {
|
|
540
|
+
if (typeof p[key] !== "number") {
|
|
541
|
+
throw new FFIDSDKError(
|
|
542
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
543
|
+
`SDK: server returned malformed SeatChangePreview \u2014 ${key} must be a number (got ${typeof p[key]})`
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
if (p.nextInvoiceDate !== null && typeof p.nextInvoiceDate !== "string") {
|
|
548
|
+
throw new FFIDSDKError(
|
|
549
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
550
|
+
`SDK: server returned malformed SeatChangePreview \u2014 nextInvoiceDate must be string or null (got ${typeof p.nextInvoiceDate})`
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
if (typeof p.isEstimate !== "boolean") {
|
|
554
|
+
throw new FFIDSDKError(
|
|
555
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
556
|
+
`SDK: server returned malformed SeatChangePreview \u2014 isEstimate must be boolean (got ${typeof p.isEstimate})`
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
if (p.estimateReason !== void 0 && !SEAT_ESTIMATE_REASONS.has(p.estimateReason)) {
|
|
560
|
+
throw new FFIDSDKError(
|
|
561
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
562
|
+
`SDK: server returned malformed SeatChangePreview \u2014 estimateReason must be one of 'no_stripe_data' | 'custom_pricing' | 'stripe_error' (got ${JSON.stringify(p.estimateReason)})`
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
if (!Array.isArray(p.lineItems)) {
|
|
566
|
+
throw new FFIDSDKError(
|
|
567
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
568
|
+
`SDK: server returned malformed SeatChangePreview \u2014 lineItems must be an array (got ${typeof p.lineItems})`
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
463
572
|
function createSubscriptionMethods(deps) {
|
|
464
573
|
const { fetchWithAuth, createError } = deps;
|
|
465
574
|
async function listPlans() {
|
|
@@ -546,7 +655,7 @@ function createSubscriptionMethods(deps) {
|
|
|
546
655
|
error: createError("VALIDATION_ERROR", "subscriptionId \u3068 planCode \u306F\u5FC5\u9808\u3067\u3059")
|
|
547
656
|
};
|
|
548
657
|
}
|
|
549
|
-
|
|
658
|
+
const response = await fetchWithAuth(
|
|
550
659
|
`${EXT_SUBSCRIPTION_ENDPOINT}/${encodeURIComponent(params.subscriptionId)}/plan/preview`,
|
|
551
660
|
{
|
|
552
661
|
method: "POST",
|
|
@@ -556,6 +665,36 @@ function createSubscriptionMethods(deps) {
|
|
|
556
665
|
})
|
|
557
666
|
}
|
|
558
667
|
);
|
|
668
|
+
if (response.data !== void 0) {
|
|
669
|
+
validatePlanChangePreview(response.data.preview);
|
|
670
|
+
}
|
|
671
|
+
return response;
|
|
672
|
+
}
|
|
673
|
+
async function previewSeatChange(params) {
|
|
674
|
+
if (isBlankString(params.subscriptionId)) {
|
|
675
|
+
return {
|
|
676
|
+
error: createError("VALIDATION_ERROR", "subscriptionId \u306F\u5FC5\u9808\u3067\u3059")
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
if (typeof params.quantity !== "number" || !Number.isInteger(params.quantity) || params.quantity < 1) {
|
|
680
|
+
return {
|
|
681
|
+
error: createError(
|
|
682
|
+
"VALIDATION_ERROR",
|
|
683
|
+
`quantity \u306F 1 \u4EE5\u4E0A\u306E\u6574\u6570\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 (received: ${String(params.quantity)})`
|
|
684
|
+
)
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
const response = await fetchWithAuth(
|
|
688
|
+
`${EXT_SUBSCRIPTION_ENDPOINT}/${encodeURIComponent(params.subscriptionId)}/seats/preview`,
|
|
689
|
+
{
|
|
690
|
+
method: "POST",
|
|
691
|
+
body: JSON.stringify({ quantity: params.quantity })
|
|
692
|
+
}
|
|
693
|
+
);
|
|
694
|
+
if (response.data !== void 0) {
|
|
695
|
+
validateSeatChangePreview(response.data.preview);
|
|
696
|
+
}
|
|
697
|
+
return response;
|
|
559
698
|
}
|
|
560
699
|
return {
|
|
561
700
|
listPlans,
|
|
@@ -564,7 +703,8 @@ function createSubscriptionMethods(deps) {
|
|
|
564
703
|
changePlan,
|
|
565
704
|
cancelSubscription,
|
|
566
705
|
cancelPendingDowngrade,
|
|
567
|
-
previewPlanChange
|
|
706
|
+
previewPlanChange,
|
|
707
|
+
previewSeatChange
|
|
568
708
|
};
|
|
569
709
|
}
|
|
570
710
|
|
|
@@ -621,7 +761,7 @@ function createMembersMethods(deps) {
|
|
|
621
761
|
}
|
|
622
762
|
|
|
623
763
|
// src/client/version-check.ts
|
|
624
|
-
var SDK_VERSION = "2.
|
|
764
|
+
var SDK_VERSION = "2.12.1";
|
|
625
765
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
626
766
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
627
767
|
function sdkHeaders() {
|
|
@@ -1244,6 +1384,23 @@ function createRedirectMethods(deps) {
|
|
|
1244
1384
|
return { redirectToLogin, redirectToAuthorize, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout };
|
|
1245
1385
|
}
|
|
1246
1386
|
|
|
1387
|
+
// src/client/redirect-uri.ts
|
|
1388
|
+
var AUTHORITY_BOUNDARY = /^([a-zA-Z][a-zA-Z0-9+.-]*:\/\/[^/?#]+)([/?#]?)/;
|
|
1389
|
+
function normalizeRedirectUri(input) {
|
|
1390
|
+
const url = new URL(input);
|
|
1391
|
+
const isRootPath = url.pathname === "" || url.pathname === "/";
|
|
1392
|
+
if (!isRootPath) {
|
|
1393
|
+
return { normalized: input, changed: false };
|
|
1394
|
+
}
|
|
1395
|
+
const match = input.match(AUTHORITY_BOUNDARY);
|
|
1396
|
+
if (match === null || match[2] === "/") {
|
|
1397
|
+
return { normalized: input, changed: false };
|
|
1398
|
+
}
|
|
1399
|
+
const authority = match[1];
|
|
1400
|
+
const rest = input.slice(authority.length);
|
|
1401
|
+
return { normalized: `${authority}/${rest}`, changed: true };
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1247
1404
|
// src/client/password-reset.ts
|
|
1248
1405
|
var RESET_PASSWORD_BASE = "/api/v1/auth/reset-password";
|
|
1249
1406
|
function isBlank(value) {
|
|
@@ -1754,6 +1911,24 @@ var FFID_ERROR_CODES = {
|
|
|
1754
1911
|
TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR"
|
|
1755
1912
|
};
|
|
1756
1913
|
var EXT_CHECK_ENDPOINT = "/api/v1/subscriptions/ext/check";
|
|
1914
|
+
function resolveRedirectUri(raw, logger) {
|
|
1915
|
+
if (raw === null) return null;
|
|
1916
|
+
try {
|
|
1917
|
+
const { normalized, changed } = normalizeRedirectUri(raw);
|
|
1918
|
+
if (changed) {
|
|
1919
|
+
logger.warn(
|
|
1920
|
+
`FFID Client: redirect_uri \u3092\u6B63\u898F\u5316\u3057\u307E\u3057\u305F (${raw} \u2192 ${normalized})\u3002FFID \u7BA1\u7406\u753B\u9762\u3067\u306E\u767B\u9332\u5024\u3068\u4E00\u81F4\u3055\u305B\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
1921
|
+
);
|
|
1922
|
+
}
|
|
1923
|
+
return normalized;
|
|
1924
|
+
} catch (error) {
|
|
1925
|
+
logger.warn(
|
|
1926
|
+
`FFID Client: redirectUri \u306E\u30D1\u30FC\u30B9\u306B\u5931\u6557\u3057\u305F\u305F\u3081\u6B63\u898F\u5316\u3092\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3057\u305F (${raw})`,
|
|
1927
|
+
error
|
|
1928
|
+
);
|
|
1929
|
+
return raw;
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1757
1932
|
function createFFIDClient(config) {
|
|
1758
1933
|
if (!config.serviceCode || !config.serviceCode.trim()) {
|
|
1759
1934
|
throw new Error("FFID Client: serviceCode \u304C\u672A\u8A2D\u5B9A\u3067\u3059");
|
|
@@ -1761,7 +1936,7 @@ function createFFIDClient(config) {
|
|
|
1761
1936
|
const baseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;
|
|
1762
1937
|
const authMode = config.authMode ?? "cookie";
|
|
1763
1938
|
const clientId = config.clientId ?? config.serviceCode;
|
|
1764
|
-
const
|
|
1939
|
+
const rawRedirectUri = config.redirectUri ?? null;
|
|
1765
1940
|
const serviceApiKey = config.serviceApiKey?.trim();
|
|
1766
1941
|
const verifyStrategy = config.verifyStrategy ?? "jwt";
|
|
1767
1942
|
const cache = config.cache;
|
|
@@ -1776,6 +1951,7 @@ function createFFIDClient(config) {
|
|
|
1776
1951
|
throw new Error("FFID Client: timeout \u306F\u6B63\u306E\u6570\u5024\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044");
|
|
1777
1952
|
}
|
|
1778
1953
|
const logger = config.logger ?? (config.debug ? consoleLogger : noopLogger);
|
|
1954
|
+
const resolvedRedirectUri = resolveRedirectUri(rawRedirectUri, logger);
|
|
1779
1955
|
const tokenStore = authMode === "token" ? createTokenStore() : createTokenStore("memory");
|
|
1780
1956
|
function createError(code, message) {
|
|
1781
1957
|
return { code, message };
|
|
@@ -1958,7 +2134,8 @@ function createFFIDClient(config) {
|
|
|
1958
2134
|
changePlan,
|
|
1959
2135
|
cancelSubscription,
|
|
1960
2136
|
cancelPendingDowngrade,
|
|
1961
|
-
previewPlanChange
|
|
2137
|
+
previewPlanChange,
|
|
2138
|
+
previewSeatChange
|
|
1962
2139
|
} = createSubscriptionMethods({
|
|
1963
2140
|
fetchWithAuth,
|
|
1964
2141
|
createError
|
|
@@ -2048,6 +2225,7 @@ function createFFIDClient(config) {
|
|
|
2048
2225
|
cancelSubscription,
|
|
2049
2226
|
cancelPendingDowngrade,
|
|
2050
2227
|
previewPlanChange,
|
|
2228
|
+
previewSeatChange,
|
|
2051
2229
|
verifyAccessToken,
|
|
2052
2230
|
getSubscribeUrl,
|
|
2053
2231
|
redirectToSubscribe,
|
|
@@ -3982,6 +4160,7 @@ exports.FFIDInquiryForm = FFIDInquiryForm;
|
|
|
3982
4160
|
exports.FFIDLoginButton = FFIDLoginButton;
|
|
3983
4161
|
exports.FFIDOrganizationSwitcher = FFIDOrganizationSwitcher;
|
|
3984
4162
|
exports.FFIDProvider = FFIDProvider;
|
|
4163
|
+
exports.FFIDSDKError = FFIDSDKError;
|
|
3985
4164
|
exports.FFIDSubscriptionBadge = FFIDSubscriptionBadge;
|
|
3986
4165
|
exports.FFIDUserMenu = FFIDUserMenu;
|
|
3987
4166
|
exports.FFID_ANNOUNCEMENTS_ERROR_CODES = FFID_ANNOUNCEMENTS_ERROR_CODES;
|
|
@@ -3991,6 +4170,7 @@ exports.createFFIDClient = createFFIDClient;
|
|
|
3991
4170
|
exports.createTokenStore = createTokenStore;
|
|
3992
4171
|
exports.generateCodeChallenge = generateCodeChallenge;
|
|
3993
4172
|
exports.generateCodeVerifier = generateCodeVerifier;
|
|
4173
|
+
exports.normalizeRedirectUri = normalizeRedirectUri;
|
|
3994
4174
|
exports.retrieveCodeVerifier = retrieveCodeVerifier;
|
|
3995
4175
|
exports.storeCodeVerifier = storeCodeVerifier;
|
|
3996
4176
|
exports.useFFID = useFFID;
|
|
@@ -455,9 +455,118 @@ function createBillingMethods(deps) {
|
|
|
455
455
|
var EXT_PLANS_ENDPOINT = "/api/v1/subscriptions/ext/plans";
|
|
456
456
|
var EXT_SUBSCRIPTION_ENDPOINT = "/api/v1/subscriptions/ext";
|
|
457
457
|
var EXT_SUBSCRIBE_ENDPOINT = "/api/v1/subscriptions/ext/subscribe";
|
|
458
|
+
var FFIDSDKError = class extends Error {
|
|
459
|
+
code;
|
|
460
|
+
constructor(code, message) {
|
|
461
|
+
super(message);
|
|
462
|
+
this.name = "FFIDSDKError";
|
|
463
|
+
this.code = code;
|
|
464
|
+
}
|
|
465
|
+
};
|
|
458
466
|
function isBlankString(value) {
|
|
459
467
|
return typeof value !== "string" || value.trim() === "";
|
|
460
468
|
}
|
|
469
|
+
var MALFORMED_PREVIEW_CODE = "MALFORMED_PLAN_CHANGE_PREVIEW";
|
|
470
|
+
var MALFORMED_SEAT_PREVIEW_CODE = "MALFORMED_SEAT_CHANGE_PREVIEW";
|
|
471
|
+
var SEAT_ESTIMATE_REASONS = /* @__PURE__ */ new Set(["no_stripe_data", "custom_pricing", "stripe_error"]);
|
|
472
|
+
function validatePlanChangePreview(preview) {
|
|
473
|
+
if (preview === null || typeof preview !== "object") {
|
|
474
|
+
throw new FFIDSDKError(
|
|
475
|
+
MALFORMED_PREVIEW_CODE,
|
|
476
|
+
"SDK: server returned malformed PlanChangePreview \u2014 expected object, got " + (preview === null ? "null" : typeof preview)
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
const p = preview;
|
|
480
|
+
const flag = p.willApplyAtPeriodEnd;
|
|
481
|
+
if (typeof flag !== "boolean") {
|
|
482
|
+
throw new FFIDSDKError(
|
|
483
|
+
MALFORMED_PREVIEW_CODE,
|
|
484
|
+
`SDK: server returned malformed PlanChangePreview \u2014 willApplyAtPeriodEnd must be boolean (got ${typeof flag})`
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
const { proratedAmount, effectiveDate } = p;
|
|
488
|
+
if (flag === true) {
|
|
489
|
+
if (proratedAmount !== 0) {
|
|
490
|
+
throw new FFIDSDKError(
|
|
491
|
+
MALFORMED_PREVIEW_CODE,
|
|
492
|
+
`SDK: server returned malformed PlanChangePreview \u2014 willApplyAtPeriodEnd=true requires proratedAmount=0 (got ${JSON.stringify(proratedAmount)})`
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
if (effectiveDate !== null && typeof effectiveDate !== "string") {
|
|
496
|
+
throw new FFIDSDKError(
|
|
497
|
+
MALFORMED_PREVIEW_CODE,
|
|
498
|
+
`SDK: server returned malformed PlanChangePreview \u2014 willApplyAtPeriodEnd=true requires effectiveDate to be string or null (got ${typeof effectiveDate})`
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
if (effectiveDate !== null) {
|
|
504
|
+
throw new FFIDSDKError(
|
|
505
|
+
MALFORMED_PREVIEW_CODE,
|
|
506
|
+
`SDK: server returned malformed PlanChangePreview \u2014 willApplyAtPeriodEnd=false requires effectiveDate=null (got ${JSON.stringify(effectiveDate)})`
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
if (typeof proratedAmount !== "number") {
|
|
510
|
+
throw new FFIDSDKError(
|
|
511
|
+
MALFORMED_PREVIEW_CODE,
|
|
512
|
+
`SDK: server returned malformed PlanChangePreview \u2014 willApplyAtPeriodEnd=false requires proratedAmount to be a number (got ${typeof proratedAmount})`
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
function validateSeatChangePreview(preview) {
|
|
517
|
+
if (preview === null || typeof preview !== "object") {
|
|
518
|
+
throw new FFIDSDKError(
|
|
519
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
520
|
+
"SDK: server returned malformed SeatChangePreview \u2014 expected object, got " + (preview === null ? "null" : typeof preview)
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
const p = preview;
|
|
524
|
+
if (p.type !== "seat-change") {
|
|
525
|
+
throw new FFIDSDKError(
|
|
526
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
527
|
+
`SDK: server returned malformed SeatChangePreview \u2014 type must be 'seat-change' (got ${JSON.stringify(p.type)})`
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
const numericFields = [
|
|
531
|
+
"currentQuantity",
|
|
532
|
+
"newQuantity",
|
|
533
|
+
"unitPrice",
|
|
534
|
+
"proratedAmount",
|
|
535
|
+
"nextInvoiceAmount"
|
|
536
|
+
];
|
|
537
|
+
for (const key of numericFields) {
|
|
538
|
+
if (typeof p[key] !== "number") {
|
|
539
|
+
throw new FFIDSDKError(
|
|
540
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
541
|
+
`SDK: server returned malformed SeatChangePreview \u2014 ${key} must be a number (got ${typeof p[key]})`
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
if (p.nextInvoiceDate !== null && typeof p.nextInvoiceDate !== "string") {
|
|
546
|
+
throw new FFIDSDKError(
|
|
547
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
548
|
+
`SDK: server returned malformed SeatChangePreview \u2014 nextInvoiceDate must be string or null (got ${typeof p.nextInvoiceDate})`
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
if (typeof p.isEstimate !== "boolean") {
|
|
552
|
+
throw new FFIDSDKError(
|
|
553
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
554
|
+
`SDK: server returned malformed SeatChangePreview \u2014 isEstimate must be boolean (got ${typeof p.isEstimate})`
|
|
555
|
+
);
|
|
556
|
+
}
|
|
557
|
+
if (p.estimateReason !== void 0 && !SEAT_ESTIMATE_REASONS.has(p.estimateReason)) {
|
|
558
|
+
throw new FFIDSDKError(
|
|
559
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
560
|
+
`SDK: server returned malformed SeatChangePreview \u2014 estimateReason must be one of 'no_stripe_data' | 'custom_pricing' | 'stripe_error' (got ${JSON.stringify(p.estimateReason)})`
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
if (!Array.isArray(p.lineItems)) {
|
|
564
|
+
throw new FFIDSDKError(
|
|
565
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
566
|
+
`SDK: server returned malformed SeatChangePreview \u2014 lineItems must be an array (got ${typeof p.lineItems})`
|
|
567
|
+
);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
461
570
|
function createSubscriptionMethods(deps) {
|
|
462
571
|
const { fetchWithAuth, createError } = deps;
|
|
463
572
|
async function listPlans() {
|
|
@@ -544,7 +653,7 @@ function createSubscriptionMethods(deps) {
|
|
|
544
653
|
error: createError("VALIDATION_ERROR", "subscriptionId \u3068 planCode \u306F\u5FC5\u9808\u3067\u3059")
|
|
545
654
|
};
|
|
546
655
|
}
|
|
547
|
-
|
|
656
|
+
const response = await fetchWithAuth(
|
|
548
657
|
`${EXT_SUBSCRIPTION_ENDPOINT}/${encodeURIComponent(params.subscriptionId)}/plan/preview`,
|
|
549
658
|
{
|
|
550
659
|
method: "POST",
|
|
@@ -554,6 +663,36 @@ function createSubscriptionMethods(deps) {
|
|
|
554
663
|
})
|
|
555
664
|
}
|
|
556
665
|
);
|
|
666
|
+
if (response.data !== void 0) {
|
|
667
|
+
validatePlanChangePreview(response.data.preview);
|
|
668
|
+
}
|
|
669
|
+
return response;
|
|
670
|
+
}
|
|
671
|
+
async function previewSeatChange(params) {
|
|
672
|
+
if (isBlankString(params.subscriptionId)) {
|
|
673
|
+
return {
|
|
674
|
+
error: createError("VALIDATION_ERROR", "subscriptionId \u306F\u5FC5\u9808\u3067\u3059")
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
if (typeof params.quantity !== "number" || !Number.isInteger(params.quantity) || params.quantity < 1) {
|
|
678
|
+
return {
|
|
679
|
+
error: createError(
|
|
680
|
+
"VALIDATION_ERROR",
|
|
681
|
+
`quantity \u306F 1 \u4EE5\u4E0A\u306E\u6574\u6570\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 (received: ${String(params.quantity)})`
|
|
682
|
+
)
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
const response = await fetchWithAuth(
|
|
686
|
+
`${EXT_SUBSCRIPTION_ENDPOINT}/${encodeURIComponent(params.subscriptionId)}/seats/preview`,
|
|
687
|
+
{
|
|
688
|
+
method: "POST",
|
|
689
|
+
body: JSON.stringify({ quantity: params.quantity })
|
|
690
|
+
}
|
|
691
|
+
);
|
|
692
|
+
if (response.data !== void 0) {
|
|
693
|
+
validateSeatChangePreview(response.data.preview);
|
|
694
|
+
}
|
|
695
|
+
return response;
|
|
557
696
|
}
|
|
558
697
|
return {
|
|
559
698
|
listPlans,
|
|
@@ -562,7 +701,8 @@ function createSubscriptionMethods(deps) {
|
|
|
562
701
|
changePlan,
|
|
563
702
|
cancelSubscription,
|
|
564
703
|
cancelPendingDowngrade,
|
|
565
|
-
previewPlanChange
|
|
704
|
+
previewPlanChange,
|
|
705
|
+
previewSeatChange
|
|
566
706
|
};
|
|
567
707
|
}
|
|
568
708
|
|
|
@@ -619,7 +759,7 @@ function createMembersMethods(deps) {
|
|
|
619
759
|
}
|
|
620
760
|
|
|
621
761
|
// src/client/version-check.ts
|
|
622
|
-
var SDK_VERSION = "2.
|
|
762
|
+
var SDK_VERSION = "2.12.1";
|
|
623
763
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
624
764
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
625
765
|
function sdkHeaders() {
|
|
@@ -1242,6 +1382,23 @@ function createRedirectMethods(deps) {
|
|
|
1242
1382
|
return { redirectToLogin, redirectToAuthorize, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout };
|
|
1243
1383
|
}
|
|
1244
1384
|
|
|
1385
|
+
// src/client/redirect-uri.ts
|
|
1386
|
+
var AUTHORITY_BOUNDARY = /^([a-zA-Z][a-zA-Z0-9+.-]*:\/\/[^/?#]+)([/?#]?)/;
|
|
1387
|
+
function normalizeRedirectUri(input) {
|
|
1388
|
+
const url = new URL(input);
|
|
1389
|
+
const isRootPath = url.pathname === "" || url.pathname === "/";
|
|
1390
|
+
if (!isRootPath) {
|
|
1391
|
+
return { normalized: input, changed: false };
|
|
1392
|
+
}
|
|
1393
|
+
const match = input.match(AUTHORITY_BOUNDARY);
|
|
1394
|
+
if (match === null || match[2] === "/") {
|
|
1395
|
+
return { normalized: input, changed: false };
|
|
1396
|
+
}
|
|
1397
|
+
const authority = match[1];
|
|
1398
|
+
const rest = input.slice(authority.length);
|
|
1399
|
+
return { normalized: `${authority}/${rest}`, changed: true };
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1245
1402
|
// src/client/password-reset.ts
|
|
1246
1403
|
var RESET_PASSWORD_BASE = "/api/v1/auth/reset-password";
|
|
1247
1404
|
function isBlank(value) {
|
|
@@ -1752,6 +1909,24 @@ var FFID_ERROR_CODES = {
|
|
|
1752
1909
|
TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR"
|
|
1753
1910
|
};
|
|
1754
1911
|
var EXT_CHECK_ENDPOINT = "/api/v1/subscriptions/ext/check";
|
|
1912
|
+
function resolveRedirectUri(raw, logger) {
|
|
1913
|
+
if (raw === null) return null;
|
|
1914
|
+
try {
|
|
1915
|
+
const { normalized, changed } = normalizeRedirectUri(raw);
|
|
1916
|
+
if (changed) {
|
|
1917
|
+
logger.warn(
|
|
1918
|
+
`FFID Client: redirect_uri \u3092\u6B63\u898F\u5316\u3057\u307E\u3057\u305F (${raw} \u2192 ${normalized})\u3002FFID \u7BA1\u7406\u753B\u9762\u3067\u306E\u767B\u9332\u5024\u3068\u4E00\u81F4\u3055\u305B\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
1919
|
+
);
|
|
1920
|
+
}
|
|
1921
|
+
return normalized;
|
|
1922
|
+
} catch (error) {
|
|
1923
|
+
logger.warn(
|
|
1924
|
+
`FFID Client: redirectUri \u306E\u30D1\u30FC\u30B9\u306B\u5931\u6557\u3057\u305F\u305F\u3081\u6B63\u898F\u5316\u3092\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3057\u305F (${raw})`,
|
|
1925
|
+
error
|
|
1926
|
+
);
|
|
1927
|
+
return raw;
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1755
1930
|
function createFFIDClient(config) {
|
|
1756
1931
|
if (!config.serviceCode || !config.serviceCode.trim()) {
|
|
1757
1932
|
throw new Error("FFID Client: serviceCode \u304C\u672A\u8A2D\u5B9A\u3067\u3059");
|
|
@@ -1759,7 +1934,7 @@ function createFFIDClient(config) {
|
|
|
1759
1934
|
const baseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;
|
|
1760
1935
|
const authMode = config.authMode ?? "cookie";
|
|
1761
1936
|
const clientId = config.clientId ?? config.serviceCode;
|
|
1762
|
-
const
|
|
1937
|
+
const rawRedirectUri = config.redirectUri ?? null;
|
|
1763
1938
|
const serviceApiKey = config.serviceApiKey?.trim();
|
|
1764
1939
|
const verifyStrategy = config.verifyStrategy ?? "jwt";
|
|
1765
1940
|
const cache = config.cache;
|
|
@@ -1774,6 +1949,7 @@ function createFFIDClient(config) {
|
|
|
1774
1949
|
throw new Error("FFID Client: timeout \u306F\u6B63\u306E\u6570\u5024\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044");
|
|
1775
1950
|
}
|
|
1776
1951
|
const logger = config.logger ?? (config.debug ? consoleLogger : noopLogger);
|
|
1952
|
+
const resolvedRedirectUri = resolveRedirectUri(rawRedirectUri, logger);
|
|
1777
1953
|
const tokenStore = authMode === "token" ? createTokenStore() : createTokenStore("memory");
|
|
1778
1954
|
function createError(code, message) {
|
|
1779
1955
|
return { code, message };
|
|
@@ -1956,7 +2132,8 @@ function createFFIDClient(config) {
|
|
|
1956
2132
|
changePlan,
|
|
1957
2133
|
cancelSubscription,
|
|
1958
2134
|
cancelPendingDowngrade,
|
|
1959
|
-
previewPlanChange
|
|
2135
|
+
previewPlanChange,
|
|
2136
|
+
previewSeatChange
|
|
1960
2137
|
} = createSubscriptionMethods({
|
|
1961
2138
|
fetchWithAuth,
|
|
1962
2139
|
createError
|
|
@@ -2046,6 +2223,7 @@ function createFFIDClient(config) {
|
|
|
2046
2223
|
cancelSubscription,
|
|
2047
2224
|
cancelPendingDowngrade,
|
|
2048
2225
|
previewPlanChange,
|
|
2226
|
+
previewSeatChange,
|
|
2049
2227
|
verifyAccessToken,
|
|
2050
2228
|
getSubscribeUrl,
|
|
2051
2229
|
redirectToSubscribe,
|
|
@@ -3973,4 +4151,4 @@ function FFIDInquiryForm({
|
|
|
3973
4151
|
);
|
|
3974
4152
|
}
|
|
3975
4153
|
|
|
3976
|
-
export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_INQUIRY_CATEGORIES, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useFFIDContext, useSubscription, withSubscription };
|
|
4154
|
+
export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSDKError, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_INQUIRY_CATEGORIES, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useFFIDContext, useSubscription, withSubscription };
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkDJPOGNAO_cjs = require('../chunk-DJPOGNAO.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 chunkDJPOGNAO_cjs.FFIDAnnouncementBadge; }
|
|
10
10
|
});
|
|
11
11
|
Object.defineProperty(exports, "FFIDAnnouncementList", {
|
|
12
12
|
enumerable: true,
|
|
13
|
-
get: function () { return
|
|
13
|
+
get: function () { return chunkDJPOGNAO_cjs.FFIDAnnouncementList; }
|
|
14
14
|
});
|
|
15
15
|
Object.defineProperty(exports, "FFIDInquiryForm", {
|
|
16
16
|
enumerable: true,
|
|
17
|
-
get: function () { return
|
|
17
|
+
get: function () { return chunkDJPOGNAO_cjs.FFIDInquiryForm; }
|
|
18
18
|
});
|
|
19
19
|
Object.defineProperty(exports, "FFIDLoginButton", {
|
|
20
20
|
enumerable: true,
|
|
21
|
-
get: function () { return
|
|
21
|
+
get: function () { return chunkDJPOGNAO_cjs.FFIDLoginButton; }
|
|
22
22
|
});
|
|
23
23
|
Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
|
|
24
24
|
enumerable: true,
|
|
25
|
-
get: function () { return
|
|
25
|
+
get: function () { return chunkDJPOGNAO_cjs.FFIDOrganizationSwitcher; }
|
|
26
26
|
});
|
|
27
27
|
Object.defineProperty(exports, "FFIDSubscriptionBadge", {
|
|
28
28
|
enumerable: true,
|
|
29
|
-
get: function () { return
|
|
29
|
+
get: function () { return chunkDJPOGNAO_cjs.FFIDSubscriptionBadge; }
|
|
30
30
|
});
|
|
31
31
|
Object.defineProperty(exports, "FFIDUserMenu", {
|
|
32
32
|
enumerable: true,
|
|
33
|
-
get: function () { return
|
|
33
|
+
get: function () { return chunkDJPOGNAO_cjs.FFIDUserMenu; }
|
|
34
34
|
});
|
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-MDBV4WY3.js';
|