@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.
- package/dist/index.mjs +28 -36
- 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,
|
|
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
|
-
|
|
231
|
-
|
|
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("
|
|
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
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
1530
|
-
|
|
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
|
|
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
|
-
}
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
34
|
+
"zudoku": "0.71.10"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"react": ">=19.2.0",
|