@carlonicora/nextjs-jsonapi 5.5.0 → 5.7.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.
Files changed (152) hide show
  1. package/dist/{BlockNoteEditor-GVQCKRMU.mjs → BlockNoteEditor-R3WXUFHX.mjs} +4 -4
  2. package/dist/{BlockNoteEditor-THBJH2UR.js → BlockNoteEditor-ZHXXFWUJ.js} +19 -19
  3. package/dist/{BlockNoteEditor-THBJH2UR.js.map → BlockNoteEditor-ZHXXFWUJ.js.map} +1 -1
  4. package/dist/{BlockNoteViewer-U6E3DS4F.mjs → BlockNoteViewer-BVVN6D3T.mjs} +2 -2
  5. package/dist/{BlockNoteViewer-VZOVKTFO.js → BlockNoteViewer-SD3ZFIXD.js} +3 -3
  6. package/dist/{BlockNoteViewer-VZOVKTFO.js.map → BlockNoteViewer-SD3ZFIXD.js.map} +1 -1
  7. package/dist/billing/index.d.mts +197 -46
  8. package/dist/billing/index.d.ts +197 -46
  9. package/dist/billing/index.js +1166 -589
  10. package/dist/billing/index.js.map +1 -1
  11. package/dist/billing/index.mjs +803 -226
  12. package/dist/billing/index.mjs.map +1 -1
  13. package/dist/{chunk-WPYT4UKJ.js → chunk-2TXE57LE.js} +3 -3
  14. package/dist/{chunk-WPYT4UKJ.js.map → chunk-2TXE57LE.js.map} +1 -1
  15. package/dist/{chunk-G6UE6MEP.js → chunk-5TH2DSAH.js} +901 -204
  16. package/dist/chunk-5TH2DSAH.js.map +1 -0
  17. package/dist/{chunk-X5WIUUNG.mjs → chunk-CFB6FHIY.mjs} +3342 -2377
  18. package/dist/chunk-CFB6FHIY.mjs.map +1 -0
  19. package/dist/{chunk-VC5A3AUZ.mjs → chunk-FK26NX3S.mjs} +701 -4
  20. package/dist/chunk-FK26NX3S.mjs.map +1 -0
  21. package/dist/{chunk-YDYVJM4I.js → chunk-IJME5SAM.js} +4 -4
  22. package/dist/{chunk-YDYVJM4I.js.map → chunk-IJME5SAM.js.map} +1 -1
  23. package/dist/{chunk-W7F5BDSV.mjs → chunk-OKCV4GPJ.mjs} +2 -2
  24. package/dist/{chunk-3CGROPF3.mjs → chunk-RGQYFSJF.mjs} +2 -2
  25. package/dist/{chunk-6SQYXUVP.mjs → chunk-WCHLCOZG.mjs} +2 -2
  26. package/dist/{chunk-S4YJ5WCW.js → chunk-XOSC3FFP.js} +8 -8
  27. package/dist/{chunk-S4YJ5WCW.js.map → chunk-XOSC3FFP.js.map} +1 -1
  28. package/dist/{chunk-TY5FYP3G.js → chunk-ZCOPOO7T.js} +2024 -1059
  29. package/dist/chunk-ZCOPOO7T.js.map +1 -0
  30. package/dist/client/index.js +4 -4
  31. package/dist/client/index.mjs +3 -3
  32. package/dist/components/index.js +4 -4
  33. package/dist/components/index.mjs +3 -3
  34. package/dist/contexts/index.js +4 -4
  35. package/dist/contexts/index.mjs +3 -3
  36. package/dist/core/index.d.mts +248 -3
  37. package/dist/core/index.d.ts +248 -3
  38. package/dist/core/index.js +42 -2
  39. package/dist/core/index.js.map +1 -1
  40. package/dist/core/index.mjs +41 -1
  41. package/dist/{stripe-promotion-code.interface-ClZ7DxS9.d.mts → currency-DT_dveBx.d.mts} +137 -1
  42. package/dist/{stripe-promotion-code.interface-C3qqh3mi.d.ts → currency-pK9eRYRC.d.ts} +137 -1
  43. package/dist/email-automations/index.js +92 -92
  44. package/dist/email-automations/index.mjs +3 -3
  45. package/dist/features/analytics/index.js +121 -121
  46. package/dist/features/analytics/index.mjs +4 -4
  47. package/dist/features/analytics/server.js +4 -4
  48. package/dist/features/analytics/server.mjs +2 -2
  49. package/dist/features/blog/index.js +150 -150
  50. package/dist/features/blog/index.mjs +3 -3
  51. package/dist/features/blog/server.js +16 -16
  52. package/dist/features/blog/server.mjs +1 -1
  53. package/dist/features/help/index.js +37 -37
  54. package/dist/features/help/index.mjs +3 -3
  55. package/dist/features/tokenusage/index.js +124 -124
  56. package/dist/features/tokenusage/index.mjs +4 -4
  57. package/dist/index.d.mts +2 -2
  58. package/dist/index.d.ts +2 -2
  59. package/dist/index.js +43 -3
  60. package/dist/index.js.map +1 -1
  61. package/dist/index.mjs +42 -2
  62. package/dist/server/index.js +3 -3
  63. package/dist/server/index.mjs +2 -2
  64. package/messages/en.json +125 -3
  65. package/messages/it.json +125 -3
  66. package/package.json +1 -1
  67. package/scripts/validate-messages.mjs +1 -0
  68. package/src/billing/index.ts +1 -0
  69. package/src/client/index.ts +4 -0
  70. package/src/core/index.ts +4 -0
  71. package/src/core/registry/ModuleRegistry.ts +3 -0
  72. package/src/features/billing/components/cards/InvoicesSummaryCard.tsx +3 -2
  73. package/src/features/billing/components/cards/SubscriptionSummaryCard.tsx +4 -3
  74. package/src/features/billing/components/containers/BillingDashboardContainer.tsx +22 -5
  75. package/src/features/billing/components/utils/__tests__/discount.spec.ts +59 -0
  76. package/src/features/billing/components/utils/__tests__/url.spec.ts +32 -0
  77. package/src/features/billing/components/utils/discount.ts +38 -0
  78. package/src/features/billing/components/utils/index.ts +2 -0
  79. package/src/features/billing/components/utils/url.ts +12 -0
  80. package/src/features/billing/contexts/CouponContext.tsx +209 -0
  81. package/src/features/billing/contexts/index.ts +1 -0
  82. package/src/features/billing/i18n-keys.ts +79 -0
  83. package/src/features/billing/stripe-coupon/components/containers/CouponContainer.tsx +38 -0
  84. package/src/features/billing/stripe-coupon/components/containers/index.ts +1 -0
  85. package/src/features/billing/stripe-coupon/components/details/CouponDetails.tsx +72 -0
  86. package/src/features/billing/stripe-coupon/components/details/index.ts +1 -0
  87. package/src/features/billing/stripe-coupon/components/forms/CouponCodeEditor.tsx +80 -0
  88. package/src/features/billing/stripe-coupon/components/forms/CouponCodeFields.tsx +214 -0
  89. package/src/features/billing/stripe-coupon/components/forms/CouponEditor.tsx +425 -0
  90. package/src/features/billing/stripe-coupon/components/forms/CouponRefresher.tsx +45 -0
  91. package/src/features/billing/stripe-coupon/components/forms/index.ts +6 -0
  92. package/src/features/billing/stripe-coupon/components/index.ts +5 -0
  93. package/src/features/billing/stripe-coupon/components/lists/CouponCodesList.tsx +61 -0
  94. package/src/features/billing/stripe-coupon/components/lists/CouponsList.tsx +67 -0
  95. package/src/features/billing/stripe-coupon/components/lists/index.ts +2 -0
  96. package/src/features/billing/stripe-coupon/components/widgets/CouponCodeActions.tsx +81 -0
  97. package/src/features/billing/stripe-coupon/components/widgets/index.ts +1 -0
  98. package/src/features/billing/stripe-coupon/data/__tests__/stripe-coupon-models.spec.ts +114 -0
  99. package/src/features/billing/stripe-coupon/data/index.ts +10 -0
  100. package/src/features/billing/stripe-coupon/data/stripe-coupon-code.fields.ts +8 -0
  101. package/src/features/billing/stripe-coupon/data/stripe-coupon-code.interface.ts +44 -0
  102. package/src/features/billing/stripe-coupon/data/stripe-coupon-code.service.ts +92 -0
  103. package/src/features/billing/stripe-coupon/data/stripe-coupon-code.ts +132 -0
  104. package/src/features/billing/stripe-coupon/data/stripe-coupon-offer.interface.ts +17 -0
  105. package/src/features/billing/stripe-coupon/data/stripe-coupon-offer.ts +70 -0
  106. package/src/features/billing/stripe-coupon/data/stripe-coupon.fields.ts +7 -0
  107. package/src/features/billing/stripe-coupon/data/stripe-coupon.interface.ts +55 -0
  108. package/src/features/billing/stripe-coupon/data/stripe-coupon.service.ts +93 -0
  109. package/src/features/billing/stripe-coupon/data/stripe-coupon.ts +167 -0
  110. package/src/features/billing/stripe-coupon/hooks/useStripeCouponCodeTableStructure.tsx +161 -0
  111. package/src/features/billing/stripe-coupon/hooks/useStripeCouponTableStructure.tsx +113 -0
  112. package/src/features/billing/stripe-coupon/index.ts +5 -0
  113. package/src/features/billing/stripe-coupon/stripe-coupon-code.module.ts +15 -0
  114. package/src/features/billing/stripe-coupon/stripe-coupon-offer.module.ts +10 -0
  115. package/src/features/billing/stripe-coupon/stripe-coupon.module.ts +25 -0
  116. package/src/features/billing/stripe-coupon/utils/__tests__/coupon-places.spec.ts +19 -0
  117. package/src/features/billing/stripe-coupon/utils/__tests__/to-promotion-code-result.spec.ts +41 -0
  118. package/src/features/billing/stripe-coupon/utils/coupon-places.ts +23 -0
  119. package/src/features/billing/stripe-coupon/utils/format-coupon-discount.ts +36 -0
  120. package/src/features/billing/stripe-coupon/utils/index.ts +3 -0
  121. package/src/features/billing/stripe-coupon/utils/to-promotion-code-result.ts +23 -0
  122. package/src/features/billing/stripe-customer/components/forms/PaymentMethodForm.tsx +24 -8
  123. package/src/features/billing/stripe-product/components/containers/ProductsListContainer.tsx +21 -6
  124. package/src/features/billing/stripe-promotion-code/components/PromoCodeInput.tsx +60 -19
  125. package/src/features/billing/stripe-promotion-code/data/stripe-promotion-code.interface.ts +2 -0
  126. package/src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx +24 -5
  127. package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +21 -2
  128. package/src/features/billing/stripe-subscription/components/wizards/SubscriptionWizard.tsx +1 -1
  129. package/src/features/billing/stripe-subscription/components/wizards/WizardStepPaymentMethod.tsx +1 -1
  130. package/src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx +60 -49
  131. package/src/features/billing/stripe-subscription/components/wizards/__tests__/review-card.spec.ts +34 -0
  132. package/src/features/billing/stripe-subscription/components/wizards/review-card.ts +24 -0
  133. package/src/features/billing/stripe-subscription/data/__tests__/stripe-subscription.discount.spec.ts +67 -0
  134. package/src/features/billing/stripe-subscription/data/stripe-subscription.interface.ts +14 -0
  135. package/src/features/billing/stripe-subscription/data/stripe-subscription.service.ts +39 -0
  136. package/src/features/billing/stripe-subscription/data/stripe-subscription.ts +21 -0
  137. package/src/features/billing/stripe-subscription/hooks/__tests__/wizard-payment.spec.ts +48 -0
  138. package/src/features/billing/stripe-subscription/hooks/__tests__/wizard-promotion.spec.ts +132 -0
  139. package/src/features/billing/stripe-subscription/hooks/useSubscriptionWizard.ts +138 -12
  140. package/src/features/billing/stripe-subscription/hooks/wizard-payment.ts +30 -0
  141. package/src/features/billing/stripe-subscription/hooks/wizard-promotion.ts +61 -0
  142. package/src/features/user/contexts/CurrentUserContext.tsx +25 -0
  143. package/src/features/user/contexts/__tests__/CurrentUserContext.spec.tsx +121 -2
  144. package/dist/chunk-G6UE6MEP.js.map +0 -1
  145. package/dist/chunk-TY5FYP3G.js.map +0 -1
  146. package/dist/chunk-VC5A3AUZ.mjs.map +0 -1
  147. package/dist/chunk-X5WIUUNG.mjs.map +0 -1
  148. /package/dist/{BlockNoteEditor-GVQCKRMU.mjs.map → BlockNoteEditor-R3WXUFHX.mjs.map} +0 -0
  149. /package/dist/{BlockNoteViewer-U6E3DS4F.mjs.map → BlockNoteViewer-BVVN6D3T.mjs.map} +0 -0
  150. /package/dist/{chunk-W7F5BDSV.mjs.map → chunk-OKCV4GPJ.mjs.map} +0 -0
  151. /package/dist/{chunk-3CGROPF3.mjs.map → chunk-RGQYFSJF.mjs.map} +0 -0
  152. /package/dist/{chunk-6SQYXUVP.mjs.map → chunk-WCHLCOZG.mjs.map} +0 -0
@@ -4571,6 +4571,7 @@ var StripeSubscription = class extends AbstractApiData {
4571
4571
  _trialStart;
4572
4572
  _trialEnd;
4573
4573
  _price;
4574
+ _discount;
4574
4575
  get stripeSubscriptionId() {
4575
4576
  if (!this._stripeSubscriptionId) throw new Error("stripeSubscriptionId is not defined");
4576
4577
  return this._stripeSubscriptionId;
@@ -4602,6 +4603,9 @@ var StripeSubscription = class extends AbstractApiData {
4602
4603
  get price() {
4603
4604
  return this._price;
4604
4605
  }
4606
+ get discount() {
4607
+ return this._discount;
4608
+ }
4605
4609
  rehydrate(data) {
4606
4610
  super.rehydrate(data);
4607
4611
  this._stripeSubscriptionId = data.jsonApi.attributes.stripeSubscriptionId;
@@ -4612,6 +4616,17 @@ var StripeSubscription = class extends AbstractApiData {
4612
4616
  this._canceledAt = data.jsonApi.attributes.canceledAt ? new Date(data.jsonApi.attributes.canceledAt) : void 0;
4613
4617
  this._trialStart = data.jsonApi.attributes.trialStart ? new Date(data.jsonApi.attributes.trialStart) : void 0;
4614
4618
  this._trialEnd = data.jsonApi.attributes.trialEnd ? new Date(data.jsonApi.attributes.trialEnd) : void 0;
4619
+ const attributes = data.jsonApi.attributes;
4620
+ const percentOff = attributes.discountPercentOff ?? void 0;
4621
+ const amountOff = attributes.discountAmountOff ?? void 0;
4622
+ this._discount = attributes.discountDuration && (percentOff !== void 0 || amountOff !== void 0) ? {
4623
+ percentOff,
4624
+ amountOff,
4625
+ currency: attributes.discountCurrency ?? void 0,
4626
+ duration: attributes.discountDuration,
4627
+ durationInMonths: attributes.discountDurationInMonths ?? void 0,
4628
+ end: attributes.discountEnd ? new Date(attributes.discountEnd) : void 0
4629
+ } : void 0;
4615
4630
  this._price = this._readIncluded(data, "price", Modules.StripePrice);
4616
4631
  return this;
4617
4632
  }
@@ -4720,7 +4735,9 @@ var StripeSubscriptionService = class extends AbstractService {
4720
4735
  type: Modules.StripeSubscription,
4721
4736
  method: "POST" /* POST */,
4722
4737
  endpoint: endpoint.generate(),
4723
- input: params
4738
+ input: params,
4739
+ // The wizard reads 410 / 409 / 402 / 422 itself; a global handler must not swallow them
4740
+ suppressGlobalError: true
4724
4741
  });
4725
4742
  return {
4726
4743
  subscription: result.data,
@@ -4744,9 +4761,41 @@ var StripeSubscriptionService = class extends AbstractService {
4744
4761
  type: Modules.StripeSubscription,
4745
4762
  method: "POST" /* POST */,
4746
4763
  endpoint: endpoint.generate(),
4747
- input: params
4764
+ input: params,
4765
+ // The wizard reads 410 / 409 / 402 / 422 itself; a global handler must not swallow them
4766
+ suppressGlobalError: true
4748
4767
  });
4749
4768
  }
4769
+ /**
4770
+ * Change the plan of an existing subscription, with the payment meta.
4771
+ *
4772
+ * A trial upgrade charges at once; when the card asks for 3D Secure the API
4773
+ * answers with `meta.requiresAction` and the `clientSecret` to confirm in the
4774
+ * browser. Without that meta the change needs nothing more.
4775
+ */
4776
+ static async changePlanWithMeta(params) {
4777
+ const endpoint = new EndpointCreator({
4778
+ endpoint: Modules.StripeSubscription,
4779
+ id: params.id,
4780
+ childEndpoint: "change-plan"
4781
+ });
4782
+ const result = await this.callApiWithMeta({
4783
+ type: Modules.StripeSubscription,
4784
+ method: "POST" /* POST */,
4785
+ endpoint: endpoint.generate(),
4786
+ input: params,
4787
+ // The wizard reads 410 / 409 / 402 / 422 itself; a global handler must not swallow them
4788
+ suppressGlobalError: true
4789
+ });
4790
+ return {
4791
+ subscription: result.data,
4792
+ meta: result.meta ?? {
4793
+ clientSecret: null,
4794
+ paymentIntentId: null,
4795
+ requiresAction: false
4796
+ }
4797
+ };
4798
+ }
4750
4799
  /**
4751
4800
  * Get a proration preview for a plan change
4752
4801
  */
@@ -4825,7 +4874,9 @@ var StripeSubscriptionService = class extends AbstractService {
4825
4874
  return this.callApi({
4826
4875
  type: Modules.StripeSubscription,
4827
4876
  method: "POST" /* POST */,
4828
- endpoint: endpoint.generate()
4877
+ endpoint: endpoint.generate(),
4878
+ // The wizard logs a failed sync and carries on (the webhook catches up): no global error after a paid subscription
4879
+ suppressGlobalError: true
4829
4880
  });
4830
4881
  }
4831
4882
  };
@@ -5120,6 +5171,631 @@ var StripePromotionCodeModule = /* @__PURE__ */ __name((factory) => factory({
5120
5171
  moduleId: "b8e4f6a2-9d0c-5b3f-c7e8-4g2d9f0a5c6e"
5121
5172
  }), "StripePromotionCodeModule");
5122
5173
 
5174
+ // src/features/billing/stripe-coupon/data/stripe-coupon.ts
5175
+ var StripeCoupon = class _StripeCoupon extends AbstractApiData {
5176
+ static {
5177
+ __name(this, "StripeCoupon");
5178
+ }
5179
+ _stripeCouponId;
5180
+ _name;
5181
+ _discountType;
5182
+ _percentOff;
5183
+ _amountOff;
5184
+ _currency;
5185
+ _duration;
5186
+ _durationInMonths;
5187
+ _stripeProductIds = [];
5188
+ _redeemBy;
5189
+ _maxRedemptions;
5190
+ _timesRedeemed = 0;
5191
+ _valid = true;
5192
+ _codes = [];
5193
+ get stripeCouponId() {
5194
+ if (!this._stripeCouponId) throw new Error("stripeCouponId is not defined");
5195
+ return this._stripeCouponId;
5196
+ }
5197
+ get name() {
5198
+ return this._name ?? "";
5199
+ }
5200
+ get discountType() {
5201
+ if (!this._discountType) throw new Error("discountType is not defined");
5202
+ return this._discountType;
5203
+ }
5204
+ get percentOff() {
5205
+ return this._percentOff;
5206
+ }
5207
+ get amountOff() {
5208
+ return this._amountOff;
5209
+ }
5210
+ get currency() {
5211
+ return this._currency;
5212
+ }
5213
+ get duration() {
5214
+ if (!this._duration) throw new Error("duration is not defined");
5215
+ return this._duration;
5216
+ }
5217
+ get durationInMonths() {
5218
+ return this._durationInMonths;
5219
+ }
5220
+ get stripeProductIds() {
5221
+ return this._stripeProductIds;
5222
+ }
5223
+ get redeemBy() {
5224
+ return this._redeemBy;
5225
+ }
5226
+ get maxRedemptions() {
5227
+ return this._maxRedemptions;
5228
+ }
5229
+ get timesRedeemed() {
5230
+ return this._timesRedeemed;
5231
+ }
5232
+ get valid() {
5233
+ return this._valid;
5234
+ }
5235
+ get codes() {
5236
+ return this._codes;
5237
+ }
5238
+ rehydrate(data) {
5239
+ super.rehydrate(data);
5240
+ const attributes = data.jsonApi.attributes;
5241
+ this._stripeCouponId = attributes.stripeCouponId;
5242
+ this._name = attributes.name;
5243
+ this._discountType = attributes.discountType;
5244
+ this._percentOff = attributes.percentOff ?? void 0;
5245
+ this._amountOff = attributes.amountOff ?? void 0;
5246
+ this._currency = attributes.currency ?? void 0;
5247
+ this._duration = attributes.duration;
5248
+ this._durationInMonths = attributes.durationInMonths ?? void 0;
5249
+ this._stripeProductIds = attributes.stripeProductIds ?? [];
5250
+ this._redeemBy = attributes.redeemBy ? new Date(attributes.redeemBy) : void 0;
5251
+ this._maxRedemptions = attributes.maxRedemptions ?? void 0;
5252
+ this._timesRedeemed = attributes.timesRedeemed ?? 0;
5253
+ this._valid = attributes.valid ?? true;
5254
+ this._codes = this._readIncluded(data, "codes", Modules.StripeCouponCode) ?? [];
5255
+ return this;
5256
+ }
5257
+ createJsonApi(data) {
5258
+ const response = {
5259
+ data: {
5260
+ type: Modules.StripeCoupon.name,
5261
+ id: data.id,
5262
+ attributes: {
5263
+ name: data.name,
5264
+ discountType: data.discountType,
5265
+ duration: data.duration,
5266
+ firstCode: _StripeCoupon.codeAttributes(data.firstCode)
5267
+ }
5268
+ }
5269
+ };
5270
+ const attributes = response.data.attributes;
5271
+ if (data.stripeCouponId) attributes.stripeCouponId = data.stripeCouponId;
5272
+ if (data.discountType === "percent_off") attributes.percentOff = data.percentOff;
5273
+ else {
5274
+ attributes.amountOff = data.amountOff;
5275
+ attributes.currency = data.currency;
5276
+ }
5277
+ if (data.duration === "repeating") attributes.durationInMonths = data.durationInMonths;
5278
+ if (data.productIds && data.productIds.length > 0) attributes.productIds = data.productIds;
5279
+ if (data.redeemBy !== void 0) attributes.redeemBy = data.redeemBy.toISOString();
5280
+ if (data.maxRedemptions !== void 0) attributes.maxRedemptions = data.maxRedemptions;
5281
+ return response;
5282
+ }
5283
+ /**
5284
+ * Rename is the only change Stripe allows on a coupon after creation.
5285
+ * Dedicated method so the service never needs a generic override.
5286
+ */
5287
+ createRenameJsonApi(data) {
5288
+ return {
5289
+ data: {
5290
+ type: Modules.StripeCoupon.name,
5291
+ id: data.id,
5292
+ attributes: { name: data.name }
5293
+ }
5294
+ };
5295
+ }
5296
+ /** Attributes of a code, shared by the coupon's first code and StripeCouponCode.createJsonApi. */
5297
+ static codeAttributes(code) {
5298
+ const attributes = {};
5299
+ if (code.code) attributes.code = code.code;
5300
+ if (code.firstTimeTransaction !== void 0) attributes.firstTimeTransaction = code.firstTimeTransaction;
5301
+ if (code.minimumAmount !== void 0) attributes.minimumAmount = code.minimumAmount;
5302
+ if (code.minimumAmountCurrency) attributes.minimumAmountCurrency = code.minimumAmountCurrency;
5303
+ if (code.stripeCustomerId) attributes.stripeCustomerId = code.stripeCustomerId;
5304
+ if (code.expiresAt !== void 0) attributes.expiresAt = code.expiresAt.toISOString();
5305
+ if (code.maxRedemptions !== void 0) attributes.maxRedemptions = code.maxRedemptions;
5306
+ if (code.automatic !== void 0) attributes.automatic = code.automatic;
5307
+ return attributes;
5308
+ }
5309
+ };
5310
+
5311
+ // src/features/billing/stripe-coupon/data/stripe-coupon.fields.ts
5312
+ var StripeCouponFields = /* @__PURE__ */ ((StripeCouponFields2) => {
5313
+ StripeCouponFields2["name"] = "name";
5314
+ StripeCouponFields2["discount"] = "discount";
5315
+ StripeCouponFields2["places"] = "places";
5316
+ StripeCouponFields2["codes"] = "codes";
5317
+ StripeCouponFields2["status"] = "status";
5318
+ return StripeCouponFields2;
5319
+ })(StripeCouponFields || {});
5320
+
5321
+ // src/features/billing/stripe-coupon/stripe-coupon.module.ts
5322
+ import { TicketPercentIcon } from "lucide-react";
5323
+ var STRIPE_COUPON_REFRESH_SEGMENT = "refresh";
5324
+ var STRIPE_COUPON_DETAIL_PAGE_URL = "/administration/coupons";
5325
+ var StripeCouponModule = /* @__PURE__ */ __name((factory) => factory({
5326
+ name: "stripe-coupons",
5327
+ // The coupons list lives on the products page (Codes tab), so the module
5328
+ // points there, same value as StripeProductModule. Links to a single coupon
5329
+ // use STRIPE_COUPON_DETAIL_PAGE_URL.
5330
+ pageUrl: "/administration/products",
5331
+ model: StripeCoupon,
5332
+ moduleId: "50bdb0d2-539c-4358-b609-d6beab248bdb",
5333
+ icon: TicketPercentIcon
5334
+ }), "StripeCouponModule");
5335
+
5336
+ // src/features/billing/stripe-coupon/data/stripe-coupon.service.ts
5337
+ var StripeCouponService = class extends AbstractService {
5338
+ static {
5339
+ __name(this, "StripeCouponService");
5340
+ }
5341
+ /**
5342
+ * List all coupons with their codes (admin)
5343
+ */
5344
+ static async listCoupons(params) {
5345
+ const endpoint = new EndpointCreator({
5346
+ endpoint: Modules.StripeCoupon
5347
+ });
5348
+ return this.callApi({
5349
+ type: Modules.StripeCoupon,
5350
+ method: "GET" /* GET */,
5351
+ endpoint: endpoint.generate(),
5352
+ next: params?.next,
5353
+ previous: params?.prev
5354
+ });
5355
+ }
5356
+ /**
5357
+ * Get a specific coupon by ID (admin)
5358
+ */
5359
+ static async getCoupon(params) {
5360
+ const endpoint = new EndpointCreator({
5361
+ endpoint: Modules.StripeCoupon,
5362
+ id: params.id
5363
+ });
5364
+ return this.callApi({
5365
+ type: Modules.StripeCoupon,
5366
+ method: "GET" /* GET */,
5367
+ endpoint: endpoint.generate()
5368
+ });
5369
+ }
5370
+ /**
5371
+ * Create a coupon and its first code (admin)
5372
+ */
5373
+ static async createCoupon(params) {
5374
+ const endpoint = new EndpointCreator({
5375
+ endpoint: Modules.StripeCoupon
5376
+ });
5377
+ return this.callApi({
5378
+ type: Modules.StripeCoupon,
5379
+ method: "POST" /* POST */,
5380
+ endpoint: endpoint.generate(),
5381
+ input: params
5382
+ });
5383
+ }
5384
+ /**
5385
+ * Rename a coupon (admin). The only coupon field Stripe allows to change.
5386
+ */
5387
+ static async renameCoupon(params) {
5388
+ const endpoint = new EndpointCreator({
5389
+ endpoint: Modules.StripeCoupon,
5390
+ id: params.id
5391
+ });
5392
+ return this.callApi({
5393
+ type: Modules.StripeCoupon,
5394
+ method: "PATCH" /* PATCH */,
5395
+ endpoint: endpoint.generate(),
5396
+ input: new StripeCoupon().createRenameJsonApi(params),
5397
+ overridesJsonApiCreation: true
5398
+ });
5399
+ }
5400
+ /**
5401
+ * Re-read the coupon and its codes from Stripe and store the counts (admin)
5402
+ */
5403
+ static async refreshCounts(params) {
5404
+ const endpoint = new EndpointCreator({
5405
+ endpoint: Modules.StripeCoupon,
5406
+ id: params.id,
5407
+ childEndpoint: STRIPE_COUPON_REFRESH_SEGMENT
5408
+ });
5409
+ return this.callApi({
5410
+ type: Modules.StripeCoupon,
5411
+ method: "POST" /* POST */,
5412
+ endpoint: endpoint.generate()
5413
+ });
5414
+ }
5415
+ };
5416
+
5417
+ // src/features/billing/stripe-coupon/data/stripe-coupon-code.ts
5418
+ var StripeCouponCode = class extends AbstractApiData {
5419
+ static {
5420
+ __name(this, "StripeCouponCode");
5421
+ }
5422
+ _stripePromotionCodeId;
5423
+ _code = "";
5424
+ _active = true;
5425
+ _automatic = false;
5426
+ _firstTimeTransaction = false;
5427
+ _minimumAmount;
5428
+ _minimumAmountCurrency;
5429
+ _stripeCustomerId;
5430
+ _expiresAt;
5431
+ _maxRedemptions;
5432
+ _timesRedeemed = 0;
5433
+ _coupon;
5434
+ get stripePromotionCodeId() {
5435
+ if (!this._stripePromotionCodeId) throw new Error("stripePromotionCodeId is not defined");
5436
+ return this._stripePromotionCodeId;
5437
+ }
5438
+ get code() {
5439
+ return this._code;
5440
+ }
5441
+ get active() {
5442
+ return this._active;
5443
+ }
5444
+ get automatic() {
5445
+ return this._automatic;
5446
+ }
5447
+ get firstTimeTransaction() {
5448
+ return this._firstTimeTransaction;
5449
+ }
5450
+ get minimumAmount() {
5451
+ return this._minimumAmount;
5452
+ }
5453
+ get minimumAmountCurrency() {
5454
+ return this._minimumAmountCurrency;
5455
+ }
5456
+ get stripeCustomerId() {
5457
+ return this._stripeCustomerId;
5458
+ }
5459
+ get expiresAt() {
5460
+ return this._expiresAt;
5461
+ }
5462
+ get maxRedemptions() {
5463
+ return this._maxRedemptions;
5464
+ }
5465
+ get timesRedeemed() {
5466
+ return this._timesRedeemed;
5467
+ }
5468
+ get coupon() {
5469
+ return this._coupon;
5470
+ }
5471
+ rehydrate(data) {
5472
+ super.rehydrate(data);
5473
+ const attributes = data.jsonApi.attributes;
5474
+ this._stripePromotionCodeId = attributes.stripePromotionCodeId;
5475
+ this._code = attributes.code ?? "";
5476
+ this._active = attributes.active ?? true;
5477
+ this._automatic = attributes.automatic ?? false;
5478
+ this._firstTimeTransaction = attributes.firstTimeTransaction ?? false;
5479
+ this._minimumAmount = attributes.minimumAmount ?? void 0;
5480
+ this._minimumAmountCurrency = attributes.minimumAmountCurrency ?? void 0;
5481
+ this._stripeCustomerId = attributes.stripeCustomerId ?? void 0;
5482
+ this._expiresAt = attributes.expiresAt ? new Date(attributes.expiresAt) : void 0;
5483
+ this._maxRedemptions = attributes.maxRedemptions ?? void 0;
5484
+ this._timesRedeemed = attributes.timesRedeemed ?? 0;
5485
+ this._coupon = this._readIncluded(data, "coupon", Modules.StripeCoupon);
5486
+ return this;
5487
+ }
5488
+ createJsonApi(data) {
5489
+ const { id, couponId, ...code } = data;
5490
+ return {
5491
+ data: {
5492
+ type: Modules.StripeCouponCode.name,
5493
+ id,
5494
+ attributes: StripeCoupon.codeAttributes(code),
5495
+ relationships: {
5496
+ coupon: {
5497
+ data: {
5498
+ type: Modules.StripeCoupon.name,
5499
+ id: couponId
5500
+ }
5501
+ }
5502
+ }
5503
+ }
5504
+ };
5505
+ }
5506
+ /**
5507
+ * PATCH body for the flags a code can still change after creation.
5508
+ * Only the flags that are set are sent, so switching one never touches the other.
5509
+ */
5510
+ createFlagsJsonApi(data) {
5511
+ const attributes = {};
5512
+ if (data.active !== void 0) attributes.active = data.active;
5513
+ if (data.automatic !== void 0) attributes.automatic = data.automatic;
5514
+ return {
5515
+ data: {
5516
+ type: Modules.StripeCouponCode.name,
5517
+ id: data.id,
5518
+ attributes
5519
+ }
5520
+ };
5521
+ }
5522
+ };
5523
+
5524
+ // src/features/billing/stripe-coupon/data/stripe-coupon-code.fields.ts
5525
+ var StripeCouponCodeFields = /* @__PURE__ */ ((StripeCouponCodeFields2) => {
5526
+ StripeCouponCodeFields2["code"] = "code";
5527
+ StripeCouponCodeFields2["places"] = "places";
5528
+ StripeCouponCodeFields2["expiresAt"] = "expiresAt";
5529
+ StripeCouponCodeFields2["automatic"] = "automatic";
5530
+ StripeCouponCodeFields2["status"] = "status";
5531
+ StripeCouponCodeFields2["actions"] = "actions";
5532
+ return StripeCouponCodeFields2;
5533
+ })(StripeCouponCodeFields || {});
5534
+
5535
+ // src/features/billing/stripe-coupon/stripe-coupon-code.module.ts
5536
+ var STRIPE_COUPON_CODE_AUTOMATIC_SEGMENT = "automatic";
5537
+ var StripeCouponCodeModule = /* @__PURE__ */ __name((factory) => factory({
5538
+ name: "stripe-coupon-codes",
5539
+ // Codes are listed on the products page (Codes tab), same value as
5540
+ // StripeProductModule. A code has no page of its own.
5541
+ pageUrl: "/administration/products",
5542
+ model: StripeCouponCode,
5543
+ moduleId: "85feb4c7-ff22-416a-b856-8dafcf28ff26"
5544
+ }), "StripeCouponCodeModule");
5545
+
5546
+ // src/features/billing/stripe-coupon/data/stripe-coupon-code.service.ts
5547
+ var StripeCouponCodeService = class extends AbstractService {
5548
+ static {
5549
+ __name(this, "StripeCouponCodeService");
5550
+ }
5551
+ /**
5552
+ * List the codes of a coupon (admin)
5553
+ */
5554
+ static async listByCoupon(params) {
5555
+ const endpoint = new EndpointCreator({
5556
+ endpoint: Modules.StripeCoupon,
5557
+ id: params.couponId,
5558
+ childEndpoint: Modules.StripeCouponCode
5559
+ });
5560
+ return this.callApi({
5561
+ type: Modules.StripeCouponCode,
5562
+ method: "GET" /* GET */,
5563
+ endpoint: endpoint.generate(),
5564
+ next: params.next,
5565
+ previous: params.prev
5566
+ });
5567
+ }
5568
+ /**
5569
+ * Create a code on an existing coupon (admin)
5570
+ */
5571
+ static async createCode(params) {
5572
+ const endpoint = new EndpointCreator({
5573
+ endpoint: Modules.StripeCouponCode
5574
+ });
5575
+ return this.callApi({
5576
+ type: Modules.StripeCouponCode,
5577
+ method: "POST" /* POST */,
5578
+ endpoint: endpoint.generate(),
5579
+ input: params
5580
+ });
5581
+ }
5582
+ /**
5583
+ * Switch "Apply automatically" and / or deactivate / reactivate a code (admin)
5584
+ */
5585
+ static async updateFlags(params) {
5586
+ const endpoint = new EndpointCreator({
5587
+ endpoint: Modules.StripeCouponCode,
5588
+ id: params.id
5589
+ });
5590
+ return this.callApi({
5591
+ type: Modules.StripeCouponCode,
5592
+ method: "PATCH" /* PATCH */,
5593
+ endpoint: endpoint.generate(),
5594
+ input: new StripeCouponCode().createFlagsJsonApi(params),
5595
+ overridesJsonApiCreation: true
5596
+ });
5597
+ }
5598
+ /**
5599
+ * The code the server would apply automatically for this price at a first
5600
+ * payment, or null when none applies (logged-in company administrator)
5601
+ */
5602
+ static async findAutomatic(params) {
5603
+ const endpoint = new EndpointCreator({
5604
+ endpoint: Modules.StripeCouponCode,
5605
+ id: STRIPE_COUPON_CODE_AUTOMATIC_SEGMENT
5606
+ });
5607
+ endpoint.addAdditionalParam("priceId", params.priceId);
5608
+ const codes = await this.callApi({
5609
+ type: Modules.StripeCouponCode,
5610
+ method: "GET" /* GET */,
5611
+ endpoint: endpoint.generate(),
5612
+ // A failed lookup must reach the wizard, which then refuses to show full price as the truth
5613
+ suppressGlobalError: true
5614
+ });
5615
+ return codes?.[0] ?? null;
5616
+ }
5617
+ };
5618
+
5619
+ // src/features/billing/stripe-coupon/data/stripe-coupon-offer.ts
5620
+ var StripeCouponOffer = class extends AbstractApiData {
5621
+ static {
5622
+ __name(this, "StripeCouponOffer");
5623
+ }
5624
+ _discountType;
5625
+ _percentOff;
5626
+ _amountOff;
5627
+ _currency;
5628
+ _duration;
5629
+ _durationInMonths;
5630
+ _placesLeft = 0;
5631
+ _placesTotal = 0;
5632
+ get discountType() {
5633
+ if (!this._discountType) throw new Error("discountType is not defined");
5634
+ return this._discountType;
5635
+ }
5636
+ get percentOff() {
5637
+ return this._percentOff;
5638
+ }
5639
+ get amountOff() {
5640
+ return this._amountOff;
5641
+ }
5642
+ get currency() {
5643
+ return this._currency;
5644
+ }
5645
+ get duration() {
5646
+ if (!this._duration) throw new Error("duration is not defined");
5647
+ return this._duration;
5648
+ }
5649
+ get durationInMonths() {
5650
+ return this._durationInMonths;
5651
+ }
5652
+ get placesLeft() {
5653
+ return this._placesLeft;
5654
+ }
5655
+ get placesTotal() {
5656
+ return this._placesTotal;
5657
+ }
5658
+ rehydrate(data) {
5659
+ super.rehydrate(data);
5660
+ const attributes = data.jsonApi.attributes;
5661
+ this._discountType = attributes.discountType;
5662
+ this._percentOff = attributes.percentOff ?? void 0;
5663
+ this._amountOff = attributes.amountOff ?? void 0;
5664
+ this._currency = attributes.currency ?? void 0;
5665
+ this._duration = attributes.duration;
5666
+ this._durationInMonths = attributes.durationInMonths ?? void 0;
5667
+ this._placesLeft = attributes.placesLeft ?? 0;
5668
+ this._placesTotal = attributes.placesTotal ?? 0;
5669
+ return this;
5670
+ }
5671
+ createJsonApi(_data) {
5672
+ throw new Error("StripeCouponOffer is declared by the API and is read-only");
5673
+ }
5674
+ };
5675
+
5676
+ // src/features/billing/stripe-coupon/utils/coupon-places.ts
5677
+ function couponPlacesLeft(code, coupon) {
5678
+ const remaining = [code, coupon].filter((item) => typeof item.maxRedemptions === "number").map((item) => Math.max(0, item.maxRedemptions - (item.timesRedeemed ?? 0)));
5679
+ return remaining.length === 0 ? null : Math.min(...remaining);
5680
+ }
5681
+ __name(couponPlacesLeft, "couponPlacesLeft");
5682
+ function couponPlacesTotal(code, coupon) {
5683
+ const limits = [code.maxRedemptions, coupon.maxRedemptions].filter(
5684
+ (limit) => typeof limit === "number"
5685
+ );
5686
+ return limits.length === 0 ? null : Math.min(...limits);
5687
+ }
5688
+ __name(couponPlacesTotal, "couponPlacesTotal");
5689
+
5690
+ // src/features/billing/components/utils/format-options.ts
5691
+ var DEFAULT_BILLING_LOCALE = "en-US";
5692
+
5693
+ // src/features/billing/components/utils/currency.ts
5694
+ function formatIntervalEnglish(price) {
5695
+ if (price.priceType === "one_time" || !price.recurring) {
5696
+ return "one-time";
5697
+ }
5698
+ const { interval, intervalCount } = price.recurring;
5699
+ if (intervalCount === 1) {
5700
+ return `/${interval}`;
5701
+ }
5702
+ const pluralInterval = interval === "day" ? "days" : interval === "week" ? "weeks" : interval === "month" ? "months" : "years";
5703
+ return `/${intervalCount} ${pluralInterval}`;
5704
+ }
5705
+ __name(formatIntervalEnglish, "formatIntervalEnglish");
5706
+ function formatInterval(price, options = {}) {
5707
+ const { t } = options;
5708
+ if (!t) return formatIntervalEnglish(price);
5709
+ if (price.priceType === "one_time" || !price.recurring) {
5710
+ return t("billing.ui.interval.one_time");
5711
+ }
5712
+ const { interval, intervalCount } = price.recurring;
5713
+ if (intervalCount === 1) {
5714
+ switch (interval) {
5715
+ case "day":
5716
+ return t("billing.ui.interval.per_day");
5717
+ case "week":
5718
+ return t("billing.ui.interval.per_week");
5719
+ case "month":
5720
+ return t("billing.ui.interval.per_month");
5721
+ default:
5722
+ return t("billing.ui.interval.per_year");
5723
+ }
5724
+ }
5725
+ switch (interval) {
5726
+ case "day":
5727
+ return t("billing.ui.interval.per_days", { count: intervalCount });
5728
+ case "week":
5729
+ return t("billing.ui.interval.per_weeks", { count: intervalCount });
5730
+ case "month":
5731
+ return t("billing.ui.interval.per_months", { count: intervalCount });
5732
+ default:
5733
+ return t("billing.ui.interval.per_years", { count: intervalCount });
5734
+ }
5735
+ }
5736
+ __name(formatInterval, "formatInterval");
5737
+ function formatCurrency(amount, currency2, options = {}) {
5738
+ const { locale } = options;
5739
+ if (amount === void 0 && !locale) return "$0.00";
5740
+ const dollars = (amount ?? 0) / 100;
5741
+ try {
5742
+ return new Intl.NumberFormat(locale ?? DEFAULT_BILLING_LOCALE, {
5743
+ style: "currency",
5744
+ currency: currency2.toUpperCase(),
5745
+ minimumFractionDigits: 2,
5746
+ maximumFractionDigits: 2
5747
+ }).format(dollars);
5748
+ } catch (error) {
5749
+ console.error("Error formatting currency:", error);
5750
+ return `$${dollars.toFixed(2)}`;
5751
+ }
5752
+ }
5753
+ __name(formatCurrency, "formatCurrency");
5754
+ function formatFixed(value, locale, digits) {
5755
+ return new Intl.NumberFormat(locale ?? DEFAULT_BILLING_LOCALE, {
5756
+ minimumFractionDigits: digits,
5757
+ maximumFractionDigits: digits,
5758
+ useGrouping: false
5759
+ }).format(value);
5760
+ }
5761
+ __name(formatFixed, "formatFixed");
5762
+
5763
+ // src/features/billing/stripe-coupon/utils/format-coupon-discount.ts
5764
+ function formatCouponDiscount(coupon, t, fmt = {}) {
5765
+ const amount = coupon.discountType === "percent_off" ? t("billing.admin.coupons.discount.percent", { value: String(coupon.percentOff ?? 0) }) : t("billing.admin.coupons.discount.amount", {
5766
+ amount: formatCurrency(coupon.amountOff, coupon.currency ?? "eur", fmt)
5767
+ });
5768
+ const duration = coupon.duration === "repeating" ? t("billing.admin.coupons.discount.repeating", { months: String(coupon.durationInMonths ?? 0) }) : coupon.duration === "once" ? t("billing.admin.coupons.discount.once") : t("billing.admin.coupons.discount.forever");
5769
+ return `${amount} ${duration}`;
5770
+ }
5771
+ __name(formatCouponDiscount, "formatCouponDiscount");
5772
+
5773
+ // src/features/billing/stripe-coupon/utils/to-promotion-code-result.ts
5774
+ function toPromotionCodeResult(code) {
5775
+ const coupon = code.coupon;
5776
+ const discountType = coupon?.discountType;
5777
+ return {
5778
+ valid: true,
5779
+ automatic: true,
5780
+ promotionCodeId: code.stripePromotionCodeId,
5781
+ code: code.code,
5782
+ discountType,
5783
+ discountValue: discountType === "amount_off" ? coupon?.amountOff : coupon?.percentOff,
5784
+ currency: discountType === "amount_off" ? coupon?.currency : void 0,
5785
+ duration: coupon?.duration,
5786
+ durationInMonths: coupon?.durationInMonths
5787
+ };
5788
+ }
5789
+ __name(toPromotionCodeResult, "toPromotionCodeResult");
5790
+
5791
+ // src/features/billing/stripe-coupon/stripe-coupon-offer.module.ts
5792
+ var StripeCouponOfferModule = /* @__PURE__ */ __name((factory) => factory({
5793
+ name: "stripe-coupon-offers",
5794
+ pageUrl: "/pricing",
5795
+ model: StripeCouponOffer,
5796
+ moduleId: "6859d6cc-b94c-4cf7-8a02-b71ad59d75d2"
5797
+ }), "StripeCouponOfferModule");
5798
+
5123
5799
  // src/features/ai-connection/data/ai-connection.ts
5124
5800
  var AiConnection = class extends AbstractApiData {
5125
5801
  static {
@@ -11510,6 +12186,27 @@ export {
11510
12186
  StripePromotionCodeService,
11511
12187
  StripePromotionCode,
11512
12188
  StripePromotionCodeModule,
12189
+ StripeCoupon,
12190
+ StripeCouponFields,
12191
+ STRIPE_COUPON_REFRESH_SEGMENT,
12192
+ STRIPE_COUPON_DETAIL_PAGE_URL,
12193
+ StripeCouponModule,
12194
+ StripeCouponService,
12195
+ StripeCouponCode,
12196
+ StripeCouponCodeFields,
12197
+ STRIPE_COUPON_CODE_AUTOMATIC_SEGMENT,
12198
+ StripeCouponCodeModule,
12199
+ StripeCouponCodeService,
12200
+ StripeCouponOffer,
12201
+ couponPlacesLeft,
12202
+ couponPlacesTotal,
12203
+ DEFAULT_BILLING_LOCALE,
12204
+ formatInterval,
12205
+ formatCurrency,
12206
+ formatFixed,
12207
+ formatCouponDiscount,
12208
+ toPromotionCodeResult,
12209
+ StripeCouponOfferModule,
11513
12210
  AiConnection,
11514
12211
  AiConnectionFields,
11515
12212
  AiConnectionService,
@@ -11667,4 +12364,4 @@ export {
11667
12364
  AuditLogService,
11668
12365
  AuditLogModule
11669
12366
  };
11670
- //# sourceMappingURL=chunk-VC5A3AUZ.mjs.map
12367
+ //# sourceMappingURL=chunk-FK26NX3S.mjs.map