zudoku 0.37.1 → 0.38.0
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/app/main.js +2 -0
- package/dist/app/main.js.map +1 -1
- package/dist/config/validators/common.d.ts +287 -18
- package/dist/config/validators/common.js +2 -0
- package/dist/config/validators/common.js.map +1 -1
- package/dist/config/validators/validate.d.ts +107 -7
- package/dist/lib/authentication/authentication.d.ts +1 -0
- package/dist/lib/authentication/providers/clerk.js +19 -0
- package/dist/lib/authentication/providers/clerk.js.map +1 -1
- package/dist/lib/authentication/providers/openid.d.ts +1 -0
- package/dist/lib/authentication/providers/openid.js +5 -0
- package/dist/lib/authentication/providers/openid.js.map +1 -1
- package/dist/lib/authentication/providers/supabase.js +5 -0
- package/dist/lib/authentication/providers/supabase.js.map +1 -1
- package/dist/lib/authentication/state.d.ts +0 -26
- package/dist/lib/authentication/state.js +1 -16
- package/dist/lib/authentication/state.js.map +1 -1
- package/dist/lib/components/Layout.js +5 -3
- package/dist/lib/components/Layout.js.map +1 -1
- package/dist/lib/core/ZudokuContext.d.ts +7 -0
- package/dist/lib/core/ZudokuContext.js +8 -3
- package/dist/lib/core/ZudokuContext.js.map +1 -1
- package/dist/lib/core/plugins.d.ts +1 -1
- package/dist/lib/plugins/markdown/MdxPage.js +2 -8
- package/dist/lib/plugins/markdown/MdxPage.js.map +1 -1
- package/dist/lib/plugins/openapi/Endpoint.js +1 -1
- package/dist/lib/plugins/openapi/Endpoint.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationList.js +1 -1
- package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js +29 -5
- package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
- package/dist/lib/plugins/openapi/interfaces.d.ts +26 -0
- package/dist/lib/plugins/openapi/playground/Playground.js +1 -1
- package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/result-panel/ResultPanel.js +2 -2
- package/dist/lib/plugins/openapi/playground/result-panel/ResultPanel.js.map +1 -1
- package/dist/lib/plugins/openapi/state.d.ts +25 -0
- package/dist/lib/plugins/openapi/state.js +18 -0
- package/dist/lib/plugins/openapi/state.js.map +1 -0
- package/dist/lib/plugins/search-pagefind/PagefindSearch.js +13 -4
- package/dist/lib/plugins/search-pagefind/PagefindSearch.js.map +1 -1
- package/dist/lib/plugins/search-pagefind/ResultList.js +19 -12
- package/dist/lib/plugins/search-pagefind/ResultList.js.map +1 -1
- package/dist/lib/plugins/search-pagefind/get-results.d.ts +8 -1
- package/dist/lib/plugins/search-pagefind/get-results.js +9 -4
- package/dist/lib/plugins/search-pagefind/get-results.js.map +1 -1
- package/dist/lib/util/traverse.d.ts +2 -8
- package/dist/lib/util/traverse.js.map +1 -1
- package/dist/lib/util/types.d.ts +7 -0
- package/dist/lib/util/types.js +2 -0
- package/dist/lib/util/types.js.map +1 -0
- package/dist/lib/util/useScrollToAnchor.js +18 -12
- package/dist/lib/util/useScrollToAnchor.js.map +1 -1
- package/dist/vite/plugin-api.js +4 -1
- package/dist/vite/plugin-api.js.map +1 -1
- package/lib/{AuthenticationPlugin-Cij2tPWa.js → AuthenticationPlugin-Duy_R1TU.js} +3 -3
- package/lib/{AuthenticationPlugin-Cij2tPWa.js.map → AuthenticationPlugin-Duy_R1TU.js.map} +1 -1
- package/lib/{Markdown-DT5Rrq8_.js → Markdown-DIZ8nBVC.js} +742 -738
- package/lib/{Markdown-DT5Rrq8_.js.map → Markdown-DIZ8nBVC.js.map} +1 -1
- package/lib/{MdxPage-D2rD1vC4.js → MdxPage-JEdbfW-f.js} +42 -47
- package/lib/MdxPage-JEdbfW-f.js.map +1 -0
- package/lib/{OasProvider-DdEBf2qS.js → OasProvider-D1A10JeA.js} +4 -4
- package/lib/{OasProvider-DdEBf2qS.js.map → OasProvider-D1A10JeA.js.map} +1 -1
- package/lib/{OperationList-DT4-gm_S.js → OperationList-yOmYzMIp.js} +1128 -1112
- package/lib/OperationList-yOmYzMIp.js.map +1 -0
- package/lib/{Select-z1Lwl0-J.js → Select-fAYcJ0OU.js} +8 -8
- package/lib/{Select-z1Lwl0-J.js.map → Select-fAYcJ0OU.js.map} +1 -1
- package/lib/{SlotletProvider-D8OBnr77.js → SlotletProvider-BEwNY8q0.js} +4 -4
- package/lib/{SlotletProvider-D8OBnr77.js.map → SlotletProvider-BEwNY8q0.js.map} +1 -1
- package/lib/{chunk-HA7DTUK3-ZGg2W6yV.js → chunk-HA7DTUK3-C4gP41vD.js} +5 -5
- package/lib/{chunk-HA7DTUK3-ZGg2W6yV.js.map → chunk-HA7DTUK3-C4gP41vD.js.map} +1 -1
- package/lib/hook-Cge6LiTK.js +1483 -0
- package/lib/hook-Cge6LiTK.js.map +1 -0
- package/lib/{index-DdQSV2RF.js → index-B0y3fTg-.js} +261 -243
- package/lib/index-B0y3fTg-.js.map +1 -0
- package/lib/{mutation-_Z5C2wFZ.js → mutation-EChriCeF.js} +2 -2
- package/lib/{mutation-_Z5C2wFZ.js.map → mutation-EChriCeF.js.map} +1 -1
- package/lib/post-processors/traverse.js.map +1 -1
- package/lib/{useExposedProps-BslIn-FE.js → useExposedProps-B9qXJedG.js} +2 -2
- package/lib/{useExposedProps-BslIn-FE.js.map → useExposedProps-B9qXJedG.js.map} +1 -1
- package/lib/zudoku.auth-auth0.js +1 -1
- package/lib/zudoku.auth-clerk.js +59 -41
- package/lib/zudoku.auth-clerk.js.map +1 -1
- package/lib/zudoku.auth-openid.js +76 -73
- package/lib/zudoku.auth-openid.js.map +1 -1
- package/lib/zudoku.components.js +229 -215
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.hooks.js +1 -1
- package/lib/zudoku.plugin-api-catalog.js +23 -24
- package/lib/zudoku.plugin-api-catalog.js.map +1 -1
- package/lib/zudoku.plugin-api-keys.js +15 -16
- package/lib/zudoku.plugin-api-keys.js.map +1 -1
- package/lib/zudoku.plugin-custom-pages.js +2 -2
- package/lib/zudoku.plugin-markdown.js +1 -1
- package/lib/zudoku.plugin-openapi.js +5 -6
- package/lib/zudoku.plugin-openapi.js.map +1 -1
- package/lib/zudoku.plugin-redirect.js +1 -1
- package/lib/zudoku.plugin-search-pagefind.js +133 -98
- package/lib/zudoku.plugin-search-pagefind.js.map +1 -1
- package/lib/zudoku.plugins.js.map +1 -1
- package/package.json +1 -1
- package/src/app/main.tsx +2 -0
- package/src/lib/authentication/authentication.ts +2 -0
- package/src/lib/authentication/providers/clerk.tsx +20 -0
- package/src/lib/authentication/providers/openid.tsx +6 -0
- package/src/lib/authentication/providers/supabase.tsx +6 -0
- package/src/lib/authentication/state.ts +1 -35
- package/src/lib/components/Layout.tsx +14 -2
- package/src/lib/core/ZudokuContext.ts +13 -6
- package/src/lib/core/plugins.ts +1 -1
- package/src/lib/plugins/markdown/MdxPage.tsx +1 -8
- package/src/lib/plugins/openapi/Endpoint.tsx +1 -1
- package/src/lib/plugins/openapi/OperationList.tsx +1 -1
- package/src/lib/plugins/openapi/Sidecar.tsx +36 -7
- package/src/lib/plugins/openapi/interfaces.ts +29 -0
- package/src/lib/plugins/openapi/playground/Playground.tsx +1 -1
- package/src/lib/plugins/openapi/playground/result-panel/ResultPanel.tsx +2 -1
- package/src/lib/plugins/openapi/state.ts +36 -0
- package/src/lib/plugins/search-pagefind/PagefindSearch.tsx +26 -4
- package/src/lib/plugins/search-pagefind/ResultList.tsx +59 -47
- package/src/lib/plugins/search-pagefind/get-results.tsx +31 -10
- package/src/lib/util/traverse.ts +2 -6
- package/src/lib/util/types.ts +7 -0
- package/src/lib/util/useScrollToAnchor.ts +20 -12
- package/lib/MdxPage-D2rD1vC4.js.map +0 -1
- package/lib/OperationList-DT4-gm_S.js.map +0 -1
- package/lib/hook-DzQC8PzJ.js +0 -355
- package/lib/hook-DzQC8PzJ.js.map +0 -1
- package/lib/index-DdQSV2RF.js.map +0 -1
- package/lib/joinUrl-BjDooT-T.js +0 -1154
- package/lib/joinUrl-BjDooT-T.js.map +0 -1
package/lib/zudoku.hooks.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z as f } from "./index-DwT-v3zK.js";
|
|
2
2
|
import { useState as m, useEffect as i } from "react";
|
|
3
|
-
import { a } from "./hook-
|
|
3
|
+
import { a } from "./hook-Cge6LiTK.js";
|
|
4
4
|
function d(e, t) {
|
|
5
5
|
const s = a(), [n, o] = m();
|
|
6
6
|
return i(() => s.addEventListener(e, (...u) => {
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { j as e } from "./jsx-runtime-CYK1ROHF.js";
|
|
2
2
|
import { s as h } from "./index-LNp6rxyU.js";
|
|
3
|
-
import { d as b, m as x } from "./chunk-HA7DTUK3-
|
|
4
|
-
import { j as d } from "./
|
|
5
|
-
import { u as j, b as y } from "./hook-DzQC8PzJ.js";
|
|
3
|
+
import { d as b, m as x } from "./chunk-HA7DTUK3-C4gP41vD.js";
|
|
4
|
+
import { u as j, b as y, d } from "./hook-Cge6LiTK.js";
|
|
6
5
|
import { H as v } from "./index.esm-CltAN0Tf.js";
|
|
7
6
|
import { Link as N } from "./zudoku.components.js";
|
|
8
|
-
import { H as S, M as w } from "./Markdown-
|
|
7
|
+
import { H as S, M as w } from "./Markdown-DIZ8nBVC.js";
|
|
9
8
|
const H = ({
|
|
10
9
|
items: s,
|
|
11
|
-
filterCatalogItems:
|
|
10
|
+
filterCatalogItems: r = (n) => n,
|
|
12
11
|
label: c = "API Library",
|
|
13
|
-
categoryLabel:
|
|
12
|
+
categoryLabel: l
|
|
14
13
|
}) => {
|
|
15
14
|
const n = j(), o = b({ path: "/catalog/:category" }), a = o == null ? void 0 : o.params.category, p = y({
|
|
16
|
-
queryFn: () =>
|
|
15
|
+
queryFn: () => r(s, { auth: n }),
|
|
17
16
|
queryKey: ["catalogItems", n]
|
|
18
17
|
}), i = a ? { "data-pagefind-ignore": "all" } : {};
|
|
19
18
|
return /* @__PURE__ */ e.jsxs(
|
|
@@ -23,17 +22,17 @@ const H = ({
|
|
|
23
22
|
...i,
|
|
24
23
|
children: [
|
|
25
24
|
/* @__PURE__ */ e.jsx(v, { children: /* @__PURE__ */ e.jsxs("title", { children: [
|
|
26
|
-
|
|
25
|
+
l ? `${l} - ` : "",
|
|
27
26
|
c
|
|
28
27
|
] }) }),
|
|
29
28
|
/* @__PURE__ */ e.jsxs("div", { className: "grid gap-4", children: [
|
|
30
29
|
/* @__PURE__ */ e.jsxs(S, { level: 2, children: [
|
|
31
30
|
c,
|
|
32
|
-
|
|
31
|
+
l && ` - ${l}`
|
|
33
32
|
] }),
|
|
34
33
|
/* @__PURE__ */ e.jsx("div", { className: "grid grid-cols-2 gap-4", children: p.data.filter(
|
|
35
34
|
(t) => !a || t.categories.find(
|
|
36
|
-
(m) => m.tags.find((u) =>
|
|
35
|
+
(m) => m.tags.find((u) => g(m.label, u) === a)
|
|
37
36
|
)
|
|
38
37
|
).map((t) => /* @__PURE__ */ e.jsx(
|
|
39
38
|
N,
|
|
@@ -57,30 +56,30 @@ const H = ({
|
|
|
57
56
|
]
|
|
58
57
|
}
|
|
59
58
|
);
|
|
60
|
-
},
|
|
59
|
+
}, g = (s, r) => h(`${s}-${r}`), K = ({
|
|
61
60
|
navigationId: s,
|
|
62
|
-
items:
|
|
61
|
+
items: r,
|
|
63
62
|
label: c,
|
|
64
|
-
categories:
|
|
63
|
+
categories: l = [],
|
|
65
64
|
filterCatalogItems: n
|
|
66
65
|
}) => ({
|
|
67
66
|
getSidebar: async function(a) {
|
|
68
67
|
if (!x({ path: d(s), end: !1 }, a))
|
|
69
68
|
return [];
|
|
70
|
-
const p =
|
|
69
|
+
const p = l.map((i) => ({
|
|
71
70
|
type: "category",
|
|
72
71
|
label: i.label,
|
|
73
72
|
collapsible: !1,
|
|
74
73
|
items: i.tags.map((t) => {
|
|
75
|
-
const m =
|
|
74
|
+
const m = g(i.label, t);
|
|
76
75
|
return {
|
|
77
76
|
type: "doc",
|
|
78
77
|
id: d(s, m),
|
|
79
78
|
label: t,
|
|
80
79
|
badge: {
|
|
81
80
|
label: String(
|
|
82
|
-
|
|
83
|
-
(u) => u.categories.find((
|
|
81
|
+
r.filter(
|
|
82
|
+
(u) => u.categories.find((f) => f.tags.includes(t))
|
|
84
83
|
).length
|
|
85
84
|
),
|
|
86
85
|
color: "outline"
|
|
@@ -92,30 +91,30 @@ const H = ({
|
|
|
92
91
|
type: "doc",
|
|
93
92
|
id: d(s),
|
|
94
93
|
label: "Overview",
|
|
95
|
-
badge: { label: String(
|
|
94
|
+
badge: { label: String(r.length), color: "outline" }
|
|
96
95
|
}), p;
|
|
97
96
|
},
|
|
98
|
-
getRoutes: () =>
|
|
97
|
+
getRoutes: () => l.flatMap(
|
|
99
98
|
(o) => [void 0, ...o.tags].map((a) => ({
|
|
100
99
|
path: d(
|
|
101
100
|
s,
|
|
102
|
-
a ?
|
|
101
|
+
a ? g(o.label, a) : void 0
|
|
103
102
|
),
|
|
104
103
|
element: /* @__PURE__ */ e.jsx(
|
|
105
104
|
H,
|
|
106
105
|
{
|
|
107
106
|
label: c,
|
|
108
107
|
categoryLabel: a,
|
|
109
|
-
items:
|
|
108
|
+
items: r,
|
|
110
109
|
filterCatalogItems: n,
|
|
111
|
-
categories:
|
|
110
|
+
categories: l
|
|
112
111
|
}
|
|
113
112
|
)
|
|
114
113
|
}))
|
|
115
114
|
)
|
|
116
115
|
});
|
|
117
116
|
export {
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
K as apiCatalogPlugin,
|
|
118
|
+
g as getKey
|
|
120
119
|
};
|
|
121
120
|
//# sourceMappingURL=zudoku.plugin-api-catalog.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zudoku.plugin-api-catalog.js","sources":["../src/lib/plugins/api-catalog/Catalog.tsx","../src/lib/plugins/api-catalog/index.tsx"],"sourcesContent":["import { useSuspenseQuery } from \"@tanstack/react-query\";\nimport { Helmet } from \"@zudoku/react-helmet-async\";\nimport { useMatch } from \"react-router\";\nimport { Link } from \"zudoku/components\";\nimport { useAuthState } from \"../../authentication/state.js\";\nimport { Heading } from \"../../components/Heading.js\";\nimport { Markdown } from \"../../components/Markdown.js\";\nimport { joinUrl } from \"../../util/joinUrl.js\";\nimport { type ApiCatalogPluginOptions, getKey } from \"./index.js\";\n\nexport const Catalog = ({\n items,\n filterCatalogItems = (items) => items,\n label = \"API Library\",\n categoryLabel,\n}: Omit<ApiCatalogPluginOptions, \"navigationId\"> & {\n categoryLabel?: string;\n}) => {\n const auth = useAuthState();\n const match = useMatch({ path: \"/catalog/:category\" });\n const activeCategory = match?.params.category;\n\n const catalogItems = useSuspenseQuery({\n queryFn: () => filterCatalogItems(items, { auth }),\n queryKey: [\"catalogItems\", auth],\n });\n\n // Only index the overview page, ignore the rest\n const dataSet = activeCategory ? { \"data-pagefind-ignore\": \"all\" } : {};\n\n return (\n <section\n className=\"pt-[--padding-content-top] pb-[--padding-content-bottom]\"\n {...dataSet}\n >\n <Helmet>\n <title>\n {categoryLabel ? `${categoryLabel} - ` : \"\"}\n {label}\n </title>\n </Helmet>\n <div className=\"grid gap-4\">\n <Heading level={2}>\n {label}\n {categoryLabel && ` - ${categoryLabel}`}\n </Heading>\n\n <div className=\"grid grid-cols-2 gap-4\">\n {catalogItems.data\n .filter(\n (api) =>\n !activeCategory ||\n api.categories.find((c) =>\n c.tags.find((t) => getKey(c.label, t) === activeCategory),\n ),\n )\n .map((api) => (\n <Link\n to={joinUrl(api.path)}\n className=\"no-underline hover:!text-foreground\"\n key={api.path}\n >\n <div className=\"border h-full rounded-lg p-4 flex flex-col gap-2 cursor-pointer hover:bg-border/20 font-normal\">\n <span className=\"font-semibold\">{api.label}</span>\n <Markdown\n className=\"text-sm whitespace-pre-wrap mb-6 line-clamp-2\"\n content={api.description}\n />\n </div>\n </Link>\n ))}\n </div>\n </div>\n </section>\n );\n};\n","import slugify from \"@sindresorhus/slugify\";\nimport { matchPath } from \"react-router\";\nimport type { SidebarItem } from \"../../../config/validators/SidebarSchema.js\";\nimport type { AuthState } from \"../../authentication/state.js\";\nimport type { ZudokuPlugin } from \"../../core/plugins.js\";\nimport { joinUrl } from \"../../util/joinUrl.js\";\nimport { Catalog } from \"./Catalog.js\";\n\nexport const getKey = (category: string, tag: string) =>\n slugify(`${category}-${tag}`);\n\nexport type ApiCatalogItem = {\n path: string;\n label: string;\n description: string;\n categories: CatalogCategory[];\n};\n\nexport type CatalogCategory = {\n label: string;\n tags: string[];\n};\n\nexport type ApiCatalogPluginOptions = {\n navigationId: string;\n label: string;\n categories?: CatalogCategory[];\n items: ApiCatalogItem[];\n filterCatalogItems?: filterCatalogItems;\n};\n\nexport type CatalogContext<ProviderData = unknown> = {\n auth: AuthState<ProviderData>;\n};\n\nexport type filterCatalogItems<ProviderData = unknown> = (\n items: ApiCatalogItem[],\n { auth }: CatalogContext<ProviderData>,\n) => ApiCatalogItem[];\n\nexport const apiCatalogPlugin = ({\n navigationId,\n items,\n label,\n categories = [],\n filterCatalogItems,\n}: {\n navigationId: string;\n label: string;\n categories?: CatalogCategory[];\n items: ApiCatalogItem[];\n filterCatalogItems?: filterCatalogItems;\n}): ZudokuPlugin => {\n return {\n getSidebar: async function Sidebar(path) {\n if (!matchPath({ path: joinUrl(navigationId), end: false }, path)) {\n return [];\n }\n\n const sidebar: SidebarItem[] = categories.map((category) => ({\n type: \"category\" as const,\n label: category.label,\n collapsible: false,\n items: category.tags.map((tag) => {\n const tagPath = getKey(category.label, tag);\n return {\n type: \"doc\" as const,\n id: joinUrl(navigationId, tagPath),\n label: tag,\n badge: {\n label: String(\n items.filter((api) =>\n api.categories.find((c) => c.tags.includes(tag)),\n ).length,\n ),\n color: \"outline\" as const,\n },\n };\n }),\n }));\n\n sidebar.unshift({\n type: \"doc\" as const,\n id: joinUrl(navigationId),\n label: \"Overview\",\n badge: { label: String(items.length), color: \"outline\" as const },\n });\n\n return sidebar;\n },\n getRoutes: () =>\n categories.flatMap((category) =>\n [undefined, ...category.tags].map((tag) => ({\n path: joinUrl(\n navigationId,\n tag ? getKey(category.label, tag) : undefined,\n ),\n element: (\n <Catalog\n label={label}\n categoryLabel={tag}\n items={items}\n filterCatalogItems={filterCatalogItems}\n categories={categories}\n />\n ),\n })),\n ),\n };\n};\n"],"names":["Catalog","items","filterCatalogItems","label","categoryLabel","auth","useAuthState","match","useMatch","activeCategory","catalogItems","useSuspenseQuery","dataSet","jsxs","jsx","Helmet","Heading","api","c","t","getKey","Link","joinUrl","Markdown","category","tag","slugify","apiCatalogPlugin","navigationId","categories","path","matchPath","sidebar","tagPath"],"mappings":"
|
|
1
|
+
{"version":3,"file":"zudoku.plugin-api-catalog.js","sources":["../src/lib/plugins/api-catalog/Catalog.tsx","../src/lib/plugins/api-catalog/index.tsx"],"sourcesContent":["import { useSuspenseQuery } from \"@tanstack/react-query\";\nimport { Helmet } from \"@zudoku/react-helmet-async\";\nimport { useMatch } from \"react-router\";\nimport { Link } from \"zudoku/components\";\nimport { useAuthState } from \"../../authentication/state.js\";\nimport { Heading } from \"../../components/Heading.js\";\nimport { Markdown } from \"../../components/Markdown.js\";\nimport { joinUrl } from \"../../util/joinUrl.js\";\nimport { type ApiCatalogPluginOptions, getKey } from \"./index.js\";\n\nexport const Catalog = ({\n items,\n filterCatalogItems = (items) => items,\n label = \"API Library\",\n categoryLabel,\n}: Omit<ApiCatalogPluginOptions, \"navigationId\"> & {\n categoryLabel?: string;\n}) => {\n const auth = useAuthState();\n const match = useMatch({ path: \"/catalog/:category\" });\n const activeCategory = match?.params.category;\n\n const catalogItems = useSuspenseQuery({\n queryFn: () => filterCatalogItems(items, { auth }),\n queryKey: [\"catalogItems\", auth],\n });\n\n // Only index the overview page, ignore the rest\n const dataSet = activeCategory ? { \"data-pagefind-ignore\": \"all\" } : {};\n\n return (\n <section\n className=\"pt-[--padding-content-top] pb-[--padding-content-bottom]\"\n {...dataSet}\n >\n <Helmet>\n <title>\n {categoryLabel ? `${categoryLabel} - ` : \"\"}\n {label}\n </title>\n </Helmet>\n <div className=\"grid gap-4\">\n <Heading level={2}>\n {label}\n {categoryLabel && ` - ${categoryLabel}`}\n </Heading>\n\n <div className=\"grid grid-cols-2 gap-4\">\n {catalogItems.data\n .filter(\n (api) =>\n !activeCategory ||\n api.categories.find((c) =>\n c.tags.find((t) => getKey(c.label, t) === activeCategory),\n ),\n )\n .map((api) => (\n <Link\n to={joinUrl(api.path)}\n className=\"no-underline hover:!text-foreground\"\n key={api.path}\n >\n <div className=\"border h-full rounded-lg p-4 flex flex-col gap-2 cursor-pointer hover:bg-border/20 font-normal\">\n <span className=\"font-semibold\">{api.label}</span>\n <Markdown\n className=\"text-sm whitespace-pre-wrap mb-6 line-clamp-2\"\n content={api.description}\n />\n </div>\n </Link>\n ))}\n </div>\n </div>\n </section>\n );\n};\n","import slugify from \"@sindresorhus/slugify\";\nimport { matchPath } from \"react-router\";\nimport type { SidebarItem } from \"../../../config/validators/SidebarSchema.js\";\nimport type { AuthState } from \"../../authentication/state.js\";\nimport type { ZudokuPlugin } from \"../../core/plugins.js\";\nimport { joinUrl } from \"../../util/joinUrl.js\";\nimport { Catalog } from \"./Catalog.js\";\n\nexport const getKey = (category: string, tag: string) =>\n slugify(`${category}-${tag}`);\n\nexport type ApiCatalogItem = {\n path: string;\n label: string;\n description: string;\n categories: CatalogCategory[];\n};\n\nexport type CatalogCategory = {\n label: string;\n tags: string[];\n};\n\nexport type ApiCatalogPluginOptions = {\n navigationId: string;\n label: string;\n categories?: CatalogCategory[];\n items: ApiCatalogItem[];\n filterCatalogItems?: filterCatalogItems;\n};\n\nexport type CatalogContext<ProviderData = unknown> = {\n auth: AuthState<ProviderData>;\n};\n\nexport type filterCatalogItems<ProviderData = unknown> = (\n items: ApiCatalogItem[],\n { auth }: CatalogContext<ProviderData>,\n) => ApiCatalogItem[];\n\nexport const apiCatalogPlugin = ({\n navigationId,\n items,\n label,\n categories = [],\n filterCatalogItems,\n}: {\n navigationId: string;\n label: string;\n categories?: CatalogCategory[];\n items: ApiCatalogItem[];\n filterCatalogItems?: filterCatalogItems;\n}): ZudokuPlugin => {\n return {\n getSidebar: async function Sidebar(path) {\n if (!matchPath({ path: joinUrl(navigationId), end: false }, path)) {\n return [];\n }\n\n const sidebar: SidebarItem[] = categories.map((category) => ({\n type: \"category\" as const,\n label: category.label,\n collapsible: false,\n items: category.tags.map((tag) => {\n const tagPath = getKey(category.label, tag);\n return {\n type: \"doc\" as const,\n id: joinUrl(navigationId, tagPath),\n label: tag,\n badge: {\n label: String(\n items.filter((api) =>\n api.categories.find((c) => c.tags.includes(tag)),\n ).length,\n ),\n color: \"outline\" as const,\n },\n };\n }),\n }));\n\n sidebar.unshift({\n type: \"doc\" as const,\n id: joinUrl(navigationId),\n label: \"Overview\",\n badge: { label: String(items.length), color: \"outline\" as const },\n });\n\n return sidebar;\n },\n getRoutes: () =>\n categories.flatMap((category) =>\n [undefined, ...category.tags].map((tag) => ({\n path: joinUrl(\n navigationId,\n tag ? getKey(category.label, tag) : undefined,\n ),\n element: (\n <Catalog\n label={label}\n categoryLabel={tag}\n items={items}\n filterCatalogItems={filterCatalogItems}\n categories={categories}\n />\n ),\n })),\n ),\n };\n};\n"],"names":["Catalog","items","filterCatalogItems","label","categoryLabel","auth","useAuthState","match","useMatch","activeCategory","catalogItems","useSuspenseQuery","dataSet","jsxs","jsx","Helmet","Heading","api","c","t","getKey","Link","joinUrl","Markdown","category","tag","slugify","apiCatalogPlugin","navigationId","categories","path","matchPath","sidebar","tagPath"],"mappings":"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"}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import { j as e } from "./jsx-runtime-CYK1ROHF.js";
|
|
2
2
|
import { RotateCwIcon as j, TrashIcon as v, EyeOffIcon as w, EyeIcon as K, CheckIcon as b, CopyIcon as k, FileKey2Icon as N } from "lucide-react";
|
|
3
|
-
import { D as I, S as x, R as S } from "./SlotletProvider-
|
|
3
|
+
import { D as I, S as x, R as S } from "./SlotletProvider-BEwNY8q0.js";
|
|
4
4
|
import { i as c } from "./invariant-Caa8-XvF.js";
|
|
5
|
-
import {
|
|
6
|
-
import { u as d, S as
|
|
7
|
-
import { a as
|
|
8
|
-
import { a as
|
|
9
|
-
import { a as g, e as z, b as F } from "./hook-DzQC8PzJ.js";
|
|
5
|
+
import { a as h, g, l as A, b as C } from "./hook-Cge6LiTK.js";
|
|
6
|
+
import { u as d, S as E, a as P, b as D, c as q, d as R, e as p } from "./Select-fAYcJ0OU.js";
|
|
7
|
+
import { a as O } from "./index.esm--gIChbWs.js";
|
|
8
|
+
import { a as z, L as u, O as F } from "./chunk-HA7DTUK3-C4gP41vD.js";
|
|
10
9
|
import { Button as l } from "./ui/Button.js";
|
|
11
10
|
import { Input as T } from "./ui/Input.js";
|
|
12
11
|
import { useState as y } from "react";
|
|
13
12
|
import { c as L } from "./cn-qaFjX9_3.js";
|
|
14
13
|
const V = ({ service: t }) => {
|
|
15
|
-
const n =
|
|
14
|
+
const n = h(), i = g(), r = z(), a = O({
|
|
16
15
|
defaultValues: {
|
|
17
16
|
expiresOn: "30"
|
|
18
17
|
}
|
|
@@ -41,13 +40,13 @@ const V = ({ service: t }) => {
|
|
|
41
40
|
/* @__PURE__ */ e.jsx(T, { ...a.register("description") }),
|
|
42
41
|
"Expiration",
|
|
43
42
|
/* @__PURE__ */ e.jsxs(
|
|
44
|
-
|
|
43
|
+
E,
|
|
45
44
|
{
|
|
46
45
|
onValueChange: (s) => a.setValue("expiresOn", s),
|
|
47
46
|
defaultValue: a.getValues("expiresOn"),
|
|
48
47
|
children: [
|
|
49
|
-
/* @__PURE__ */ e.jsx(
|
|
50
|
-
/* @__PURE__ */ e.jsx(
|
|
48
|
+
/* @__PURE__ */ e.jsx(P, { children: /* @__PURE__ */ e.jsx(D, {}) }),
|
|
49
|
+
/* @__PURE__ */ e.jsx(q, { children: /* @__PURE__ */ e.jsxs(R, { children: [
|
|
51
50
|
[7, 30, 60, 90].map((s) => /* @__PURE__ */ e.jsxs(p, { value: String(s), children: [
|
|
52
51
|
s,
|
|
53
52
|
" days"
|
|
@@ -69,8 +68,8 @@ const V = ({ service: t }) => {
|
|
|
69
68
|
const n = /* @__PURE__ */ new Date();
|
|
70
69
|
return n.setDate(n.getDate() + t), n.toISOString();
|
|
71
70
|
}, Q = () => {
|
|
72
|
-
const t =
|
|
73
|
-
return t.isAuthEnabled && t.isPending ? null : t.isAuthenticated ? /* @__PURE__ */ e.jsx(
|
|
71
|
+
const t = A();
|
|
72
|
+
return t.isAuthEnabled && t.isPending ? null : t.isAuthenticated ? /* @__PURE__ */ e.jsx(F, {}) : t.isAuthEnabled ? /* @__PURE__ */ e.jsxs("div", { className: "flex flex-col justify-center gap-2 items-center h-1/2", children: [
|
|
74
73
|
"Please login first to view this page",
|
|
75
74
|
/* @__PURE__ */ e.jsx(l, { onClick: () => t.login(), children: "Login" })
|
|
76
75
|
] }) : /* @__PURE__ */ e.jsx("div", { className: "flex flex-col justify-center gap-2 items-center h-1/2", children: /* @__PURE__ */ e.jsxs(I, { className: "max-w-[600px]", children: [
|
|
@@ -79,7 +78,7 @@ const V = ({ service: t }) => {
|
|
|
79
78
|
"."
|
|
80
79
|
] }) });
|
|
81
80
|
}, _ = ({ service: t }) => {
|
|
82
|
-
const n =
|
|
81
|
+
const n = h(), i = g(), { data: r } = C({
|
|
83
82
|
queryFn: () => t.getKeys(n),
|
|
84
83
|
queryKey: ["api-keys"],
|
|
85
84
|
retry: !1
|
|
@@ -237,7 +236,7 @@ const V = ({ service: t }) => {
|
|
|
237
236
|
const r = await fetch(i);
|
|
238
237
|
return c(r.ok, "Failed to fetch API keys"), await r.json();
|
|
239
238
|
}
|
|
240
|
-
}),
|
|
239
|
+
}), re = (t) => t, ae = (t) => {
|
|
241
240
|
const n = "endpoint" in t ? t.endpoint : $, i = "getKeys" in t ? t : B(n);
|
|
242
241
|
return {
|
|
243
242
|
getProfileMenuItems: () => [
|
|
@@ -278,7 +277,7 @@ const V = ({ service: t }) => {
|
|
|
278
277
|
};
|
|
279
278
|
};
|
|
280
279
|
export {
|
|
281
|
-
|
|
282
|
-
|
|
280
|
+
ae as apiKeyPlugin,
|
|
281
|
+
re as createApiKeyService
|
|
283
282
|
};
|
|
284
283
|
//# sourceMappingURL=zudoku.plugin-api-keys.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zudoku.plugin-api-keys.js","sources":["../src/lib/plugins/api-keys/CreateApiKey.tsx","../src/lib/plugins/api-keys/ProtectedRoute.tsx","../src/lib/plugins/api-keys/SettingsApiKeys.tsx","../src/lib/plugins/api-keys/index.tsx"],"sourcesContent":["import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { useForm } from \"react-hook-form\";\nimport { Link, useNavigate } from \"react-router\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"zudoku/ui/Select.js\";\nimport { useZudoku } from \"../../components/context/ZudokuContext.js\";\nimport { Button } from \"../../ui/Button.js\";\nimport { Input } from \"../../ui/Input.js\";\nimport { ApiKeyService } from \"./index.js\";\n\ntype CreateApiKey = { description: string; expiresOn?: string };\n\nexport const CreateApiKey = ({ service }: { service: ApiKeyService }) => {\n const context = useZudoku();\n const queryClient = useQueryClient();\n const navigate = useNavigate();\n const form = useForm<CreateApiKey>({\n defaultValues: {\n expiresOn: \"30\",\n },\n });\n const createKeyMutation = useMutation({\n mutationFn: ({ description, expiresOn }: CreateApiKey) => {\n if (!service.createKey) {\n throw new Error(\"createKey not implemented\");\n }\n\n const expiresOnDate =\n expiresOn !== \"never\" ? addDaysToDate(Number(expiresOn)) : undefined;\n\n return service.createKey(\n { description: description, expiresOn: expiresOnDate },\n context,\n );\n },\n onSuccess: async () => {\n await queryClient.invalidateQueries({ queryKey: [\"api-keys\"] });\n await navigate(\"/settings/api-keys/\");\n },\n });\n\n if (!service.createKey) {\n return null;\n }\n\n return (\n <div className=\"max-w-screen-lg pt-[--padding-content-top] pb-[--padding-content-bottom]\">\n <div className=\"flex justify-between mb-4 border-b pb-1\">\n <h1 className=\"font-medium text-2xl\">New API Key</h1>\n </div>\n <form\n onSubmit={form.handleSubmit((data) => createKeyMutation.mutate(data))}\n >\n <div className=\"flex gap-2 flex-col\">\n Note\n <Input {...form.register(\"description\")} />\n Expiration\n <Select\n onValueChange={(value) => form.setValue(\"expiresOn\", value)}\n defaultValue={form.getValues(\"expiresOn\")}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectGroup>\n {[7, 30, 60, 90].map((option) => (\n <SelectItem value={String(option)} key={option}>\n {option} days\n </SelectItem>\n ))}\n <SelectItem value=\"never\">Never</SelectItem>\n </SelectGroup>\n </SelectContent>\n </Select>\n <div className=\"flex gap-2\">\n <Button>Generate Key</Button>\n <Button variant=\"outline\" asChild>\n <Link to=\"/settings/api-keys/\">Cancel</Link>\n </Button>\n </div>\n </div>\n </form>\n </div>\n );\n};\n\nconst addDaysToDate = (days: number): string => {\n const date = new Date();\n date.setDate(date.getDate() + days);\n return date.toISOString();\n};\n","import { Outlet } from \"react-router\";\nimport { useAuth } from \"../../authentication/hook.js\";\nimport { DeveloperHint } from \"../../components/DeveloperHint.js\";\nimport { Button } from \"../../ui/Button.js\";\n\nexport const ProtectedRoute = () => {\n const auth = useAuth();\n\n // TODO: should we suspend here somehow?\n if (auth.isAuthEnabled && auth.isPending) {\n return null;\n }\n\n return auth.isAuthenticated ? (\n <Outlet />\n ) : !auth.isAuthEnabled ? (\n <div className=\"flex flex-col justify-center gap-2 items-center h-1/2\">\n <DeveloperHint className=\"max-w-[600px]\">\n Authentication needs to be enabled for API keys to work. Enable it in\n your Zudoku configuration under <code>authentication</code>.\n </DeveloperHint>\n </div>\n ) : (\n <div className=\"flex flex-col justify-center gap-2 items-center h-1/2\">\n Please login first to view this page\n <Button onClick={() => auth.login()}>Login</Button>\n </div>\n );\n};\n","import {\n useMutation,\n useQueryClient,\n useSuspenseQuery,\n} from \"@tanstack/react-query\";\nimport {\n CheckIcon,\n CopyIcon,\n EyeIcon,\n EyeOffIcon,\n RotateCwIcon,\n TrashIcon,\n} from \"lucide-react\";\nimport { useState } from \"react\";\nimport { Link } from \"react-router\";\nimport { useZudoku } from \"../../components/context/ZudokuContext.js\";\nimport { Slotlet } from \"../../components/SlotletProvider.js\";\nimport { Button } from \"../../ui/Button.js\";\nimport { cn } from \"../../util/cn.js\";\nimport { ApiKeyService } from \"./index.js\";\n\nexport const SettingsApiKeys = ({ service }: { service: ApiKeyService }) => {\n const context = useZudoku();\n const queryClient = useQueryClient();\n const { data } = useSuspenseQuery({\n queryFn: () => service.getKeys(context),\n queryKey: [\"api-keys\"],\n retry: false,\n });\n\n const deleteKeyMutation = useMutation({\n mutationFn: (id: string) => {\n if (!service.deleteKey) {\n throw new Error(\"deleteKey not implemented\");\n }\n\n return service.deleteKey(id, context);\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [\"api-keys\"] });\n },\n });\n\n const rollKeyMutation = useMutation({\n mutationFn: (id: string) => {\n if (!service.rollKey) {\n throw new Error(\"rollKey not implemented\");\n }\n\n return service.rollKey(id, context);\n },\n onSuccess: () => queryClient.invalidateQueries({ queryKey: [\"api-keys\"] }),\n });\n\n return (\n <div className=\"max-w-screen-lg h-full pt-[--padding-content-top] pb-[--padding-content-bottom]\">\n <Slotlet name=\"api-keys-list-page\" />\n\n <div className=\"flex justify-between mb-4 border-b pb-3\">\n <h1 className=\"font-medium text-2xl\">API Keys</h1>\n {service.createKey && (\n <Button asChild>\n <Link to=\"/settings/api-keys/new\">Create API Key</Link>\n </Button>\n )}\n </div>\n\n <Slotlet name=\"api-keys-list-page-before-keys\" />\n\n {data.length === 0 ? (\n <div className=\"flex flex-col justify-center gap-4 items-center p-8 border rounded bg-muted/30 text-muted-foreground\">\n <p className=\"text-center\">\n No API keys created yet.\n <br />\n Get started and create your first key.\n </p>\n {service.createKey && (\n <Button asChild variant=\"outline\">\n <Link to=\"/settings/api-keys/new\">Create API Key</Link>\n </Button>\n )}\n </div>\n ) : (\n <ul\n className={cn(\n \"grid grid-cols-1 rounded border divide-y divide-border\",\n \"lg:grid-cols-[minmax(250px,min-content)_1fr_min-content]\",\n )}\n >\n {data.map((key) => (\n <li\n className=\"p-5 grid grid-cols-subgrid col-span-full gap-2 items-center\"\n key={key.id}\n >\n <div className=\"flex flex-col gap-1 text-sm\">\n {key.description ?? key.id}\n <div className=\"text-muted-foreground text-xs\">\n {key.createdOn && (\n <div>\n Created on {new Date(key.createdOn).toLocaleDateString()}\n </div>\n )}\n {key.expiresOn && (\n <div>\n Expires on {new Date(key.expiresOn).toLocaleDateString()}\n </div>\n )}\n </div>\n </div>\n <div className=\"items-center flex lg:justify-center\">\n <RevealApiKey apiKey={key.key} />\n </div>\n <div className=\"flex gap-2\">\n {service.rollKey && (\n <Button\n size=\"icon\"\n title=\"Roll this key\"\n variant=\"ghost\"\n onClick={() => {\n if (!confirm(\"Do you want to roll this key?\")) {\n return;\n }\n\n rollKeyMutation.mutate(key.id);\n }}\n >\n <RotateCwIcon size={16} />\n </Button>\n )}\n {service.deleteKey && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n if (!confirm(\"Do you want to delete this key?\")) {\n return;\n }\n\n deleteKeyMutation.mutate(key.id);\n }}\n disabled={deleteKeyMutation.isPending}\n >\n <TrashIcon size={16} />\n </Button>\n )}\n </div>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n};\n\nconst RevealApiKey = ({ apiKey }: { apiKey: string }) => {\n const [revealed, setRevealed] = useState(false);\n const [copied, setCopied] = useState(false);\n\n return (\n <div className=\"flex gap-2 items-center text-sm\">\n <div className=\"border rounded bg-gray-100 dark:bg-gray-950 p-1 font-mono truncate h-9 items-center flex px-2\">\n {revealed ? apiKey : \"•\".repeat(apiKey.length)}\n </div>\n <Button\n variant=\"outline\"\n onClick={() => setRevealed((prev) => !prev)}\n size=\"icon\"\n >\n {revealed ? <EyeOffIcon size={16} /> : <EyeIcon size={16} />}\n </Button>\n <Button\n variant=\"outline\"\n onClick={() => {\n void navigator.clipboard.writeText(apiKey).then(() => {\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n });\n }}\n size=\"icon\"\n >\n {copied ? <CheckIcon size={16} /> : <CopyIcon size={16} />}\n </Button>\n </div>\n );\n};\n","import { FileKey2Icon } from \"lucide-react\";\nimport { type RouteObject } from \"react-router\";\nimport { ZudokuContext } from \"../../core/ZudokuContext.js\";\nimport {\n type ApiIdentityPlugin,\n type ZudokuPlugin,\n ProfileMenuPlugin,\n} from \"../../core/plugins.js\";\nimport { RouterError } from \"../../errors/RouterError.js\";\nimport invariant from \"../../util/invariant.js\";\nimport { CreateApiKey } from \"./CreateApiKey.js\";\nimport { ProtectedRoute } from \"./ProtectedRoute.js\";\nimport { SettingsApiKeys } from \"./SettingsApiKeys.js\";\n\nconst DEFAULT_API_KEY_ENDPOINT =\n \"https://zudoku-rewiringamerica-main-ef9c9c0.d2.zuplo.dev\";\n\nexport type ApiKeyService = {\n getKeys: (context: ZudokuContext) => Promise<ApiKey[]>;\n rollKey?: (id: string, context: ZudokuContext) => Promise<void>;\n deleteKey?: (id: string, context: ZudokuContext) => Promise<void>;\n updateKeyDescription?: (\n apiKey: { id: string; description: string },\n context: ZudokuContext,\n ) => Promise<void>;\n getUsage?: (apiKeys: string[], context: ZudokuContext) => Promise<void>;\n createKey?: (\n apiKey: { description: string; expiresOn?: string },\n context: ZudokuContext,\n ) => Promise<void>;\n};\n\nexport type GetApiKeysOptions = ApiKeyService | { endpoint: string } | object;\n\nexport type ApiKeyPluginOptions = object & GetApiKeysOptions;\n\nexport interface ApiKey {\n id: string;\n description?: string;\n createdOn?: string;\n updatedOn?: string;\n expiresOn?: string;\n key: string;\n}\n\nconst createDefaultHandler = (endpoint: string): ApiKeyService => {\n return {\n deleteKey: async (id, context) => {\n const request = new Request(endpoint + `/v1/developer/api-keys/${id}`, {\n method: \"DELETE\",\n });\n\n await context.signRequest(request);\n\n const response = await fetch(request);\n invariant(response.ok, \"Failed to delete API key\");\n },\n rollKey: async (id, context) => {\n const response = await fetch(\n await context.signRequest(\n new Request(endpoint + `/v1/developer/api-keys/${id}/key`, {\n method: \"DELETE\",\n }),\n ),\n );\n invariant(response.ok, \"Failed to delete API key\");\n },\n createKey: async (apiKey, context) => {\n const request = new Request(endpoint + `/v1/developer/api-keys`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(apiKey),\n });\n\n await context.signRequest(request);\n\n const response = await fetch(request);\n invariant(response.ok, \"Failed to create API key\");\n },\n getKeys: async (context) => {\n const request = new Request(endpoint + `/v1/developer/api-keys`);\n\n await context.signRequest(request);\n\n const keys = await fetch(request);\n invariant(keys.ok, \"Failed to fetch API keys\");\n\n return await keys.json();\n },\n };\n};\n\nexport const createApiKeyService = <T extends ApiKeyService>(service: T): T =>\n service;\n\nexport const apiKeyPlugin = (\n options: ApiKeyPluginOptions,\n): ZudokuPlugin & ApiIdentityPlugin & ProfileMenuPlugin => {\n const endpoint =\n \"endpoint\" in options ? options.endpoint : DEFAULT_API_KEY_ENDPOINT;\n\n const service =\n \"getKeys\" in options ? options : createDefaultHandler(endpoint);\n\n return {\n getProfileMenuItems: () => [\n {\n label: \"API Keys\",\n path: \"/settings/api-keys\",\n category: \"middle\",\n icon: FileKey2Icon,\n },\n ],\n getIdentities: async (context) => {\n try {\n const keys = await service.getKeys(context);\n\n return keys.map((key) => ({\n authorizeRequest: (request) => {\n request.headers.set(\"Authorization\", `Bearer ${key.key}`);\n return request;\n },\n id: key.id,\n label: key.description ?? key.id,\n }));\n } catch {\n return [];\n }\n },\n getRoutes: (): RouteObject[] => {\n // TODO: Make lazy\n return [\n {\n element: <ProtectedRoute />,\n errorElement: <RouterError />,\n children: [\n {\n path: \"/settings/api-keys\",\n element: <SettingsApiKeys service={service} />,\n },\n {\n path: \"/settings/api-keys/new\",\n element: <CreateApiKey service={service} />,\n },\n ],\n },\n ];\n },\n };\n};\n"],"names":["CreateApiKey","service","context","useZudoku","queryClient","useQueryClient","navigate","useNavigate","form","useForm","createKeyMutation","useMutation","description","expiresOn","expiresOnDate","addDaysToDate","jsxs","jsx","data","Input","Select","value","SelectTrigger","SelectValue","SelectContent","SelectGroup","option","SelectItem","Button","Link","days","date","ProtectedRoute","auth","useAuth","Outlet","DeveloperHint","SettingsApiKeys","useSuspenseQuery","deleteKeyMutation","id","rollKeyMutation","Slotlet","cn","key","RevealApiKey","RotateCwIcon","TrashIcon","apiKey","revealed","setRevealed","useState","copied","setCopied","prev","EyeOffIcon","EyeIcon","CheckIcon","CopyIcon","DEFAULT_API_KEY_ENDPOINT","createDefaultHandler","endpoint","request","response","invariant","keys","createApiKeyService","apiKeyPlugin","options","FileKey2Icon","RouterError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"zudoku.plugin-api-keys.js","sources":["../src/lib/plugins/api-keys/CreateApiKey.tsx","../src/lib/plugins/api-keys/ProtectedRoute.tsx","../src/lib/plugins/api-keys/SettingsApiKeys.tsx","../src/lib/plugins/api-keys/index.tsx"],"sourcesContent":["import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { useForm } from \"react-hook-form\";\nimport { Link, useNavigate } from \"react-router\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"zudoku/ui/Select.js\";\nimport { useZudoku } from \"../../components/context/ZudokuContext.js\";\nimport { Button } from \"../../ui/Button.js\";\nimport { Input } from \"../../ui/Input.js\";\nimport { ApiKeyService } from \"./index.js\";\n\ntype CreateApiKey = { description: string; expiresOn?: string };\n\nexport const CreateApiKey = ({ service }: { service: ApiKeyService }) => {\n const context = useZudoku();\n const queryClient = useQueryClient();\n const navigate = useNavigate();\n const form = useForm<CreateApiKey>({\n defaultValues: {\n expiresOn: \"30\",\n },\n });\n const createKeyMutation = useMutation({\n mutationFn: ({ description, expiresOn }: CreateApiKey) => {\n if (!service.createKey) {\n throw new Error(\"createKey not implemented\");\n }\n\n const expiresOnDate =\n expiresOn !== \"never\" ? addDaysToDate(Number(expiresOn)) : undefined;\n\n return service.createKey(\n { description: description, expiresOn: expiresOnDate },\n context,\n );\n },\n onSuccess: async () => {\n await queryClient.invalidateQueries({ queryKey: [\"api-keys\"] });\n await navigate(\"/settings/api-keys/\");\n },\n });\n\n if (!service.createKey) {\n return null;\n }\n\n return (\n <div className=\"max-w-screen-lg pt-[--padding-content-top] pb-[--padding-content-bottom]\">\n <div className=\"flex justify-between mb-4 border-b pb-1\">\n <h1 className=\"font-medium text-2xl\">New API Key</h1>\n </div>\n <form\n onSubmit={form.handleSubmit((data) => createKeyMutation.mutate(data))}\n >\n <div className=\"flex gap-2 flex-col\">\n Note\n <Input {...form.register(\"description\")} />\n Expiration\n <Select\n onValueChange={(value) => form.setValue(\"expiresOn\", value)}\n defaultValue={form.getValues(\"expiresOn\")}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectGroup>\n {[7, 30, 60, 90].map((option) => (\n <SelectItem value={String(option)} key={option}>\n {option} days\n </SelectItem>\n ))}\n <SelectItem value=\"never\">Never</SelectItem>\n </SelectGroup>\n </SelectContent>\n </Select>\n <div className=\"flex gap-2\">\n <Button>Generate Key</Button>\n <Button variant=\"outline\" asChild>\n <Link to=\"/settings/api-keys/\">Cancel</Link>\n </Button>\n </div>\n </div>\n </form>\n </div>\n );\n};\n\nconst addDaysToDate = (days: number): string => {\n const date = new Date();\n date.setDate(date.getDate() + days);\n return date.toISOString();\n};\n","import { Outlet } from \"react-router\";\nimport { useAuth } from \"../../authentication/hook.js\";\nimport { DeveloperHint } from \"../../components/DeveloperHint.js\";\nimport { Button } from \"../../ui/Button.js\";\n\nexport const ProtectedRoute = () => {\n const auth = useAuth();\n\n // TODO: should we suspend here somehow?\n if (auth.isAuthEnabled && auth.isPending) {\n return null;\n }\n\n return auth.isAuthenticated ? (\n <Outlet />\n ) : !auth.isAuthEnabled ? (\n <div className=\"flex flex-col justify-center gap-2 items-center h-1/2\">\n <DeveloperHint className=\"max-w-[600px]\">\n Authentication needs to be enabled for API keys to work. Enable it in\n your Zudoku configuration under <code>authentication</code>.\n </DeveloperHint>\n </div>\n ) : (\n <div className=\"flex flex-col justify-center gap-2 items-center h-1/2\">\n Please login first to view this page\n <Button onClick={() => auth.login()}>Login</Button>\n </div>\n );\n};\n","import {\n useMutation,\n useQueryClient,\n useSuspenseQuery,\n} from \"@tanstack/react-query\";\nimport {\n CheckIcon,\n CopyIcon,\n EyeIcon,\n EyeOffIcon,\n RotateCwIcon,\n TrashIcon,\n} from \"lucide-react\";\nimport { useState } from \"react\";\nimport { Link } from \"react-router\";\nimport { useZudoku } from \"../../components/context/ZudokuContext.js\";\nimport { Slotlet } from \"../../components/SlotletProvider.js\";\nimport { Button } from \"../../ui/Button.js\";\nimport { cn } from \"../../util/cn.js\";\nimport { ApiKeyService } from \"./index.js\";\n\nexport const SettingsApiKeys = ({ service }: { service: ApiKeyService }) => {\n const context = useZudoku();\n const queryClient = useQueryClient();\n const { data } = useSuspenseQuery({\n queryFn: () => service.getKeys(context),\n queryKey: [\"api-keys\"],\n retry: false,\n });\n\n const deleteKeyMutation = useMutation({\n mutationFn: (id: string) => {\n if (!service.deleteKey) {\n throw new Error(\"deleteKey not implemented\");\n }\n\n return service.deleteKey(id, context);\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [\"api-keys\"] });\n },\n });\n\n const rollKeyMutation = useMutation({\n mutationFn: (id: string) => {\n if (!service.rollKey) {\n throw new Error(\"rollKey not implemented\");\n }\n\n return service.rollKey(id, context);\n },\n onSuccess: () => queryClient.invalidateQueries({ queryKey: [\"api-keys\"] }),\n });\n\n return (\n <div className=\"max-w-screen-lg h-full pt-[--padding-content-top] pb-[--padding-content-bottom]\">\n <Slotlet name=\"api-keys-list-page\" />\n\n <div className=\"flex justify-between mb-4 border-b pb-3\">\n <h1 className=\"font-medium text-2xl\">API Keys</h1>\n {service.createKey && (\n <Button asChild>\n <Link to=\"/settings/api-keys/new\">Create API Key</Link>\n </Button>\n )}\n </div>\n\n <Slotlet name=\"api-keys-list-page-before-keys\" />\n\n {data.length === 0 ? (\n <div className=\"flex flex-col justify-center gap-4 items-center p-8 border rounded bg-muted/30 text-muted-foreground\">\n <p className=\"text-center\">\n No API keys created yet.\n <br />\n Get started and create your first key.\n </p>\n {service.createKey && (\n <Button asChild variant=\"outline\">\n <Link to=\"/settings/api-keys/new\">Create API Key</Link>\n </Button>\n )}\n </div>\n ) : (\n <ul\n className={cn(\n \"grid grid-cols-1 rounded border divide-y divide-border\",\n \"lg:grid-cols-[minmax(250px,min-content)_1fr_min-content]\",\n )}\n >\n {data.map((key) => (\n <li\n className=\"p-5 grid grid-cols-subgrid col-span-full gap-2 items-center\"\n key={key.id}\n >\n <div className=\"flex flex-col gap-1 text-sm\">\n {key.description ?? key.id}\n <div className=\"text-muted-foreground text-xs\">\n {key.createdOn && (\n <div>\n Created on {new Date(key.createdOn).toLocaleDateString()}\n </div>\n )}\n {key.expiresOn && (\n <div>\n Expires on {new Date(key.expiresOn).toLocaleDateString()}\n </div>\n )}\n </div>\n </div>\n <div className=\"items-center flex lg:justify-center\">\n <RevealApiKey apiKey={key.key} />\n </div>\n <div className=\"flex gap-2\">\n {service.rollKey && (\n <Button\n size=\"icon\"\n title=\"Roll this key\"\n variant=\"ghost\"\n onClick={() => {\n if (!confirm(\"Do you want to roll this key?\")) {\n return;\n }\n\n rollKeyMutation.mutate(key.id);\n }}\n >\n <RotateCwIcon size={16} />\n </Button>\n )}\n {service.deleteKey && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n if (!confirm(\"Do you want to delete this key?\")) {\n return;\n }\n\n deleteKeyMutation.mutate(key.id);\n }}\n disabled={deleteKeyMutation.isPending}\n >\n <TrashIcon size={16} />\n </Button>\n )}\n </div>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n};\n\nconst RevealApiKey = ({ apiKey }: { apiKey: string }) => {\n const [revealed, setRevealed] = useState(false);\n const [copied, setCopied] = useState(false);\n\n return (\n <div className=\"flex gap-2 items-center text-sm\">\n <div className=\"border rounded bg-gray-100 dark:bg-gray-950 p-1 font-mono truncate h-9 items-center flex px-2\">\n {revealed ? apiKey : \"•\".repeat(apiKey.length)}\n </div>\n <Button\n variant=\"outline\"\n onClick={() => setRevealed((prev) => !prev)}\n size=\"icon\"\n >\n {revealed ? <EyeOffIcon size={16} /> : <EyeIcon size={16} />}\n </Button>\n <Button\n variant=\"outline\"\n onClick={() => {\n void navigator.clipboard.writeText(apiKey).then(() => {\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n });\n }}\n size=\"icon\"\n >\n {copied ? <CheckIcon size={16} /> : <CopyIcon size={16} />}\n </Button>\n </div>\n );\n};\n","import { FileKey2Icon } from \"lucide-react\";\nimport { type RouteObject } from \"react-router\";\nimport { ZudokuContext } from \"../../core/ZudokuContext.js\";\nimport {\n type ApiIdentityPlugin,\n type ZudokuPlugin,\n ProfileMenuPlugin,\n} from \"../../core/plugins.js\";\nimport { RouterError } from \"../../errors/RouterError.js\";\nimport invariant from \"../../util/invariant.js\";\nimport { CreateApiKey } from \"./CreateApiKey.js\";\nimport { ProtectedRoute } from \"./ProtectedRoute.js\";\nimport { SettingsApiKeys } from \"./SettingsApiKeys.js\";\n\nconst DEFAULT_API_KEY_ENDPOINT =\n \"https://zudoku-rewiringamerica-main-ef9c9c0.d2.zuplo.dev\";\n\nexport type ApiKeyService = {\n getKeys: (context: ZudokuContext) => Promise<ApiKey[]>;\n rollKey?: (id: string, context: ZudokuContext) => Promise<void>;\n deleteKey?: (id: string, context: ZudokuContext) => Promise<void>;\n updateKeyDescription?: (\n apiKey: { id: string; description: string },\n context: ZudokuContext,\n ) => Promise<void>;\n getUsage?: (apiKeys: string[], context: ZudokuContext) => Promise<void>;\n createKey?: (\n apiKey: { description: string; expiresOn?: string },\n context: ZudokuContext,\n ) => Promise<void>;\n};\n\nexport type GetApiKeysOptions = ApiKeyService | { endpoint: string } | object;\n\nexport type ApiKeyPluginOptions = object & GetApiKeysOptions;\n\nexport interface ApiKey {\n id: string;\n description?: string;\n createdOn?: string;\n updatedOn?: string;\n expiresOn?: string;\n key: string;\n}\n\nconst createDefaultHandler = (endpoint: string): ApiKeyService => {\n return {\n deleteKey: async (id, context) => {\n const request = new Request(endpoint + `/v1/developer/api-keys/${id}`, {\n method: \"DELETE\",\n });\n\n await context.signRequest(request);\n\n const response = await fetch(request);\n invariant(response.ok, \"Failed to delete API key\");\n },\n rollKey: async (id, context) => {\n const response = await fetch(\n await context.signRequest(\n new Request(endpoint + `/v1/developer/api-keys/${id}/key`, {\n method: \"DELETE\",\n }),\n ),\n );\n invariant(response.ok, \"Failed to delete API key\");\n },\n createKey: async (apiKey, context) => {\n const request = new Request(endpoint + `/v1/developer/api-keys`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(apiKey),\n });\n\n await context.signRequest(request);\n\n const response = await fetch(request);\n invariant(response.ok, \"Failed to create API key\");\n },\n getKeys: async (context) => {\n const request = new Request(endpoint + `/v1/developer/api-keys`);\n\n await context.signRequest(request);\n\n const keys = await fetch(request);\n invariant(keys.ok, \"Failed to fetch API keys\");\n\n return await keys.json();\n },\n };\n};\n\nexport const createApiKeyService = <T extends ApiKeyService>(service: T): T =>\n service;\n\nexport const apiKeyPlugin = (\n options: ApiKeyPluginOptions,\n): ZudokuPlugin & ApiIdentityPlugin & ProfileMenuPlugin => {\n const endpoint =\n \"endpoint\" in options ? options.endpoint : DEFAULT_API_KEY_ENDPOINT;\n\n const service =\n \"getKeys\" in options ? options : createDefaultHandler(endpoint);\n\n return {\n getProfileMenuItems: () => [\n {\n label: \"API Keys\",\n path: \"/settings/api-keys\",\n category: \"middle\",\n icon: FileKey2Icon,\n },\n ],\n getIdentities: async (context) => {\n try {\n const keys = await service.getKeys(context);\n\n return keys.map((key) => ({\n authorizeRequest: (request) => {\n request.headers.set(\"Authorization\", `Bearer ${key.key}`);\n return request;\n },\n id: key.id,\n label: key.description ?? key.id,\n }));\n } catch {\n return [];\n }\n },\n getRoutes: (): RouteObject[] => {\n // TODO: Make lazy\n return [\n {\n element: <ProtectedRoute />,\n errorElement: <RouterError />,\n children: [\n {\n path: \"/settings/api-keys\",\n element: <SettingsApiKeys service={service} />,\n },\n {\n path: \"/settings/api-keys/new\",\n element: <CreateApiKey service={service} />,\n },\n ],\n },\n ];\n },\n };\n};\n"],"names":["CreateApiKey","service","context","useZudoku","queryClient","useQueryClient","navigate","useNavigate","form","useForm","createKeyMutation","useMutation","description","expiresOn","expiresOnDate","addDaysToDate","jsxs","jsx","data","Input","Select","value","SelectTrigger","SelectValue","SelectContent","SelectGroup","option","SelectItem","Button","Link","days","date","ProtectedRoute","auth","useAuth","Outlet","DeveloperHint","SettingsApiKeys","useSuspenseQuery","deleteKeyMutation","id","rollKeyMutation","Slotlet","cn","key","RevealApiKey","RotateCwIcon","TrashIcon","apiKey","revealed","setRevealed","useState","copied","setCopied","prev","EyeOffIcon","EyeIcon","CheckIcon","CopyIcon","DEFAULT_API_KEY_ENDPOINT","createDefaultHandler","endpoint","request","response","invariant","keys","createApiKeyService","apiKeyPlugin","options","FileKey2Icon","RouterError"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { j as o } from "./jsx-runtime-CYK1ROHF.js";
|
|
2
2
|
import a from "react";
|
|
3
|
-
import { P as n } from "./Markdown-
|
|
3
|
+
import { P as n } from "./Markdown-DIZ8nBVC.js";
|
|
4
4
|
import { c } from "./cn-qaFjX9_3.js";
|
|
5
|
-
import { u as p } from "./useExposedProps-
|
|
5
|
+
import { u as p } from "./useExposedProps-B9qXJedG.js";
|
|
6
6
|
const u = ({
|
|
7
7
|
element: t,
|
|
8
8
|
render: s,
|
|
@@ -53,7 +53,7 @@ const P = (e) => ({
|
|
|
53
53
|
const u = {
|
|
54
54
|
path: r,
|
|
55
55
|
lazy: async () => {
|
|
56
|
-
const { MdxPage: p } = await import("./MdxPage-
|
|
56
|
+
const { MdxPage: p } = await import("./MdxPage-JEdbfW-f.js"), { default: f, ...l } = await i();
|
|
57
57
|
return {
|
|
58
58
|
element: /* @__PURE__ */ d.jsx(
|
|
59
59
|
p,
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import "./jsx-runtime-CYK1ROHF.js";
|
|
2
2
|
import "lucide-react";
|
|
3
|
-
import "./chunk-HA7DTUK3-
|
|
4
|
-
import "./hook-
|
|
3
|
+
import "./chunk-HA7DTUK3-C4gP41vD.js";
|
|
4
|
+
import "./hook-Cge6LiTK.js";
|
|
5
5
|
import "./ui/Button.js";
|
|
6
|
-
import "./
|
|
7
|
-
import { U as e, o as n } from "./index-DdQSV2RF.js";
|
|
6
|
+
import { U as a, o as e } from "./index-B0y3fTg-.js";
|
|
8
7
|
export {
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
a as UNTAGGED_PATH,
|
|
9
|
+
e as openApiPlugin
|
|
11
10
|
};
|
|
12
11
|
//# sourceMappingURL=zudoku.plugin-openapi.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zudoku.plugin-openapi.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"zudoku.plugin-openapi.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
|