zudoku 0.23.2 → 0.23.4
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/config/validators/common.d.ts +45 -11
- package/dist/config/validators/common.js +2 -1
- package/dist/config/validators/common.js.map +1 -1
- package/dist/config/validators/validate.d.ts +19 -5
- package/dist/lib/authentication/providers/openid.d.ts +7 -0
- package/dist/lib/authentication/providers/openid.js +1 -0
- package/dist/lib/authentication/providers/openid.js.map +1 -1
- package/dist/lib/plugins/api-catalog/Catalog.d.ts +2 -6
- package/dist/lib/plugins/api-catalog/Catalog.js +22 -15
- package/dist/lib/plugins/api-catalog/Catalog.js.map +1 -1
- package/dist/lib/plugins/api-catalog/index.d.ts +8 -1
- package/dist/lib/plugins/api-catalog/index.js +2 -2
- package/dist/lib/plugins/api-catalog/index.js.map +1 -1
- package/dist/lib/plugins/search-inkeep/index.js +21 -7
- package/dist/lib/plugins/search-inkeep/index.js.map +1 -1
- package/dist/vite/plugin-api.js +12 -7
- package/dist/vite/plugin-api.js.map +1 -1
- package/lib/{AuthenticationPlugin-DQy635W9.js → AuthenticationPlugin-fB7viE7A.js} +2 -2
- package/lib/{AuthenticationPlugin-DQy635W9.js.map → AuthenticationPlugin-fB7viE7A.js.map} +1 -1
- package/lib/{MdxPage-CBa4X6L5.js → MdxPage-CPBw4_lf.js} +18 -18
- package/lib/{MdxPage-CBa4X6L5.js.map → MdxPage-CPBw4_lf.js.map} +1 -1
- package/lib/OperationList-C7ac3kR5.js +5014 -0
- package/lib/OperationList-C7ac3kR5.js.map +1 -0
- package/lib/{Select-Bb_Hqc70.js → Select-D3XuKKuH.js} +3 -3
- package/lib/{Select-Bb_Hqc70.js.map → Select-D3XuKKuH.js.map} +1 -1
- package/lib/assets/{worker-BmEAZjUP.js → worker-D2kRl-cG.js} +1487 -1436
- package/lib/assets/worker-D2kRl-cG.js.map +1 -0
- package/lib/cn-qaFjX9_3.js.map +1 -1
- package/lib/{createServer-BVFp6Bl3.js → createServer-69sLlmQA.js} +1968 -1917
- package/lib/createServer-69sLlmQA.js.map +1 -0
- package/lib/{hook-DMHiUaIV.js → hook-DgGeo5iL.js} +2 -2
- package/lib/{hook-DMHiUaIV.js.map → hook-DgGeo5iL.js.map} +1 -1
- package/lib/{index-B6rTMjdI.js → index-C8ubT49C.js} +6 -6
- package/lib/{index-B6rTMjdI.js.map → index-C8ubT49C.js.map} +1 -1
- package/lib/{utils-R0j3Raw1.js → utils-B4O1uet5.js} +8 -8
- package/lib/{utils-R0j3Raw1.js.map → utils-B4O1uet5.js.map} +1 -1
- package/lib/zudoku.auth-clerk.js +1 -1
- package/lib/zudoku.auth-openid.js +70 -69
- package/lib/zudoku.auth-openid.js.map +1 -1
- package/lib/zudoku.components.js +2 -2
- package/lib/zudoku.openapi-worker.js +1 -1
- package/lib/zudoku.plugin-api-catalog.js +80 -78
- package/lib/zudoku.plugin-api-catalog.js.map +1 -1
- package/lib/zudoku.plugin-api-keys.js +3 -3
- package/lib/zudoku.plugin-markdown.js +1 -1
- package/lib/zudoku.plugin-openapi.js +3 -3
- package/lib/zudoku.plugin-search-inkeep.js +34 -26
- package/lib/zudoku.plugin-search-inkeep.js.map +1 -1
- package/package.json +8 -8
- package/src/lib/authentication/providers/openid.tsx +5 -3
- package/src/lib/plugins/api-catalog/Catalog.tsx +59 -60
- package/src/lib/plugins/api-catalog/index.tsx +14 -0
- package/src/lib/plugins/search-inkeep/index.tsx +27 -8
- package/lib/OperationList-Bj-6EKhp.js +0 -4889
- package/lib/OperationList-Bj-6EKhp.js.map +0 -1
- package/lib/assets/worker-BmEAZjUP.js.map +0 -1
- package/lib/createServer-BVFp6Bl3.js.map +0 -1
|
@@ -1,37 +1,45 @@
|
|
|
1
1
|
import slugify from "@sindresorhus/slugify";
|
|
2
|
-
import {
|
|
2
|
+
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
3
|
+
import { useSearchParams } from "react-router";
|
|
3
4
|
import { Head, Link } from "zudoku/components";
|
|
5
|
+
import { useAuthState } from "../../authentication/state.js";
|
|
4
6
|
import { Markdown } from "../../components/Markdown.js";
|
|
5
|
-
import {
|
|
6
|
-
import type {
|
|
7
|
+
import { cn } from "../../util/cn.js";
|
|
8
|
+
import type { ApiCatalogPluginOptions } from "./index.js";
|
|
9
|
+
|
|
10
|
+
const getKey = (category: string, tag: string) => slugify(`${category}-${tag}`);
|
|
7
11
|
|
|
8
12
|
export const Catalog = ({
|
|
9
13
|
items,
|
|
14
|
+
filterCatalogItems = (items) => items,
|
|
10
15
|
categories,
|
|
11
16
|
label = "API Library",
|
|
12
|
-
}: {
|
|
13
|
-
|
|
14
|
-
items: ApiCatalogItem[];
|
|
15
|
-
categories: CatalogCategory[];
|
|
16
|
-
}) => {
|
|
17
|
-
const { searchParams, setSearchParams } = useExposedProps();
|
|
17
|
+
}: Omit<ApiCatalogPluginOptions, "navigationId">) => {
|
|
18
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
18
19
|
const activeCategory = searchParams.get("category");
|
|
20
|
+
const auth = useAuthState();
|
|
21
|
+
|
|
22
|
+
const catalogItems = useSuspenseQuery({
|
|
23
|
+
queryFn: () => filterCatalogItems(items, { auth }),
|
|
24
|
+
queryKey: ["catalogItems", auth],
|
|
25
|
+
});
|
|
26
|
+
|
|
19
27
|
return (
|
|
20
28
|
<section className="pt-[--padding-content-top] pb-[--padding-content-bottom]">
|
|
21
29
|
<Head>
|
|
22
30
|
<title>{label}</title>
|
|
23
31
|
</Head>
|
|
24
32
|
<div className="grid grid-cols-12 gap-12">
|
|
25
|
-
<div className="flex flex-col gap-4 col-span-3
|
|
26
|
-
<div className="justify-between">
|
|
27
|
-
{categories
|
|
28
|
-
<
|
|
33
|
+
<div className="flex flex-col gap-4 col-span-3 not-prose sticky top-48">
|
|
34
|
+
<div className="max-w-[--side-nav-width] flex flex-col gap-4 justify-between">
|
|
35
|
+
{categories?.map((category, idx) => (
|
|
36
|
+
<div key={category.label}>
|
|
29
37
|
<div className="flex justify-between mb-2.5">
|
|
30
38
|
<span className="font-medium text-sm">{category.label}</span>
|
|
31
39
|
{idx === 0 && activeCategory && (
|
|
32
40
|
<button
|
|
33
41
|
type="button"
|
|
34
|
-
className="text-end text-sm
|
|
42
|
+
className="text-end text-sm text-foreground/60 hover:text-foreground"
|
|
35
43
|
onClick={() => setSearchParams({})}
|
|
36
44
|
>
|
|
37
45
|
Clear
|
|
@@ -39,45 +47,41 @@ export const Catalog = ({
|
|
|
39
47
|
)}
|
|
40
48
|
</div>
|
|
41
49
|
<ul className="space-y-1 [&>li]:py-2">
|
|
42
|
-
{
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
50
|
+
{category.tags
|
|
51
|
+
.map((tag) => ({
|
|
52
|
+
tag,
|
|
53
|
+
count: items.filter((api) =>
|
|
54
|
+
api.categories.find((c) => c.tags.includes(tag)),
|
|
55
|
+
).length,
|
|
56
|
+
}))
|
|
57
|
+
.map(({ tag, count }) => {
|
|
58
|
+
const slug = getKey(category.label, tag);
|
|
59
|
+
const isActive = slug === activeCategory;
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<li
|
|
63
|
+
key={slug}
|
|
64
|
+
className={cn(
|
|
65
|
+
"flex rounded-lg justify-between text-sm cursor-pointer hover:text-primary transition px-[--padding-nav-item] -mx-[--padding-nav-item]",
|
|
66
|
+
isActive && "bg-border/30 rounded",
|
|
67
|
+
)}
|
|
68
|
+
onClick={() => setSearchParams({ category: slug })}
|
|
69
|
+
>
|
|
70
|
+
<span>{tag}</span>
|
|
71
|
+
<span
|
|
72
|
+
className={cn(
|
|
73
|
+
"flex items-center justify-center border rounded-md w-8 text-xs font-semibold",
|
|
74
|
+
isActive &&
|
|
75
|
+
"bg-primary border-primary text-primary-foreground",
|
|
76
|
+
)}
|
|
64
77
|
>
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
: ""
|
|
71
|
-
}`}
|
|
72
|
-
>
|
|
73
|
-
{count}
|
|
74
|
-
</span>
|
|
75
|
-
</li>
|
|
76
|
-
)),
|
|
77
|
-
),
|
|
78
|
-
)}
|
|
78
|
+
{count}
|
|
79
|
+
</span>
|
|
80
|
+
</li>
|
|
81
|
+
);
|
|
82
|
+
})}
|
|
79
83
|
</ul>
|
|
80
|
-
</
|
|
84
|
+
</div>
|
|
81
85
|
))}
|
|
82
86
|
</div>
|
|
83
87
|
</div>
|
|
@@ -85,17 +89,15 @@ export const Catalog = ({
|
|
|
85
89
|
<h3 className="mt-0 text-2xl font-bold mb-4">{label}</h3>
|
|
86
90
|
|
|
87
91
|
<div className="grid grid-cols-2 gap-4">
|
|
88
|
-
{
|
|
92
|
+
{catalogItems.data
|
|
89
93
|
.filter(
|
|
90
94
|
(api) =>
|
|
91
95
|
!activeCategory ||
|
|
92
96
|
api.categories.find((c) =>
|
|
93
|
-
c.tags.find(
|
|
94
|
-
(t) => slugify(c.label + " " + t) === activeCategory,
|
|
95
|
-
),
|
|
97
|
+
c.tags.find((t) => getKey(c.label, t) === activeCategory),
|
|
96
98
|
),
|
|
97
99
|
)
|
|
98
|
-
.map((api
|
|
100
|
+
.map((api) => (
|
|
99
101
|
<Link
|
|
100
102
|
to={{
|
|
101
103
|
pathname: `/${api.path}`,
|
|
@@ -104,10 +106,7 @@ export const Catalog = ({
|
|
|
104
106
|
className="no-underline hover:!text-foreground"
|
|
105
107
|
key={api.path}
|
|
106
108
|
>
|
|
107
|
-
<div
|
|
108
|
-
className="border h-full rounded p-4 flex flex-col gap-2 cursor-pointer hover:bg-border/20 font-normal"
|
|
109
|
-
key={i}
|
|
110
|
-
>
|
|
109
|
+
<div className="border h-full rounded p-4 flex flex-col gap-2 cursor-pointer hover:bg-border/20 font-normal">
|
|
111
110
|
<span className="font-semibold">{api.label}</span>
|
|
112
111
|
<Markdown
|
|
113
112
|
className="text-sm whitespace-pre-wrap mb-6 line-clamp-2"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AuthState } from "../../authentication/state.js";
|
|
1
2
|
import type { ZudokuPlugin } from "../../core/plugins.js";
|
|
2
3
|
import { Catalog } from "./Catalog.js";
|
|
3
4
|
|
|
@@ -18,18 +19,30 @@ export type ApiCatalogPluginOptions = {
|
|
|
18
19
|
label: string;
|
|
19
20
|
categories?: CatalogCategory[];
|
|
20
21
|
items: ApiCatalogItem[];
|
|
22
|
+
filterCatalogItems?: filterCatalogItems;
|
|
21
23
|
};
|
|
22
24
|
|
|
25
|
+
export type CatalogContext<ProviderData = unknown> = {
|
|
26
|
+
auth: AuthState<ProviderData>;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type filterCatalogItems<ProviderData = unknown> = (
|
|
30
|
+
items: ApiCatalogItem[],
|
|
31
|
+
{ auth }: CatalogContext<ProviderData>,
|
|
32
|
+
) => ApiCatalogItem[];
|
|
33
|
+
|
|
23
34
|
export const apiCatalogPlugin = ({
|
|
24
35
|
navigationId,
|
|
25
36
|
items,
|
|
26
37
|
label,
|
|
27
38
|
categories,
|
|
39
|
+
filterCatalogItems,
|
|
28
40
|
}: {
|
|
29
41
|
navigationId: string;
|
|
30
42
|
label: string;
|
|
31
43
|
categories?: CatalogCategory[];
|
|
32
44
|
items: ApiCatalogItem[];
|
|
45
|
+
filterCatalogItems?: filterCatalogItems;
|
|
33
46
|
}): ZudokuPlugin => {
|
|
34
47
|
return {
|
|
35
48
|
getRoutes: () => {
|
|
@@ -40,6 +53,7 @@ export const apiCatalogPlugin = ({
|
|
|
40
53
|
<Catalog
|
|
41
54
|
label={label}
|
|
42
55
|
items={items}
|
|
56
|
+
filterCatalogItems={filterCatalogItems}
|
|
43
57
|
categories={categories ?? []}
|
|
44
58
|
/>
|
|
45
59
|
),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useMemo, useRef } from "react";
|
|
1
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
2
2
|
import { ClientOnly } from "../../components/ClientOnly.js";
|
|
3
3
|
import type { ZudokuPlugin } from "../../core/plugins.js";
|
|
4
4
|
import { aiChatSettings, baseSettings } from "./inkeep.js";
|
|
@@ -39,6 +39,10 @@ const InkeepSearch = ({
|
|
|
39
39
|
settings: PluginInkeepBaseSettings;
|
|
40
40
|
}) => {
|
|
41
41
|
const ref = useRef<HTMLDivElement>(null);
|
|
42
|
+
const widgetRef = useRef<InkeepWidget | null>(null);
|
|
43
|
+
const [isInkeepAvailable, setIsInkeepAvailable] = useState(
|
|
44
|
+
typeof Inkeep !== "undefined",
|
|
45
|
+
);
|
|
42
46
|
|
|
43
47
|
const config: InkeepEmbedConfig = useMemo(
|
|
44
48
|
() => ({
|
|
@@ -59,12 +63,27 @@ const InkeepSearch = ({
|
|
|
59
63
|
);
|
|
60
64
|
|
|
61
65
|
useEffect(() => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
if (isInkeepAvailable) return;
|
|
67
|
+
|
|
68
|
+
const checkInkeep = setInterval(() => {
|
|
69
|
+
if (typeof Inkeep !== "undefined") {
|
|
70
|
+
setIsInkeepAvailable(true);
|
|
71
|
+
clearInterval(checkInkeep);
|
|
72
|
+
}
|
|
73
|
+
}, 100);
|
|
74
|
+
|
|
75
|
+
return () => clearInterval(checkInkeep);
|
|
76
|
+
}, [isInkeepAvailable]);
|
|
77
|
+
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
if (!isInkeepAvailable || widgetRef.current) return;
|
|
80
|
+
|
|
81
|
+
widgetRef.current = Inkeep().embed(config);
|
|
82
|
+
}, [config, isInkeepAvailable]);
|
|
83
|
+
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
widgetRef.current?.render({ ...config, isOpen });
|
|
86
|
+
}, [config, isOpen]);
|
|
68
87
|
|
|
69
88
|
return <div ref={ref} />;
|
|
70
89
|
};
|
|
@@ -79,7 +98,7 @@ export const inkeepSearchPlugin = (
|
|
|
79
98
|
type="module"
|
|
80
99
|
src="https://unpkg.com/@inkeep/uikit-js@0.3.19/dist/embed.js"
|
|
81
100
|
defer
|
|
82
|
-
|
|
101
|
+
/>
|
|
83
102
|
);
|
|
84
103
|
},
|
|
85
104
|
renderSearch: ({
|