@carlonicora/nextjs-jsonapi 6.4.0 → 6.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 (86) hide show
  1. package/dist/{BlockNoteEditor-CT4XUXPC.js → BlockNoteEditor-E4V7AEG2.js} +19 -19
  2. package/dist/{BlockNoteEditor-CT4XUXPC.js.map → BlockNoteEditor-E4V7AEG2.js.map} +1 -1
  3. package/dist/{BlockNoteEditor-M6UQRVRK.mjs → BlockNoteEditor-MWGVWNSE.mjs} +4 -4
  4. package/dist/{BlockNoteViewer-MFLWF3Y2.js → BlockNoteViewer-LGRKM7OA.js} +3 -3
  5. package/dist/{BlockNoteViewer-MFLWF3Y2.js.map → BlockNoteViewer-LGRKM7OA.js.map} +1 -1
  6. package/dist/{BlockNoteViewer-XZJ5Y7WN.mjs → BlockNoteViewer-VNU7WVN5.mjs} +2 -2
  7. package/dist/billing/index.d.mts +174 -157
  8. package/dist/billing/index.d.ts +174 -157
  9. package/dist/billing/index.js +523 -501
  10. package/dist/billing/index.js.map +1 -1
  11. package/dist/billing/index.mjs +34 -12
  12. package/dist/billing/index.mjs.map +1 -1
  13. package/dist/{chunk-3FD6Y734.mjs → chunk-7GB5MR77.mjs} +78 -1
  14. package/dist/chunk-7GB5MR77.mjs.map +1 -0
  15. package/dist/{chunk-ELQHE2DK.js → chunk-AEVLFZRK.js} +3 -3
  16. package/dist/{chunk-ELQHE2DK.js.map → chunk-AEVLFZRK.js.map} +1 -1
  17. package/dist/{chunk-DSGP6GC3.js → chunk-AMN2XDN5.js} +8 -8
  18. package/dist/{chunk-DSGP6GC3.js.map → chunk-AMN2XDN5.js.map} +1 -1
  19. package/dist/{chunk-QJIDORHM.js → chunk-F2MZ7GY6.js} +4 -4
  20. package/dist/{chunk-QJIDORHM.js.map → chunk-F2MZ7GY6.js.map} +1 -1
  21. package/dist/{chunk-TIT4CJYQ.mjs → chunk-IDV534SJ.mjs} +5 -5
  22. package/dist/{chunk-DYOSXIEL.mjs → chunk-IQ2XYAB5.mjs} +2 -2
  23. package/dist/{chunk-XZCCIKX3.js → chunk-OJAIKQR2.js} +79 -2
  24. package/dist/chunk-OJAIKQR2.js.map +1 -0
  25. package/dist/{chunk-O2TEUH5S.mjs → chunk-PDS57QPD.mjs} +2 -2
  26. package/dist/{chunk-Y7JIQNM6.js → chunk-R2XBVIO5.js} +870 -870
  27. package/dist/{chunk-Y7JIQNM6.js.map → chunk-R2XBVIO5.js.map} +1 -1
  28. package/dist/{chunk-RUJCWOJE.mjs → chunk-RSMBRI3E.mjs} +2 -2
  29. package/dist/client/index.js +4 -4
  30. package/dist/client/index.mjs +3 -3
  31. package/dist/components/index.js +4 -4
  32. package/dist/components/index.mjs +3 -3
  33. package/dist/contexts/index.js +4 -4
  34. package/dist/contexts/index.mjs +3 -3
  35. package/dist/core/index.d.mts +32 -3
  36. package/dist/core/index.d.ts +32 -3
  37. package/dist/core/index.js +6 -2
  38. package/dist/core/index.js.map +1 -1
  39. package/dist/core/index.mjs +5 -1
  40. package/dist/email-automations/index.js +92 -92
  41. package/dist/email-automations/index.mjs +3 -3
  42. package/dist/features/analytics/index.js +121 -121
  43. package/dist/features/analytics/index.mjs +4 -4
  44. package/dist/features/analytics/server.js +4 -4
  45. package/dist/features/analytics/server.mjs +2 -2
  46. package/dist/features/blog/index.js +150 -150
  47. package/dist/features/blog/index.mjs +3 -3
  48. package/dist/features/blog/server.js +16 -16
  49. package/dist/features/blog/server.mjs +1 -1
  50. package/dist/features/help/index.js +37 -37
  51. package/dist/features/help/index.mjs +3 -3
  52. package/dist/features/tokenusage/index.js +127 -127
  53. package/dist/features/tokenusage/index.mjs +4 -4
  54. package/dist/index.d.mts +2 -2
  55. package/dist/index.d.ts +2 -2
  56. package/dist/index.js +7 -3
  57. package/dist/index.js.map +1 -1
  58. package/dist/index.mjs +6 -2
  59. package/dist/{s3.service-CzFBDEuQ.d.mts → s3.service-BNBD9YTg.d.mts} +17 -1
  60. package/dist/{s3.service-BTCpmp5g.d.ts → s3.service-Da7C2gtt.d.ts} +17 -1
  61. package/dist/server/index.d.mts +1 -1
  62. package/dist/server/index.d.ts +1 -1
  63. package/dist/server/index.js +3 -3
  64. package/dist/server/index.mjs +2 -2
  65. package/package.json +1 -1
  66. package/src/core/index.ts +1 -0
  67. package/src/core/registry/ModuleRegistry.ts +2 -0
  68. package/src/features/auth/data/__tests__/pending-registration.spec.ts +37 -0
  69. package/src/features/auth/data/auth.service.ts +19 -0
  70. package/src/features/auth/data/index.ts +2 -0
  71. package/src/features/auth/data/pending-registration.interface.ts +10 -0
  72. package/src/features/auth/data/pending-registration.ts +57 -0
  73. package/src/features/auth/pending-registration.module.ts +9 -0
  74. package/src/features/billing/components/containers/BillingDashboardContainer.tsx +3 -2
  75. package/src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx +5 -0
  76. package/src/features/billing/stripe-subscription/components/details/SubscriptionDetails.tsx +44 -12
  77. package/src/features/billing/stripe-subscription/components/details/__tests__/SubscriptionDetails.spec.tsx +79 -0
  78. package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +9 -2
  79. package/dist/chunk-3FD6Y734.mjs.map +0 -1
  80. package/dist/chunk-XZCCIKX3.js.map +0 -1
  81. /package/dist/{BlockNoteEditor-M6UQRVRK.mjs.map → BlockNoteEditor-MWGVWNSE.mjs.map} +0 -0
  82. /package/dist/{BlockNoteViewer-XZJ5Y7WN.mjs.map → BlockNoteViewer-VNU7WVN5.mjs.map} +0 -0
  83. /package/dist/{chunk-TIT4CJYQ.mjs.map → chunk-IDV534SJ.mjs.map} +0 -0
  84. /package/dist/{chunk-DYOSXIEL.mjs.map → chunk-IQ2XYAB5.mjs.map} +0 -0
  85. /package/dist/{chunk-O2TEUH5S.mjs.map → chunk-PDS57QPD.mjs.map} +0 -0
  86. /package/dist/{chunk-RUJCWOJE.mjs.map → chunk-RSMBRI3E.mjs.map} +0 -0
@@ -10,7 +10,7 @@ import { PaymentMethodsContainer } from "../../stripe-customer/components";
10
10
  import { StripeInvoiceInterface, StripeInvoiceService } from "../../stripe-invoice";
11
11
  import { InvoicesContainer } from "../../stripe-invoice/components";
12
12
  import { StripeSubscriptionInterface, StripeSubscriptionService, SubscriptionStatus } from "../../stripe-subscription";
13
- import { SubscriptionsContainer } from "../../stripe-subscription/components";
13
+ import { type RenderCancelDialog, SubscriptionsContainer } from "../../stripe-subscription/components";
14
14
  import { SubscriptionWizard } from "../../stripe-subscription/components/wizards";
15
15
  import { MeterInterface, MeterSummaryInterface, StripeUsageService } from "../../stripe-usage";
16
16
  import { UsageContainer } from "../../stripe-usage/components";
@@ -53,7 +53,7 @@ type ErrorState = {
53
53
  usage: string | null;
54
54
  };
55
55
 
56
- export function BillingDashboardContainer() {
56
+ export function BillingDashboardContainer({ renderCancelDialog }: { renderCancelDialog?: RenderCancelDialog } = {}) {
57
57
  const t = useTranslations();
58
58
  const [data, setData] = useState<DataState>({
59
59
  customer: null,
@@ -482,6 +482,7 @@ export function BillingDashboardContainer() {
482
482
  hasActiveRecurringSubscription={hasActiveRecurringSubscription}
483
483
  subscriptions={data.subscriptions}
484
484
  onSubscriptionsChange={refreshData}
485
+ renderCancelDialog={renderCancelDialog}
485
486
  />
486
487
  </BillingDetailModal>
487
488
 
@@ -6,6 +6,7 @@ import { useCallback, useEffect, useState } from "react";
6
6
  import { Button } from "../../../../../shadcnui";
7
7
  import { BillingAlertBanner } from "../../../components";
8
8
  import { StripeSubscriptionInterface, StripeSubscriptionService, SubscriptionStatus } from "../../data";
9
+ import type { RenderCancelDialog } from "../details/SubscriptionDetails";
9
10
  import { SubscriptionsList } from "../lists";
10
11
 
11
12
  type SubscriptionsContainerProps = {
@@ -18,6 +19,8 @@ type SubscriptionsContainerProps = {
18
19
  */
19
20
  subscriptions?: StripeSubscriptionInterface[];
20
21
  onSubscriptionsChange?: () => void;
22
+ /** Replaces the library cancel dialog; absent, the library dialog renders. */
23
+ renderCancelDialog?: RenderCancelDialog;
21
24
  };
22
25
 
23
26
  export function SubscriptionsContainer({
@@ -25,6 +28,7 @@ export function SubscriptionsContainer({
25
28
  hasActiveRecurringSubscription,
26
29
  subscriptions: parentSubscriptions,
27
30
  onSubscriptionsChange,
31
+ renderCancelDialog,
28
32
  }: SubscriptionsContainerProps) {
29
33
  const t = useTranslations();
30
34
  const isControlled = parentSubscriptions !== undefined;
@@ -110,6 +114,7 @@ export function SubscriptionsContainer({
110
114
  subscriptions={subscriptions}
111
115
  onSubscriptionsChange={loadSubscriptions}
112
116
  onChangePlan={(sub) => onOpenWizard?.(sub)}
117
+ renderCancelDialog={renderCancelDialog}
113
118
  />
114
119
  )}
115
120
  </div>
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { useTranslations } from "next-intl";
4
- import { useState } from "react";
4
+ import { type ReactNode, useState } from "react";
5
5
  import { Button, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "../../../../../shadcnui";
6
6
  import {
7
7
  type BillingFormatOptions,
@@ -57,12 +57,26 @@ function formatBillingAmount(
57
57
  return formatCurrency(price.unitAmount, price.currency, fmt);
58
58
  }
59
59
 
60
+ /** Props an app receives when it replaces the library cancel dialog. */
61
+ export type CancelDialogRenderProps = {
62
+ subscription: StripeSubscriptionInterface;
63
+ open: boolean;
64
+ onOpenChange: (open: boolean) => void;
65
+ onSuccess: () => void;
66
+ /** Opens the plan-change wizard for this subscription and closes the details. Undefined when the host gave no onChangePlan. */
67
+ openChangePlan?: () => void;
68
+ };
69
+
70
+ /** Optional replacement for the library cancel dialog. Absent, the library renders CancelSubscriptionDialog. */
71
+ export type RenderCancelDialog = (props: CancelDialogRenderProps) => ReactNode;
72
+
60
73
  type SubscriptionDetailsProps = {
61
74
  subscription: StripeSubscriptionInterface;
62
75
  open: boolean;
63
76
  onOpenChange: (open: boolean) => void;
64
77
  onSubscriptionChange: () => void;
65
78
  onChangePlan?: (subscription: StripeSubscriptionInterface) => void;
79
+ renderCancelDialog?: RenderCancelDialog;
66
80
  };
67
81
 
68
82
  export function SubscriptionDetails({
@@ -71,6 +85,7 @@ export function SubscriptionDetails({
71
85
  onOpenChange,
72
86
  onSubscriptionChange,
73
87
  onChangePlan,
88
+ renderCancelDialog,
74
89
  }: SubscriptionDetailsProps) {
75
90
  const t = useTranslations();
76
91
  const fmt = useBillingFormatOptions();
@@ -175,17 +190,34 @@ export function SubscriptionDetails({
175
190
  </Dialog>
176
191
 
177
192
  {/* Cancel Subscription Dialog */}
178
- {showCancel && (
179
- <CancelSubscriptionDialog
180
- subscription={subscription}
181
- open={showCancel}
182
- onOpenChange={setShowCancel}
183
- onSuccess={() => {
184
- onSubscriptionChange();
185
- setShowCancel(false);
186
- }}
187
- />
188
- )}
193
+ {showCancel &&
194
+ (renderCancelDialog ? (
195
+ renderCancelDialog({
196
+ subscription,
197
+ open: showCancel,
198
+ onOpenChange: setShowCancel,
199
+ onSuccess: () => {
200
+ onSubscriptionChange();
201
+ setShowCancel(false);
202
+ },
203
+ openChangePlan: onChangePlan
204
+ ? () => {
205
+ onChangePlan(subscription);
206
+ onOpenChange(false);
207
+ }
208
+ : undefined,
209
+ })
210
+ ) : (
211
+ <CancelSubscriptionDialog
212
+ subscription={subscription}
213
+ open={showCancel}
214
+ onOpenChange={setShowCancel}
215
+ onSuccess={() => {
216
+ onSubscriptionChange();
217
+ setShowCancel(false);
218
+ }}
219
+ />
220
+ ))}
189
221
  </>
190
222
  );
191
223
  }
@@ -0,0 +1,79 @@
1
+ import { cleanup, fireEvent, render, screen } from "@testing-library/react";
2
+ import { afterEach, describe, expect, it, vi } from "vitest";
3
+ import { StripeSubscriptionInterface, SubscriptionStatus } from "../../../data";
4
+ import { CancelDialogRenderProps, SubscriptionDetails } from "../SubscriptionDetails";
5
+
6
+ vi.mock("../../forms/CancelSubscriptionDialog", () => ({
7
+ CancelSubscriptionDialog: () => <div data-testid="default-cancel" />,
8
+ }));
9
+
10
+ vi.mock("../../../../stripe-customer", () => ({
11
+ StripeCustomerService: { createPortalSession: vi.fn() },
12
+ }));
13
+
14
+ afterEach(cleanup);
15
+
16
+ const sub = {
17
+ id: "sub-1",
18
+ status: SubscriptionStatus.ACTIVE,
19
+ cancelAtPeriodEnd: false,
20
+ currentPeriodStart: new Date("2026-10-01T00:00:00Z"),
21
+ currentPeriodEnd: new Date("2026-11-01T00:00:00Z"),
22
+ } as unknown as StripeSubscriptionInterface;
23
+
24
+ function renderDetails(props: Partial<Parameters<typeof SubscriptionDetails>[0]> = {}) {
25
+ const onOpenChange = vi.fn();
26
+ const onSubscriptionChange = vi.fn();
27
+ render(
28
+ <SubscriptionDetails
29
+ subscription={sub}
30
+ open
31
+ onOpenChange={onOpenChange}
32
+ onSubscriptionChange={onSubscriptionChange}
33
+ {...props}
34
+ />,
35
+ );
36
+ fireEvent.click(screen.getByText("ui.buttons.cancel"));
37
+ return { onOpenChange, onSubscriptionChange };
38
+ }
39
+
40
+ describe("SubscriptionDetails cancel dialog", () => {
41
+ it("renders the library dialog when no renderCancelDialog is given", () => {
42
+ renderDetails();
43
+ expect(screen.getByTestId("default-cancel")).toBeInTheDocument();
44
+ });
45
+
46
+ it("renders the app dialog with the subscription when renderCancelDialog is given", () => {
47
+ const renderCancelDialog = vi.fn((_props: CancelDialogRenderProps) => <div data-testid="app-cancel" />);
48
+ renderDetails({ renderCancelDialog });
49
+ expect(screen.getByTestId("app-cancel")).toBeInTheDocument();
50
+ expect(screen.queryByTestId("default-cancel")).not.toBeInTheDocument();
51
+ const props = renderCancelDialog.mock.calls.at(-1)![0];
52
+ expect(props.subscription).toBe(sub);
53
+ expect(props.open).toBe(true);
54
+ });
55
+
56
+ it("openChangePlan opens the wizard for this subscription and closes the details", () => {
57
+ const renderCancelDialog = vi.fn((_props: CancelDialogRenderProps) => <div data-testid="app-cancel" />);
58
+ const onChangePlan = vi.fn();
59
+ const { onOpenChange } = renderDetails({ renderCancelDialog, onChangePlan });
60
+ const props = renderCancelDialog.mock.calls.at(-1)![0];
61
+ expect(props.openChangePlan).toBeTypeOf("function");
62
+ props.openChangePlan!();
63
+ expect(onChangePlan).toHaveBeenCalledWith(sub);
64
+ expect(onOpenChange).toHaveBeenCalledWith(false);
65
+ });
66
+
67
+ it("openChangePlan is undefined when no onChangePlan is given", () => {
68
+ const renderCancelDialog = vi.fn((_props: CancelDialogRenderProps) => <div data-testid="app-cancel" />);
69
+ renderDetails({ renderCancelDialog });
70
+ expect(renderCancelDialog.mock.calls.at(-1)![0].openChangePlan).toBeUndefined();
71
+ });
72
+
73
+ it("onSuccess refreshes the subscriptions", () => {
74
+ const renderCancelDialog = vi.fn((_props: CancelDialogRenderProps) => <div data-testid="app-cancel" />);
75
+ const { onSubscriptionChange } = renderDetails({ renderCancelDialog });
76
+ renderCancelDialog.mock.calls.at(-1)![0].onSuccess();
77
+ expect(onSubscriptionChange).toHaveBeenCalledTimes(1);
78
+ });
79
+ });
@@ -12,7 +12,7 @@ import {
12
12
  } from "../../../components/utils";
13
13
  import { StripePriceInterface } from "../../../stripe-price/data/stripe-price.interface";
14
14
  import { StripeSubscriptionInterface, SubscriptionStatus } from "../../data";
15
- import { SubscriptionDetails } from "../details/SubscriptionDetails";
15
+ import { type RenderCancelDialog, SubscriptionDetails } from "../details/SubscriptionDetails";
16
16
  import { SubscriptionStatusBadge } from "../widgets/SubscriptionStatusBadge";
17
17
 
18
18
  /**
@@ -49,9 +49,15 @@ type SubscriptionsListProps = {
49
49
  subscriptions: StripeSubscriptionInterface[];
50
50
  onSubscriptionsChange: () => void;
51
51
  onChangePlan?: (subscription: StripeSubscriptionInterface) => void;
52
+ renderCancelDialog?: RenderCancelDialog;
52
53
  };
53
54
 
54
- export function SubscriptionsList({ subscriptions, onSubscriptionsChange, onChangePlan }: SubscriptionsListProps) {
55
+ export function SubscriptionsList({
56
+ subscriptions,
57
+ onSubscriptionsChange,
58
+ onChangePlan,
59
+ renderCancelDialog,
60
+ }: SubscriptionsListProps) {
55
61
  const t = useTranslations();
56
62
  const fmt = useBillingFormatOptions();
57
63
  const [selectedSub, setSelectedSub] = useState<StripeSubscriptionInterface | null>(null);
@@ -148,6 +154,7 @@ export function SubscriptionsList({ subscriptions, onSubscriptionsChange, onChan
148
154
  }
149
155
  : undefined
150
156
  }
157
+ renderCancelDialog={renderCancelDialog}
151
158
  />
152
159
  )}
153
160
  </>