@lukoweb/apitogo-plugin-dev-portal-billing 0.1.73 → 0.1.75

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
@@ -5,17 +5,6 @@ import * as _tanstack_react_query0 from "@tanstack/react-query";
5
5
  //#region src/pages/AccountPlansPage.d.ts
6
6
  declare const AccountPlansPage: () => react_jsx_runtime0.JSX.Element;
7
7
  //#endregion
8
- //#region src/components/ApiKeysPanel.d.ts
9
- /**
10
- * Lists the developer's gateway API keys with create and revoke. The plaintext key is returned by the
11
- * platform exactly once, so it is held in local state until dismissed and never re-fetched.
12
- */
13
- declare const ApiKeysPanel: ({
14
- readOnly
15
- }: {
16
- readOnly?: boolean;
17
- }) => react_jsx_runtime0.JSX.Element;
18
- //#endregion
19
8
  //#region src/types.d.ts
20
9
  type DevPortalApiKey = {
21
10
  id: string;
@@ -26,11 +15,16 @@ type DevPortalApiKey = {
26
15
  revokedAtUtc: string | null; /** Present only in the response to a successful create; never returned again. */
27
16
  key: string | null;
28
17
  };
29
- type DevPortalApiKeyListResponse = {
18
+ type DevPortalApiKeyPlan = {
19
+ planSku: string;
20
+ displayName: string;
30
21
  keys: DevPortalApiKey[];
31
22
  activeCount: number; /** Per-developer cap from the project's platform plan; null means unlimited. */
32
23
  maxKeys: number | null;
33
- canCreate: boolean; /** Header the key must be sent in when calling the gateway. */
24
+ canCreate: boolean;
25
+ };
26
+ type DevPortalApiKeyListResponse = {
27
+ plans: DevPortalApiKeyPlan[]; /** Header the key must be sent in when calling the gateway. */
34
28
  header: string;
35
29
  gatewayBaseUrl: string | null;
36
30
  };
@@ -50,6 +44,21 @@ type DevPortalBillingConfig = {
50
44
  }>;
51
45
  };
52
46
  //#endregion
47
+ //#region src/components/ApiKeysPanel.d.ts
48
+ /**
49
+ * Lists gateway API keys for one plan with create and revoke. The plaintext key is returned by the
50
+ * platform exactly once, so it is held in local state until dismissed and never re-fetched.
51
+ */
52
+ declare const ApiKeysPanel: ({
53
+ plan,
54
+ header,
55
+ readOnly
56
+ }: {
57
+ plan: DevPortalApiKeyPlan;
58
+ header: string;
59
+ readOnly?: boolean;
60
+ }) => react_jsx_runtime0.JSX.Element;
61
+ //#endregion
53
62
  //#region src/paths.d.ts
54
63
  declare const PRICING_PATH = "/pricing";
55
64
  declare const CHECKOUT_PATH = "/checkout";
@@ -171,7 +180,10 @@ declare function useApiKeys(): _tanstack_react_query0.QueryObserverRefetchErrorR
171
180
  fetchStatus: _tanstack_react_query0.FetchStatus;
172
181
  promise: Promise<DevPortalApiKeyListResponse>;
173
182
  };
174
- declare function useCreateApiKey(): _tanstack_react_query0.UseMutationResult<DevPortalApiKey, Error, string, unknown>;
183
+ declare function useCreateApiKey(): _tanstack_react_query0.UseMutationResult<DevPortalApiKey, Error, {
184
+ name: string;
185
+ planSku: string;
186
+ }, unknown>;
175
187
  declare function useRevokeApiKey(): _tanstack_react_query0.UseMutationResult<void, Error, string, unknown>;
176
188
  //#endregion
177
189
  export { API_KEY_CAP_REACHED, AccountPlansPage, ApiKeysPanel, CHECKOUT_PATH, CREDENTIALS_PATH, PRICING_PATH, SUBSCRIPTIONS_PATH, devPortalBillingPlugin, useApiKeys, useCreateApiKey, useRevokeApiKey };
package/dist/index.mjs CHANGED
@@ -177,7 +177,7 @@ const PricingCard = ({ plan, mode = "public", subscriptionStatus, isSubscribed =
177
177
  variant: "secondary",
178
178
  className: "w-full",
179
179
  disabled: true,
180
- children: "Current plan"
180
+ children: "Subscribed"
181
181
  }),
182
182
  onUnsubscribe ? /* @__PURE__ */ jsxs(AlertDialog, { children: [/* @__PURE__ */ jsx(AlertDialogTrigger, {
183
183
  asChild: true,
@@ -292,22 +292,28 @@ function useCancelSubscription() {
292
292
  const DEMO_SUBSCRIPTION_KEY = "demo-subscription-key";
293
293
  const DEMO_GATEWAY_KEY_HEADER = "Ocp-Apim-Subscription-Key";
294
294
  const DEMO_MAX_KEYS = 5;
295
- function resolveDemoPlanSku(plans) {
296
- return plans?.[0]?.sku ?? "free";
295
+ function resolveDemoPlans(plans) {
296
+ if (plans && plans.length > 0) return plans.map((plan) => ({
297
+ sku: plan.sku,
298
+ displayName: plan.displayName
299
+ }));
300
+ return [{
301
+ sku: "free",
302
+ displayName: "Free"
303
+ }];
297
304
  }
298
305
  function createDemoMeResponse(plans) {
299
- const planSku = resolveDemoPlanSku(plans);
300
306
  const periodEnd = /* @__PURE__ */ new Date();
301
307
  periodEnd.setMonth(periodEnd.getMonth() + 1);
302
308
  return {
303
309
  userId: "00000000-0000-0000-0000-000000000001",
304
310
  displayName: "Demo User",
305
- subscriptions: [{
306
- planSku,
311
+ subscriptions: resolveDemoPlans(plans).map((plan) => ({
312
+ planSku: plan.sku,
307
313
  status: "Active",
308
314
  entitlementState: "active",
309
315
  currentPeriodEnd: periodEnd.toISOString()
310
- }]
316
+ }))
311
317
  };
312
318
  }
313
319
  function createDemoCredentials(plans) {
@@ -315,24 +321,28 @@ function createDemoCredentials(plans) {
315
321
  idToken: "demo-id-token",
316
322
  accessToken: null,
317
323
  gatewayBaseUrl: null,
318
- planSku: resolveDemoPlanSku(plans),
324
+ planSkus: resolveDemoPlans(plans).map((plan) => plan.sku),
319
325
  expiresAt: null
320
326
  };
321
327
  }
322
- function createDemoApiKeys() {
328
+ function createDemoApiKeys(plans) {
323
329
  return {
324
- keys: [{
325
- id: "00000000-0000-0000-0000-0000000000a1",
326
- name: "default",
327
- keyPrefix: DEMO_SUBSCRIPTION_KEY.slice(0, 8),
328
- status: "active",
329
- createdAtUtc: (/* @__PURE__ */ new Date()).toISOString(),
330
- revokedAtUtc: null,
331
- key: null
332
- }],
333
- activeCount: 1,
334
- maxKeys: DEMO_MAX_KEYS,
335
- canCreate: true,
330
+ plans: resolveDemoPlans(plans).map((plan, index) => ({
331
+ planSku: plan.sku,
332
+ displayName: plan.displayName,
333
+ keys: index === 0 ? [{
334
+ id: "00000000-0000-0000-0000-0000000000a1",
335
+ name: "default",
336
+ keyPrefix: DEMO_SUBSCRIPTION_KEY.slice(0, 8),
337
+ status: "active",
338
+ createdAtUtc: (/* @__PURE__ */ new Date()).toISOString(),
339
+ revokedAtUtc: null,
340
+ key: null
341
+ }] : [],
342
+ activeCount: index === 0 ? 1 : 0,
343
+ maxKeys: DEMO_MAX_KEYS,
344
+ canCreate: true
345
+ })),
336
346
  header: DEMO_GATEWAY_KEY_HEADER,
337
347
  gatewayBaseUrl: null
338
348
  };
@@ -502,6 +512,7 @@ function useApiKeys() {
502
512
  const apiBaseUrl = useDevPortalApiBaseUrl();
503
513
  const isPreview = useDevPortalPreviewMode();
504
514
  const isDemoSession = useIsDemoSession();
515
+ const { previewPlans } = useDevPortalBillingConfig();
505
516
  const liveQuery = useQuery({
506
517
  queryKey: apiKeysQueryKey(apiBaseUrl),
507
518
  enabled: auth.isAuthenticated && !isPreview && !isDemoSession && Boolean(apiBaseUrl),
@@ -519,7 +530,7 @@ function useApiKeys() {
519
530
  });
520
531
  if (isDemoSession && auth.isAuthenticated) return {
521
532
  ...liveQuery,
522
- data: createDemoApiKeys(),
533
+ data: createDemoApiKeys(previewPlans),
523
534
  error: null,
524
535
  isError: false,
525
536
  isFetching: false,
@@ -534,7 +545,7 @@ function useCreateApiKey() {
534
545
  const apiBaseUrl = useDevPortalApiBaseUrl();
535
546
  const queryClient = useQueryClient();
536
547
  return useMutation({
537
- mutationFn: async (name) => {
548
+ mutationFn: async ({ name, planSku }) => {
538
549
  if (!apiBaseUrl) throw new Error("Dev portal API is not configured.");
539
550
  const response = await fetch(`${apiBaseUrl}/api/v1/api-keys`, {
540
551
  method: "POST",
@@ -543,7 +554,10 @@ function useCreateApiKey() {
543
554
  "Content-Type": "application/json"
544
555
  },
545
556
  credentials: "include",
546
- body: JSON.stringify({ name })
557
+ body: JSON.stringify({
558
+ name,
559
+ planSku
560
+ })
547
561
  });
548
562
  if (response.status === 409) throw new Error(API_KEY_CAP_REACHED);
549
563
  if (!response.ok) throw new Error(await readProblemDetail(response) ?? "Failed to create API key.");
@@ -583,24 +597,27 @@ async function readProblemDetail(response) {
583
597
  //#endregion
584
598
  //#region src/components/ApiKeysPanel.tsx
585
599
  /**
586
- * Lists the developer's gateway API keys with create and revoke. The plaintext key is returned by the
600
+ * Lists gateway API keys for one plan with create and revoke. The plaintext key is returned by the
587
601
  * platform exactly once, so it is held in local state until dismissed and never re-fetched.
588
602
  */
589
- const ApiKeysPanel = ({ readOnly = false }) => {
590
- const { data, isLoading, error } = useApiKeys();
603
+ const ApiKeysPanel = ({ plan, header, readOnly = false }) => {
591
604
  const createKey = useCreateApiKey();
592
605
  const revokeKey = useRevokeApiKey();
593
606
  const [name, setName] = useState("");
594
607
  const [newKey, setNewKey] = useState(null);
595
608
  const [openRevokeId, setOpenRevokeId] = useState(null);
596
609
  const [pendingRevokeId, setPendingRevokeId] = useState(null);
597
- const activeKeys = data?.keys.filter((key) => key.status === "active") ?? [];
598
- const capLabel = data?.maxKeys == null ? `${data?.activeCount ?? activeKeys.length} active` : `${data.activeCount} of ${data.maxKeys} used`;
599
- const canCreate = !readOnly && (data?.canCreate ?? false);
610
+ const activeKeys = plan.keys.filter((key) => key.status === "active");
611
+ const planActiveCount = activeKeys.length;
612
+ const capLabel = plan.maxKeys == null ? `${plan.activeCount} active` : `${plan.activeCount} of ${plan.maxKeys} used`;
613
+ const canCreate = !readOnly && plan.canCreate;
600
614
  const handleCreate = () => {
601
615
  const trimmed = name.trim();
602
616
  if (!trimmed) return;
603
- createKey.mutate(trimmed, { onSuccess: (key) => {
617
+ createKey.mutate({
618
+ name: trimmed,
619
+ planSku: plan.planSku
620
+ }, { onSuccess: (key) => {
604
621
  setNewKey(key);
605
622
  setName("");
606
623
  } });
@@ -619,9 +636,9 @@ const ApiKeysPanel = ({ readOnly = false }) => {
619
636
  className: "flex flex-wrap items-start justify-between gap-3",
620
637
  children: [/* @__PURE__ */ jsxs("div", {
621
638
  className: "space-y-1",
622
- children: [/* @__PURE__ */ jsx("h2", {
639
+ children: [/* @__PURE__ */ jsxs("h2", {
623
640
  className: "text-lg font-medium",
624
- children: "API keys"
641
+ children: [plan.displayName, " API keys"]
625
642
  }), /* @__PURE__ */ jsxs("p", {
626
643
  className: "text-sm text-muted-foreground",
627
644
  children: [
@@ -629,16 +646,16 @@ const ApiKeysPanel = ({ readOnly = false }) => {
629
646
  " ",
630
647
  /* @__PURE__ */ jsx("code", {
631
648
  className: "rounded bg-muted px-1 py-0.5 text-xs",
632
- children: data?.header ?? "Ocp-Apim-Subscription-Key"
649
+ children: header
633
650
  }),
634
651
  " ",
635
- "header when calling the gateway. Keys share your plan's rate limit and quota."
652
+ "header when calling this plan's endpoints. Keys share this plan's rate limit and key cap."
636
653
  ]
637
654
  })]
638
- }), data ? /* @__PURE__ */ jsx("span", {
655
+ }), /* @__PURE__ */ jsx("span", {
639
656
  className: "shrink-0 rounded-full border px-3 py-1 text-xs text-muted-foreground",
640
657
  children: capLabel
641
- }) : null]
658
+ })]
642
659
  }),
643
660
  newKey?.key ? /* @__PURE__ */ jsxs(Alert, { children: [
644
661
  /* @__PURE__ */ jsx(KeyRoundIcon, { size: 16 }),
@@ -658,23 +675,15 @@ const ApiKeysPanel = ({ readOnly = false }) => {
658
675
  ] }) : null,
659
676
  createKey.isError ? /* @__PURE__ */ jsx(Alert, {
660
677
  variant: "destructive",
661
- children: /* @__PURE__ */ jsx(AlertTitle, { children: createKey.error.message === API_KEY_CAP_REACHED ? data?.maxKeys == null ? "You cannot create more API keys right now." : `You already have the maximum of ${data.maxKeys} active API keys. Revoke one to create another.` : createKey.error.message })
678
+ children: /* @__PURE__ */ jsx(AlertTitle, { children: createKey.error.message === API_KEY_CAP_REACHED ? plan.maxKeys == null ? "You cannot create more API keys right now." : `You already have the maximum of ${plan.maxKeys} active API keys. Revoke one to create another.` : createKey.error.message })
662
679
  }) : null,
663
680
  revokeKey.isError ? /* @__PURE__ */ jsx(Alert, {
664
681
  variant: "destructive",
665
682
  children: /* @__PURE__ */ jsx(AlertTitle, { children: revokeKey.error.message })
666
683
  }) : null,
667
- isLoading ? /* @__PURE__ */ jsx("p", {
668
- className: "text-sm text-muted-foreground",
669
- children: "Loading…"
670
- }) : null,
671
- error ? /* @__PURE__ */ jsx("p", {
672
- className: "text-sm text-muted-foreground",
673
- children: error instanceof Error && error.message === "NO_ENTITLEMENT" ? "Choose a plan to get your first API key." : "Unable to load your API keys. Try again in a moment."
674
- }) : null,
675
- data && activeKeys.length === 0 && !isLoading ? /* @__PURE__ */ jsx("p", {
684
+ planActiveCount === 0 ? /* @__PURE__ */ jsx("p", {
676
685
  className: "text-sm text-muted-foreground",
677
- children: "You have no active API keys yet."
686
+ children: "You have no active API keys for this plan yet."
678
687
  }) : null,
679
688
  activeKeys.length > 0 ? /* @__PURE__ */ jsx("ul", {
680
689
  className: "divide-y rounded-lg border",
@@ -738,7 +747,7 @@ const ApiKeysPanel = ({ readOnly = false }) => {
738
747
  className: "max-w-xs",
739
748
  maxLength: 64,
740
749
  placeholder: "Key name (e.g. production)",
741
- "aria-label": "New API key name",
750
+ "aria-label": `New API key name for ${plan.displayName}`,
742
751
  value: name,
743
752
  disabled: !canCreate || createKey.isPending,
744
753
  onChange: (event) => setName(event.target.value),
@@ -752,9 +761,9 @@ const ApiKeysPanel = ({ readOnly = false }) => {
752
761
  children: createKey.isPending ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Spinner, { size: 14 }), "Creating…"] }) : "Create API key"
753
762
  })]
754
763
  }),
755
- data && !data.canCreate && !readOnly ? /* @__PURE__ */ jsx("p", {
764
+ plan && !plan.canCreate && !readOnly ? /* @__PURE__ */ jsx("p", {
756
765
  className: "text-sm text-muted-foreground",
757
- children: data.maxKeys == null ? "API key creation is currently disabled for this API." : `You have reached your plan limit of ${data.maxKeys} API keys. Revoke a key to create a new one.`
766
+ children: plan.maxKeys == null ? "API key creation is currently disabled for this API." : `You have reached this plan's limit of ${plan.maxKeys} API keys. Revoke a key to create a new one.`
758
767
  }) : null
759
768
  ]
760
769
  });
@@ -981,8 +990,10 @@ const CredentialsPage = () => {
981
990
  const isPreview = useDevPortalPreviewMode();
982
991
  const isDemoSession = useIsDemoSession();
983
992
  const { data: credentials, isLoading, error } = useCredentials();
984
- const { data: catalog } = usePlans();
985
- const plan = catalog?.plans.find((item) => item.sku === credentials?.planSku);
993
+ const { data: apiKeys, isLoading: keysLoading, error: keysError } = useApiKeys();
994
+ const gatewayBaseUrl = credentials?.gatewayBaseUrl ?? apiKeys?.gatewayBaseUrl ?? null;
995
+ const header = apiKeys?.header ?? "Ocp-Apim-Subscription-Key";
996
+ const plans = apiKeys?.plans ?? [];
986
997
  return /* @__PURE__ */ jsxs("div", {
987
998
  className: "mx-auto max-w-screen-lg px-4 pb-16 pt-(--padding-content-top) lg:px-8",
988
999
  children: [
@@ -999,7 +1010,7 @@ const CredentialsPage = () => {
999
1010
  children: "API credentials"
1000
1011
  }), /* @__PURE__ */ jsx("p", {
1001
1012
  className: "text-muted-foreground",
1002
- children: "Create API keys and use them to authenticate requests to the API gateway."
1013
+ children: "Create API keys for each subscribed plan and use them to authenticate requests to the API gateway."
1003
1014
  })]
1004
1015
  })]
1005
1016
  }),
@@ -1018,7 +1029,7 @@ const CredentialsPage = () => {
1018
1029
  className: "rounded-xl border border-dashed p-8 text-center",
1019
1030
  children: [/* @__PURE__ */ jsx("p", {
1020
1031
  className: "text-muted-foreground",
1021
- children: "Sign in to view your subscription key."
1032
+ children: "Sign in to view your subscription keys."
1022
1033
  }), /* @__PURE__ */ jsx(Button$2, {
1023
1034
  className: "mt-4",
1024
1035
  asChild: true,
@@ -1028,15 +1039,15 @@ const CredentialsPage = () => {
1028
1039
  })
1029
1040
  })]
1030
1041
  }) : null,
1031
- !isPreview && !isDemoSession && auth.isAuthenticated && isLoading ? /* @__PURE__ */ jsx("p", {
1042
+ !isPreview && !isDemoSession && auth.isAuthenticated && (isLoading || keysLoading) ? /* @__PURE__ */ jsx("p", {
1032
1043
  className: "text-muted-foreground",
1033
1044
  children: "Loading credentials…"
1034
1045
  }) : null,
1035
- !isPreview && !isDemoSession && auth.isAuthenticated && error ? /* @__PURE__ */ jsxs("div", {
1046
+ !isPreview && !isDemoSession && auth.isAuthenticated && (error || keysError) ? /* @__PURE__ */ jsxs("div", {
1036
1047
  className: "rounded-xl border border-dashed p-8 text-center",
1037
1048
  children: [/* @__PURE__ */ jsx("p", {
1038
1049
  className: "text-muted-foreground",
1039
- children: error instanceof Error && error.message === "NO_ENTITLEMENT" ? "No active subscription found. Choose a plan to get your API key." : "Unable to load API credentials. Try again in a moment."
1050
+ children: error instanceof Error && error.message === "NO_ENTITLEMENT" || keysError instanceof Error && keysError.message === "NO_ENTITLEMENT" ? "No active subscription found. Choose a plan to get your API key." : "Unable to load API credentials. Try again in a moment."
1040
1051
  }), /* @__PURE__ */ jsx(Button$2, {
1041
1052
  className: "mt-4",
1042
1053
  asChild: true,
@@ -1046,43 +1057,44 @@ const CredentialsPage = () => {
1046
1057
  })
1047
1058
  })]
1048
1059
  }) : null,
1049
- (isDemoSession || !isPreview) && credentials ? /* @__PURE__ */ jsxs("div", {
1060
+ (isDemoSession || !isPreview) && auth.isAuthenticated && !error && !keysError && !isLoading && !keysLoading ? /* @__PURE__ */ jsxs("div", {
1050
1061
  className: "space-y-6",
1051
- children: [
1052
- /* @__PURE__ */ jsx("article", {
1053
- className: "rounded-xl border bg-card/60 p-6",
1054
- children: /* @__PURE__ */ jsxs("div", {
1055
- className: "space-y-1",
1056
- children: [/* @__PURE__ */ jsx("h2", {
1057
- className: "text-lg font-medium",
1058
- children: "Active plan"
1059
- }), /* @__PURE__ */ jsx("p", {
1060
- className: "text-sm text-muted-foreground",
1061
- children: plan?.displayName ?? credentials.planSku
1062
- })]
1062
+ children: [plans.length === 0 ? /* @__PURE__ */ jsxs("div", {
1063
+ className: "rounded-xl border border-dashed p-8 text-center",
1064
+ children: [/* @__PURE__ */ jsx("p", {
1065
+ className: "text-muted-foreground",
1066
+ children: "Choose a plan to get your first API key."
1067
+ }), /* @__PURE__ */ jsx(Button$2, {
1068
+ className: "mt-4",
1069
+ asChild: true,
1070
+ children: /* @__PURE__ */ jsx(Link, {
1071
+ to: "/account/plans",
1072
+ children: "View plans"
1063
1073
  })
1064
- }),
1065
- /* @__PURE__ */ jsx(ApiKeysPanel, { readOnly: isDemoSession }),
1066
- /* @__PURE__ */ jsxs("article", {
1067
- className: "rounded-xl border bg-card/60 p-6 space-y-4",
1068
- children: [/* @__PURE__ */ jsxs("div", {
1069
- className: "space-y-1",
1070
- children: [/* @__PURE__ */ jsx("h2", {
1071
- className: "text-lg font-medium",
1072
- children: "Gateway URL"
1073
- }), /* @__PURE__ */ jsx("p", {
1074
- className: "text-sm text-muted-foreground",
1075
- children: "Base URL for API requests through the gateway."
1076
- })]
1077
- }), credentials.gatewayBaseUrl ? /* @__PURE__ */ jsx(Value, {
1078
- className: "max-w-full w-full",
1079
- value: credentials.gatewayBaseUrl
1080
- }) : /* @__PURE__ */ jsx("p", {
1074
+ })]
1075
+ }) : plans.map((plan) => /* @__PURE__ */ jsx(ApiKeysPanel, {
1076
+ plan,
1077
+ header,
1078
+ readOnly: isDemoSession
1079
+ }, plan.planSku)), /* @__PURE__ */ jsxs("article", {
1080
+ className: "rounded-xl border bg-card/60 p-6 space-y-4",
1081
+ children: [/* @__PURE__ */ jsxs("div", {
1082
+ className: "space-y-1",
1083
+ children: [/* @__PURE__ */ jsx("h2", {
1084
+ className: "text-lg font-medium",
1085
+ children: "Gateway URL"
1086
+ }), /* @__PURE__ */ jsx("p", {
1081
1087
  className: "text-sm text-muted-foreground",
1082
- children: "Available after your API is deployed to the gateway."
1088
+ children: "Base URL for API requests through the gateway."
1083
1089
  })]
1084
- })
1085
- ]
1090
+ }), gatewayBaseUrl ? /* @__PURE__ */ jsx(Value, {
1091
+ className: "max-w-full w-full",
1092
+ value: gatewayBaseUrl
1093
+ }) : /* @__PURE__ */ jsx("p", {
1094
+ className: "text-sm text-muted-foreground",
1095
+ children: "Available after your API is deployed to the gateway."
1096
+ })]
1097
+ })]
1086
1098
  }) : null,
1087
1099
  /* @__PURE__ */ jsxs("div", {
1088
1100
  className: "mt-8 flex flex-wrap gap-3",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lukoweb/apitogo-plugin-dev-portal-billing",
3
- "version": "0.1.73",
3
+ "version": "0.1.75",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/zuplo/zudoku",
@@ -46,7 +46,7 @@
46
46
  "react": "19.2.4",
47
47
  "react-dom": "19.2.4",
48
48
  "tsdown": "0.20.3",
49
- "@lukoweb/apitogo": "0.1.73"
49
+ "@lukoweb/apitogo": "0.1.75"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "react": ">=19.2.0",