@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
package/dist/server/index.d.cts
CHANGED
|
@@ -358,6 +358,62 @@ type FFIDPlanChangePreview = FFIDPlanChangePreviewBase & ({
|
|
|
358
358
|
interface FFIDPlanChangePreviewResponse {
|
|
359
359
|
preview: FFIDPlanChangePreview;
|
|
360
360
|
}
|
|
361
|
+
/** Parameters for previewing a seat count change */
|
|
362
|
+
interface FFIDPreviewSeatChangeParams {
|
|
363
|
+
/** Subscription ID (UUID) */
|
|
364
|
+
subscriptionId: string;
|
|
365
|
+
/** New seat quantity. Must be an integer within the plan's allowed range. */
|
|
366
|
+
quantity: number;
|
|
367
|
+
}
|
|
368
|
+
/** Seat change preview line item */
|
|
369
|
+
interface FFIDSeatChangeLineItem {
|
|
370
|
+
description: string;
|
|
371
|
+
amount: number;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Seat change proration preview.
|
|
375
|
+
*
|
|
376
|
+
* Sister type to `FFIDPlanChangePreview`. The shared `type` discriminant lets
|
|
377
|
+
* consumers narrow a preview payload without inspecting unrelated fields.
|
|
378
|
+
*
|
|
379
|
+
* - `isEstimate=true` (default when Stripe is not configured or data is unavailable):
|
|
380
|
+
* `proratedAmount` is computed locally as `(newQuantity - currentQuantity) * unitPrice`.
|
|
381
|
+
* - `isEstimate=false`: `proratedAmount` reflects Stripe's live proration calculation.
|
|
382
|
+
*
|
|
383
|
+
* `nextInvoiceAmount` is always a local estimate (`unitPrice * newQuantity`).
|
|
384
|
+
*
|
|
385
|
+
* `pricingUnavailable=true` indicates the plan uses custom pricing with a zero unit
|
|
386
|
+
* price (Enterprise). Consumers should hide monetary amounts in this case.
|
|
387
|
+
*/
|
|
388
|
+
interface FFIDSeatChangePreview {
|
|
389
|
+
/** Discriminant for preview response variants (pairs with `FFIDPlanChangePreview.type`) */
|
|
390
|
+
type: 'seat-change';
|
|
391
|
+
currentQuantity: number;
|
|
392
|
+
newQuantity: number;
|
|
393
|
+
/** Per-seat price for the current billing interval */
|
|
394
|
+
unitPrice: number;
|
|
395
|
+
billingInterval: FFIDBillingInterval;
|
|
396
|
+
/**
|
|
397
|
+
* Prorated cost for the current billing period. Negative when seats are decreased
|
|
398
|
+
* (credit). `0` when `pricingUnavailable === true` (Enterprise custom pricing).
|
|
399
|
+
*/
|
|
400
|
+
proratedAmount: number;
|
|
401
|
+
/** Next invoice full amount — always a local estimate (`unitPrice * newQuantity`) */
|
|
402
|
+
nextInvoiceAmount: number;
|
|
403
|
+
nextInvoiceDate: string | null;
|
|
404
|
+
currency: FFIDSupportedCurrency;
|
|
405
|
+
/** true when proratedAmount is estimated from local prices rather than Stripe proration data */
|
|
406
|
+
isEstimate: boolean;
|
|
407
|
+
/** true when unit price is 0 due to custom pricing (Enterprise) — hide monetary amounts */
|
|
408
|
+
pricingUnavailable?: boolean;
|
|
409
|
+
/** Reason why `isEstimate` is true. Only meaningful when `isEstimate === true`. */
|
|
410
|
+
estimateReason?: 'no_stripe_data' | 'custom_pricing' | 'stripe_error';
|
|
411
|
+
lineItems: FFIDSeatChangeLineItem[];
|
|
412
|
+
}
|
|
413
|
+
/** Response from seat change preview endpoint */
|
|
414
|
+
interface FFIDSeatChangePreviewResponse {
|
|
415
|
+
preview: FFIDSeatChangePreview;
|
|
416
|
+
}
|
|
361
417
|
|
|
362
418
|
/**
|
|
363
419
|
* FFID SDK Type Definitions
|
|
@@ -845,6 +901,7 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
845
901
|
cancelSubscription: (params: FFIDCancelSubscriptionParams) => Promise<FFIDApiResponse<FFIDCancelSubscriptionResponse>>;
|
|
846
902
|
cancelPendingDowngrade: (subscriptionId: string) => Promise<FFIDApiResponse<FFIDCancelPendingDowngradeResponse>>;
|
|
847
903
|
previewPlanChange: (params: FFIDPreviewPlanChangeParams) => Promise<FFIDApiResponse<FFIDPlanChangePreviewResponse>>;
|
|
904
|
+
previewSeatChange: (params: FFIDPreviewSeatChangeParams) => Promise<FFIDApiResponse<FFIDSeatChangePreviewResponse>>;
|
|
848
905
|
verifyAccessToken: (accessToken: string, options?: FFIDVerifyAccessTokenOptions) => Promise<FFIDApiResponse<FFIDOAuthUserInfo>>;
|
|
849
906
|
getSubscribeUrl: (options?: ContractWizardSubscribeOptions) => string;
|
|
850
907
|
redirectToSubscribe: (options?: ContractWizardSubscribeOptions) => FFIDRedirectResult;
|
package/dist/server/index.d.ts
CHANGED
|
@@ -358,6 +358,62 @@ type FFIDPlanChangePreview = FFIDPlanChangePreviewBase & ({
|
|
|
358
358
|
interface FFIDPlanChangePreviewResponse {
|
|
359
359
|
preview: FFIDPlanChangePreview;
|
|
360
360
|
}
|
|
361
|
+
/** Parameters for previewing a seat count change */
|
|
362
|
+
interface FFIDPreviewSeatChangeParams {
|
|
363
|
+
/** Subscription ID (UUID) */
|
|
364
|
+
subscriptionId: string;
|
|
365
|
+
/** New seat quantity. Must be an integer within the plan's allowed range. */
|
|
366
|
+
quantity: number;
|
|
367
|
+
}
|
|
368
|
+
/** Seat change preview line item */
|
|
369
|
+
interface FFIDSeatChangeLineItem {
|
|
370
|
+
description: string;
|
|
371
|
+
amount: number;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Seat change proration preview.
|
|
375
|
+
*
|
|
376
|
+
* Sister type to `FFIDPlanChangePreview`. The shared `type` discriminant lets
|
|
377
|
+
* consumers narrow a preview payload without inspecting unrelated fields.
|
|
378
|
+
*
|
|
379
|
+
* - `isEstimate=true` (default when Stripe is not configured or data is unavailable):
|
|
380
|
+
* `proratedAmount` is computed locally as `(newQuantity - currentQuantity) * unitPrice`.
|
|
381
|
+
* - `isEstimate=false`: `proratedAmount` reflects Stripe's live proration calculation.
|
|
382
|
+
*
|
|
383
|
+
* `nextInvoiceAmount` is always a local estimate (`unitPrice * newQuantity`).
|
|
384
|
+
*
|
|
385
|
+
* `pricingUnavailable=true` indicates the plan uses custom pricing with a zero unit
|
|
386
|
+
* price (Enterprise). Consumers should hide monetary amounts in this case.
|
|
387
|
+
*/
|
|
388
|
+
interface FFIDSeatChangePreview {
|
|
389
|
+
/** Discriminant for preview response variants (pairs with `FFIDPlanChangePreview.type`) */
|
|
390
|
+
type: 'seat-change';
|
|
391
|
+
currentQuantity: number;
|
|
392
|
+
newQuantity: number;
|
|
393
|
+
/** Per-seat price for the current billing interval */
|
|
394
|
+
unitPrice: number;
|
|
395
|
+
billingInterval: FFIDBillingInterval;
|
|
396
|
+
/**
|
|
397
|
+
* Prorated cost for the current billing period. Negative when seats are decreased
|
|
398
|
+
* (credit). `0` when `pricingUnavailable === true` (Enterprise custom pricing).
|
|
399
|
+
*/
|
|
400
|
+
proratedAmount: number;
|
|
401
|
+
/** Next invoice full amount — always a local estimate (`unitPrice * newQuantity`) */
|
|
402
|
+
nextInvoiceAmount: number;
|
|
403
|
+
nextInvoiceDate: string | null;
|
|
404
|
+
currency: FFIDSupportedCurrency;
|
|
405
|
+
/** true when proratedAmount is estimated from local prices rather than Stripe proration data */
|
|
406
|
+
isEstimate: boolean;
|
|
407
|
+
/** true when unit price is 0 due to custom pricing (Enterprise) — hide monetary amounts */
|
|
408
|
+
pricingUnavailable?: boolean;
|
|
409
|
+
/** Reason why `isEstimate` is true. Only meaningful when `isEstimate === true`. */
|
|
410
|
+
estimateReason?: 'no_stripe_data' | 'custom_pricing' | 'stripe_error';
|
|
411
|
+
lineItems: FFIDSeatChangeLineItem[];
|
|
412
|
+
}
|
|
413
|
+
/** Response from seat change preview endpoint */
|
|
414
|
+
interface FFIDSeatChangePreviewResponse {
|
|
415
|
+
preview: FFIDSeatChangePreview;
|
|
416
|
+
}
|
|
361
417
|
|
|
362
418
|
/**
|
|
363
419
|
* FFID SDK Type Definitions
|
|
@@ -845,6 +901,7 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
845
901
|
cancelSubscription: (params: FFIDCancelSubscriptionParams) => Promise<FFIDApiResponse<FFIDCancelSubscriptionResponse>>;
|
|
846
902
|
cancelPendingDowngrade: (subscriptionId: string) => Promise<FFIDApiResponse<FFIDCancelPendingDowngradeResponse>>;
|
|
847
903
|
previewPlanChange: (params: FFIDPreviewPlanChangeParams) => Promise<FFIDApiResponse<FFIDPlanChangePreviewResponse>>;
|
|
904
|
+
previewSeatChange: (params: FFIDPreviewSeatChangeParams) => Promise<FFIDApiResponse<FFIDSeatChangePreviewResponse>>;
|
|
848
905
|
verifyAccessToken: (accessToken: string, options?: FFIDVerifyAccessTokenOptions) => Promise<FFIDApiResponse<FFIDOAuthUserInfo>>;
|
|
849
906
|
getSubscribeUrl: (options?: ContractWizardSubscribeOptions) => string;
|
|
850
907
|
redirectToSubscribe: (options?: ContractWizardSubscribeOptions) => FFIDRedirectResult;
|
package/dist/server/index.js
CHANGED
|
@@ -452,9 +452,118 @@ function createBillingMethods(deps) {
|
|
|
452
452
|
var EXT_PLANS_ENDPOINT = "/api/v1/subscriptions/ext/plans";
|
|
453
453
|
var EXT_SUBSCRIPTION_ENDPOINT = "/api/v1/subscriptions/ext";
|
|
454
454
|
var EXT_SUBSCRIBE_ENDPOINT = "/api/v1/subscriptions/ext/subscribe";
|
|
455
|
+
var FFIDSDKError = class extends Error {
|
|
456
|
+
code;
|
|
457
|
+
constructor(code, message) {
|
|
458
|
+
super(message);
|
|
459
|
+
this.name = "FFIDSDKError";
|
|
460
|
+
this.code = code;
|
|
461
|
+
}
|
|
462
|
+
};
|
|
455
463
|
function isBlankString(value) {
|
|
456
464
|
return typeof value !== "string" || value.trim() === "";
|
|
457
465
|
}
|
|
466
|
+
var MALFORMED_PREVIEW_CODE = "MALFORMED_PLAN_CHANGE_PREVIEW";
|
|
467
|
+
var MALFORMED_SEAT_PREVIEW_CODE = "MALFORMED_SEAT_CHANGE_PREVIEW";
|
|
468
|
+
var SEAT_ESTIMATE_REASONS = /* @__PURE__ */ new Set(["no_stripe_data", "custom_pricing", "stripe_error"]);
|
|
469
|
+
function validatePlanChangePreview(preview) {
|
|
470
|
+
if (preview === null || typeof preview !== "object") {
|
|
471
|
+
throw new FFIDSDKError(
|
|
472
|
+
MALFORMED_PREVIEW_CODE,
|
|
473
|
+
"SDK: server returned malformed PlanChangePreview \u2014 expected object, got " + (preview === null ? "null" : typeof preview)
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
const p = preview;
|
|
477
|
+
const flag = p.willApplyAtPeriodEnd;
|
|
478
|
+
if (typeof flag !== "boolean") {
|
|
479
|
+
throw new FFIDSDKError(
|
|
480
|
+
MALFORMED_PREVIEW_CODE,
|
|
481
|
+
`SDK: server returned malformed PlanChangePreview \u2014 willApplyAtPeriodEnd must be boolean (got ${typeof flag})`
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
const { proratedAmount, effectiveDate } = p;
|
|
485
|
+
if (flag === true) {
|
|
486
|
+
if (proratedAmount !== 0) {
|
|
487
|
+
throw new FFIDSDKError(
|
|
488
|
+
MALFORMED_PREVIEW_CODE,
|
|
489
|
+
`SDK: server returned malformed PlanChangePreview \u2014 willApplyAtPeriodEnd=true requires proratedAmount=0 (got ${JSON.stringify(proratedAmount)})`
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
if (effectiveDate !== null && typeof effectiveDate !== "string") {
|
|
493
|
+
throw new FFIDSDKError(
|
|
494
|
+
MALFORMED_PREVIEW_CODE,
|
|
495
|
+
`SDK: server returned malformed PlanChangePreview \u2014 willApplyAtPeriodEnd=true requires effectiveDate to be string or null (got ${typeof effectiveDate})`
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
if (effectiveDate !== null) {
|
|
501
|
+
throw new FFIDSDKError(
|
|
502
|
+
MALFORMED_PREVIEW_CODE,
|
|
503
|
+
`SDK: server returned malformed PlanChangePreview \u2014 willApplyAtPeriodEnd=false requires effectiveDate=null (got ${JSON.stringify(effectiveDate)})`
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
if (typeof proratedAmount !== "number") {
|
|
507
|
+
throw new FFIDSDKError(
|
|
508
|
+
MALFORMED_PREVIEW_CODE,
|
|
509
|
+
`SDK: server returned malformed PlanChangePreview \u2014 willApplyAtPeriodEnd=false requires proratedAmount to be a number (got ${typeof proratedAmount})`
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
function validateSeatChangePreview(preview) {
|
|
514
|
+
if (preview === null || typeof preview !== "object") {
|
|
515
|
+
throw new FFIDSDKError(
|
|
516
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
517
|
+
"SDK: server returned malformed SeatChangePreview \u2014 expected object, got " + (preview === null ? "null" : typeof preview)
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
const p = preview;
|
|
521
|
+
if (p.type !== "seat-change") {
|
|
522
|
+
throw new FFIDSDKError(
|
|
523
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
524
|
+
`SDK: server returned malformed SeatChangePreview \u2014 type must be 'seat-change' (got ${JSON.stringify(p.type)})`
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
const numericFields = [
|
|
528
|
+
"currentQuantity",
|
|
529
|
+
"newQuantity",
|
|
530
|
+
"unitPrice",
|
|
531
|
+
"proratedAmount",
|
|
532
|
+
"nextInvoiceAmount"
|
|
533
|
+
];
|
|
534
|
+
for (const key of numericFields) {
|
|
535
|
+
if (typeof p[key] !== "number") {
|
|
536
|
+
throw new FFIDSDKError(
|
|
537
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
538
|
+
`SDK: server returned malformed SeatChangePreview \u2014 ${key} must be a number (got ${typeof p[key]})`
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
if (p.nextInvoiceDate !== null && typeof p.nextInvoiceDate !== "string") {
|
|
543
|
+
throw new FFIDSDKError(
|
|
544
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
545
|
+
`SDK: server returned malformed SeatChangePreview \u2014 nextInvoiceDate must be string or null (got ${typeof p.nextInvoiceDate})`
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
if (typeof p.isEstimate !== "boolean") {
|
|
549
|
+
throw new FFIDSDKError(
|
|
550
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
551
|
+
`SDK: server returned malformed SeatChangePreview \u2014 isEstimate must be boolean (got ${typeof p.isEstimate})`
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
if (p.estimateReason !== void 0 && !SEAT_ESTIMATE_REASONS.has(p.estimateReason)) {
|
|
555
|
+
throw new FFIDSDKError(
|
|
556
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
557
|
+
`SDK: server returned malformed SeatChangePreview \u2014 estimateReason must be one of 'no_stripe_data' | 'custom_pricing' | 'stripe_error' (got ${JSON.stringify(p.estimateReason)})`
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
if (!Array.isArray(p.lineItems)) {
|
|
561
|
+
throw new FFIDSDKError(
|
|
562
|
+
MALFORMED_SEAT_PREVIEW_CODE,
|
|
563
|
+
`SDK: server returned malformed SeatChangePreview \u2014 lineItems must be an array (got ${typeof p.lineItems})`
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
458
567
|
function createSubscriptionMethods(deps) {
|
|
459
568
|
const { fetchWithAuth, createError } = deps;
|
|
460
569
|
async function listPlans() {
|
|
@@ -541,7 +650,7 @@ function createSubscriptionMethods(deps) {
|
|
|
541
650
|
error: createError("VALIDATION_ERROR", "subscriptionId \u3068 planCode \u306F\u5FC5\u9808\u3067\u3059")
|
|
542
651
|
};
|
|
543
652
|
}
|
|
544
|
-
|
|
653
|
+
const response = await fetchWithAuth(
|
|
545
654
|
`${EXT_SUBSCRIPTION_ENDPOINT}/${encodeURIComponent(params.subscriptionId)}/plan/preview`,
|
|
546
655
|
{
|
|
547
656
|
method: "POST",
|
|
@@ -551,6 +660,36 @@ function createSubscriptionMethods(deps) {
|
|
|
551
660
|
})
|
|
552
661
|
}
|
|
553
662
|
);
|
|
663
|
+
if (response.data !== void 0) {
|
|
664
|
+
validatePlanChangePreview(response.data.preview);
|
|
665
|
+
}
|
|
666
|
+
return response;
|
|
667
|
+
}
|
|
668
|
+
async function previewSeatChange(params) {
|
|
669
|
+
if (isBlankString(params.subscriptionId)) {
|
|
670
|
+
return {
|
|
671
|
+
error: createError("VALIDATION_ERROR", "subscriptionId \u306F\u5FC5\u9808\u3067\u3059")
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
if (typeof params.quantity !== "number" || !Number.isInteger(params.quantity) || params.quantity < 1) {
|
|
675
|
+
return {
|
|
676
|
+
error: createError(
|
|
677
|
+
"VALIDATION_ERROR",
|
|
678
|
+
`quantity \u306F 1 \u4EE5\u4E0A\u306E\u6574\u6570\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 (received: ${String(params.quantity)})`
|
|
679
|
+
)
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
const response = await fetchWithAuth(
|
|
683
|
+
`${EXT_SUBSCRIPTION_ENDPOINT}/${encodeURIComponent(params.subscriptionId)}/seats/preview`,
|
|
684
|
+
{
|
|
685
|
+
method: "POST",
|
|
686
|
+
body: JSON.stringify({ quantity: params.quantity })
|
|
687
|
+
}
|
|
688
|
+
);
|
|
689
|
+
if (response.data !== void 0) {
|
|
690
|
+
validateSeatChangePreview(response.data.preview);
|
|
691
|
+
}
|
|
692
|
+
return response;
|
|
554
693
|
}
|
|
555
694
|
return {
|
|
556
695
|
listPlans,
|
|
@@ -559,7 +698,8 @@ function createSubscriptionMethods(deps) {
|
|
|
559
698
|
changePlan,
|
|
560
699
|
cancelSubscription,
|
|
561
700
|
cancelPendingDowngrade,
|
|
562
|
-
previewPlanChange
|
|
701
|
+
previewPlanChange,
|
|
702
|
+
previewSeatChange
|
|
563
703
|
};
|
|
564
704
|
}
|
|
565
705
|
|
|
@@ -616,7 +756,7 @@ function createMembersMethods(deps) {
|
|
|
616
756
|
}
|
|
617
757
|
|
|
618
758
|
// src/client/version-check.ts
|
|
619
|
-
var SDK_VERSION = "2.
|
|
759
|
+
var SDK_VERSION = "2.12.1";
|
|
620
760
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
621
761
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
622
762
|
function sdkHeaders() {
|
|
@@ -1226,6 +1366,23 @@ function createRedirectMethods(deps) {
|
|
|
1226
1366
|
return { redirectToLogin, redirectToAuthorize, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout };
|
|
1227
1367
|
}
|
|
1228
1368
|
|
|
1369
|
+
// src/client/redirect-uri.ts
|
|
1370
|
+
var AUTHORITY_BOUNDARY = /^([a-zA-Z][a-zA-Z0-9+.-]*:\/\/[^/?#]+)([/?#]?)/;
|
|
1371
|
+
function normalizeRedirectUri(input) {
|
|
1372
|
+
const url = new URL(input);
|
|
1373
|
+
const isRootPath = url.pathname === "" || url.pathname === "/";
|
|
1374
|
+
if (!isRootPath) {
|
|
1375
|
+
return { normalized: input, changed: false };
|
|
1376
|
+
}
|
|
1377
|
+
const match = input.match(AUTHORITY_BOUNDARY);
|
|
1378
|
+
if (match === null || match[2] === "/") {
|
|
1379
|
+
return { normalized: input, changed: false };
|
|
1380
|
+
}
|
|
1381
|
+
const authority = match[1];
|
|
1382
|
+
const rest = input.slice(authority.length);
|
|
1383
|
+
return { normalized: `${authority}/${rest}`, changed: true };
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1229
1386
|
// src/client/password-reset.ts
|
|
1230
1387
|
var RESET_PASSWORD_BASE = "/api/v1/auth/reset-password";
|
|
1231
1388
|
function isBlank(value) {
|
|
@@ -1736,6 +1893,24 @@ var FFID_ERROR_CODES = {
|
|
|
1736
1893
|
TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR"
|
|
1737
1894
|
};
|
|
1738
1895
|
var EXT_CHECK_ENDPOINT = "/api/v1/subscriptions/ext/check";
|
|
1896
|
+
function resolveRedirectUri(raw, logger) {
|
|
1897
|
+
if (raw === null) return null;
|
|
1898
|
+
try {
|
|
1899
|
+
const { normalized, changed } = normalizeRedirectUri(raw);
|
|
1900
|
+
if (changed) {
|
|
1901
|
+
logger.warn(
|
|
1902
|
+
`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`
|
|
1903
|
+
);
|
|
1904
|
+
}
|
|
1905
|
+
return normalized;
|
|
1906
|
+
} catch (error) {
|
|
1907
|
+
logger.warn(
|
|
1908
|
+
`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})`,
|
|
1909
|
+
error
|
|
1910
|
+
);
|
|
1911
|
+
return raw;
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1739
1914
|
function createFFIDClient(config) {
|
|
1740
1915
|
if (!config.serviceCode || !config.serviceCode.trim()) {
|
|
1741
1916
|
throw new Error("FFID Client: serviceCode \u304C\u672A\u8A2D\u5B9A\u3067\u3059");
|
|
@@ -1743,7 +1918,7 @@ function createFFIDClient(config) {
|
|
|
1743
1918
|
const baseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;
|
|
1744
1919
|
const authMode = config.authMode ?? "cookie";
|
|
1745
1920
|
const clientId = config.clientId ?? config.serviceCode;
|
|
1746
|
-
const
|
|
1921
|
+
const rawRedirectUri = config.redirectUri ?? null;
|
|
1747
1922
|
const serviceApiKey = config.serviceApiKey?.trim();
|
|
1748
1923
|
const verifyStrategy = config.verifyStrategy ?? "jwt";
|
|
1749
1924
|
const cache = config.cache;
|
|
@@ -1758,6 +1933,7 @@ function createFFIDClient(config) {
|
|
|
1758
1933
|
throw new Error("FFID Client: timeout \u306F\u6B63\u306E\u6570\u5024\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044");
|
|
1759
1934
|
}
|
|
1760
1935
|
const logger = config.logger ?? (config.debug ? consoleLogger : noopLogger);
|
|
1936
|
+
const resolvedRedirectUri = resolveRedirectUri(rawRedirectUri, logger);
|
|
1761
1937
|
const tokenStore = authMode === "token" ? createTokenStore() : createTokenStore("memory");
|
|
1762
1938
|
function createError(code, message) {
|
|
1763
1939
|
return { code, message };
|
|
@@ -1940,7 +2116,8 @@ function createFFIDClient(config) {
|
|
|
1940
2116
|
changePlan,
|
|
1941
2117
|
cancelSubscription,
|
|
1942
2118
|
cancelPendingDowngrade,
|
|
1943
|
-
previewPlanChange
|
|
2119
|
+
previewPlanChange,
|
|
2120
|
+
previewSeatChange
|
|
1944
2121
|
} = createSubscriptionMethods({
|
|
1945
2122
|
fetchWithAuth,
|
|
1946
2123
|
createError
|
|
@@ -2030,6 +2207,7 @@ function createFFIDClient(config) {
|
|
|
2030
2207
|
cancelSubscription,
|
|
2031
2208
|
cancelPendingDowngrade,
|
|
2032
2209
|
previewPlanChange,
|
|
2210
|
+
previewSeatChange,
|
|
2033
2211
|
verifyAccessToken,
|
|
2034
2212
|
getSubscribeUrl,
|
|
2035
2213
|
redirectToSubscribe,
|