zudoku 0.0.0-monetization-standalone.z2a065bd9 → 0.0.0-money-plugin.z605c614d
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/create-plugin.d.ts +2 -2
- package/dist/config/create-plugin.js.map +1 -1
- package/dist/config/validators/InputNavigationSchema.d.ts +103 -53
- package/dist/config/validators/InputNavigationSchema.js +17 -0
- package/dist/config/validators/InputNavigationSchema.js.map +1 -1
- package/dist/config/validators/NavigationSchema.d.ts +10 -2
- package/dist/config/validators/NavigationSchema.js +7 -0
- package/dist/config/validators/NavigationSchema.js.map +1 -1
- package/dist/config/validators/ProtectedRoutesSchema.d.ts +1 -1
- package/dist/config/validators/validate.d.ts +3 -3
- package/dist/flat-config.d.ts +35 -24
- package/dist/lib/components/Heading.d.ts +1 -1
- package/dist/lib/components/MobileTopNavigation.js +2 -1
- package/dist/lib/components/MobileTopNavigation.js.map +1 -1
- package/dist/lib/components/TopNavigation.d.ts +7 -1
- package/dist/lib/components/TopNavigation.js +7 -2
- package/dist/lib/components/TopNavigation.js.map +1 -1
- package/dist/lib/components/context/ZudokuContext.d.ts +8 -1
- package/dist/lib/components/context/ZudokuContext.js +2 -0
- package/dist/lib/components/context/ZudokuContext.js.map +1 -1
- package/dist/lib/components/index.d.ts +18 -76
- package/dist/lib/components/index.js +19 -36
- package/dist/lib/components/index.js.map +1 -1
- package/dist/lib/components/navigation/Navigation.js +4 -3
- package/dist/lib/components/navigation/Navigation.js.map +1 -1
- package/dist/lib/components/navigation/NavigationCategory.js +8 -0
- package/dist/lib/components/navigation/NavigationCategory.js.map +1 -1
- package/dist/lib/components/navigation/NavigationFilterContext.d.ts +8 -0
- package/dist/lib/components/navigation/NavigationFilterContext.js +12 -0
- package/dist/lib/components/navigation/NavigationFilterContext.js.map +1 -0
- package/dist/lib/components/navigation/NavigationFilterInput.d.ts +3 -0
- package/dist/lib/components/navigation/NavigationFilterInput.js +9 -0
- package/dist/lib/components/navigation/NavigationFilterInput.js.map +1 -0
- package/dist/lib/components/navigation/NavigationItem.js +11 -1
- package/dist/lib/components/navigation/NavigationItem.js.map +1 -1
- package/dist/lib/components/navigation/utils.d.ts +2 -1
- package/dist/lib/components/navigation/utils.js +22 -1
- package/dist/lib/components/navigation/utils.js.map +1 -1
- package/dist/lib/hooks/index.d.ts +7 -30
- package/dist/lib/hooks/index.js +7 -15
- package/dist/lib/hooks/index.js.map +1 -1
- package/dist/lib/oas/graphql/circular.d.ts +1 -1
- package/dist/lib/oas/graphql/circular.js +18 -35
- package/dist/lib/oas/graphql/circular.js.map +1 -1
- package/dist/lib/oas/graphql/circular.test.js +33 -2
- package/dist/lib/oas/graphql/circular.test.js.map +1 -1
- package/dist/lib/oas/parser/index.js +14 -5
- package/dist/lib/oas/parser/index.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/fileUtils.d.ts +1 -0
- package/dist/lib/plugins/openapi/playground/fileUtils.js +3 -0
- package/dist/lib/plugins/openapi/playground/fileUtils.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/result-panel/AudioPlayer.d.ts +6 -0
- package/dist/lib/plugins/openapi/playground/result-panel/AudioPlayer.js +20 -0
- package/dist/lib/plugins/openapi/playground/result-panel/AudioPlayer.js.map +1 -0
- package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.js +7 -2
- package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.js.map +1 -1
- package/dist/lib/ui/Alert.d.ts +3 -2
- package/dist/lib/ui/Alert.js +9 -5
- package/dist/lib/ui/Alert.js.map +1 -1
- package/dist/lib/ui/Command.d.ts +3 -3
- package/dist/lib/ui/InputGroup.d.ts +16 -0
- package/dist/lib/ui/InputGroup.js +65 -0
- package/dist/lib/ui/InputGroup.js.map +1 -0
- package/dist/lib/util/flattenAllOf.d.ts +0 -2
- package/dist/lib/util/flattenAllOf.js +0 -46
- package/dist/lib/util/flattenAllOf.js.map +1 -1
- package/dist/lib/util/flattenAllOf.test.js +2 -1
- package/dist/lib/util/flattenAllOf.test.js.map +1 -1
- package/dist/lib/util/flattenAllOfProcessor.d.ts +2 -0
- package/dist/lib/util/flattenAllOfProcessor.js +48 -0
- package/dist/lib/util/flattenAllOfProcessor.js.map +1 -0
- package/dist/lib/util/readFrontmatter.js +2 -1
- package/dist/lib/util/readFrontmatter.js.map +1 -1
- package/dist/vite/api/SchemaManager.js +1 -1
- package/dist/vite/api/SchemaManager.js.map +1 -1
- package/dist/vite/api/SchemaManager.test.js +1 -1
- package/dist/vite/api/SchemaManager.test.js.map +1 -1
- package/dist/vite/build.js +91 -73
- package/dist/vite/build.js.map +1 -1
- package/dist/vite/mdx/remark-inject-filepath.js +5 -1
- package/dist/vite/mdx/remark-inject-filepath.js.map +1 -1
- package/dist/vite/mdx/remark-link-rewrite.js +3 -2
- package/dist/vite/mdx/remark-link-rewrite.js.map +1 -1
- package/dist/vite/plugin-docs.js +9 -7
- package/dist/vite/plugin-docs.js.map +1 -1
- package/dist/vite/plugin-markdown-export.js +4 -2
- package/dist/vite/plugin-markdown-export.js.map +1 -1
- package/lib/{ClaudeLogo-K64Qm6gS.js → ClaudeLogo-DP6JOmz1.js} +26 -22
- package/lib/{ClaudeLogo-K64Qm6gS.js.map → ClaudeLogo-DP6JOmz1.js.map} +1 -1
- package/lib/{HydrationBoundary-CNF2ZV3E.js → HydrationBoundary-CJu4vUlG.js} +6 -6
- package/lib/{HydrationBoundary-CNF2ZV3E.js.map → HydrationBoundary-CJu4vUlG.js.map} +1 -1
- package/lib/{MdxPage-Cr99RARi.js → MdxPage-BR_7-0cT.js} +8 -8
- package/lib/{MdxPage-Cr99RARi.js.map → MdxPage-BR_7-0cT.js.map} +1 -1
- package/lib/Mermaid-DAWm9rzb.js +104 -0
- package/lib/Mermaid-DAWm9rzb.js.map +1 -0
- package/lib/{OAuthErrorPage-BRXS5AMu.js → OAuthErrorPage-l0orKh-A.js} +22 -19
- package/lib/{OAuthErrorPage-BRXS5AMu.js.map → OAuthErrorPage-l0orKh-A.js.map} +1 -1
- package/lib/{OasProvider-sP_SqSM7.js → OasProvider-DPW0x8dk.js} +3 -3
- package/lib/{OasProvider-sP_SqSM7.js.map → OasProvider-DPW0x8dk.js.map} +1 -1
- package/lib/{OperationList-DR0APPhk.js → OperationList-Dcm9TZG7.js} +952 -948
- package/lib/OperationList-Dcm9TZG7.js.map +1 -0
- package/lib/{RouteGuard-CZuPjknT.js → RouteGuard-CVs3yvEs.js} +5 -5
- package/lib/{RouteGuard-CZuPjknT.js.map → RouteGuard-CVs3yvEs.js.map} +1 -1
- package/lib/{SchemaList-DgqAAHSI.js → SchemaList-B7RzviG5.js} +8 -8
- package/lib/{SchemaList-DgqAAHSI.js.map → SchemaList-B7RzviG5.js.map} +1 -1
- package/lib/{SchemaView-7IyQYEqk.js → SchemaView-Dt5-T06r.js} +3 -3
- package/lib/{SchemaView-7IyQYEqk.js.map → SchemaView-Dt5-T06r.js.map} +1 -1
- package/lib/{Secret-BE7V0Vb5.js → Secret-DUpgv4V3.js} +4 -4
- package/lib/{Secret-BE7V0Vb5.js.map → Secret-DUpgv4V3.js.map} +1 -1
- package/lib/{SignUp-D3zhMk7q.js → SignUp-CifBTCq4.js} +31 -26
- package/lib/{SignUp-D3zhMk7q.js.map → SignUp-CifBTCq4.js.map} +1 -1
- package/lib/{SyntaxHighlight-paLQ8NP8.js → SyntaxHighlight-BMu0b_hF.js} +3 -3
- package/lib/{SyntaxHighlight-paLQ8NP8.js.map → SyntaxHighlight-BMu0b_hF.js.map} +1 -1
- package/lib/{Toc-GluXkcIk.js → Toc-CeMXYWgp.js} +2 -2
- package/lib/{Toc-GluXkcIk.js.map → Toc-CeMXYWgp.js.map} +1 -1
- package/lib/{index-DYfX9H7i.js → Zudoku-B5YsolG1.js} +2869 -2710
- package/lib/Zudoku-B5YsolG1.js.map +1 -0
- package/lib/ZudokuContext-CYyb_PB_.js +175 -0
- package/lib/ZudokuContext-CYyb_PB_.js.map +1 -0
- package/lib/ZudokuReactContext-DGJAP1sN.js +222 -0
- package/lib/ZudokuReactContext-DGJAP1sN.js.map +1 -0
- package/lib/{circular-Bunzbpsy.js → circular-BV9K7T3F.js} +1327 -1346
- package/lib/{circular-Bunzbpsy.js.map → circular-BV9K7T3F.js.map} +1 -1
- package/lib/createServer-DYUdwZG4.js +13036 -0
- package/lib/createServer-DYUdwZG4.js.map +1 -0
- package/lib/{errors-D2NINcVk.js → errors-C3XsqYso.js} +3 -3
- package/lib/{errors-D2NINcVk.js.map → errors-C3XsqYso.js.map} +1 -1
- package/lib/{firebase-BVAmGV_v.js → firebase-CL9aCRn0.js} +26 -25
- package/lib/firebase-CL9aCRn0.js.map +1 -0
- package/lib/{hook-Da8QTnPd.js → hook-Dz_n9SoE.js} +16 -15
- package/lib/{hook-Da8QTnPd.js.map → hook-Dz_n9SoE.js.map} +1 -1
- package/lib/{index-DTjrb36R.js → index-CFW_9FdI.js} +2 -2
- package/lib/{index-DTjrb36R.js.map → index-CFW_9FdI.js.map} +1 -1
- package/lib/index-DAWHN3cH.js +86 -0
- package/lib/index-DAWHN3cH.js.map +1 -0
- package/lib/{index-BfTLawvZ.js → index-DywuWe2u.js} +589 -551
- package/lib/index-DywuWe2u.js.map +1 -0
- package/lib/{index.esm-B_0dvNjB.js → index.esm-Ca5zvoff.js} +20 -20
- package/lib/{index.esm-B_0dvNjB.js.map → index.esm-Ca5zvoff.js.map} +1 -1
- package/lib/{index.esm-GMDd_9gw.js → index.esm-ld_S_9qs.js} +2 -2
- package/lib/index.esm-ld_S_9qs.js.map +1 -0
- package/lib/{invariant-BJAl77rw.js → invariant-B_t_F2s_.js} +3 -3
- package/lib/{invariant-BJAl77rw.js.map → invariant-B_t_F2s_.js.map} +1 -1
- package/lib/{mutation-BISOc7OM.js → mutation-B7eFBLZY.js} +2 -2
- package/lib/{mutation-BISOc7OM.js.map → mutation-B7eFBLZY.js.map} +1 -1
- package/lib/ui/Alert.js +36 -24
- package/lib/ui/Alert.js.map +1 -1
- package/lib/ui/InputGroup.js +155 -0
- package/lib/ui/InputGroup.js.map +1 -0
- package/lib/ui/SyntaxHighlight.js +3 -3
- package/lib/useExposedProps-CzTDfXfq.js +30 -0
- package/lib/useExposedProps-CzTDfXfq.js.map +1 -0
- package/lib/{useMutation-CFMGlAMW.js → useMutation-CErliDZ9.js} +5 -5
- package/lib/{useMutation-CFMGlAMW.js.map → useMutation-CErliDZ9.js.map} +1 -1
- package/lib/{useSuspenseQuery-CSB_rVek.js → useQuery-ht7aWJ3S.js} +432 -446
- package/lib/useQuery-ht7aWJ3S.js.map +1 -0
- package/lib/useSuspenseQuery-DQH4Bmc2.js +18 -0
- package/lib/useSuspenseQuery-DQH4Bmc2.js.map +1 -0
- package/lib/zudoku.__internal.js +1504 -1041
- package/lib/zudoku.__internal.js.map +1 -1
- package/lib/zudoku.auth-auth0.js +6 -5
- package/lib/zudoku.auth-auth0.js.map +1 -1
- package/lib/zudoku.auth-azureb2c.js +14 -13
- package/lib/zudoku.auth-azureb2c.js.map +1 -1
- package/lib/zudoku.auth-clerk.js +2 -2
- package/lib/zudoku.auth-firebase.js +5 -5
- package/lib/zudoku.auth-openid.js +8 -7
- package/lib/zudoku.auth-openid.js.map +1 -1
- package/lib/zudoku.auth-supabase.js +4 -4
- package/lib/zudoku.components.js +31 -29
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.hooks.js +24 -11
- package/lib/zudoku.hooks.js.map +1 -1
- package/lib/zudoku.mermaid.js +5 -4
- package/lib/zudoku.mermaid.js.map +1 -1
- package/lib/zudoku.plugin-api-catalog.js +41 -36
- package/lib/zudoku.plugin-api-catalog.js.map +1 -1
- package/lib/zudoku.plugin-api-keys.js +156 -153
- package/lib/zudoku.plugin-api-keys.js.map +1 -1
- package/lib/zudoku.plugin-custom-pages.js +1 -1
- package/lib/zudoku.plugin-markdown.js +1 -1
- package/lib/zudoku.plugin-openapi.js +2 -2
- package/lib/zudoku.plugin-search-pagefind.js +19 -18
- package/lib/zudoku.plugin-search-pagefind.js.map +1 -1
- package/lib/zudoku.react-query.js +26 -25
- package/lib/zudoku.react-query.js.map +1 -1
- package/package.json +5 -4
- package/src/app/defaultTheme.css +4 -0
- package/src/app/main.css +2 -0
- package/src/lib/components/MobileTopNavigation.tsx +13 -8
- package/src/lib/components/TopNavigation.tsx +25 -7
- package/src/lib/components/context/ZudokuContext.ts +1 -0
- package/src/lib/components/index.ts +19 -39
- package/src/lib/components/navigation/Navigation.tsx +4 -3
- package/src/lib/components/navigation/NavigationCategory.tsx +9 -0
- package/src/lib/components/navigation/NavigationFilterContext.tsx +28 -0
- package/src/lib/components/navigation/NavigationFilterInput.tsx +35 -0
- package/src/lib/components/navigation/NavigationItem.tsx +17 -1
- package/src/lib/components/navigation/utils.ts +32 -1
- package/src/lib/hooks/index.ts +7 -16
- package/src/lib/oas/graphql/circular.test.ts +37 -2
- package/src/lib/oas/graphql/circular.ts +25 -51
- package/src/lib/oas/parser/index.ts +17 -6
- package/src/lib/plugins/openapi/playground/fileUtils.ts +4 -0
- package/src/lib/plugins/openapi/playground/result-panel/AudioPlayer.tsx +50 -0
- package/src/lib/plugins/openapi/playground/result-panel/ResponseTab.tsx +33 -17
- package/src/lib/ui/Alert.tsx +17 -5
- package/src/lib/ui/InputGroup.tsx +168 -0
- package/src/lib/util/flattenAllOf.test.ts +2 -1
- package/src/lib/util/flattenAllOf.ts +0 -57
- package/src/lib/util/flattenAllOfProcessor.ts +58 -0
- package/src/lib/util/readFrontmatter.ts +2 -1
- package/src/zuplo/enrich-with-zuplo-mcp.ts +168 -0
- package/src/zuplo/enrich-with-zuplo.ts +254 -0
- package/src/zuplo/policy-types.ts +46 -0
- package/src/zuplo/with-zuplo-processors.ts +35 -0
- package/src/zuplo/with-zuplo.ts +14 -0
- package/lib/Mermaid-DEztDKFw.js +0 -102
- package/lib/Mermaid-DEztDKFw.js.map +0 -1
- package/lib/OperationList-DR0APPhk.js.map +0 -1
- package/lib/Separator-BXt1LYnm.js +0 -27
- package/lib/Separator-BXt1LYnm.js.map +0 -1
- package/lib/ZudokuContext-CnEI8jPU.js +0 -389
- package/lib/ZudokuContext-CnEI8jPU.js.map +0 -1
- package/lib/___vite-browser-external_commonjs-proxy-BttVsNON.js +0 -9
- package/lib/___vite-browser-external_commonjs-proxy-BttVsNON.js.map +0 -1
- package/lib/createServer-Dl4Xwsm4.js +0 -16693
- package/lib/createServer-Dl4Xwsm4.js.map +0 -1
- package/lib/firebase-BVAmGV_v.js.map +0 -1
- package/lib/index-Ba6RP577.js +0 -133
- package/lib/index-Ba6RP577.js.map +0 -1
- package/lib/index-BfTLawvZ.js.map +0 -1
- package/lib/index-DYfX9H7i.js.map +0 -1
- package/lib/index.esm-GMDd_9gw.js.map +0 -1
- package/lib/useSuspenseQuery-CSB_rVek.js.map +0 -1
package/src/lib/ui/Alert.tsx
CHANGED
|
@@ -3,13 +3,15 @@ import type * as React from "react";
|
|
|
3
3
|
import { cn } from "../util/cn.js";
|
|
4
4
|
|
|
5
5
|
const alertVariants = cva(
|
|
6
|
-
"
|
|
6
|
+
"grid gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 w-full relative group/alert",
|
|
7
7
|
{
|
|
8
8
|
variants: {
|
|
9
9
|
variant: {
|
|
10
10
|
default: "bg-card text-card-foreground",
|
|
11
11
|
destructive:
|
|
12
|
-
"text-destructive bg-card
|
|
12
|
+
"text-destructive bg-card bg-destructive/5 border-destructive/20 *:data-[slot=alert-description]:text-destructive *:[svg]:text-current",
|
|
13
|
+
warning:
|
|
14
|
+
"text-warning-foreground bg-card bg-warning/5 border-warning/50 *:data-[slot=alert-description]:text-warning-foreground *:[svg]:text-current",
|
|
13
15
|
},
|
|
14
16
|
},
|
|
15
17
|
defaultVariants: {
|
|
@@ -38,7 +40,7 @@ function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
|
38
40
|
<div
|
|
39
41
|
data-slot="alert-title"
|
|
40
42
|
className={cn(
|
|
41
|
-
"col-start-2
|
|
43
|
+
"font-medium group-has-[>svg]/alert:col-start-2 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3",
|
|
42
44
|
className,
|
|
43
45
|
)}
|
|
44
46
|
{...props}
|
|
@@ -54,7 +56,7 @@ function AlertDescription({
|
|
|
54
56
|
<div
|
|
55
57
|
data-slot="alert-description"
|
|
56
58
|
className={cn(
|
|
57
|
-
"text-muted-foreground
|
|
59
|
+
"text-muted-foreground text-sm text-balance md:text-pretty [&_p:not(:last-child)]:mb-4 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3",
|
|
58
60
|
className,
|
|
59
61
|
)}
|
|
60
62
|
{...props}
|
|
@@ -62,4 +64,14 @@ function AlertDescription({
|
|
|
62
64
|
);
|
|
63
65
|
}
|
|
64
66
|
|
|
65
|
-
|
|
67
|
+
function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
68
|
+
return (
|
|
69
|
+
<div
|
|
70
|
+
data-slot="alert-action"
|
|
71
|
+
className={cn("absolute top-2 right-2", className)}
|
|
72
|
+
{...props}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { Alert, AlertTitle, AlertDescription, AlertAction };
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
2
|
+
import type * as React from "react";
|
|
3
|
+
import { cn } from "../util/cn.js";
|
|
4
|
+
import { Button } from "./Button.js";
|
|
5
|
+
import { Input } from "./Input.js";
|
|
6
|
+
import { Textarea } from "./Textarea.js";
|
|
7
|
+
|
|
8
|
+
function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
9
|
+
return (
|
|
10
|
+
<div
|
|
11
|
+
data-slot="input-group"
|
|
12
|
+
role="group"
|
|
13
|
+
className={cn(
|
|
14
|
+
"group/input-group border-input dark:bg-input/30 relative flex w-full items-center rounded-md border shadow-xs transition-[color,box-shadow] outline-none",
|
|
15
|
+
"h-9 min-w-0 has-[>textarea]:h-auto",
|
|
16
|
+
|
|
17
|
+
// Variants based on alignment.
|
|
18
|
+
"has-[>[data-align=inline-start]]:[&>input]:pl-2",
|
|
19
|
+
"has-[>[data-align=inline-end]]:[&>input]:pr-2",
|
|
20
|
+
"has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3",
|
|
21
|
+
"has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3",
|
|
22
|
+
|
|
23
|
+
// Focus state.
|
|
24
|
+
"has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot=input-group-control]:focus-visible]:ring-[3px]",
|
|
25
|
+
|
|
26
|
+
// Error state.
|
|
27
|
+
"has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40",
|
|
28
|
+
|
|
29
|
+
className,
|
|
30
|
+
)}
|
|
31
|
+
{...props}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const inputGroupAddonVariants = cva(
|
|
37
|
+
"text-muted-foreground flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium select-none [&>svg:not([class*='size-'])]:size-4 [&>kbd]:rounded-[calc(var(--radius)-5px)] group-data-[disabled=true]/input-group:opacity-50",
|
|
38
|
+
{
|
|
39
|
+
variants: {
|
|
40
|
+
align: {
|
|
41
|
+
"inline-start":
|
|
42
|
+
"order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]",
|
|
43
|
+
"inline-end":
|
|
44
|
+
"order-last pr-3 has-[>button]:mr-[-0.45rem] has-[>kbd]:mr-[-0.35rem]",
|
|
45
|
+
"block-start":
|
|
46
|
+
"order-first w-full justify-start px-3 pt-3 [.border-b]:pb-3 group-has-[>input]/input-group:pt-2.5",
|
|
47
|
+
"block-end":
|
|
48
|
+
"order-last w-full justify-start px-3 pb-3 [.border-t]:pt-3 group-has-[>input]/input-group:pb-2.5",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
defaultVariants: {
|
|
52
|
+
align: "inline-start",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
function InputGroupAddon({
|
|
58
|
+
className,
|
|
59
|
+
align = "inline-start",
|
|
60
|
+
...props
|
|
61
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) {
|
|
62
|
+
return (
|
|
63
|
+
// biome-ignore lint/a11y/useKeyWithClickEvents: Focus management
|
|
64
|
+
<div
|
|
65
|
+
role="group"
|
|
66
|
+
data-slot="input-group-addon"
|
|
67
|
+
data-align={align}
|
|
68
|
+
className={cn(inputGroupAddonVariants({ align }), className)}
|
|
69
|
+
onClick={(e) => {
|
|
70
|
+
if ((e.target as HTMLElement).closest("button")) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
e.currentTarget.parentElement?.querySelector("input")?.focus();
|
|
74
|
+
}}
|
|
75
|
+
{...props}
|
|
76
|
+
/>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const inputGroupButtonVariants = cva(
|
|
81
|
+
"text-sm shadow-none flex gap-2 items-center",
|
|
82
|
+
{
|
|
83
|
+
variants: {
|
|
84
|
+
size: {
|
|
85
|
+
xs: "h-6 gap-1 px-2 rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-3.5 has-[>svg]:px-2",
|
|
86
|
+
sm: "h-8 px-2.5 gap-1.5 rounded-md has-[>svg]:px-2.5",
|
|
87
|
+
"icon-xs":
|
|
88
|
+
"size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0",
|
|
89
|
+
"icon-sm": "size-8 p-0 has-[>svg]:p-0",
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
defaultVariants: {
|
|
93
|
+
size: "xs",
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
function InputGroupButton({
|
|
99
|
+
className,
|
|
100
|
+
type = "button",
|
|
101
|
+
variant = "ghost",
|
|
102
|
+
size = "xs",
|
|
103
|
+
...props
|
|
104
|
+
}: Omit<React.ComponentProps<typeof Button>, "size"> &
|
|
105
|
+
VariantProps<typeof inputGroupButtonVariants>) {
|
|
106
|
+
return (
|
|
107
|
+
<Button
|
|
108
|
+
type={type}
|
|
109
|
+
data-size={size}
|
|
110
|
+
variant={variant}
|
|
111
|
+
className={cn(inputGroupButtonVariants({ size }), className)}
|
|
112
|
+
{...props}
|
|
113
|
+
/>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function InputGroupText({ className, ...props }: React.ComponentProps<"span">) {
|
|
118
|
+
return (
|
|
119
|
+
<span
|
|
120
|
+
className={cn(
|
|
121
|
+
"text-muted-foreground flex items-center gap-2 text-sm [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
|
|
122
|
+
className,
|
|
123
|
+
)}
|
|
124
|
+
{...props}
|
|
125
|
+
/>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function InputGroupInput({
|
|
130
|
+
className,
|
|
131
|
+
...props
|
|
132
|
+
}: React.ComponentProps<"input">) {
|
|
133
|
+
return (
|
|
134
|
+
<Input
|
|
135
|
+
data-slot="input-group-control"
|
|
136
|
+
className={cn(
|
|
137
|
+
"flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent",
|
|
138
|
+
className,
|
|
139
|
+
)}
|
|
140
|
+
{...props}
|
|
141
|
+
/>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function InputGroupTextarea({
|
|
146
|
+
className,
|
|
147
|
+
...props
|
|
148
|
+
}: React.ComponentProps<"textarea">) {
|
|
149
|
+
return (
|
|
150
|
+
<Textarea
|
|
151
|
+
data-slot="input-group-control"
|
|
152
|
+
className={cn(
|
|
153
|
+
"flex-1 resize-none rounded-none border-0 bg-transparent py-3 shadow-none focus-visible:ring-0 dark:bg-transparent",
|
|
154
|
+
className,
|
|
155
|
+
)}
|
|
156
|
+
{...props}
|
|
157
|
+
/>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export {
|
|
162
|
+
InputGroup,
|
|
163
|
+
InputGroupAddon,
|
|
164
|
+
InputGroupButton,
|
|
165
|
+
InputGroupText,
|
|
166
|
+
InputGroupInput,
|
|
167
|
+
InputGroupTextarea,
|
|
168
|
+
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { JSONSchema7 } from "json-schema";
|
|
2
2
|
import { describe, expect, it, vi } from "vitest";
|
|
3
3
|
import type { OpenAPIDocument } from "../oas/parser/index.js";
|
|
4
|
-
import { flattenAllOf
|
|
4
|
+
import { flattenAllOf } from "./flattenAllOf.js";
|
|
5
|
+
import { flattenAllOfProcessor } from "./flattenAllOfProcessor.js";
|
|
5
6
|
import invariant from "./invariant.js";
|
|
6
7
|
|
|
7
8
|
describe("flattenAllOf", () => {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { $RefParser } from "@apidevtools/json-schema-ref-parser";
|
|
2
1
|
import {
|
|
3
2
|
createComparator,
|
|
4
3
|
createMerger,
|
|
@@ -9,62 +8,6 @@ import {
|
|
|
9
8
|
createIntersector,
|
|
10
9
|
} from "@x0k/json-schema-merge/lib/array";
|
|
11
10
|
import type { JSONSchema7Definition } from "json-schema";
|
|
12
|
-
import type { Processor } from "../../config/validators/BuildSchema.js";
|
|
13
|
-
import type { OpenAPIDocument } from "../oas/parser/index.js";
|
|
14
|
-
import { type RecordAny, traverse } from "./traverse.js";
|
|
15
|
-
|
|
16
|
-
export const flattenAllOfProcessor: Processor = async ({ schema, file }) => {
|
|
17
|
-
try {
|
|
18
|
-
// Resolve refs once - creates a lookup table without modifying the schema
|
|
19
|
-
const parser = new $RefParser();
|
|
20
|
-
await parser.resolve(schema);
|
|
21
|
-
const $refs = parser.$refs;
|
|
22
|
-
|
|
23
|
-
const flattened = traverse(schema, (spec) => {
|
|
24
|
-
if (!spec || typeof spec !== "object" || Array.isArray(spec)) {
|
|
25
|
-
return spec;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const isSchemaObject =
|
|
29
|
-
"type" in spec ||
|
|
30
|
-
"properties" in spec ||
|
|
31
|
-
"allOf" in spec ||
|
|
32
|
-
"anyOf" in spec ||
|
|
33
|
-
"oneOf" in spec;
|
|
34
|
-
|
|
35
|
-
if (!isSchemaObject) return spec;
|
|
36
|
-
|
|
37
|
-
if ("allOf" in spec && Array.isArray(spec.allOf)) {
|
|
38
|
-
const resolvedAllOf = spec.allOf.map((item) => {
|
|
39
|
-
if (
|
|
40
|
-
item &&
|
|
41
|
-
typeof item === "object" &&
|
|
42
|
-
"$ref" in item &&
|
|
43
|
-
typeof item.$ref === "string"
|
|
44
|
-
) {
|
|
45
|
-
try {
|
|
46
|
-
return $refs.get(item.$ref) ?? item;
|
|
47
|
-
} catch {
|
|
48
|
-
return item;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return item;
|
|
52
|
-
});
|
|
53
|
-
return flattenAllOf({ ...spec, allOf: resolvedAllOf }) as RecordAny;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return flattenAllOf(spec) as RecordAny;
|
|
57
|
-
}) as OpenAPIDocument;
|
|
58
|
-
|
|
59
|
-
return flattened;
|
|
60
|
-
} catch (error) {
|
|
61
|
-
// biome-ignore lint/suspicious/noConsole: Logging allowed here
|
|
62
|
-
console.warn(
|
|
63
|
-
`Failed to flatten \`allOf\` in ${file}: ${error instanceof Error ? error.message : error}`,
|
|
64
|
-
);
|
|
65
|
-
return schema;
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
11
|
|
|
69
12
|
const { compareSchemaDefinitions, compareSchemaValues } = createComparator();
|
|
70
13
|
const { mergeArrayOfSchemaDefinitions } = createMerger({
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { $RefParser } from "@apidevtools/json-schema-ref-parser";
|
|
2
|
+
import type { Processor } from "../../config/validators/BuildSchema.js";
|
|
3
|
+
import type { OpenAPIDocument } from "../oas/parser/index.js";
|
|
4
|
+
import { flattenAllOf } from "./flattenAllOf.js";
|
|
5
|
+
import { type RecordAny, traverse } from "./traverse.js";
|
|
6
|
+
|
|
7
|
+
export const flattenAllOfProcessor: Processor = async ({ schema, file }) => {
|
|
8
|
+
try {
|
|
9
|
+
// Resolve refs once - creates a lookup table without modifying the schema
|
|
10
|
+
const parser = new $RefParser();
|
|
11
|
+
await parser.resolve(schema);
|
|
12
|
+
const $refs = parser.$refs;
|
|
13
|
+
|
|
14
|
+
const flattened = traverse(schema, (spec) => {
|
|
15
|
+
if (!spec || typeof spec !== "object" || Array.isArray(spec)) {
|
|
16
|
+
return spec;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const isSchemaObject =
|
|
20
|
+
"type" in spec ||
|
|
21
|
+
"properties" in spec ||
|
|
22
|
+
"allOf" in spec ||
|
|
23
|
+
"anyOf" in spec ||
|
|
24
|
+
"oneOf" in spec;
|
|
25
|
+
|
|
26
|
+
if (!isSchemaObject) return spec;
|
|
27
|
+
|
|
28
|
+
if ("allOf" in spec && Array.isArray(spec.allOf)) {
|
|
29
|
+
const resolvedAllOf = spec.allOf.map((item) => {
|
|
30
|
+
if (
|
|
31
|
+
item &&
|
|
32
|
+
typeof item === "object" &&
|
|
33
|
+
"$ref" in item &&
|
|
34
|
+
typeof item.$ref === "string"
|
|
35
|
+
) {
|
|
36
|
+
try {
|
|
37
|
+
return $refs.get(item.$ref) ?? item;
|
|
38
|
+
} catch {
|
|
39
|
+
return item;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return item;
|
|
43
|
+
});
|
|
44
|
+
return flattenAllOf({ ...spec, allOf: resolvedAllOf }) as RecordAny;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return flattenAllOf(spec) as RecordAny;
|
|
48
|
+
}) as OpenAPIDocument;
|
|
49
|
+
|
|
50
|
+
return flattened;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
// biome-ignore lint/suspicious/noConsole: Logging allowed here
|
|
53
|
+
console.warn(
|
|
54
|
+
`Failed to flatten \`allOf\` in ${file}: ${error instanceof Error ? error.message : error}`,
|
|
55
|
+
);
|
|
56
|
+
return schema;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
@@ -9,5 +9,6 @@ export const yaml = {
|
|
|
9
9
|
|
|
10
10
|
export const readFrontmatter = async (filePath: string) => {
|
|
11
11
|
const content = await readFile(filePath, "utf-8");
|
|
12
|
-
|
|
12
|
+
const normalizedContent = content.replace(/\r\n/g, "\n");
|
|
13
|
+
return matter(normalizedContent, { engines: { yaml } });
|
|
13
14
|
};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import type {
|
|
4
|
+
ExtensionMcpServer,
|
|
5
|
+
ExtensionMcpServerTool,
|
|
6
|
+
} from "@zuplo/mcp/openapi/types";
|
|
7
|
+
import {
|
|
8
|
+
DEFAULT_MCP_SERVER_NAME,
|
|
9
|
+
DEFAULT_MCP_SERVER_VERSION,
|
|
10
|
+
} from "@zuplo/mcp/server";
|
|
11
|
+
import type { OpenAPIV3_1 } from "openapi-types";
|
|
12
|
+
import type { ProcessorArg } from "../config/validators/BuildSchema.js";
|
|
13
|
+
import { traverse, traverseAsync } from "../lib/util/traverse.js";
|
|
14
|
+
import type { RecordAny } from "../lib/util/types.js";
|
|
15
|
+
import { operations } from "./enrich-with-zuplo.js";
|
|
16
|
+
|
|
17
|
+
// extracts x-mcp-server metadata from the operation using x-zuplo-mcp-tool
|
|
18
|
+
// as a first class citizen.
|
|
19
|
+
const extractOperationSchema = (
|
|
20
|
+
operation: OpenAPIV3_1.OperationObject & RecordAny,
|
|
21
|
+
): ExtensionMcpServerTool | null => {
|
|
22
|
+
if (!operation.operationId) return null;
|
|
23
|
+
|
|
24
|
+
// Check if tool is explicitly disabled
|
|
25
|
+
const mcpToolConfig = operation["x-zuplo-mcp-tool"];
|
|
26
|
+
if (mcpToolConfig?.enabled === false) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const tool: ExtensionMcpServerTool = {
|
|
31
|
+
// Use custom name from x-zuplo-mcp-tool or fallback to operationId
|
|
32
|
+
name: mcpToolConfig?.name || operation.operationId,
|
|
33
|
+
|
|
34
|
+
// Use custom description from x-zuplo-mcp-tool or fallback
|
|
35
|
+
// to operation description
|
|
36
|
+
description:
|
|
37
|
+
mcpToolConfig?.description ||
|
|
38
|
+
operation.summary ||
|
|
39
|
+
operation.description ||
|
|
40
|
+
`Operation ${operation.operationId}`,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Grab valid request body JSON schema for the tool
|
|
44
|
+
const requestBody = operation.requestBody as
|
|
45
|
+
| OpenAPIV3_1.RequestBodyObject
|
|
46
|
+
| undefined;
|
|
47
|
+
|
|
48
|
+
const schema = requestBody?.content?.["application/json"]?.schema;
|
|
49
|
+
if (schema && typeof schema === "object") {
|
|
50
|
+
// TODO: @jpmcb - Zuplo also supports in-path parameters and query parameters
|
|
51
|
+
// as MCP "inputSchema" arguments. In order to document full argument params,
|
|
52
|
+
// Zudoku will need to more intelligently parse these elements of an operation.
|
|
53
|
+
tool.inputSchema = { body: schema };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return tool;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Builds a lookup map of operationId -> operation for efficient access
|
|
60
|
+
const buildOperationLookup = (
|
|
61
|
+
document: OpenAPIV3_1.Document,
|
|
62
|
+
): Map<string, OpenAPIV3_1.OperationObject> => {
|
|
63
|
+
const operationMap = new Map<string, OpenAPIV3_1.OperationObject>();
|
|
64
|
+
|
|
65
|
+
traverse(document, (node, path) => {
|
|
66
|
+
// Check if we're at a path item level (paths -> /some/path -> method)
|
|
67
|
+
// and validate it's in allowed operations
|
|
68
|
+
if (
|
|
69
|
+
!path ||
|
|
70
|
+
path.length < 2 ||
|
|
71
|
+
path[0] !== "paths" ||
|
|
72
|
+
!operations.includes(path[path.length - 1] as string)
|
|
73
|
+
) {
|
|
74
|
+
return node;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (node.operationId) {
|
|
78
|
+
operationMap.set(node.operationId, node);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return node;
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
return operationMap;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Takes an OpenAPI document and returns the x-mcp-server tools list defined
|
|
88
|
+
// by an MCP server's options.files[x].operationIds array.
|
|
89
|
+
const findOperationsInDocument = (
|
|
90
|
+
document: OpenAPIV3_1.Document,
|
|
91
|
+
operationIds: string[],
|
|
92
|
+
): ExtensionMcpServerTool[] => {
|
|
93
|
+
const tools: ExtensionMcpServerTool[] = [];
|
|
94
|
+
const operationLookup = buildOperationLookup(document);
|
|
95
|
+
|
|
96
|
+
operationIds.forEach((operationId) => {
|
|
97
|
+
const operation = operationLookup.get(operationId);
|
|
98
|
+
if (operation) {
|
|
99
|
+
const tool = extractOperationSchema(operation);
|
|
100
|
+
if (tool) {
|
|
101
|
+
tools.push(tool);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return tools;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// Enriches an OpenAPI schema with x-mcp-server data based on the Zuplo MCP server handler
|
|
110
|
+
export const enrichWithZuploMcpServerData = ({
|
|
111
|
+
rootDir,
|
|
112
|
+
}: {
|
|
113
|
+
rootDir: string;
|
|
114
|
+
}) => {
|
|
115
|
+
return async ({ schema }: ProcessorArg) => {
|
|
116
|
+
if (!schema.paths) return schema;
|
|
117
|
+
const modifiedSchema = { ...schema };
|
|
118
|
+
if (!modifiedSchema?.paths) return modifiedSchema;
|
|
119
|
+
|
|
120
|
+
await traverseAsync(modifiedSchema, async (node, nodePath) => {
|
|
121
|
+
// Check if we're at a "post" operation (paths -> /some/path -> "post").
|
|
122
|
+
// HTTP MCP servers are only allow post operations.
|
|
123
|
+
if (!nodePath || nodePath.length !== 3 || nodePath[2] !== "post") {
|
|
124
|
+
return node;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const operation = node as RecordAny;
|
|
128
|
+
if (!operation?.["x-zuplo-route"]) return node;
|
|
129
|
+
|
|
130
|
+
const handler = operation["x-zuplo-route"]?.handler;
|
|
131
|
+
if (handler?.export !== "mcpServerHandler" || !handler.options?.files)
|
|
132
|
+
return node;
|
|
133
|
+
|
|
134
|
+
const tools: ExtensionMcpServerTool[] = [];
|
|
135
|
+
|
|
136
|
+
for (const fileConfig of handler.options.files) {
|
|
137
|
+
if (!fileConfig.path || !fileConfig.operationIds) continue;
|
|
138
|
+
|
|
139
|
+
const resolvedPath = path.resolve(rootDir, "../", fileConfig.path);
|
|
140
|
+
const fileContent = await fs.readFile(resolvedPath, "utf-8");
|
|
141
|
+
const document = JSON.parse(fileContent);
|
|
142
|
+
|
|
143
|
+
if (document) {
|
|
144
|
+
const fileTools = findOperationsInDocument(
|
|
145
|
+
document,
|
|
146
|
+
fileConfig.operationIds,
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
tools.push(...fileTools);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const mcpExtension: ExtensionMcpServer = {
|
|
154
|
+
name: DEFAULT_MCP_SERVER_NAME,
|
|
155
|
+
version: DEFAULT_MCP_SERVER_VERSION,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
if (tools.length > 0) {
|
|
159
|
+
mcpExtension.tools = tools;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
node["x-mcp-server"] = mcpExtension;
|
|
163
|
+
return node;
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
return modifiedSchema;
|
|
167
|
+
};
|
|
168
|
+
};
|