@carlonicora/nextjs-jsonapi 5.5.0 → 5.6.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-THBJH2UR.js → BlockNoteEditor-AE3ZTEEH.js} +19 -19
  2. package/dist/{BlockNoteEditor-THBJH2UR.js.map → BlockNoteEditor-AE3ZTEEH.js.map} +1 -1
  3. package/dist/{BlockNoteEditor-GVQCKRMU.mjs → BlockNoteEditor-NEYG5L6W.mjs} +4 -4
  4. package/dist/{BlockNoteViewer-U6E3DS4F.mjs → BlockNoteViewer-3OUT5UFY.mjs} +2 -2
  5. package/dist/{BlockNoteViewer-VZOVKTFO.js → BlockNoteViewer-4CFKQM7U.js} +3 -3
  6. package/dist/{BlockNoteViewer-VZOVKTFO.js.map → BlockNoteViewer-4CFKQM7U.js.map} +1 -1
  7. package/dist/billing/index.d.mts +186 -25
  8. package/dist/billing/index.d.ts +186 -25
  9. package/dist/billing/index.js +1148 -587
  10. package/dist/billing/index.js.map +1 -1
  11. package/dist/billing/index.mjs +785 -224
  12. package/dist/billing/index.mjs.map +1 -1
  13. package/dist/{chunk-WPYT4UKJ.js → chunk-3I5AAJXV.js} +3 -3
  14. package/dist/{chunk-WPYT4UKJ.js.map → chunk-3I5AAJXV.js.map} +1 -1
  15. package/dist/{chunk-YDYVJM4I.js → chunk-53BAULDP.js} +4 -4
  16. package/dist/{chunk-YDYVJM4I.js.map → chunk-53BAULDP.js.map} +1 -1
  17. package/dist/{chunk-3CGROPF3.mjs → chunk-BTPUYUQ3.mjs} +2 -2
  18. package/dist/{chunk-VC5A3AUZ.mjs → chunk-EYA2F6AN.mjs} +696 -4
  19. package/dist/chunk-EYA2F6AN.mjs.map +1 -0
  20. package/dist/{chunk-G6UE6MEP.js → chunk-HKZAESS6.js} +896 -204
  21. package/dist/chunk-HKZAESS6.js.map +1 -0
  22. package/dist/{chunk-W7F5BDSV.mjs → chunk-KQHBONL4.mjs} +2 -2
  23. package/dist/{chunk-TY5FYP3G.js → chunk-LQ4DK4JF.js} +1919 -1056
  24. package/dist/chunk-LQ4DK4JF.js.map +1 -0
  25. package/dist/{chunk-S4YJ5WCW.js → chunk-RL3PL3KV.js} +8 -8
  26. package/dist/{chunk-S4YJ5WCW.js.map → chunk-RL3PL3KV.js.map} +1 -1
  27. package/dist/{chunk-X5WIUUNG.mjs → chunk-SFYPXCK4.mjs} +3237 -2374
  28. package/dist/chunk-SFYPXCK4.mjs.map +1 -0
  29. package/dist/{chunk-6SQYXUVP.mjs → chunk-Y7RR57EW.mjs} +2 -2
  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 +242 -3
  37. package/dist/core/index.d.ts +242 -3
  38. package/dist/core/index.js +34 -2
  39. package/dist/core/index.js.map +1 -1
  40. package/dist/core/index.mjs +33 -1
  41. package/dist/email-automations/index.js +92 -92
  42. package/dist/email-automations/index.mjs +3 -3
  43. package/dist/features/analytics/index.js +121 -121
  44. package/dist/features/analytics/index.mjs +4 -4
  45. package/dist/features/analytics/server.js +4 -4
  46. package/dist/features/analytics/server.mjs +2 -2
  47. package/dist/features/blog/index.js +150 -150
  48. package/dist/features/blog/index.mjs +3 -3
  49. package/dist/features/blog/server.js +16 -16
  50. package/dist/features/blog/server.mjs +1 -1
  51. package/dist/features/help/index.js +37 -37
  52. package/dist/features/help/index.mjs +3 -3
  53. package/dist/features/tokenusage/index.js +124 -124
  54. package/dist/features/tokenusage/index.mjs +4 -4
  55. package/dist/{stripe-promotion-code.interface-C3qqh3mi.d.ts → format-options-BtX3o0Yu.d.ts} +104 -1
  56. package/dist/{stripe-promotion-code.interface-ClZ7DxS9.d.mts → format-options-D6c7FNDi.d.mts} +104 -1
  57. package/dist/index.d.mts +2 -2
  58. package/dist/index.d.ts +2 -2
  59. package/dist/index.js +35 -3
  60. package/dist/index.js.map +1 -1
  61. package/dist/index.mjs +34 -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 +1 -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 +211 -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 +69 -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 +79 -0
  88. package/src/features/billing/stripe-coupon/components/forms/CouponCodeFields.tsx +192 -0
  89. package/src/features/billing/stripe-coupon/components/forms/CouponEditor.tsx +333 -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 +80 -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 +51 -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 +165 -0
  110. package/src/features/billing/stripe-coupon/hooks/useStripeCouponCodeTableStructure.tsx +154 -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 +14 -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 +18 -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 +54 -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-NEYG5L6W.mjs.map} +0 -0
  149. /package/dist/{BlockNoteViewer-U6E3DS4F.mjs.map → BlockNoteViewer-3OUT5UFY.mjs.map} +0 -0
  150. /package/dist/{chunk-3CGROPF3.mjs.map → chunk-BTPUYUQ3.mjs.map} +0 -0
  151. /package/dist/{chunk-W7F5BDSV.mjs.map → chunk-KQHBONL4.mjs.map} +0 -0
  152. /package/dist/{chunk-6SQYXUVP.mjs.map → chunk-Y7RR57EW.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,627 @@ 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.percentOff !== void 0) attributes.percentOff = data.percentOff;
5273
+ if (data.amountOff !== void 0) attributes.amountOff = data.amountOff;
5274
+ if (data.currency) attributes.currency = data.currency;
5275
+ if (data.durationInMonths !== void 0) attributes.durationInMonths = data.durationInMonths;
5276
+ if (data.productIds && data.productIds.length > 0) attributes.productIds = data.productIds;
5277
+ if (data.redeemBy !== void 0) attributes.redeemBy = data.redeemBy.toISOString();
5278
+ if (data.maxRedemptions !== void 0) attributes.maxRedemptions = data.maxRedemptions;
5279
+ return response;
5280
+ }
5281
+ /**
5282
+ * Rename is the only change Stripe allows on a coupon after creation.
5283
+ * Dedicated method so the service never needs a generic override.
5284
+ */
5285
+ createRenameJsonApi(data) {
5286
+ return {
5287
+ data: {
5288
+ type: Modules.StripeCoupon.name,
5289
+ id: data.id,
5290
+ attributes: { name: data.name }
5291
+ }
5292
+ };
5293
+ }
5294
+ /** Attributes of a code, shared by the coupon's first code and StripeCouponCode.createJsonApi. */
5295
+ static codeAttributes(code) {
5296
+ const attributes = {};
5297
+ if (code.code) attributes.code = code.code;
5298
+ if (code.firstTimeTransaction !== void 0) attributes.firstTimeTransaction = code.firstTimeTransaction;
5299
+ if (code.minimumAmount !== void 0) attributes.minimumAmount = code.minimumAmount;
5300
+ if (code.minimumAmountCurrency) attributes.minimumAmountCurrency = code.minimumAmountCurrency;
5301
+ if (code.stripeCustomerId) attributes.stripeCustomerId = code.stripeCustomerId;
5302
+ if (code.expiresAt !== void 0) attributes.expiresAt = code.expiresAt.toISOString();
5303
+ if (code.maxRedemptions !== void 0) attributes.maxRedemptions = code.maxRedemptions;
5304
+ if (code.automatic !== void 0) attributes.automatic = code.automatic;
5305
+ return attributes;
5306
+ }
5307
+ };
5308
+
5309
+ // src/features/billing/stripe-coupon/data/stripe-coupon.fields.ts
5310
+ var StripeCouponFields = /* @__PURE__ */ ((StripeCouponFields2) => {
5311
+ StripeCouponFields2["name"] = "name";
5312
+ StripeCouponFields2["discount"] = "discount";
5313
+ StripeCouponFields2["places"] = "places";
5314
+ StripeCouponFields2["codes"] = "codes";
5315
+ StripeCouponFields2["status"] = "status";
5316
+ return StripeCouponFields2;
5317
+ })(StripeCouponFields || {});
5318
+
5319
+ // src/features/billing/stripe-coupon/stripe-coupon.module.ts
5320
+ import { TicketPercentIcon } from "lucide-react";
5321
+ var STRIPE_COUPON_REFRESH_SEGMENT = "refresh";
5322
+ var StripeCouponModule = /* @__PURE__ */ __name((factory) => factory({
5323
+ name: "stripe-coupons",
5324
+ // The administration route this entity is served at. `name` above stays the
5325
+ // API endpoint; this drives generateUrl / rewriteUrl / EditorSheet
5326
+ // navigation, so it must match the real Next.js route.
5327
+ pageUrl: "/administration/coupons",
5328
+ model: StripeCoupon,
5329
+ moduleId: "50bdb0d2-539c-4358-b609-d6beab248bdb",
5330
+ icon: TicketPercentIcon
5331
+ }), "StripeCouponModule");
5332
+
5333
+ // src/features/billing/stripe-coupon/data/stripe-coupon.service.ts
5334
+ var StripeCouponService = class extends AbstractService {
5335
+ static {
5336
+ __name(this, "StripeCouponService");
5337
+ }
5338
+ /**
5339
+ * List all coupons with their codes (admin)
5340
+ */
5341
+ static async listCoupons(params) {
5342
+ const endpoint = new EndpointCreator({
5343
+ endpoint: Modules.StripeCoupon
5344
+ });
5345
+ return this.callApi({
5346
+ type: Modules.StripeCoupon,
5347
+ method: "GET" /* GET */,
5348
+ endpoint: endpoint.generate(),
5349
+ next: params?.next,
5350
+ previous: params?.prev
5351
+ });
5352
+ }
5353
+ /**
5354
+ * Get a specific coupon by ID (admin)
5355
+ */
5356
+ static async getCoupon(params) {
5357
+ const endpoint = new EndpointCreator({
5358
+ endpoint: Modules.StripeCoupon,
5359
+ id: params.id
5360
+ });
5361
+ return this.callApi({
5362
+ type: Modules.StripeCoupon,
5363
+ method: "GET" /* GET */,
5364
+ endpoint: endpoint.generate()
5365
+ });
5366
+ }
5367
+ /**
5368
+ * Create a coupon and its first code (admin)
5369
+ */
5370
+ static async createCoupon(params) {
5371
+ const endpoint = new EndpointCreator({
5372
+ endpoint: Modules.StripeCoupon
5373
+ });
5374
+ return this.callApi({
5375
+ type: Modules.StripeCoupon,
5376
+ method: "POST" /* POST */,
5377
+ endpoint: endpoint.generate(),
5378
+ input: params
5379
+ });
5380
+ }
5381
+ /**
5382
+ * Rename a coupon (admin). The only coupon field Stripe allows to change.
5383
+ */
5384
+ static async renameCoupon(params) {
5385
+ const endpoint = new EndpointCreator({
5386
+ endpoint: Modules.StripeCoupon,
5387
+ id: params.id
5388
+ });
5389
+ return this.callApi({
5390
+ type: Modules.StripeCoupon,
5391
+ method: "PATCH" /* PATCH */,
5392
+ endpoint: endpoint.generate(),
5393
+ input: new StripeCoupon().createRenameJsonApi(params),
5394
+ overridesJsonApiCreation: true
5395
+ });
5396
+ }
5397
+ /**
5398
+ * Re-read the coupon and its codes from Stripe and store the counts (admin)
5399
+ */
5400
+ static async refreshCounts(params) {
5401
+ const endpoint = new EndpointCreator({
5402
+ endpoint: Modules.StripeCoupon,
5403
+ id: params.id,
5404
+ childEndpoint: STRIPE_COUPON_REFRESH_SEGMENT
5405
+ });
5406
+ return this.callApi({
5407
+ type: Modules.StripeCoupon,
5408
+ method: "POST" /* POST */,
5409
+ endpoint: endpoint.generate()
5410
+ });
5411
+ }
5412
+ };
5413
+
5414
+ // src/features/billing/stripe-coupon/data/stripe-coupon-code.ts
5415
+ var StripeCouponCode = class extends AbstractApiData {
5416
+ static {
5417
+ __name(this, "StripeCouponCode");
5418
+ }
5419
+ _stripePromotionCodeId;
5420
+ _code = "";
5421
+ _active = true;
5422
+ _automatic = false;
5423
+ _firstTimeTransaction = false;
5424
+ _minimumAmount;
5425
+ _minimumAmountCurrency;
5426
+ _stripeCustomerId;
5427
+ _expiresAt;
5428
+ _maxRedemptions;
5429
+ _timesRedeemed = 0;
5430
+ _coupon;
5431
+ get stripePromotionCodeId() {
5432
+ if (!this._stripePromotionCodeId) throw new Error("stripePromotionCodeId is not defined");
5433
+ return this._stripePromotionCodeId;
5434
+ }
5435
+ get code() {
5436
+ return this._code;
5437
+ }
5438
+ get active() {
5439
+ return this._active;
5440
+ }
5441
+ get automatic() {
5442
+ return this._automatic;
5443
+ }
5444
+ get firstTimeTransaction() {
5445
+ return this._firstTimeTransaction;
5446
+ }
5447
+ get minimumAmount() {
5448
+ return this._minimumAmount;
5449
+ }
5450
+ get minimumAmountCurrency() {
5451
+ return this._minimumAmountCurrency;
5452
+ }
5453
+ get stripeCustomerId() {
5454
+ return this._stripeCustomerId;
5455
+ }
5456
+ get expiresAt() {
5457
+ return this._expiresAt;
5458
+ }
5459
+ get maxRedemptions() {
5460
+ return this._maxRedemptions;
5461
+ }
5462
+ get timesRedeemed() {
5463
+ return this._timesRedeemed;
5464
+ }
5465
+ get coupon() {
5466
+ return this._coupon;
5467
+ }
5468
+ rehydrate(data) {
5469
+ super.rehydrate(data);
5470
+ const attributes = data.jsonApi.attributes;
5471
+ this._stripePromotionCodeId = attributes.stripePromotionCodeId;
5472
+ this._code = attributes.code ?? "";
5473
+ this._active = attributes.active ?? true;
5474
+ this._automatic = attributes.automatic ?? false;
5475
+ this._firstTimeTransaction = attributes.firstTimeTransaction ?? false;
5476
+ this._minimumAmount = attributes.minimumAmount ?? void 0;
5477
+ this._minimumAmountCurrency = attributes.minimumAmountCurrency ?? void 0;
5478
+ this._stripeCustomerId = attributes.stripeCustomerId ?? void 0;
5479
+ this._expiresAt = attributes.expiresAt ? new Date(attributes.expiresAt) : void 0;
5480
+ this._maxRedemptions = attributes.maxRedemptions ?? void 0;
5481
+ this._timesRedeemed = attributes.timesRedeemed ?? 0;
5482
+ this._coupon = this._readIncluded(data, "coupon", Modules.StripeCoupon);
5483
+ return this;
5484
+ }
5485
+ createJsonApi(data) {
5486
+ const { id, couponId, ...code } = data;
5487
+ return {
5488
+ data: {
5489
+ type: Modules.StripeCouponCode.name,
5490
+ id,
5491
+ attributes: StripeCoupon.codeAttributes(code),
5492
+ relationships: {
5493
+ coupon: {
5494
+ data: {
5495
+ type: Modules.StripeCoupon.name,
5496
+ id: couponId
5497
+ }
5498
+ }
5499
+ }
5500
+ }
5501
+ };
5502
+ }
5503
+ /**
5504
+ * PATCH body for the flags a code can still change after creation.
5505
+ * Only the flags that are set are sent, so switching one never touches the other.
5506
+ */
5507
+ createFlagsJsonApi(data) {
5508
+ const attributes = {};
5509
+ if (data.active !== void 0) attributes.active = data.active;
5510
+ if (data.automatic !== void 0) attributes.automatic = data.automatic;
5511
+ return {
5512
+ data: {
5513
+ type: Modules.StripeCouponCode.name,
5514
+ id: data.id,
5515
+ attributes
5516
+ }
5517
+ };
5518
+ }
5519
+ };
5520
+
5521
+ // src/features/billing/stripe-coupon/data/stripe-coupon-code.fields.ts
5522
+ var StripeCouponCodeFields = /* @__PURE__ */ ((StripeCouponCodeFields2) => {
5523
+ StripeCouponCodeFields2["code"] = "code";
5524
+ StripeCouponCodeFields2["places"] = "places";
5525
+ StripeCouponCodeFields2["expiresAt"] = "expiresAt";
5526
+ StripeCouponCodeFields2["automatic"] = "automatic";
5527
+ StripeCouponCodeFields2["status"] = "status";
5528
+ StripeCouponCodeFields2["actions"] = "actions";
5529
+ return StripeCouponCodeFields2;
5530
+ })(StripeCouponCodeFields || {});
5531
+
5532
+ // src/features/billing/stripe-coupon/stripe-coupon-code.module.ts
5533
+ var STRIPE_COUPON_CODE_AUTOMATIC_SEGMENT = "automatic";
5534
+ var StripeCouponCodeModule = /* @__PURE__ */ __name((factory) => factory({
5535
+ name: "stripe-coupon-codes",
5536
+ // Codes are managed on their coupon's page.
5537
+ pageUrl: "/administration/coupons",
5538
+ model: StripeCouponCode,
5539
+ moduleId: "85feb4c7-ff22-416a-b856-8dafcf28ff26"
5540
+ }), "StripeCouponCodeModule");
5541
+
5542
+ // src/features/billing/stripe-coupon/data/stripe-coupon-code.service.ts
5543
+ var StripeCouponCodeService = class extends AbstractService {
5544
+ static {
5545
+ __name(this, "StripeCouponCodeService");
5546
+ }
5547
+ /**
5548
+ * List the codes of a coupon (admin)
5549
+ */
5550
+ static async listByCoupon(params) {
5551
+ const endpoint = new EndpointCreator({
5552
+ endpoint: Modules.StripeCoupon,
5553
+ id: params.couponId,
5554
+ childEndpoint: Modules.StripeCouponCode
5555
+ });
5556
+ return this.callApi({
5557
+ type: Modules.StripeCouponCode,
5558
+ method: "GET" /* GET */,
5559
+ endpoint: endpoint.generate(),
5560
+ next: params.next,
5561
+ previous: params.prev
5562
+ });
5563
+ }
5564
+ /**
5565
+ * Create a code on an existing coupon (admin)
5566
+ */
5567
+ static async createCode(params) {
5568
+ const endpoint = new EndpointCreator({
5569
+ endpoint: Modules.StripeCouponCode
5570
+ });
5571
+ return this.callApi({
5572
+ type: Modules.StripeCouponCode,
5573
+ method: "POST" /* POST */,
5574
+ endpoint: endpoint.generate(),
5575
+ input: params
5576
+ });
5577
+ }
5578
+ /**
5579
+ * Switch "Apply automatically" and / or deactivate / reactivate a code (admin)
5580
+ */
5581
+ static async updateFlags(params) {
5582
+ const endpoint = new EndpointCreator({
5583
+ endpoint: Modules.StripeCouponCode,
5584
+ id: params.id
5585
+ });
5586
+ return this.callApi({
5587
+ type: Modules.StripeCouponCode,
5588
+ method: "PATCH" /* PATCH */,
5589
+ endpoint: endpoint.generate(),
5590
+ input: new StripeCouponCode().createFlagsJsonApi(params),
5591
+ overridesJsonApiCreation: true
5592
+ });
5593
+ }
5594
+ /**
5595
+ * The code the server would apply automatically for this price at a first
5596
+ * payment, or null when none applies (logged-in company administrator)
5597
+ */
5598
+ static async findAutomatic(params) {
5599
+ const endpoint = new EndpointCreator({
5600
+ endpoint: Modules.StripeCouponCode,
5601
+ id: STRIPE_COUPON_CODE_AUTOMATIC_SEGMENT
5602
+ });
5603
+ endpoint.addAdditionalParam("priceId", params.priceId);
5604
+ const codes = await this.callApi({
5605
+ type: Modules.StripeCouponCode,
5606
+ method: "GET" /* GET */,
5607
+ endpoint: endpoint.generate(),
5608
+ // A failed lookup must reach the wizard, which then refuses to show full price as the truth
5609
+ suppressGlobalError: true
5610
+ });
5611
+ return codes?.[0] ?? null;
5612
+ }
5613
+ };
5614
+
5615
+ // src/features/billing/stripe-coupon/data/stripe-coupon-offer.ts
5616
+ var StripeCouponOffer = class extends AbstractApiData {
5617
+ static {
5618
+ __name(this, "StripeCouponOffer");
5619
+ }
5620
+ _discountType;
5621
+ _percentOff;
5622
+ _amountOff;
5623
+ _currency;
5624
+ _duration;
5625
+ _durationInMonths;
5626
+ _placesLeft = 0;
5627
+ _placesTotal = 0;
5628
+ get discountType() {
5629
+ if (!this._discountType) throw new Error("discountType is not defined");
5630
+ return this._discountType;
5631
+ }
5632
+ get percentOff() {
5633
+ return this._percentOff;
5634
+ }
5635
+ get amountOff() {
5636
+ return this._amountOff;
5637
+ }
5638
+ get currency() {
5639
+ return this._currency;
5640
+ }
5641
+ get duration() {
5642
+ if (!this._duration) throw new Error("duration is not defined");
5643
+ return this._duration;
5644
+ }
5645
+ get durationInMonths() {
5646
+ return this._durationInMonths;
5647
+ }
5648
+ get placesLeft() {
5649
+ return this._placesLeft;
5650
+ }
5651
+ get placesTotal() {
5652
+ return this._placesTotal;
5653
+ }
5654
+ rehydrate(data) {
5655
+ super.rehydrate(data);
5656
+ const attributes = data.jsonApi.attributes;
5657
+ this._discountType = attributes.discountType;
5658
+ this._percentOff = attributes.percentOff ?? void 0;
5659
+ this._amountOff = attributes.amountOff ?? void 0;
5660
+ this._currency = attributes.currency ?? void 0;
5661
+ this._duration = attributes.duration;
5662
+ this._durationInMonths = attributes.durationInMonths ?? void 0;
5663
+ this._placesLeft = attributes.placesLeft ?? 0;
5664
+ this._placesTotal = attributes.placesTotal ?? 0;
5665
+ return this;
5666
+ }
5667
+ createJsonApi(_data) {
5668
+ throw new Error("StripeCouponOffer is declared by the API and is read-only");
5669
+ }
5670
+ };
5671
+
5672
+ // src/features/billing/stripe-coupon/utils/coupon-places.ts
5673
+ function couponPlacesLeft(code, coupon) {
5674
+ const remaining = [code, coupon].filter((item) => typeof item.maxRedemptions === "number").map((item) => Math.max(0, item.maxRedemptions - (item.timesRedeemed ?? 0)));
5675
+ return remaining.length === 0 ? null : Math.min(...remaining);
5676
+ }
5677
+ __name(couponPlacesLeft, "couponPlacesLeft");
5678
+ function couponPlacesTotal(code, coupon) {
5679
+ const limits = [code.maxRedemptions, coupon.maxRedemptions].filter(
5680
+ (limit) => typeof limit === "number"
5681
+ );
5682
+ return limits.length === 0 ? null : Math.min(...limits);
5683
+ }
5684
+ __name(couponPlacesTotal, "couponPlacesTotal");
5685
+
5686
+ // src/features/billing/components/utils/format-options.ts
5687
+ var DEFAULT_BILLING_LOCALE = "en-US";
5688
+
5689
+ // src/features/billing/components/utils/currency.ts
5690
+ function formatIntervalEnglish(price) {
5691
+ if (price.priceType === "one_time" || !price.recurring) {
5692
+ return "one-time";
5693
+ }
5694
+ const { interval, intervalCount } = price.recurring;
5695
+ if (intervalCount === 1) {
5696
+ return `/${interval}`;
5697
+ }
5698
+ const pluralInterval = interval === "day" ? "days" : interval === "week" ? "weeks" : interval === "month" ? "months" : "years";
5699
+ return `/${intervalCount} ${pluralInterval}`;
5700
+ }
5701
+ __name(formatIntervalEnglish, "formatIntervalEnglish");
5702
+ function formatInterval(price, options = {}) {
5703
+ const { t } = options;
5704
+ if (!t) return formatIntervalEnglish(price);
5705
+ if (price.priceType === "one_time" || !price.recurring) {
5706
+ return t("billing.ui.interval.one_time");
5707
+ }
5708
+ const { interval, intervalCount } = price.recurring;
5709
+ if (intervalCount === 1) {
5710
+ switch (interval) {
5711
+ case "day":
5712
+ return t("billing.ui.interval.per_day");
5713
+ case "week":
5714
+ return t("billing.ui.interval.per_week");
5715
+ case "month":
5716
+ return t("billing.ui.interval.per_month");
5717
+ default:
5718
+ return t("billing.ui.interval.per_year");
5719
+ }
5720
+ }
5721
+ switch (interval) {
5722
+ case "day":
5723
+ return t("billing.ui.interval.per_days", { count: intervalCount });
5724
+ case "week":
5725
+ return t("billing.ui.interval.per_weeks", { count: intervalCount });
5726
+ case "month":
5727
+ return t("billing.ui.interval.per_months", { count: intervalCount });
5728
+ default:
5729
+ return t("billing.ui.interval.per_years", { count: intervalCount });
5730
+ }
5731
+ }
5732
+ __name(formatInterval, "formatInterval");
5733
+ function formatCurrency(amount, currency2, options = {}) {
5734
+ const { locale } = options;
5735
+ if (amount === void 0 && !locale) return "$0.00";
5736
+ const dollars = (amount ?? 0) / 100;
5737
+ try {
5738
+ return new Intl.NumberFormat(locale ?? DEFAULT_BILLING_LOCALE, {
5739
+ style: "currency",
5740
+ currency: currency2.toUpperCase(),
5741
+ minimumFractionDigits: 2,
5742
+ maximumFractionDigits: 2
5743
+ }).format(dollars);
5744
+ } catch (error) {
5745
+ console.error("Error formatting currency:", error);
5746
+ return `$${dollars.toFixed(2)}`;
5747
+ }
5748
+ }
5749
+ __name(formatCurrency, "formatCurrency");
5750
+ function formatFixed(value, locale, digits) {
5751
+ return new Intl.NumberFormat(locale ?? DEFAULT_BILLING_LOCALE, {
5752
+ minimumFractionDigits: digits,
5753
+ maximumFractionDigits: digits,
5754
+ useGrouping: false
5755
+ }).format(value);
5756
+ }
5757
+ __name(formatFixed, "formatFixed");
5758
+
5759
+ // src/features/billing/stripe-coupon/utils/format-coupon-discount.ts
5760
+ function formatCouponDiscount(coupon, t, fmt = {}) {
5761
+ const amount = coupon.discountType === "percent_off" ? t("billing.admin.coupons.discount.percent", { value: String(coupon.percentOff ?? 0) }) : t("billing.admin.coupons.discount.amount", {
5762
+ amount: formatCurrency(coupon.amountOff, coupon.currency ?? "eur", fmt)
5763
+ });
5764
+ 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");
5765
+ return `${amount} ${duration}`;
5766
+ }
5767
+ __name(formatCouponDiscount, "formatCouponDiscount");
5768
+
5769
+ // src/features/billing/stripe-coupon/utils/to-promotion-code-result.ts
5770
+ function toPromotionCodeResult(code) {
5771
+ const coupon = code.coupon;
5772
+ const discountType = coupon?.discountType;
5773
+ return {
5774
+ valid: true,
5775
+ automatic: true,
5776
+ promotionCodeId: code.stripePromotionCodeId,
5777
+ code: code.code,
5778
+ discountType,
5779
+ discountValue: discountType === "amount_off" ? coupon?.amountOff : coupon?.percentOff,
5780
+ currency: discountType === "amount_off" ? coupon?.currency : void 0,
5781
+ duration: coupon?.duration,
5782
+ durationInMonths: coupon?.durationInMonths
5783
+ };
5784
+ }
5785
+ __name(toPromotionCodeResult, "toPromotionCodeResult");
5786
+
5787
+ // src/features/billing/stripe-coupon/stripe-coupon-offer.module.ts
5788
+ var StripeCouponOfferModule = /* @__PURE__ */ __name((factory) => factory({
5789
+ name: "stripe-coupon-offers",
5790
+ pageUrl: "/pricing",
5791
+ model: StripeCouponOffer,
5792
+ moduleId: "6859d6cc-b94c-4cf7-8a02-b71ad59d75d2"
5793
+ }), "StripeCouponOfferModule");
5794
+
5123
5795
  // src/features/ai-connection/data/ai-connection.ts
5124
5796
  var AiConnection = class extends AbstractApiData {
5125
5797
  static {
@@ -11510,6 +12182,26 @@ export {
11510
12182
  StripePromotionCodeService,
11511
12183
  StripePromotionCode,
11512
12184
  StripePromotionCodeModule,
12185
+ StripeCoupon,
12186
+ StripeCouponFields,
12187
+ STRIPE_COUPON_REFRESH_SEGMENT,
12188
+ StripeCouponModule,
12189
+ StripeCouponService,
12190
+ StripeCouponCode,
12191
+ StripeCouponCodeFields,
12192
+ STRIPE_COUPON_CODE_AUTOMATIC_SEGMENT,
12193
+ StripeCouponCodeModule,
12194
+ StripeCouponCodeService,
12195
+ StripeCouponOffer,
12196
+ couponPlacesLeft,
12197
+ couponPlacesTotal,
12198
+ DEFAULT_BILLING_LOCALE,
12199
+ formatInterval,
12200
+ formatCurrency,
12201
+ formatFixed,
12202
+ formatCouponDiscount,
12203
+ toPromotionCodeResult,
12204
+ StripeCouponOfferModule,
11513
12205
  AiConnection,
11514
12206
  AiConnectionFields,
11515
12207
  AiConnectionService,
@@ -11667,4 +12359,4 @@ export {
11667
12359
  AuditLogService,
11668
12360
  AuditLogModule
11669
12361
  };
11670
- //# sourceMappingURL=chunk-VC5A3AUZ.mjs.map
12362
+ //# sourceMappingURL=chunk-EYA2F6AN.mjs.map