@zuplo/zudoku-plugin-monetization 0.0.25 → 0.0.26

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.d.mts CHANGED
@@ -1,14 +1,17 @@
1
1
  import * as zudoku from "zudoku";
2
+ import "react";
2
3
 
3
- //#region src/ZuploMonetizationPlugin.d.ts
4
- type ZudokuMonetizationPluginOptions = {
4
+ //#region src/MonetizationContext.d.ts
5
+ interface MonetizationConfig {
5
6
  pricing?: {
6
7
  subtitle?: string;
7
8
  title?: string;
8
- units?: Record<string, string>;
9
9
  showYearlyPrice?: boolean;
10
+ units?: Record<string, string>;
10
11
  };
11
- };
12
- declare const zuploMonetizationPlugin: (options?: ZudokuMonetizationPluginOptions | undefined) => zudoku.ZudokuPlugin;
12
+ }
13
+ //#endregion
14
+ //#region src/ZuploMonetizationPlugin.d.ts
15
+ declare const zuploMonetizationPlugin: (options?: MonetizationConfig | undefined) => zudoku.ZudokuPlugin;
13
16
  //#endregion
14
17
  export { zuploMonetizationPlugin };
package/dist/index.mjs CHANGED
@@ -8,9 +8,9 @@ import { Alert, AlertAction, AlertDescription, AlertTitle } from "zudoku/ui/Aler
8
8
  import { Card, CardContent, CardHeader, CardTitle } from "zudoku/ui/Card";
9
9
  import { Separator } from "zudoku/ui/Separator";
10
10
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
+ import { createContext, use, useEffect, useMemo, useState } from "react";
11
12
  import { parse } from "tinyduration";
12
13
  import { Button as Button$1 } from "zudoku/ui/Button";
13
- import { useEffect, useMemo, useState } from "react";
14
14
  import { DismissibleAlert, DismissibleAlertAction } from "zudoku/ui/DismissibleAlert";
15
15
  import { ActionButton } from "zudoku/ui/ActionButton";
16
16
  import { Item, ItemContent, ItemDescription, ItemMedia, ItemTitle } from "zudoku/ui/Item";
@@ -90,6 +90,11 @@ const usePlans = () => {
90
90
  });
91
91
  };
92
92
 
93
+ //#endregion
94
+ //#region src/MonetizationContext.tsx
95
+ const MonetizationContext = createContext({});
96
+ const useMonetizationConfig = () => use(MonetizationContext);
97
+
93
98
  //#endregion
94
99
  //#region src/utils/formatDuration.ts
95
100
  const formatDuration = (iso) => {
@@ -124,6 +129,24 @@ const formatDurationInterval = (iso) => {
124
129
  return iso;
125
130
  }
126
131
  };
132
+ /**
133
+ * Returns an adjective form suitable for possessive context
134
+ * e.g. "your monthly quota", "your weekly limit".
135
+ * Falls back to "billing period" for multi-unit cadences
136
+ * where "every 3 months" would be grammatically awkward.
137
+ */
138
+ const formatDurationAdjective = (iso) => {
139
+ try {
140
+ const d = parse(iso);
141
+ if (d.years === 1) return "yearly";
142
+ if (d.months === 1) return "monthly";
143
+ if (d.weeks === 1) return "weekly";
144
+ if (d.days === 1) return "daily";
145
+ return "billing period";
146
+ } catch {
147
+ return "billing period";
148
+ }
149
+ };
127
150
 
128
151
  //#endregion
129
152
  //#region src/utils/formatPrice.ts
@@ -137,7 +160,8 @@ const formatPrice = (amount, currency) => new Intl.NumberFormat("en-US", {
137
160
 
138
161
  //#endregion
139
162
  //#region src/utils/categorizeRateCards.ts
140
- const categorizeRateCards = (rateCards, currency, units) => {
163
+ const categorizeRateCards = (rateCards, options) => {
164
+ const { currency, units, planBillingCadence } = options ?? {};
141
165
  const quotas = [];
142
166
  const features = [];
143
167
  for (const rc of rateCards) {
@@ -157,7 +181,7 @@ const categorizeRateCards = (rateCards, currency, units) => {
157
181
  key: rc.featureKey ?? rc.key,
158
182
  name: rc.name,
159
183
  limit: et.issueAfterReset,
160
- period: et.usagePeriod ? formatDuration(et.usagePeriod) : "Month",
184
+ period: rc.billingCadence ? formatDuration(rc.billingCadence) : planBillingCadence ? formatDuration(planBillingCadence) : "month",
161
185
  overagePrice
162
186
  });
163
187
  } else if (et.type === "boolean") features.push({
@@ -267,12 +291,13 @@ const queryClient = new QueryClient({ defaultOptions: {
267
291
  }
268
292
  }
269
293
  } });
270
- const ZuploMonetizationWrapper = () => {
271
- return /* @__PURE__ */ jsx(QueryClientProvider, {
272
- client: queryClient,
294
+ const ZuploMonetizationWrapper = ({ options = {} }) => /* @__PURE__ */ jsx(QueryClientProvider, {
295
+ client: queryClient,
296
+ children: /* @__PURE__ */ jsx(MonetizationContext, {
297
+ value: options,
273
298
  children: /* @__PURE__ */ jsx(ClientOnly, { children: /* @__PURE__ */ jsx(Outlet, {}) })
274
- });
275
- };
299
+ })
300
+ });
276
301
 
277
302
  //#endregion
278
303
  //#region src/pages/CheckoutConfirmPage.tsx
@@ -283,10 +308,15 @@ const CheckoutConfirmPage = () => {
283
308
  const deploymentName = useDeploymentName();
284
309
  const navigate = useNavigate();
285
310
  const { data: plans } = usePlans();
311
+ const { pricing } = useMonetizationConfig();
286
312
  const selectedPlan = plans?.items?.find((plan) => plan.id === planId);
287
313
  if (!planId) throw new Error("Parameter `planId` missing");
288
314
  const rateCards = selectedPlan?.phases.at(-1)?.rateCards;
289
- const { quotas, features } = categorizeRateCards(rateCards ?? [], selectedPlan?.currency);
315
+ const { quotas, features } = categorizeRateCards(rateCards ?? [], {
316
+ currency: selectedPlan?.currency,
317
+ units: pricing?.units,
318
+ planBillingCadence: selectedPlan?.billingCadence
319
+ });
290
320
  const price = selectedPlan ? getPriceFromPlan(selectedPlan) : null;
291
321
  const billingCycle = selectedPlan?.billingCadence ? formatDuration(selectedPlan.billingCadence) : null;
292
322
  const createSubscriptionMutation = useMutation({
@@ -578,11 +608,14 @@ const ManagePaymentPage = () => {
578
608
 
579
609
  //#endregion
580
610
  //#region src/pages/pricing/PricingCard.tsx
581
- const PhaseSection = ({ phase, currency, showName, excludeKeys, units }) => {
582
- const { quotas, features } = categorizeRateCards(phase.rateCards, currency, units);
583
- const filteredQuotas = quotas.filter((q) => !excludeKeys.has(q.key));
584
- const filteredFeatures = features.filter((f) => !excludeKeys.has(f.key));
585
- if (filteredQuotas.length === 0 && filteredFeatures.length === 0) return null;
611
+ const PhaseSection = ({ phase, currency, showName, billingCadence }) => {
612
+ const { pricing } = useMonetizationConfig();
613
+ const { quotas, features } = categorizeRateCards(phase.rateCards, {
614
+ currency,
615
+ units: pricing?.units,
616
+ planBillingCadence: billingCadence
617
+ });
618
+ if (quotas.length === 0 && features.length === 0) return null;
586
619
  return /* @__PURE__ */ jsxs("div", {
587
620
  className: "space-y-2",
588
621
  children: [
@@ -597,17 +630,19 @@ const PhaseSection = ({ phase, currency, showName, excludeKeys, units }) => {
597
630
  ]
598
631
  })]
599
632
  }),
600
- filteredQuotas.map((quota) => /* @__PURE__ */ jsx(QuotaItem, { quota }, quota.key)),
601
- filteredFeatures.map((feature) => /* @__PURE__ */ jsx(FeatureItem, { feature }, feature.key))
633
+ quotas.map((quota) => /* @__PURE__ */ jsx(QuotaItem, { quota }, quota.key)),
634
+ features.map((feature) => /* @__PURE__ */ jsx(FeatureItem, { feature }, feature.key))
602
635
  ]
603
636
  });
604
637
  };
605
- const PricingCard = ({ plan, isPopular = false, isSubscribed = false, showYearlyPrice = true, units }) => {
638
+ const PricingCard = ({ plan, isPopular = false, isSubscribed = false }) => {
639
+ const { pricing } = useMonetizationConfig();
606
640
  if (plan.phases.length === 0) return null;
607
641
  const price = getPriceFromPlan(plan);
608
642
  const isFree = price.monthly === 0;
609
643
  const isCustom = plan.metadata?.isCustom === true;
610
644
  const hasMultiplePhases = plan.phases.length > 1;
645
+ const billingInterval = formatDuration(plan.billingCadence);
611
646
  return /* @__PURE__ */ jsxs("div", {
612
647
  className: cn("relative rounded-lg border p-6 flex flex-col", isPopular && "border-primary border-2"),
613
648
  children: [
@@ -636,10 +671,10 @@ const PricingCard = ({ plan, isPopular = false, isSubscribed = false, showYearly
636
671
  })] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
637
672
  className: "text-3xl font-bold text-card-foreground",
638
673
  children: isFree ? "Free" : formatPrice(price.monthly, plan.currency)
639
- }), !isFree && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
674
+ }), !isFree && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("span", {
640
675
  className: "text-muted-foreground text-sm",
641
- children: "/mo"
642
- }), showYearlyPrice && /* @__PURE__ */ jsxs("div", {
676
+ children: ["/", billingInterval]
677
+ }), pricing?.showYearlyPrice !== false && price.yearly > 0 && /* @__PURE__ */ jsxs("div", {
643
678
  className: "w-full text-sm text-muted-foreground mt-1",
644
679
  children: [formatPrice(price.yearly, plan.currency), "/year"]
645
680
  })] })] })
@@ -652,16 +687,12 @@ const PricingCard = ({ plan, isPopular = false, isSubscribed = false, showYearly
652
687
  }),
653
688
  /* @__PURE__ */ jsx("div", {
654
689
  className: "space-y-4 mb-6 grow",
655
- children: plan.phases.map((phase, index) => {
656
- const laterKeys = new Set(plan.phases.slice(index + 1).flatMap((p) => p.rateCards.map((rc) => rc.featureKey ?? rc.key)));
657
- return /* @__PURE__ */ jsx(PhaseSection, {
658
- phase,
659
- currency: plan.currency,
660
- showName: hasMultiplePhases,
661
- excludeKeys: laterKeys,
662
- units
663
- }, phase.key);
664
- })
690
+ children: plan.phases.map((phase) => /* @__PURE__ */ jsx(PhaseSection, {
691
+ phase,
692
+ currency: plan.currency,
693
+ showName: hasMultiplePhases,
694
+ billingCadence: plan.billingCadence
695
+ }, phase.key))
665
696
  }),
666
697
  isSubscribed ? /* @__PURE__ */ jsx(Button, {
667
698
  variant: isPopular ? "default" : "secondary",
@@ -684,7 +715,8 @@ const PricingCard = ({ plan, isPopular = false, isSubscribed = false, showYearly
684
715
 
685
716
  //#endregion
686
717
  //#region src/pages/PricingPage.tsx
687
- const PricingPage = ({ subtitle = "See our pricing options and choose the one that best suits your needs.", title = "Pricing", units, showYearlyPrice = true }) => {
718
+ const PricingPage = () => {
719
+ const { pricing } = useMonetizationConfig();
688
720
  const zudoku = useZudoku();
689
721
  const deploymentName = useDeploymentName();
690
722
  const auth = useAuth();
@@ -697,28 +729,26 @@ const PricingPage = ({ subtitle = "See our pricing options and choose the one th
697
729
  return /* @__PURE__ */ jsxs("div", {
698
730
  className: "w-full px-4 pt-(--padding-content-top) pb-(--padding-content-bottom)",
699
731
  children: [
700
- /* @__PURE__ */ jsxs(Head, { children: [/* @__PURE__ */ jsx("title", { children: title }), /* @__PURE__ */ jsx("meta", {
732
+ /* @__PURE__ */ jsxs(Head, { children: [/* @__PURE__ */ jsx("title", { children: pricing?.title ?? "Pricing" }), /* @__PURE__ */ jsx("meta", {
701
733
  name: "description",
702
- content: subtitle
734
+ content: pricing?.subtitle ?? "See our pricing options and choose the one that best suits your needs."
703
735
  })] }),
704
736
  /* @__PURE__ */ jsxs("div", {
705
737
  className: "text-center space-y-4 mb-12",
706
738
  children: [/* @__PURE__ */ jsx(Heading, {
707
739
  level: 1,
708
740
  "data-testid": "title",
709
- children: title
741
+ children: pricing?.title ?? "Pricing"
710
742
  }), /* @__PURE__ */ jsx("p", {
711
743
  className: "text-muted-foreground",
712
744
  "data-testid": "subtitle",
713
- children: subtitle
745
+ children: pricing?.subtitle ?? "See our pricing options and choose the one that best suits your needs."
714
746
  })]
715
747
  }),
716
748
  /* @__PURE__ */ jsx("div", {
717
749
  className: "w-full grid grid-cols-1 sm:grid-cols-[repeat(auto-fit,minmax(300px,max-content))] justify-center gap-6",
718
750
  children: pricingTable.items.map((plan) => /* @__PURE__ */ jsx(PricingCard, {
719
751
  plan,
720
- units,
721
- showYearlyPrice,
722
752
  isPopular: plan.metadata?.zuplo_most_popular === "true",
723
753
  isSubscribed: subscriptions.items.some((subscription) => ["active", "canceled"].includes(subscription.status))
724
754
  }, plan.id))
@@ -738,11 +768,16 @@ const SubscriptionChangeConfirmPage = () => {
738
768
  const deploymentName = useDeploymentName();
739
769
  const navigate = useNavigate();
740
770
  const { data: plans } = usePlans();
771
+ const { pricing } = useMonetizationConfig();
741
772
  const selectedPlan = plans?.items?.find((plan) => plan.id === planId);
742
773
  if (!planId) throw new Error("Parameter `planId` missing");
743
774
  if (!subscriptionId) throw new Error("Parameter `subscriptionId` missing");
744
775
  const rateCards = selectedPlan?.phases.at(-1)?.rateCards;
745
- const { quotas, features } = categorizeRateCards(rateCards ?? [], selectedPlan?.currency);
776
+ const { quotas, features } = categorizeRateCards(rateCards ?? [], {
777
+ currency: selectedPlan?.currency,
778
+ units: pricing?.units,
779
+ planBillingCadence: selectedPlan?.billingCadence
780
+ });
746
781
  const price = selectedPlan ? getPriceFromPlan(selectedPlan) : null;
747
782
  const billingCycle = selectedPlan?.billingCadence ? formatDuration(selectedPlan.billingCadence) : null;
748
783
  const changeMutation = useMutation({
@@ -1279,15 +1314,23 @@ const CancelSubscriptionDialog = ({ open, onOpenChange, planName, subscriptionId
1279
1314
 
1280
1315
  //#endregion
1281
1316
  //#region src/pages/subscriptions/SwitchPlanModal.tsx
1282
- const comparePlans = (currentPlan, targetPlan, currentIndex, targetIndex) => {
1317
+ const comparePlans = (currentPlan, targetPlan, currentIndex, targetIndex, units) => {
1283
1318
  const isUpgrade = targetIndex > currentIndex;
1284
1319
  const currentPhase = currentPlan?.phases.at(-1);
1285
1320
  const targetPhase = targetPlan.phases.at(-1);
1286
- const { quotas: currentQuotas, features: currentFeatures } = currentPhase ? categorizeRateCards(currentPhase.rateCards, currentPlan?.currency) : {
1321
+ const { quotas: currentQuotas, features: currentFeatures } = currentPhase ? categorizeRateCards(currentPhase.rateCards, {
1322
+ currency: currentPlan?.currency,
1323
+ units,
1324
+ planBillingCadence: currentPlan?.billingCadence
1325
+ }) : {
1287
1326
  quotas: [],
1288
1327
  features: []
1289
1328
  };
1290
- const { quotas: targetQuotas, features: targetFeatures } = targetPhase ? categorizeRateCards(targetPhase.rateCards, targetPlan.currency) : {
1329
+ const { quotas: targetQuotas, features: targetFeatures } = targetPhase ? categorizeRateCards(targetPhase.rateCards, {
1330
+ currency: targetPlan.currency,
1331
+ units,
1332
+ planBillingCadence: targetPlan.billingCadence
1333
+ }) : {
1291
1334
  quotas: [],
1292
1335
  features: []
1293
1336
  };
@@ -1394,7 +1437,11 @@ const PlanComparisonItem = ({ comparison, subscriptionId, mode, onRequestChange
1394
1437
  children: "Free"
1395
1438
  }) : /* @__PURE__ */ jsxs("span", {
1396
1439
  className: "text-primary font-medium text-lg",
1397
- children: [formatPrice(displayPrice, comparison.plan.currency), "/ mo"]
1440
+ children: [
1441
+ formatPrice(displayPrice, comparison.plan.currency),
1442
+ "/",
1443
+ formatDuration(comparison.plan.billingCadence)
1444
+ ]
1398
1445
  })]
1399
1446
  }), isCustom ? /* @__PURE__ */ jsx(Button$1, {
1400
1447
  variant: "default",
@@ -1558,6 +1605,7 @@ const SwitchPlanModal = ({ subscription, children }) => {
1558
1605
  const [open, setOpen] = useState(false);
1559
1606
  const { data: plansData } = usePlans();
1560
1607
  const [switchTo, setSwitchTo] = useState(null);
1608
+ const { pricing } = useMonetizationConfig();
1561
1609
  const currentPlan = plansData?.items.find((p) => p.id === subscription.plan.id);
1562
1610
  const { upgrades, downgrades, privatePlans } = useMemo(() => {
1563
1611
  if (!plansData?.items || !currentPlan) return {
@@ -1568,14 +1616,18 @@ const SwitchPlanModal = ({ subscription, children }) => {
1568
1616
  const isPrivatePlan = (plan) => plan.metadata?.zuplo_private_plan === "true";
1569
1617
  const currentIndex = plansData.items.findIndex((p) => p.id === currentPlan.id);
1570
1618
  const allComparisons = plansData.items.filter((p) => p.id !== currentPlan.id).map((plan) => {
1571
- return comparePlans(currentPlan, plan, currentIndex, plansData.items.indexOf(plan));
1619
+ return comparePlans(currentPlan, plan, currentIndex, plansData.items.indexOf(plan), pricing?.units);
1572
1620
  });
1573
1621
  return {
1574
1622
  upgrades: allComparisons.filter((c) => c.isUpgrade && !isPrivatePlan(c.plan)),
1575
1623
  downgrades: allComparisons.filter((c) => !c.isUpgrade && !isPrivatePlan(c.plan)),
1576
1624
  privatePlans: allComparisons.filter((c) => isPrivatePlan(c.plan))
1577
1625
  };
1578
- }, [plansData?.items, currentPlan]);
1626
+ }, [
1627
+ plansData?.items,
1628
+ currentPlan,
1629
+ pricing?.units
1630
+ ]);
1579
1631
  return /* @__PURE__ */ jsxs(Fragment, { children: [switchTo !== null && /* @__PURE__ */ jsx(ConfirmSwitchAlert, {
1580
1632
  switchTo,
1581
1633
  onRequestClose: () => setSwitchTo(null)
@@ -1763,6 +1815,8 @@ const isMeteredEntitlement = (entitlement) => {
1763
1815
  return "balance" in entitlement;
1764
1816
  };
1765
1817
  const UsageItem = ({ meter, item, subscription }) => {
1818
+ const cadence = item?.billingCadence ?? subscription?.billingCadence;
1819
+ const billingPeriod = cadence ? formatDurationAdjective(cadence) : "monthly";
1766
1820
  const isSoftLimit = item?.included?.entitlement?.isSoftLimit ?? true;
1767
1821
  const rate = (item?.price?.tiers?.find((t) => !t.upToAmount) ?? item?.price?.tiers?.at(-1))?.unitPrice?.amount;
1768
1822
  const hasOverage = meter.overage > 0;
@@ -1777,7 +1831,11 @@ const UsageItem = ({ meter, item, subscription }) => {
1777
1831
  className: "mb-4",
1778
1832
  children: [
1779
1833
  /* @__PURE__ */ jsx(AlertTriangleIcon, { className: "size-4 text-red-600 shrink-0" }),
1780
- /* @__PURE__ */ jsx(AlertTitle, { children: "You've exceeded your monthly quota" }),
1834
+ /* @__PURE__ */ jsxs(AlertTitle, { children: [
1835
+ "You've exceeded your ",
1836
+ billingPeriod,
1837
+ " quota"
1838
+ ] }),
1781
1839
  /* @__PURE__ */ jsxs(AlertDescription, { children: [
1782
1840
  "Additional usage is being charged at the overage rate",
1783
1841
  rate ? ` ($${Number(rate).toFixed(2)}/call)` : "",
@@ -1798,7 +1856,11 @@ const UsageItem = ({ meter, item, subscription }) => {
1798
1856
  className: "mb-4",
1799
1857
  children: [
1800
1858
  /* @__PURE__ */ jsx(AlertTriangleIcon, { className: "size-4 text-red-600 shrink-0" }),
1801
- /* @__PURE__ */ jsx(AlertTitle, { children: "You've reached your monthly limit" }),
1859
+ /* @__PURE__ */ jsxs(AlertTitle, { children: [
1860
+ "You've reached your ",
1861
+ billingPeriod,
1862
+ " limit"
1863
+ ] }),
1802
1864
  /* @__PURE__ */ jsx(AlertDescription, { children: "Requests beyond your quota are blocked. Upgrade to a higher plan for more usage." }),
1803
1865
  subscription && /* @__PURE__ */ jsx(AlertAction, { children: /* @__PURE__ */ jsx(SwitchPlanModal, {
1804
1866
  subscription,
@@ -1848,7 +1910,7 @@ const UsageItem = ({ meter, item, subscription }) => {
1848
1910
  }),
1849
1911
  /* @__PURE__ */ jsxs("p", {
1850
1912
  className: "text-xs text-muted-foreground",
1851
- children: [meter.balance.toLocaleString(), " remaining this month"]
1913
+ children: [meter.balance.toLocaleString(), " remaining this billing period"]
1852
1914
  })
1853
1915
  ]
1854
1916
  })]
@@ -2071,7 +2133,7 @@ const SubscriptionsPage = () => {
2071
2133
  //#endregion
2072
2134
  //#region src/ZuploMonetizationPlugin.tsx
2073
2135
  const PRICING_PATH = "/pricing";
2074
- const zuploMonetizationPlugin = createPlugin((options) => ({
2136
+ const zuploMonetizationPlugin = createPlugin((options = {}) => ({
2075
2137
  transformConfig: ({ config, merge }) => merge({
2076
2138
  apiKeys: { enabled: false },
2077
2139
  header: { navigation: [...config.header?.navigation ?? [], {
@@ -2107,7 +2169,7 @@ const zuploMonetizationPlugin = createPlugin((options) => ({
2107
2169
  }],
2108
2170
  getRoutes: () => {
2109
2171
  return [{
2110
- Component: ZuploMonetizationWrapper,
2172
+ element: /* @__PURE__ */ jsx(ZuploMonetizationWrapper, { options }),
2111
2173
  handle: { layout: "none" },
2112
2174
  children: [
2113
2175
  {
@@ -2129,12 +2191,7 @@ const zuploMonetizationPlugin = createPlugin((options) => ({
2129
2191
  {
2130
2192
  path: PRICING_PATH,
2131
2193
  handle: { layout: "default" },
2132
- element: /* @__PURE__ */ jsx(PricingPage, {
2133
- subtitle: options?.pricing?.subtitle,
2134
- title: options?.pricing?.title,
2135
- units: options?.pricing?.units,
2136
- showYearlyPrice: options?.pricing?.showYearlyPrice
2137
- })
2194
+ element: /* @__PURE__ */ jsx(PricingPage, {})
2138
2195
  },
2139
2196
  {
2140
2197
  handle: { layout: "default" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zuplo/zudoku-plugin-monetization",
3
- "version": "0.0.25",
3
+ "version": "0.0.26",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/zuplo/zudoku",