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

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 +65 -73
  2. package/package.json +2 -2
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { Button, Head, Heading } from "@lukoweb/apitogo/components";
1
+ import { Button, Head, Heading, Spinner } from "@lukoweb/apitogo/components";
2
2
  import { CreditCardIcon, KeyRoundIcon, ShieldIcon, StarsIcon, TrashIcon } from "@lukoweb/apitogo/icons";
3
3
  import { createContext, useContext, useEffect, useState } from "react";
4
4
  import { Link, Navigate, Outlet, useNavigate, useSearchParams } from "@lukoweb/apitogo/router";
@@ -11,7 +11,7 @@ import { useMutation, useQuery, useQueryClient } from "@lukoweb/apitogo/react-qu
11
11
  import { useAuth } from "@lukoweb/apitogo/hooks";
12
12
  import { Alert, AlertTitle } from "@lukoweb/apitogo/ui/Alert.js";
13
13
  import { Button as Button$1 } from "@lukoweb/apitogo/ui/Button.js";
14
- import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@lukoweb/apitogo/ui/Dialog.js";
14
+ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@lukoweb/apitogo/ui/Dialog.js";
15
15
  import { Input } from "@lukoweb/apitogo/ui/Input.js";
16
16
  import { Secret } from "@lukoweb/apitogo/ui/Secret.js";
17
17
  import { createPlugin } from "@lukoweb/apitogo/plugins";
@@ -314,7 +314,6 @@ function createDemoCredentials(plans) {
314
314
  return {
315
315
  idToken: "demo-id-token",
316
316
  accessToken: null,
317
- subscriptionKey: DEMO_SUBSCRIPTION_KEY,
318
317
  gatewayBaseUrl: null,
319
318
  planSku: resolveDemoPlanSku(plans),
320
319
  expiresAt: null
@@ -593,6 +592,8 @@ const ApiKeysPanel = ({ readOnly = false }) => {
593
592
  const revokeKey = useRevokeApiKey();
594
593
  const [name, setName] = useState("");
595
594
  const [newKey, setNewKey] = useState(null);
595
+ const [openRevokeId, setOpenRevokeId] = useState(null);
596
+ const [pendingRevokeId, setPendingRevokeId] = useState(null);
596
597
  const activeKeys = data?.keys.filter((key) => key.status === "active") ?? [];
597
598
  const capLabel = data?.maxKeys == null ? `${data?.activeCount ?? activeKeys.length} active` : `${data.activeCount} of ${data.maxKeys} used`;
598
599
  const canCreate = !readOnly && (data?.canCreate ?? false);
@@ -604,6 +605,13 @@ const ApiKeysPanel = ({ readOnly = false }) => {
604
605
  setName("");
605
606
  } });
606
607
  };
608
+ const handleRevoke = (keyId) => {
609
+ setPendingRevokeId(keyId);
610
+ revokeKey.mutate(keyId, { onSettled: () => {
611
+ setPendingRevokeId(null);
612
+ setOpenRevokeId(null);
613
+ } });
614
+ };
607
615
  return /* @__PURE__ */ jsxs("article", {
608
616
  className: "rounded-xl border bg-card/60 p-6 space-y-5",
609
617
  children: [
@@ -670,52 +678,59 @@ const ApiKeysPanel = ({ readOnly = false }) => {
670
678
  }) : null,
671
679
  activeKeys.length > 0 ? /* @__PURE__ */ jsx("ul", {
672
680
  className: "divide-y rounded-lg border",
673
- children: activeKeys.map((key) => /* @__PURE__ */ jsxs("li", {
674
- className: "flex flex-wrap items-center justify-between gap-3 p-4",
675
- children: [/* @__PURE__ */ jsxs("div", {
676
- className: "min-w-0 space-y-1",
677
- children: [/* @__PURE__ */ jsx("p", {
678
- className: "truncate font-medium",
679
- children: key.name
680
- }), /* @__PURE__ */ jsxs("p", {
681
- className: "text-xs text-muted-foreground",
682
- children: [
683
- /* @__PURE__ */ jsxs("code", { children: [key.keyPrefix, "…"] }),
684
- " · created",
685
- " ",
686
- new Date(key.createdAtUtc).toLocaleDateString()
687
- ]
688
- })]
689
- }), readOnly ? null : /* @__PURE__ */ jsxs(Dialog, { children: [/* @__PURE__ */ jsx(DialogTrigger, {
690
- asChild: true,
691
- children: /* @__PURE__ */ jsxs(Button$1, {
692
- variant: "ghost",
693
- className: "flex items-center gap-2",
694
- disabled: revokeKey.isPending,
695
- children: [/* @__PURE__ */ jsx(TrashIcon, { size: 16 }), /* @__PURE__ */ jsx("span", {
696
- className: "hidden md:block",
697
- children: "Revoke"
681
+ children: activeKeys.map((key) => {
682
+ const isRevoking = pendingRevokeId === key.id;
683
+ return /* @__PURE__ */ jsxs("li", {
684
+ className: "flex flex-wrap items-center justify-between gap-3 p-4",
685
+ children: [/* @__PURE__ */ jsxs("div", {
686
+ className: "min-w-0 space-y-1",
687
+ children: [/* @__PURE__ */ jsx("p", {
688
+ className: "truncate font-medium",
689
+ children: key.name
690
+ }), /* @__PURE__ */ jsxs("p", {
691
+ className: "text-xs text-muted-foreground",
692
+ children: [
693
+ /* @__PURE__ */ jsxs("code", { children: [key.keyPrefix, "…"] }),
694
+ " · created",
695
+ " ",
696
+ new Date(key.createdAtUtc).toLocaleDateString()
697
+ ]
698
698
  })]
699
- })
700
- }), /* @__PURE__ */ jsxs(DialogContent, { children: [/* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsxs(DialogTitle, { children: [
701
- "Revoke “",
702
- key.name,
703
- "”?"
704
- ] }), /* @__PURE__ */ jsx(DialogDescription, { children: "Any application using this key will immediately start getting 401 responses from the gateway. This cannot be undone." })] }), /* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx(DialogClose, {
705
- asChild: true,
706
- children: /* @__PURE__ */ jsx(Button$1, {
707
- variant: "outline",
708
- children: "Cancel"
709
- })
710
- }), /* @__PURE__ */ jsx(DialogClose, {
711
- asChild: true,
712
- children: /* @__PURE__ */ jsx(Button$1, {
713
- variant: "destructive",
714
- onClick: () => revokeKey.mutate(key.id),
715
- children: "Revoke key"
716
- })
717
- })] })] })] })]
718
- }, key.id))
699
+ }), readOnly ? null : /* @__PURE__ */ jsxs(Dialog, {
700
+ open: openRevokeId === key.id,
701
+ onOpenChange: (open) => {
702
+ if (isRevoking) return;
703
+ setOpenRevokeId(open ? key.id : null);
704
+ },
705
+ children: [/* @__PURE__ */ jsx(DialogTrigger, {
706
+ asChild: true,
707
+ children: /* @__PURE__ */ jsxs(Button$1, {
708
+ variant: "ghost",
709
+ className: "flex items-center gap-2",
710
+ disabled: isRevoking,
711
+ children: [isRevoking ? /* @__PURE__ */ jsx(Spinner, { size: 14 }) : /* @__PURE__ */ jsx(TrashIcon, { size: 16 }), /* @__PURE__ */ jsx("span", {
712
+ className: "hidden md:block",
713
+ children: isRevoking ? "Revoking…" : "Revoke"
714
+ })]
715
+ })
716
+ }), /* @__PURE__ */ jsxs(DialogContent, { children: [/* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsxs(DialogTitle, { children: [
717
+ "Revoke “",
718
+ key.name,
719
+ "”?"
720
+ ] }), /* @__PURE__ */ jsx(DialogDescription, { children: "Any application using this key will immediately start getting 401 responses from the gateway. This cannot be undone." })] }), /* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx(Button$1, {
721
+ variant: "outline",
722
+ disabled: isRevoking,
723
+ onClick: () => setOpenRevokeId(null),
724
+ children: "Cancel"
725
+ }), /* @__PURE__ */ jsx(Button$1, {
726
+ variant: "destructive",
727
+ disabled: isRevoking,
728
+ onClick: () => handleRevoke(key.id),
729
+ children: isRevoking ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Spinner, { size: 14 }), "Revoking…"] }) : "Revoke key"
730
+ })] })] })]
731
+ })]
732
+ }, key.id);
733
+ })
719
734
  }) : null,
720
735
  readOnly ? null : /* @__PURE__ */ jsxs("div", {
721
736
  className: "flex flex-wrap items-center gap-2",
@@ -733,7 +748,8 @@ const ApiKeysPanel = ({ readOnly = false }) => {
733
748
  }), /* @__PURE__ */ jsx(Button$1, {
734
749
  onClick: handleCreate,
735
750
  disabled: !canCreate || createKey.isPending || !name.trim(),
736
- children: createKey.isPending ? "Creating…" : "Create API key"
751
+ className: "flex items-center gap-2",
752
+ children: createKey.isPending ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Spinner, { size: 14 }), "Creating…"] }) : "Create API key"
737
753
  })]
738
754
  }),
739
755
  data && !data.canCreate && !readOnly ? /* @__PURE__ */ jsx("p", {
@@ -966,7 +982,6 @@ const CredentialsPage = () => {
966
982
  const isDemoSession = useIsDemoSession();
967
983
  const { data: credentials, isLoading, error } = useCredentials();
968
984
  const { data: catalog } = usePlans();
969
- const [revealed, setRevealed] = useState(false);
970
985
  const plan = catalog?.plans.find((item) => item.sku === credentials?.planSku);
971
986
  return /* @__PURE__ */ jsxs("div", {
972
987
  className: "mx-auto max-w-screen-lg px-4 pb-16 pt-(--padding-content-top) lg:px-8",
@@ -1048,29 +1063,6 @@ const CredentialsPage = () => {
1048
1063
  })
1049
1064
  }),
1050
1065
  /* @__PURE__ */ jsx(ApiKeysPanel, { readOnly: isDemoSession }),
1051
- credentials.subscriptionKey ? /* @__PURE__ */ jsxs("article", {
1052
- className: "rounded-xl border bg-card/60 p-6 space-y-4",
1053
- children: [/* @__PURE__ */ jsxs("div", {
1054
- className: "space-y-1",
1055
- children: [/* @__PURE__ */ jsx("h2", {
1056
- className: "text-lg font-medium",
1057
- children: "Default key value"
1058
- }), /* @__PURE__ */ jsxs("p", {
1059
- className: "text-sm text-muted-foreground",
1060
- children: [
1061
- "The full value of the ",
1062
- /* @__PURE__ */ jsx("code", { children: "default" }),
1063
- " key issued with your plan. Keys you create above are shown only once, so store them yourself."
1064
- ]
1065
- })]
1066
- }), /* @__PURE__ */ jsx(Secret, {
1067
- className: "max-w-full w-full",
1068
- secret: credentials.subscriptionKey,
1069
- status: "active",
1070
- revealed,
1071
- onReveal: setRevealed
1072
- })]
1073
- }) : null,
1074
1066
  /* @__PURE__ */ jsxs("article", {
1075
1067
  className: "rounded-xl border bg-card/60 p-6 space-y-4",
1076
1068
  children: [/* @__PURE__ */ jsxs("div", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lukoweb/apitogo-plugin-dev-portal-billing",
3
- "version": "0.1.72",
3
+ "version": "0.1.73",
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.72"
49
+ "@lukoweb/apitogo": "0.1.73"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "react": ">=19.2.0",