@feelflow/ffid-sdk 2.10.0 → 2.12.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.
@@ -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
- return fetchWithAuth(
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.10.0";
759
+ var SDK_VERSION = "2.12.0";
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() {
@@ -1940,7 +2080,8 @@ function createFFIDClient(config) {
1940
2080
  changePlan,
1941
2081
  cancelSubscription,
1942
2082
  cancelPendingDowngrade,
1943
- previewPlanChange
2083
+ previewPlanChange,
2084
+ previewSeatChange
1944
2085
  } = createSubscriptionMethods({
1945
2086
  fetchWithAuth,
1946
2087
  createError
@@ -2030,6 +2171,7 @@ function createFFIDClient(config) {
2030
2171
  cancelSubscription,
2031
2172
  cancelPendingDowngrade,
2032
2173
  previewPlanChange,
2174
+ previewSeatChange,
2033
2175
  verifyAccessToken,
2034
2176
  getSubscribeUrl,
2035
2177
  redirectToSubscribe,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feelflow/ffid-sdk",
3
- "version": "2.10.0",
3
+ "version": "2.12.0",
4
4
  "description": "FeelFlow ID Platform SDK for React/Next.js applications",
5
5
  "keywords": [
6
6
  "feelflow",