@lukoweb/apitogo 0.1.0 → 0.1.2
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/cli/cli.js +37 -147
- package/dist/declarations/lib/ui/Command.d.ts +1 -1
- package/dist/declarations/lib/util/MdxComponents.d.ts +1 -1
- package/package.json +1 -1
- package/src/app/main.tsx +150 -150
- package/src/config/loader.ts +245 -245
- package/src/index.ts +33 -33
- package/src/lib/authentication/components/CallbackHandler.tsx +45 -45
- package/src/lib/authentication/components/SignIn.tsx +46 -46
- package/src/lib/authentication/components/SignUp.tsx +48 -48
- package/src/lib/authentication/providers/clerk.tsx +224 -224
- package/src/lib/authentication/ui/AuthCard.tsx +7 -7
- package/src/lib/authentication/ui/EmailLinkCallbackUi.tsx +129 -125
- package/src/lib/authentication/ui/EmailLinkSentUi.tsx +105 -101
- package/src/lib/authentication/ui/EmailLinkSignInUi.tsx +100 -96
- package/src/lib/authentication/ui/EmailVerificationUi.tsx +128 -124
- package/src/lib/authentication/ui/ZudokuAuthUi.tsx +620 -616
- package/src/lib/components/AiAssistantMenuItems.tsx +102 -102
- package/src/lib/components/Autocomplete.tsx +123 -123
- package/src/lib/components/DeveloperHint.tsx +39 -35
- package/src/lib/components/Header.tsx +260 -260
- package/src/lib/components/Layout.tsx +53 -53
- package/src/lib/components/Main.tsx +51 -51
- package/src/lib/components/Mermaid.tsx +74 -70
- package/src/lib/components/MobileTopNavigation.tsx +276 -276
- package/src/lib/components/MultiSelect.tsx +86 -82
- package/src/lib/components/TopNavigation.tsx +103 -103
- package/src/lib/components/index.ts +26 -26
- package/src/lib/components/navigation/NavigationCategory.tsx +157 -157
- package/src/lib/components/navigation/NavigationFilterInput.tsx +35 -35
- package/src/lib/components/navigation/NavigationItem.tsx +181 -177
- package/src/lib/core/RouteGuard.tsx +193 -193
- package/src/lib/errors/ErrorMessage.tsx +50 -46
- package/src/lib/plugins/api-catalog/Catalog.tsx +80 -80
- package/src/lib/plugins/api-keys/CreateApiKey.tsx +128 -124
- package/src/lib/plugins/api-keys/CreateApiKeyDialog.tsx +49 -49
- package/src/lib/plugins/api-keys/SettingsApiKeys.tsx +72 -72
- package/src/lib/plugins/api-keys/settings/ApiKeyItem.tsx +342 -342
- package/src/lib/plugins/api-keys/settings/RevealApiKey.tsx +127 -127
- package/src/lib/plugins/markdown/MdxPage.tsx +285 -285
- package/src/lib/plugins/openapi/ApiHeader.tsx +96 -96
- package/src/lib/plugins/openapi/CollapsibleCode.tsx +88 -88
- package/src/lib/plugins/openapi/DownloadSchemaButton.tsx +94 -94
- package/src/lib/plugins/openapi/GeneratedExampleSidecarBox.tsx +52 -52
- package/src/lib/plugins/openapi/OperationListItem.tsx +183 -183
- package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +63 -63
- package/src/lib/plugins/openapi/ResponsesSidecarBox.tsx +120 -117
- package/src/lib/plugins/openapi/SchemaInfo.tsx +344 -344
- package/src/lib/plugins/openapi/SchemaList.tsx +113 -113
- package/src/lib/plugins/openapi/Sidecar.tsx +312 -309
- package/src/lib/plugins/openapi/SidecarExamples.tsx +177 -174
- package/src/lib/plugins/openapi/components/EnumValues.tsx +58 -58
- package/src/lib/plugins/openapi/components/ResponseContent.tsx +117 -114
- package/src/lib/plugins/openapi/playground/BodyPanel.tsx +274 -271
- package/src/lib/plugins/openapi/playground/CollapsibleHeader.tsx +51 -51
- package/src/lib/plugins/openapi/playground/ExamplesDropdown.tsx +60 -60
- package/src/lib/plugins/openapi/playground/Headers.tsx +188 -181
- package/src/lib/plugins/openapi/playground/IdentityDialog.tsx +75 -75
- package/src/lib/plugins/openapi/playground/IdentitySelector.tsx +38 -38
- package/src/lib/plugins/openapi/playground/ParamsGrid.tsx +45 -45
- package/src/lib/plugins/openapi/playground/Playground.tsx +602 -599
- package/src/lib/plugins/openapi/playground/PlaygroundDialog.tsx +56 -56
- package/src/lib/plugins/openapi/playground/QueryParams.tsx +151 -148
- package/src/lib/plugins/openapi/playground/RequestLoginDialog.tsx +70 -70
- package/src/lib/plugins/openapi/playground/request-panel/MultipartField.tsx +91 -91
- package/src/lib/plugins/openapi/playground/result-panel/AudioPlayer.tsx +50 -50
- package/src/lib/plugins/openapi/playground/result-panel/ResponseTab.tsx +355 -355
- package/src/lib/plugins/openapi/playground/result-panel/ResultPanel.tsx +106 -102
- package/src/lib/plugins/openapi/schema/SchemaPropertyItem.tsx +189 -184
- package/src/lib/plugins/openapi/schema/SchemaView.tsx +299 -299
- package/src/lib/plugins/search-pagefind/IndexingDialog.tsx +162 -162
- package/src/lib/plugins/search-pagefind/PagefindSearch.tsx +202 -202
- package/src/lib/plugins/search-pagefind/ResultList.tsx +122 -118
- package/src/lib/ui/ActionButton.tsx +21 -21
- package/src/lib/ui/Command.tsx +191 -191
- package/src/lib/util/MdxComponents.tsx +150 -150
- package/src/vite/config.ts +234 -231
- package/src/vite/dev-server.ts +291 -291
- package/src/vite/plugin-api-keys.ts +50 -50
- package/src/vite/plugin-api.ts +320 -318
- package/src/vite/plugin-auth.ts +38 -38
- package/src/vite/plugin-component.ts +45 -39
- package/src/vite/plugin-config.ts +75 -75
- package/src/vite/plugin-custom-pages.ts +36 -36
- package/src/vite/plugin-docs.ts +202 -202
- package/src/vite/plugin-markdown-export.ts +214 -214
- package/src/vite/plugin-mdx.ts +149 -149
- package/src/vite/plugin-navigation.ts +106 -106
- package/src/vite/plugin-search.ts +47 -47
- package/src/vite/plugin.ts +42 -42
- package/src/vite/prerender/prerender.ts +233 -233
|
@@ -1,127 +1,127 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from "
|
|
14
|
-
import {
|
|
15
|
-
import { cn } from "../../../util/cn.js";
|
|
16
|
-
import type { ApiKey } from "../index.js";
|
|
17
|
-
|
|
18
|
-
export const RevealApiKey = ({
|
|
19
|
-
apiKey,
|
|
20
|
-
onDeleteKey,
|
|
21
|
-
className,
|
|
22
|
-
}: {
|
|
23
|
-
apiKey: ApiKey;
|
|
24
|
-
onDeleteKey: () => void;
|
|
25
|
-
className?: string;
|
|
26
|
-
}) => {
|
|
27
|
-
const [revealed, setRevealed] = useState(false);
|
|
28
|
-
|
|
29
|
-
const { key, description, createdOn, expiresOn } = apiKey;
|
|
30
|
-
const isExpired = expiresOn && new Date(expiresOn) < new Date();
|
|
31
|
-
const daysUntilExpiry = expiresOn
|
|
32
|
-
? Math.ceil(
|
|
33
|
-
(new Date(expiresOn).getTime() - Date.now()) / (1000 * 60 * 60 * 24),
|
|
34
|
-
)
|
|
35
|
-
: Infinity;
|
|
36
|
-
const expiresSoon = daysUntilExpiry <= 7 && !isExpired;
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<div className={cn("grid col-span-full grid-cols-subgrid p-6", className)}>
|
|
40
|
-
<div className="flex flex-col gap-1">
|
|
41
|
-
{description && (
|
|
42
|
-
<span className="text-sm font-medium">{description}</span>
|
|
43
|
-
)}
|
|
44
|
-
<Secret
|
|
45
|
-
className="max-w-fit w-full"
|
|
46
|
-
secret={key}
|
|
47
|
-
status={isExpired ? "expired" : expiresSoon ? "expiring" : "active"}
|
|
48
|
-
revealed={revealed}
|
|
49
|
-
onReveal={setRevealed}
|
|
50
|
-
/>
|
|
51
|
-
<div className="flex gap-1 mt-0.5 text-nowrap">
|
|
52
|
-
{createdOn && (
|
|
53
|
-
<span className="text-xs text-muted-foreground">
|
|
54
|
-
Created {getTimeAgo(createdOn)}.
|
|
55
|
-
</span>
|
|
56
|
-
)}{" "}
|
|
57
|
-
{expiresOn && expiresSoon && (
|
|
58
|
-
<span className="text-xs text-primary">
|
|
59
|
-
Expires in {daysUntilExpiry}{" "}
|
|
60
|
-
{daysUntilExpiry === 1 ? "day" : "days"}.
|
|
61
|
-
</span>
|
|
62
|
-
)}
|
|
63
|
-
{expiresOn && isExpired && (
|
|
64
|
-
<span className="text-xs text-primary">
|
|
65
|
-
Expired{" "}
|
|
66
|
-
{daysUntilExpiry === 0
|
|
67
|
-
? "today."
|
|
68
|
-
: `${daysUntilExpiry * -1} days ago.`}
|
|
69
|
-
</span>
|
|
70
|
-
)}
|
|
71
|
-
</div>
|
|
72
|
-
</div>
|
|
73
|
-
<div className="flex justify-end">
|
|
74
|
-
{expiresOn && onDeleteKey && (
|
|
75
|
-
<Dialog>
|
|
76
|
-
<DialogTrigger asChild>
|
|
77
|
-
<Button variant="ghost" size="icon">
|
|
78
|
-
<TrashIcon size={16} />
|
|
79
|
-
</Button>
|
|
80
|
-
</DialogTrigger>
|
|
81
|
-
<DialogContent>
|
|
82
|
-
<DialogHeader>
|
|
83
|
-
<DialogTitle>Delete API Key</DialogTitle>
|
|
84
|
-
<DialogDescription>
|
|
85
|
-
Are you sure you want to delete this API key?
|
|
86
|
-
</DialogDescription>
|
|
87
|
-
</DialogHeader>
|
|
88
|
-
<DialogFooter>
|
|
89
|
-
<DialogClose asChild>
|
|
90
|
-
<Button variant="outline">Cancel</Button>
|
|
91
|
-
</DialogClose>
|
|
92
|
-
<DialogClose asChild>
|
|
93
|
-
<Button
|
|
94
|
-
onClick={() => {
|
|
95
|
-
onDeleteKey();
|
|
96
|
-
}}
|
|
97
|
-
>
|
|
98
|
-
Delete
|
|
99
|
-
</Button>
|
|
100
|
-
</DialogClose>
|
|
101
|
-
</DialogFooter>
|
|
102
|
-
</DialogContent>
|
|
103
|
-
</Dialog>
|
|
104
|
-
)}
|
|
105
|
-
</div>
|
|
106
|
-
</div>
|
|
107
|
-
);
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const getTimeAgo = (date: string) => {
|
|
111
|
-
const now = new Date();
|
|
112
|
-
const created = new Date(date);
|
|
113
|
-
const diffInSeconds = Math.floor((now.getTime() - created.getTime()) / 1000);
|
|
114
|
-
|
|
115
|
-
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
|
|
116
|
-
|
|
117
|
-
if (diffInSeconds < 60) return rtf.format(-diffInSeconds, "second");
|
|
118
|
-
if (diffInSeconds < 3600)
|
|
119
|
-
return rtf.format(-Math.floor(diffInSeconds / 60), "minute");
|
|
120
|
-
if (diffInSeconds < 86400)
|
|
121
|
-
return rtf.format(-Math.floor(diffInSeconds / 3600), "hour");
|
|
122
|
-
if (diffInSeconds < 2592000)
|
|
123
|
-
return rtf.format(-Math.floor(diffInSeconds / 86400), "day");
|
|
124
|
-
if (diffInSeconds < 31536000)
|
|
125
|
-
return rtf.format(-Math.floor(diffInSeconds / 2592000), "month");
|
|
126
|
-
return rtf.format(-Math.floor(diffInSeconds / 31536000), "year");
|
|
127
|
-
};
|
|
1
|
+
import { Button } from "@lukoweb/apitogo/ui/Button.js";
|
|
2
|
+
import {
|
|
3
|
+
Dialog,
|
|
4
|
+
DialogClose,
|
|
5
|
+
DialogContent,
|
|
6
|
+
DialogDescription,
|
|
7
|
+
DialogFooter,
|
|
8
|
+
DialogHeader,
|
|
9
|
+
DialogTitle,
|
|
10
|
+
DialogTrigger,
|
|
11
|
+
} from "@lukoweb/apitogo/ui/Dialog.js";
|
|
12
|
+
import { Secret } from "@lukoweb/apitogo/ui/Secret.js";
|
|
13
|
+
import { TrashIcon } from "lucide-react";
|
|
14
|
+
import { useState } from "react";
|
|
15
|
+
import { cn } from "../../../util/cn.js";
|
|
16
|
+
import type { ApiKey } from "../index.js";
|
|
17
|
+
|
|
18
|
+
export const RevealApiKey = ({
|
|
19
|
+
apiKey,
|
|
20
|
+
onDeleteKey,
|
|
21
|
+
className,
|
|
22
|
+
}: {
|
|
23
|
+
apiKey: ApiKey;
|
|
24
|
+
onDeleteKey: () => void;
|
|
25
|
+
className?: string;
|
|
26
|
+
}) => {
|
|
27
|
+
const [revealed, setRevealed] = useState(false);
|
|
28
|
+
|
|
29
|
+
const { key, description, createdOn, expiresOn } = apiKey;
|
|
30
|
+
const isExpired = expiresOn && new Date(expiresOn) < new Date();
|
|
31
|
+
const daysUntilExpiry = expiresOn
|
|
32
|
+
? Math.ceil(
|
|
33
|
+
(new Date(expiresOn).getTime() - Date.now()) / (1000 * 60 * 60 * 24),
|
|
34
|
+
)
|
|
35
|
+
: Infinity;
|
|
36
|
+
const expiresSoon = daysUntilExpiry <= 7 && !isExpired;
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div className={cn("grid col-span-full grid-cols-subgrid p-6", className)}>
|
|
40
|
+
<div className="flex flex-col gap-1">
|
|
41
|
+
{description && (
|
|
42
|
+
<span className="text-sm font-medium">{description}</span>
|
|
43
|
+
)}
|
|
44
|
+
<Secret
|
|
45
|
+
className="max-w-fit w-full"
|
|
46
|
+
secret={key}
|
|
47
|
+
status={isExpired ? "expired" : expiresSoon ? "expiring" : "active"}
|
|
48
|
+
revealed={revealed}
|
|
49
|
+
onReveal={setRevealed}
|
|
50
|
+
/>
|
|
51
|
+
<div className="flex gap-1 mt-0.5 text-nowrap">
|
|
52
|
+
{createdOn && (
|
|
53
|
+
<span className="text-xs text-muted-foreground">
|
|
54
|
+
Created {getTimeAgo(createdOn)}.
|
|
55
|
+
</span>
|
|
56
|
+
)}{" "}
|
|
57
|
+
{expiresOn && expiresSoon && (
|
|
58
|
+
<span className="text-xs text-primary">
|
|
59
|
+
Expires in {daysUntilExpiry}{" "}
|
|
60
|
+
{daysUntilExpiry === 1 ? "day" : "days"}.
|
|
61
|
+
</span>
|
|
62
|
+
)}
|
|
63
|
+
{expiresOn && isExpired && (
|
|
64
|
+
<span className="text-xs text-primary">
|
|
65
|
+
Expired{" "}
|
|
66
|
+
{daysUntilExpiry === 0
|
|
67
|
+
? "today."
|
|
68
|
+
: `${daysUntilExpiry * -1} days ago.`}
|
|
69
|
+
</span>
|
|
70
|
+
)}
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
<div className="flex justify-end">
|
|
74
|
+
{expiresOn && onDeleteKey && (
|
|
75
|
+
<Dialog>
|
|
76
|
+
<DialogTrigger asChild>
|
|
77
|
+
<Button variant="ghost" size="icon">
|
|
78
|
+
<TrashIcon size={16} />
|
|
79
|
+
</Button>
|
|
80
|
+
</DialogTrigger>
|
|
81
|
+
<DialogContent>
|
|
82
|
+
<DialogHeader>
|
|
83
|
+
<DialogTitle>Delete API Key</DialogTitle>
|
|
84
|
+
<DialogDescription>
|
|
85
|
+
Are you sure you want to delete this API key?
|
|
86
|
+
</DialogDescription>
|
|
87
|
+
</DialogHeader>
|
|
88
|
+
<DialogFooter>
|
|
89
|
+
<DialogClose asChild>
|
|
90
|
+
<Button variant="outline">Cancel</Button>
|
|
91
|
+
</DialogClose>
|
|
92
|
+
<DialogClose asChild>
|
|
93
|
+
<Button
|
|
94
|
+
onClick={() => {
|
|
95
|
+
onDeleteKey();
|
|
96
|
+
}}
|
|
97
|
+
>
|
|
98
|
+
Delete
|
|
99
|
+
</Button>
|
|
100
|
+
</DialogClose>
|
|
101
|
+
</DialogFooter>
|
|
102
|
+
</DialogContent>
|
|
103
|
+
</Dialog>
|
|
104
|
+
)}
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const getTimeAgo = (date: string) => {
|
|
111
|
+
const now = new Date();
|
|
112
|
+
const created = new Date(date);
|
|
113
|
+
const diffInSeconds = Math.floor((now.getTime() - created.getTime()) / 1000);
|
|
114
|
+
|
|
115
|
+
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
|
|
116
|
+
|
|
117
|
+
if (diffInSeconds < 60) return rtf.format(-diffInSeconds, "second");
|
|
118
|
+
if (diffInSeconds < 3600)
|
|
119
|
+
return rtf.format(-Math.floor(diffInSeconds / 60), "minute");
|
|
120
|
+
if (diffInSeconds < 86400)
|
|
121
|
+
return rtf.format(-Math.floor(diffInSeconds / 3600), "hour");
|
|
122
|
+
if (diffInSeconds < 2592000)
|
|
123
|
+
return rtf.format(-Math.floor(diffInSeconds / 86400), "day");
|
|
124
|
+
if (diffInSeconds < 31536000)
|
|
125
|
+
return rtf.format(-Math.floor(diffInSeconds / 2592000), "month");
|
|
126
|
+
return rtf.format(-Math.floor(diffInSeconds / 31536000), "year");
|
|
127
|
+
};
|