@zuplo/zudoku-plugin-monetization 0.0.24 → 0.0.25

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 (2) hide show
  1. package/dist/index.mjs +28 -36
  2. package/package.json +2 -2
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
- import { cn, createPlugin, joinUrl } from "zudoku";
1
+ import { cn, createPlugin, joinUrl, throwIfProblemJson } from "zudoku";
2
2
  import { AlertTriangleIcon, ArrowDownIcon, ArrowLeftRightIcon, ArrowUpIcon, CalendarIcon, CheckCheckIcon, CheckIcon, CircleAlert, CircleSlashIcon, ClockIcon, CreditCardIcon, Grid2x2XIcon, InfoIcon, Loader2Icon, LockIcon, MoreVerticalIcon, RefreshCcw, RefreshCwIcon, Settings, ShieldIcon, StarsIcon, Trash2Icon, XIcon } from "zudoku/icons";
3
3
  import { Button, ClientOnly, Head, Heading, Link, Slot } from "zudoku/components";
4
4
  import { useAuth, useZudoku } from "zudoku/hooks";
5
5
  import { QueryClient, QueryClientProvider, useMutation, useQuery, useQueryClient, useSuspenseQuery } from "zudoku/react-query";
6
- import { Link as Link$1, Outlet, useLocation, useNavigate, useParams, useSearchParams } from "zudoku/router";
6
+ import { Link as Link$1, Outlet, useLocation, useNavigate, useSearchParams } from "zudoku/router";
7
7
  import { Alert, AlertAction, AlertDescription, AlertTitle } from "zudoku/ui/Alert";
8
8
  import { Card, CardContent, CardHeader, CardTitle } from "zudoku/ui/Card";
9
9
  import { Separator } from "zudoku/ui/Separator";
@@ -227,13 +227,8 @@ const queryClient = new QueryClient({ defaultOptions: {
227
227
  }
228
228
  });
229
229
  const response = await fetch(q.meta?.context ? await q.meta.context.signRequest(request) : request);
230
- if (!response.ok) {
231
- if (response.headers.get("content-type")?.includes("application/problem+json")) {
232
- const data = await response.json();
233
- throw new Error(data.detail ?? data.title);
234
- }
235
- throw new Error("Failed to fetch request");
236
- }
230
+ await throwIfProblemJson(response);
231
+ if (!response.ok) throw new Error("Failed to fetch request");
237
232
  return response.json();
238
233
  }
239
234
  },
@@ -262,11 +257,8 @@ const queryClient = new QueryClient({ defaultOptions: {
262
257
  }
263
258
  });
264
259
  const response = await fetch(m.meta?.context ? await m.meta.context.signRequest(request) : request);
260
+ await throwIfProblemJson(response);
265
261
  if (!response.ok) {
266
- if (response.headers.get("content-type")?.includes("application/problem+json")) {
267
- const data = await response.json();
268
- throw new Error(data.detail ?? data.title);
269
- }
270
262
  const errorText = await response.text();
271
263
  throw new Error(`Request failed: ${response.status} ${errorText}`);
272
264
  }
@@ -286,7 +278,7 @@ const ZuploMonetizationWrapper = () => {
286
278
  //#region src/pages/CheckoutConfirmPage.tsx
287
279
  const CheckoutConfirmPage = () => {
288
280
  const [search] = useSearchParams();
289
- const planId = search.get("plan");
281
+ const planId = search.get("planId");
290
282
  const zudoku = useZudoku();
291
283
  const deploymentName = useDeploymentName();
292
284
  const navigate = useNavigate();
@@ -308,7 +300,7 @@ const CheckoutConfirmPage = () => {
308
300
  },
309
301
  onSuccess: async (subscription) => {
310
302
  await queryClient.invalidateQueries();
311
- navigate(`/subscriptions/${subscription.id}`);
303
+ navigate(`/subscriptions?subscriptionId=${encodeURIComponent(subscription.id)}`);
312
304
  }
313
305
  });
314
306
  return /* @__PURE__ */ jsx("div", {
@@ -484,23 +476,22 @@ const RedirectPage = ({ icon: Icon, title, description, url, children }) => {
484
476
  //#region src/hooks/useUrlUtils.ts
485
477
  const useUrlUtils = () => {
486
478
  const basePath = useZudoku().options.basePath;
487
- return { generateUrl: (path) => {
479
+ return { generateUrl: (path, { searchParams } = {}) => {
488
480
  if (!window.location.origin) throw new Error("Only works in browser environment");
489
- return joinUrl(window.location.origin, basePath, path);
481
+ return joinUrl(window.location.origin, basePath, path, searchParams ? `?${new URLSearchParams(searchParams)}` : void 0);
490
482
  } };
491
483
  };
492
484
 
493
485
  //#endregion
494
486
  //#region src/pages/CheckoutPage.tsx
495
487
  const CheckoutPage = () => {
496
- const { planId } = useParams();
488
+ const [searchParams] = useSearchParams();
489
+ const planId = searchParams.get("planId");
497
490
  const zudoku = useZudoku();
498
491
  const auth = useAuth();
499
492
  const { generateUrl } = useUrlUtils();
500
493
  const deploymentName = useDeploymentName();
501
494
  if (!planId) throw new Error(`missing planId in URL`);
502
- const successUrl = new URL(generateUrl("/checkout-confirm"));
503
- successUrl.searchParams.set("plan", planId);
504
495
  const checkoutLink = useQuery({
505
496
  queryKey: [
506
497
  `/v3/zudoku-metering/${deploymentName}/stripe/checkout`,
@@ -513,7 +504,7 @@ const CheckoutPage = () => {
513
504
  method: "POST",
514
505
  body: JSON.stringify({
515
506
  planId,
516
- successURL: successUrl.toString(),
507
+ successURL: generateUrl("/checkout-confirm", { searchParams: { planId } }),
517
508
  cancelURL: generateUrl("/pricing")
518
509
  })
519
510
  }
@@ -683,7 +674,7 @@ const PricingCard = ({ plan, isPopular = false, isSubscribed = false, showYearly
683
674
  variant: isPopular ? "default" : "secondary",
684
675
  asChild: true,
685
676
  children: /* @__PURE__ */ jsx(Link$1, {
686
- to: `/checkout/${plan.id}`,
677
+ to: `/checkout?planId=${encodeURIComponent(plan.id)}`,
687
678
  children: "Subscribe"
688
679
  })
689
680
  })
@@ -765,7 +756,7 @@ const SubscriptionChangeConfirmPage = () => {
765
756
  },
766
757
  onSuccess: async (subscription) => {
767
758
  await queryClient.invalidateQueries();
768
- navigate(`/subscriptions/${subscription.id}`, { state: { planSwitched: { newPlanName: selectedPlan?.name } } });
759
+ navigate(`/subscriptions?subscriptionId=${encodeURIComponent(subscription.id)}`, { state: { planSwitched: { newPlanName: selectedPlan?.name } } });
769
760
  }
770
761
  });
771
762
  return /* @__PURE__ */ jsx("div", {
@@ -863,7 +854,7 @@ const SubscriptionChangeConfirmPage = () => {
863
854
  disabled: changeMutation.isPending,
864
855
  asChild: !changeMutation.isPending,
865
856
  children: /* @__PURE__ */ jsx(Link$1, {
866
- to: `/subscriptions/${subscriptionId}`,
857
+ to: `/subscriptions?${new URLSearchParams({ subscriptionId: subscriptionId ?? "" })}`,
867
858
  children: "Cancel"
868
859
  })
869
860
  })]
@@ -1515,9 +1506,6 @@ const ConfirmSwitchAlert = ({ switchTo, onRequestClose }) => {
1515
1506
  const deploymentName = useDeploymentName();
1516
1507
  const context = useZudoku();
1517
1508
  const { generateUrl } = useUrlUtils();
1518
- const successUrl = new URL(generateUrl("/subscription-change-confirm"));
1519
- successUrl.searchParams.set("planId", switchTo.plan.id);
1520
- successUrl.searchParams.set("subscriptionId", switchTo.subscriptionId);
1521
1509
  const mutation = useMutation({
1522
1510
  mutationKey: [`/v3/zudoku-metering/${deploymentName}/stripe/checkout`],
1523
1511
  meta: {
@@ -1526,8 +1514,11 @@ const ConfirmSwitchAlert = ({ switchTo, onRequestClose }) => {
1526
1514
  method: "POST",
1527
1515
  body: JSON.stringify({
1528
1516
  planId: switchTo.plan.id,
1529
- successURL: successUrl.toString(),
1530
- cancelURL: generateUrl(`/subscriptions/${switchTo.subscriptionId}`)
1517
+ successURL: generateUrl(`/subscription-change-confirm`, { searchParams: {
1518
+ planId: switchTo.plan.id,
1519
+ subscriptionId: switchTo.subscriptionId
1520
+ } }),
1521
+ cancelURL: generateUrl("/subscriptions", { searchParams: { subscriptionId: switchTo.subscriptionId } })
1531
1522
  })
1532
1523
  }
1533
1524
  },
@@ -2004,7 +1995,7 @@ const SubscriptionsList = ({ subscriptions, activeSubscriptionId }) => {
2004
1995
  const SubscriptionItem = ({ subscription, isSelected, isExpired }) => {
2005
1996
  const willExpire = subscription.activeTo && new Date(subscription.activeTo) > /* @__PURE__ */ new Date();
2006
1997
  return /* @__PURE__ */ jsx(Link$1, {
2007
- to: `/subscriptions/${subscription.id}`,
1998
+ to: `/subscriptions?subscriptionId=${encodeURIComponent(subscription.id)}`,
2008
1999
  children: /* @__PURE__ */ jsx(Item, {
2009
2000
  size: "sm",
2010
2001
  variant: "outline",
@@ -2029,7 +2020,7 @@ const SubscriptionItem = ({ subscription, isSelected, isExpired }) => {
2029
2020
  ]
2030
2021
  })] })
2031
2022
  }, subscription.id)
2032
- }, subscription.id);
2023
+ });
2033
2024
  };
2034
2025
 
2035
2026
  //#endregion
@@ -2037,7 +2028,8 @@ const SubscriptionItem = ({ subscription, isSelected, isExpired }) => {
2037
2028
  const SubscriptionsPage = () => {
2038
2029
  const deploymentName = useDeploymentName();
2039
2030
  const { data } = useSubscriptions(deploymentName);
2040
- const { subscriptionId } = useParams();
2031
+ const [searchParams] = useSearchParams();
2032
+ const subscriptionId = searchParams.get("subscriptionId");
2041
2033
  const subscriptions = data?.items ?? [];
2042
2034
  const activeSubscription = useMemo(() => {
2043
2035
  if (subscriptions.length === 0) return null;
@@ -2119,7 +2111,7 @@ const zuploMonetizationPlugin = createPlugin((options) => ({
2119
2111
  handle: { layout: "none" },
2120
2112
  children: [
2121
2113
  {
2122
- path: "/checkout/:planId?",
2114
+ path: "/checkout",
2123
2115
  element: /* @__PURE__ */ jsx(CheckoutPage, {})
2124
2116
  },
2125
2117
  {
@@ -2146,7 +2138,7 @@ const zuploMonetizationPlugin = createPlugin((options) => ({
2146
2138
  },
2147
2139
  {
2148
2140
  handle: { layout: "default" },
2149
- path: "/subscriptions/:subscriptionId?",
2141
+ path: "/subscriptions",
2150
2142
  element: /* @__PURE__ */ jsx(SubscriptionsPage, {})
2151
2143
  }
2152
2144
  ]
@@ -2154,10 +2146,10 @@ const zuploMonetizationPlugin = createPlugin((options) => ({
2154
2146
  },
2155
2147
  getProtectedRoutes: () => {
2156
2148
  return [
2157
- "/checkout/*",
2149
+ "/checkout",
2158
2150
  "/checkout-confirm",
2159
2151
  "/subscription-change-confirm",
2160
- "/subscriptions/*",
2152
+ "/subscriptions",
2161
2153
  "/manage-payment"
2162
2154
  ];
2163
2155
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zuplo/zudoku-plugin-monetization",
3
- "version": "0.0.24",
3
+ "version": "0.0.25",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/zuplo/zudoku",
@@ -31,7 +31,7 @@
31
31
  "react": "19.2.4",
32
32
  "react-dom": "19.2.4",
33
33
  "tsdown": "0.20.3",
34
- "zudoku": "0.71.3"
34
+ "zudoku": "0.71.10"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "react": ">=19.2.0",