zudoku 0.3.0-dev.2 → 0.3.0-dev.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/dist/app/App.js +11 -8
  2. package/dist/app/App.js.map +1 -1
  3. package/dist/config/config.d.ts +8 -15
  4. package/dist/lib/authentication/authentication.d.ts +2 -2
  5. package/dist/lib/authentication/hook.d.ts +1 -0
  6. package/dist/lib/authentication/hook.js +1 -0
  7. package/dist/lib/authentication/hook.js.map +1 -1
  8. package/dist/lib/authentication/providers/auth0.js +1 -0
  9. package/dist/lib/authentication/providers/auth0.js.map +1 -1
  10. package/dist/lib/authentication/providers/clerk.js +2 -0
  11. package/dist/lib/authentication/providers/clerk.js.map +1 -1
  12. package/dist/lib/authentication/providers/openid.js +2 -0
  13. package/dist/lib/authentication/providers/openid.js.map +1 -1
  14. package/dist/lib/authentication/state.d.ts +1 -0
  15. package/dist/lib/authentication/state.js +1 -0
  16. package/dist/lib/authentication/state.js.map +1 -1
  17. package/dist/lib/components/DevPortal.d.ts +2 -20
  18. package/dist/lib/components/DevPortal.js +13 -9
  19. package/dist/lib/components/DevPortal.js.map +1 -1
  20. package/dist/lib/components/Header.js +4 -4
  21. package/dist/lib/components/Header.js.map +1 -1
  22. package/dist/lib/components/Heading.d.ts +9 -4
  23. package/dist/lib/components/Heading.js +17 -2
  24. package/dist/lib/components/Heading.js.map +1 -1
  25. package/dist/lib/components/Layout.js +1 -1
  26. package/dist/lib/components/Layout.js.map +1 -1
  27. package/dist/lib/components/SyntaxHighlight.js +5 -1
  28. package/dist/lib/components/SyntaxHighlight.js.map +1 -1
  29. package/dist/lib/components/context/DevPortalProvider.d.ts +1 -1
  30. package/dist/lib/components/context/DevPortalProvider.js +2 -2
  31. package/dist/lib/components/context/DevPortalProvider.js.map +1 -1
  32. package/dist/lib/components/index.d.ts +2 -0
  33. package/dist/lib/components/index.js +2 -0
  34. package/dist/lib/components/index.js.map +1 -1
  35. package/dist/lib/core/DevPortalContext.d.ts +33 -3
  36. package/dist/lib/core/DevPortalContext.js +8 -4
  37. package/dist/lib/core/DevPortalContext.js.map +1 -1
  38. package/dist/lib/core/plugins.d.ts +7 -4
  39. package/dist/lib/core/plugins.js +1 -0
  40. package/dist/lib/core/plugins.js.map +1 -1
  41. package/dist/lib/oas/graphql/index.js +1 -1
  42. package/dist/lib/oas/graphql/index.js.map +1 -1
  43. package/dist/lib/oas/parser/index.js +3 -1
  44. package/dist/lib/oas/parser/index.js.map +1 -1
  45. package/dist/lib/plugins/api-keys/CreateApiKey.d.ts +4 -0
  46. package/dist/lib/plugins/{api-key → api-keys}/CreateApiKey.js +1 -1
  47. package/dist/lib/plugins/api-keys/CreateApiKey.js.map +1 -0
  48. package/dist/lib/plugins/api-keys/SettingsApiKeys.d.ts +4 -0
  49. package/dist/lib/plugins/api-keys/SettingsApiKeys.js +38 -0
  50. package/dist/lib/plugins/api-keys/SettingsApiKeys.js.map +1 -0
  51. package/dist/lib/plugins/api-keys/index.js +94 -0
  52. package/dist/lib/plugins/api-keys/index.js.map +1 -0
  53. package/dist/lib/plugins/markdown/MdxPage.d.ts +3 -2
  54. package/dist/lib/plugins/markdown/MdxPage.js +5 -4
  55. package/dist/lib/plugins/markdown/MdxPage.js.map +1 -1
  56. package/dist/lib/plugins/markdown/generateRoutes.d.ts +2 -2
  57. package/dist/lib/plugins/markdown/generateRoutes.js +2 -2
  58. package/dist/lib/plugins/markdown/generateRoutes.js.map +1 -1
  59. package/dist/lib/plugins/markdown/index.d.ts +4 -1
  60. package/dist/lib/plugins/markdown/index.js +2 -2
  61. package/dist/lib/plugins/markdown/index.js.map +1 -1
  62. package/dist/lib/plugins/openapi/OperationList.js +4 -3
  63. package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
  64. package/dist/lib/plugins/openapi/OperationListItem.js +8 -4
  65. package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
  66. package/dist/lib/plugins/openapi/ParameterList.js +1 -1
  67. package/dist/lib/plugins/openapi/ParameterList.js.map +1 -1
  68. package/dist/lib/plugins/openapi/ParameterListItem.js +1 -1
  69. package/dist/lib/plugins/openapi/ParameterListItem.js.map +1 -1
  70. package/dist/lib/plugins/openapi/{MakeRequest.d.ts → PlaygroundDialogWrapper.d.ts} +1 -1
  71. package/dist/lib/plugins/openapi/{MakeRequest.js → PlaygroundDialogWrapper.js} +4 -4
  72. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js.map +1 -0
  73. package/dist/lib/plugins/openapi/RequestBodySidecarBox.js +1 -9
  74. package/dist/lib/plugins/openapi/RequestBodySidecarBox.js.map +1 -1
  75. package/dist/lib/plugins/openapi/ResponsesSidecarBox.js +1 -1
  76. package/dist/lib/plugins/openapi/ResponsesSidecarBox.js.map +1 -1
  77. package/dist/lib/plugins/openapi/SchemaListView.js +4 -26
  78. package/dist/lib/plugins/openapi/SchemaListView.js.map +1 -1
  79. package/dist/lib/plugins/openapi/SchemaListViewItem.d.ts +7 -0
  80. package/dist/lib/plugins/openapi/SchemaListViewItem.js +16 -0
  81. package/dist/lib/plugins/openapi/SchemaListViewItem.js.map +1 -0
  82. package/dist/lib/plugins/openapi/SchemaListViewItemGroup.d.ts +8 -0
  83. package/dist/lib/plugins/openapi/SchemaListViewItemGroup.js +17 -0
  84. package/dist/lib/plugins/openapi/SchemaListViewItemGroup.js.map +1 -0
  85. package/dist/lib/plugins/openapi/Sidecar.js +10 -8
  86. package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
  87. package/dist/lib/plugins/openapi/{Select.d.ts → SimpleSelect.d.ts} +3 -2
  88. package/dist/lib/plugins/openapi/SimpleSelect.js +5 -0
  89. package/dist/lib/plugins/openapi/SimpleSelect.js.map +1 -0
  90. package/dist/lib/plugins/openapi/index.js +8 -0
  91. package/dist/lib/plugins/openapi/index.js.map +1 -1
  92. package/dist/lib/plugins/openapi/playground/Headers.d.ts +2 -3
  93. package/dist/lib/plugins/openapi/playground/Headers.js +16 -6
  94. package/dist/lib/plugins/openapi/playground/Headers.js.map +1 -1
  95. package/dist/lib/plugins/openapi/playground/Playground.d.ts +4 -3
  96. package/dist/lib/plugins/openapi/playground/Playground.js +8 -12
  97. package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
  98. package/dist/lib/plugins/openapi/playground/PlaygroundDialog.d.ts +3 -0
  99. package/dist/lib/plugins/openapi/playground/PlaygroundDialog.js +10 -0
  100. package/dist/lib/plugins/openapi/playground/PlaygroundDialog.js.map +1 -0
  101. package/dist/lib/plugins/openapi/util/prose.d.ts +1 -0
  102. package/dist/lib/plugins/openapi/util/prose.js +4 -0
  103. package/dist/lib/plugins/openapi/util/prose.js.map +1 -0
  104. package/dist/lib/plugins/openapi/worker/worker.js +25 -1
  105. package/dist/lib/plugins/openapi/worker/worker.js.map +1 -1
  106. package/dist/lib/ui/button-variants.d.ts +1 -1
  107. package/dist/lib/util/MdxComponents.js +1 -1
  108. package/dist/lib/util/MdxComponents.js.map +1 -1
  109. package/dist/lib/util/objectEntries.d.ts +4 -0
  110. package/dist/lib/util/objectEntries.js +2 -0
  111. package/dist/lib/util/objectEntries.js.map +1 -0
  112. package/dist/lib/util/renderIf.d.ts +1 -0
  113. package/dist/lib/util/renderIf.js +2 -0
  114. package/dist/lib/util/renderIf.js.map +1 -0
  115. package/dist/vite/build.js +4 -1
  116. package/dist/vite/build.js.map +1 -1
  117. package/dist/vite/config.d.ts +7 -7
  118. package/dist/vite/config.js +34 -40
  119. package/dist/vite/config.js.map +1 -1
  120. package/dist/vite/config.test.js +7 -4
  121. package/dist/vite/config.test.js.map +1 -1
  122. package/dist/vite/dev-server.js +4 -4
  123. package/dist/vite/dev-server.js.map +1 -1
  124. package/dist/vite/plugin-api-keys.js +4 -4
  125. package/dist/vite/plugin-api-keys.js.map +1 -1
  126. package/dist/vite/plugin-api.js +5 -5
  127. package/dist/vite/plugin-api.js.map +1 -1
  128. package/dist/vite/plugin-auth.js +2 -2
  129. package/dist/vite/plugin-auth.js.map +1 -1
  130. package/dist/vite/plugin-config.d.ts +1 -1
  131. package/dist/vite/plugin-config.js +7 -6
  132. package/dist/vite/plugin-config.js.map +1 -1
  133. package/dist/vite/plugin-docs.js +2 -2
  134. package/dist/vite/plugin-docs.js.map +1 -1
  135. package/dist/vite/plugin-docs.test.js +1 -1
  136. package/dist/vite/plugin-docs.test.js.map +1 -1
  137. package/dist/vite/plugin-redirect.js +4 -4
  138. package/dist/vite/plugin-redirect.js.map +1 -1
  139. package/lib/DevPortalProvider-CRKuwoXc.js +4123 -0
  140. package/lib/Markdown-5LmPZyLV.js +8620 -0
  141. package/lib/MdxComponents-DYD_QPVF.js +3017 -0
  142. package/lib/Select-DR3PiqjV.js +4569 -0
  143. package/lib/Spinner-DjQ2eBxC.js +181 -0
  144. package/lib/assets/{worker-BCcpCNJ7.js → worker-DGvzLstc.js} +9843 -9800
  145. package/lib/hook-FCY9-FHO.js +24 -0
  146. package/lib/index-By9bEW57.js +411 -0
  147. package/lib/{index-DNx3xWa2.js → index-PyGcnQFX.js} +13 -12
  148. package/lib/loglevel-CA34MiFn.js +152 -0
  149. package/lib/prism-csharp.min-Yizuc34Y.js +34 -0
  150. package/lib/prism-objectivec.min-BXSWqpJJ.js +1 -0
  151. package/lib/{state-oycsxkHz.js → state-Ds_OxRHP.js} +19 -18
  152. package/lib/util-voKLTRDG.js +740 -0
  153. package/lib/zudoku.auth-auth0.js +2 -1
  154. package/lib/zudoku.auth-clerk.js +10 -8
  155. package/lib/zudoku.auth-openid.js +442 -588
  156. package/lib/zudoku.components.js +283 -292
  157. package/lib/zudoku.openapi-worker.js +12 -12
  158. package/lib/zudoku.plugin-api-keys.js +292 -0
  159. package/lib/zudoku.plugin-markdown.js +255 -0
  160. package/lib/zudoku.plugin-openapi.js +6240 -0
  161. package/lib/zudoku.plugin-redirect.js +10 -0
  162. package/package.json +17 -5
  163. package/src/app/App.tsx +12 -8
  164. package/src/lib/authentication/authentication.ts +2 -5
  165. package/src/lib/authentication/hook.ts +1 -0
  166. package/src/lib/authentication/providers/auth0.tsx +1 -0
  167. package/src/lib/authentication/providers/clerk.tsx +2 -0
  168. package/src/lib/authentication/providers/openid.tsx +2 -0
  169. package/src/lib/authentication/state.ts +2 -0
  170. package/src/lib/components/DevPortal.tsx +12 -28
  171. package/src/lib/components/Header.tsx +25 -22
  172. package/src/lib/components/Heading.tsx +26 -7
  173. package/src/lib/components/Layout.tsx +2 -2
  174. package/src/lib/components/SyntaxHighlight.tsx +5 -1
  175. package/src/lib/components/context/DevPortalProvider.ts +2 -2
  176. package/src/lib/components/index.ts +3 -0
  177. package/src/lib/core/DevPortalContext.ts +42 -12
  178. package/src/lib/core/plugins.ts +10 -5
  179. package/src/lib/oas/graphql/index.ts +2 -2
  180. package/src/lib/oas/parser/index.ts +3 -1
  181. package/src/lib/plugins/{api-key → api-keys}/CreateApiKey.tsx +2 -8
  182. package/src/lib/plugins/{api-key → api-keys}/SettingsApiKeys.tsx +21 -14
  183. package/src/lib/plugins/{api-key → api-keys}/index.tsx +67 -18
  184. package/src/lib/plugins/markdown/MdxPage.tsx +50 -33
  185. package/src/lib/plugins/markdown/generateRoutes.tsx +12 -2
  186. package/src/lib/plugins/markdown/index.tsx +8 -1
  187. package/src/lib/plugins/openapi/OperationList.tsx +9 -3
  188. package/src/lib/plugins/openapi/OperationListItem.tsx +66 -41
  189. package/src/lib/plugins/openapi/ParameterList.tsx +1 -1
  190. package/src/lib/plugins/openapi/ParameterListItem.tsx +3 -4
  191. package/src/lib/plugins/openapi/{MakeRequest.tsx → PlaygroundDialogWrapper.tsx} +3 -3
  192. package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +2 -16
  193. package/src/lib/plugins/openapi/ResponsesSidecarBox.tsx +3 -1
  194. package/src/lib/plugins/openapi/SchemaListView.tsx +15 -182
  195. package/src/lib/plugins/openapi/SchemaListViewItem.tsx +110 -0
  196. package/src/lib/plugins/openapi/SchemaListViewItemGroup.tsx +63 -0
  197. package/src/lib/plugins/openapi/Sidecar.tsx +15 -10
  198. package/src/lib/plugins/openapi/{Select.tsx → SimpleSelect.tsx} +5 -2
  199. package/src/lib/plugins/openapi/index.tsx +17 -4
  200. package/src/lib/plugins/openapi/playground/Headers.tsx +60 -33
  201. package/src/lib/plugins/openapi/playground/Playground.tsx +158 -193
  202. package/src/lib/plugins/openapi/playground/PlaygroundDialog.tsx +34 -0
  203. package/src/lib/plugins/openapi/util/prose.ts +7 -0
  204. package/src/lib/plugins/openapi/worker/worker.ts +27 -1
  205. package/src/lib/util/MdxComponents.tsx +1 -1
  206. package/src/lib/util/objectEntries.ts +5 -0
  207. package/src/lib/util/renderIf.ts +4 -0
  208. package/dist/lib/plugins/api-key/CreateApiKey.d.ts +0 -5
  209. package/dist/lib/plugins/api-key/CreateApiKey.js.map +0 -1
  210. package/dist/lib/plugins/api-key/SettingsApiKeys.d.ts +0 -5
  211. package/dist/lib/plugins/api-key/SettingsApiKeys.js +0 -38
  212. package/dist/lib/plugins/api-key/SettingsApiKeys.js.map +0 -1
  213. package/dist/lib/plugins/api-key/index.js +0 -62
  214. package/dist/lib/plugins/api-key/index.js.map +0 -1
  215. package/dist/lib/plugins/index.d.ts +0 -4
  216. package/dist/lib/plugins/index.js +0 -5
  217. package/dist/lib/plugins/index.js.map +0 -1
  218. package/dist/lib/plugins/openapi/MakeRequest.js.map +0 -1
  219. package/dist/lib/plugins/openapi/Select.js +0 -5
  220. package/dist/lib/plugins/openapi/Select.js.map +0 -1
  221. package/dist/vite/common.d.ts +0 -1
  222. package/dist/vite/common.js +0 -5
  223. package/dist/vite/common.js.map +0 -1
  224. package/lib/Spinner-7LezPqGn.js +0 -8393
  225. package/lib/clerk-Wslx_mPo.js +0 -19685
  226. package/lib/zudoku.plugins.js +0 -19857
  227. package/src/lib/plugins/index.ts +0 -4
  228. /package/dist/lib/plugins/{api-key → api-keys}/index.d.ts +0 -0
@@ -52,7 +52,9 @@ export const ResponsesSidecarBox = ({
52
52
  </span>
53
53
  )}
54
54
  <hr className="border-border my-1" />
55
- <div className="text-xs">{responses[tabIndex].description}</div>
55
+ <div className="text-xs text-muted-foreground">
56
+ {responses[tabIndex].description}
57
+ </div>
56
58
  </SidecarBox.Body>
57
59
  </SidecarBox.Root>
58
60
  );
@@ -1,10 +1,8 @@
1
- import * as Collapsible from "@radix-ui/react-collapsible";
2
- import { ListPlusIcon } from "lucide-react";
3
- import { useState } from "react";
4
1
  import { Markdown } from "../../components/Markdown.js";
5
2
  import { SchemaObject } from "../../oas/parser/index.js";
6
- import { Button } from "../../ui/Button.js";
7
- import { cn } from "../../util/cn.js";
3
+ import { objectEntries } from "../../util/objectEntries.js";
4
+ import { SchemaListViewItemGroup } from "./SchemaListViewItemGroup.js";
5
+ import { SchemaProseClasses } from "./util/prose.js";
8
6
 
9
7
  export const SchemaListView = ({
10
8
  name,
@@ -39,190 +37,25 @@ export const SchemaListView = ({
39
37
  );
40
38
 
41
39
  return (
42
- <div
43
- className={cn(
44
- "not-prose",
45
- level > 0 && "border border-border rounded text-sm",
46
- )}
47
- >
40
+ <div className="flex flex-col gap-2.5">
48
41
  {(schema.title ?? name) && (
49
42
  <div className="ml-2 my-1 font-bold">{schema.title ?? name}</div>
50
43
  )}
51
44
  {level === 0 && schema.description && (
52
- <p className="prose">{schema.description}</p>
53
- )}
54
- <ul>
55
- {Object.entries(groups).map(([group, properties]) => {
56
- return (
57
- <SchemaListViewItemGroup
58
- key={group}
59
- defaultOpen={defaultOpen}
60
- group={group as any}
61
- nestingLevel={level}
62
- properties={properties}
63
- required={schema.required ?? []}
64
- />
65
- );
66
- })}
67
- </ul>
68
- </div>
69
- );
70
- };
71
-
72
- const SchemaListViewItemGroup = ({
73
- group,
74
- properties,
75
- nestingLevel,
76
- required,
77
- defaultOpen = false,
78
- }: {
79
- group: "optional" | "required" | "deprecated";
80
- defaultOpen?: boolean;
81
- properties: [string, SchemaObject][];
82
- nestingLevel: number;
83
- required: string[];
84
- }) => {
85
- const notCollapsible =
86
- defaultOpen ||
87
- group === "required" ||
88
- properties.length === 1 ||
89
- nestingLevel === 0;
90
- const [open, setOpen] = useState(notCollapsible);
91
- if (properties.length === 0) {
92
- return;
93
- }
94
-
95
- return (
96
- <Collapsible.Root
97
- className="CollapsibleRoot"
98
- open={open}
99
- onOpenChange={setOpen}
100
- >
101
- {!open && (
102
- <Collapsible.Trigger
103
- className={cn(
104
- "py-2 hover:bg-muted w-full",
105
- group === "optional" && "font-semibold",
106
- group === "deprecated" && "text-muted-foreground",
107
- )}
108
- >
109
- {properties.length} {group} fields
110
- </Collapsible.Trigger>
45
+ <Markdown className={SchemaProseClasses} content={schema.description} />
111
46
  )}
112
-
113
- <Collapsible.Content>
114
- {properties.map(([propertyName, property]) => (
115
- <SchemaListViewItem
116
- key={propertyName}
117
- property={property}
118
- propertyName={propertyName}
119
- nestingLevel={nestingLevel}
120
- isRequired={required.includes(propertyName)}
47
+ <ul className="border-border border rounded overflow-hidden">
48
+ {objectEntries(groups).map(([group, properties]) => (
49
+ <SchemaListViewItemGroup
50
+ key={group}
51
+ defaultOpen={defaultOpen}
52
+ group={group}
53
+ nestingLevel={level}
54
+ properties={properties ?? []}
55
+ required={schema.required ?? []}
121
56
  />
122
57
  ))}
123
- </Collapsible.Content>
124
- </Collapsible.Root>
125
- );
126
- };
127
-
128
- const SchemaListViewItem = ({
129
- propertyName,
130
- property,
131
- nestingLevel,
132
- isRequired,
133
- }: {
134
- propertyName: string;
135
- isRequired: boolean;
136
- property: SchemaObject;
137
- nestingLevel: number;
138
- }) => {
139
- return (
140
- <div
141
- key={propertyName}
142
- className={cn(
143
- nestingLevel > 0 ? "py-2" : "py-4",
144
- "px-2 border-t border-border bg-border/20 hover:bg-border/30 flex gap-1 flex-col text-sm",
145
- property.deprecated && "opacity-50",
146
- )}
147
- >
148
- <div className="flex items-center gap-2 relative">
149
- <code>
150
- {propertyName} {property.title}
151
- </code>
152
-
153
- {property.type && (
154
- <span className="text-xs text-muted-foreground">{property.type}</span>
155
- )}
156
- {property.deprecated && (
157
- <span className="text-xs text-muted-foreground">Deprecated</span>
158
- )}
159
- {!isRequired && (
160
- <span className="py-px px-1.5 font-medium text-xs border border-border rounded-lg">
161
- optional {property.required}
162
- </span>
163
- )}
164
- </div>
165
- {property.description && (
166
- <Markdown
167
- content={property.description}
168
- className="text-sm leading-normal line-clamp-4 "
169
- />
170
- )}
171
-
172
- {property.enum && (
173
- <span className="text-sm text-muted-foreground flex gap-1 flex-wrap items-center">
174
- <span>Possible values</span>
175
- {property.enum
176
- .filter((value) => value)
177
- .map((value) => (
178
- <span
179
- key={value}
180
- className="font-mono text-xs border-border border bg-muted rounded px-1"
181
- >
182
- {value}
183
- </span>
184
- ))
185
- .slice(0, 4)}
186
- {property.enum.length > 4 && (
187
- <span className="font-mono text-xs border-border border bg-muted rounded px-1">
188
- ...
189
- </span>
190
- )}
191
- </span>
192
- )}
193
-
194
- <Collapsible.Root className="CollapsibleRoot" defaultOpen={false}>
195
- {property.type === "object" ||
196
- (property.type === "array" && property.items.type === "object") ? (
197
- <Collapsible.Trigger asChild>
198
- <Button variant="ghost" size="sm">
199
- Show nested fields
200
- <ListPlusIcon size={18} className="ml-1.5" />
201
- </Button>
202
- </Collapsible.Trigger>
203
- ) : null}
204
-
205
- <Collapsible.Content>
206
- {property.type === "object" && (
207
- <div className="mt-2.5">
208
- <SchemaListView
209
- schema={property}
210
- level={nestingLevel + 1}
211
- defaultOpen
212
- />
213
- </div>
214
- )}
215
- {property.type === "array" && property.items.type === "object" && (
216
- <div className="mt-2.5">
217
- <SchemaListView
218
- schema={property.items}
219
- defaultOpen
220
- level={nestingLevel + 1}
221
- />
222
- </div>
223
- )}
224
- </Collapsible.Content>
225
- </Collapsible.Root>
58
+ </ul>
226
59
  </div>
227
60
  );
228
61
  };
@@ -0,0 +1,110 @@
1
+ import * as Collapsible from "@radix-ui/react-collapsible";
2
+ import { ListPlusIcon } from "lucide-react";
3
+ import { Markdown } from "../../components/Markdown.js";
4
+ import { SchemaObject } from "../../oas/parser/index.js";
5
+ import { Button } from "../../ui/Button.js";
6
+ import { cn } from "../../util/cn.js";
7
+ import { SchemaListView } from "./SchemaListView.js";
8
+
9
+ export const SchemaListViewItem = ({
10
+ propertyName,
11
+ property,
12
+ nestingLevel,
13
+ isRequired,
14
+ }: {
15
+ propertyName: string;
16
+ isRequired: boolean;
17
+ property: SchemaObject;
18
+ nestingLevel: number;
19
+ }) => {
20
+ return (
21
+ <div
22
+ key={propertyName}
23
+ className={cn(
24
+ "p-4 bg-border/20 hover:bg-border/30 flex gap-1 flex-col text-sm",
25
+ property.deprecated && "opacity-50",
26
+ )}
27
+ >
28
+ <div className="flex items-center gap-2 relative">
29
+ <code>
30
+ {propertyName} {property.title}
31
+ </code>
32
+
33
+ {property.type && (
34
+ <span className="text-muted-foreground">{property.type}</span>
35
+ )}
36
+ {property.deprecated && (
37
+ <span className="text-muted-foreground">Deprecated</span>
38
+ )}
39
+ {!isRequired && (
40
+ <span className="py-px px-1.5 font-medium border border-border rounded-lg">
41
+ optional {property.required}
42
+ </span>
43
+ )}
44
+ </div>
45
+ {property.description && (
46
+ <Markdown
47
+ content={property.description}
48
+ className="text-sm leading-normal line-clamp-4 "
49
+ />
50
+ )}
51
+
52
+ {property.enum && (
53
+ <span className="text-sm text-muted-foreground flex gap-1 flex-wrap items-center">
54
+ <span>Possible values</span>
55
+ {/* Make values unique, some schemas have duplicates */}
56
+ {[...new Set(property.enum.filter((value) => value))]
57
+ .map((value) => (
58
+ <span
59
+ key={value}
60
+ className="font-mono text-xs border-border border bg-muted rounded px-1"
61
+ >
62
+ {value}
63
+ </span>
64
+ ))
65
+ .slice(0, 4)}
66
+ {property.enum.length > 4 && (
67
+ <span className="font-mono text-xs border-border border bg-muted rounded px-1">
68
+ ...
69
+ </span>
70
+ )}
71
+ </span>
72
+ )}
73
+
74
+ {(property.type === "object" &&
75
+ (property.properties?.length ??
76
+ Object.entries(property.additionalProperties ?? {}).length > 0)) ||
77
+ (property.type === "array" && property.items.type === "object") ? (
78
+ <Collapsible.Root className="CollapsibleRoot" defaultOpen={false}>
79
+ <Collapsible.Trigger asChild>
80
+ <Button variant="ghost" size="sm">
81
+ Show nested fields
82
+ <ListPlusIcon size={18} className="ml-1.5" />
83
+ </Button>
84
+ </Collapsible.Trigger>
85
+
86
+ <Collapsible.Content>
87
+ {property.type === "object" && (
88
+ <div className="mt-2.5">
89
+ <SchemaListView
90
+ schema={property}
91
+ level={nestingLevel + 1}
92
+ defaultOpen
93
+ />
94
+ </div>
95
+ )}
96
+ {property.type === "array" && property.items.type === "object" && (
97
+ <div className="mt-2.5">
98
+ <SchemaListView
99
+ schema={property.items}
100
+ defaultOpen
101
+ level={nestingLevel + 1}
102
+ />
103
+ </div>
104
+ )}
105
+ </Collapsible.Content>
106
+ </Collapsible.Root>
107
+ ) : null}
108
+ </div>
109
+ );
110
+ };
@@ -0,0 +1,63 @@
1
+ import * as Collapsible from "@radix-ui/react-collapsible";
2
+ import { useState } from "react";
3
+ import { SchemaObject } from "../../oas/parser/index.js";
4
+ import { cn } from "../../util/cn.js";
5
+ import { SchemaListViewItem } from "./SchemaListViewItem.js";
6
+
7
+ export const SchemaListViewItemGroup = ({
8
+ group,
9
+ properties,
10
+ nestingLevel,
11
+ required,
12
+ defaultOpen = false,
13
+ }: {
14
+ group: "optional" | "required" | "deprecated";
15
+ defaultOpen?: boolean;
16
+ properties: [string, SchemaObject][];
17
+ nestingLevel: number;
18
+ required: string[];
19
+ }) => {
20
+ const notCollapsible =
21
+ defaultOpen ||
22
+ group === "required" ||
23
+ properties.length === 1 ||
24
+ nestingLevel === 0;
25
+
26
+ const [open, setOpen] = useState(notCollapsible);
27
+
28
+ if (properties.length === 0) {
29
+ return;
30
+ }
31
+
32
+ return (
33
+ <Collapsible.Root
34
+ className="CollapsibleRoot"
35
+ open={open}
36
+ onOpenChange={setOpen}
37
+ >
38
+ {!open && (
39
+ <Collapsible.Trigger
40
+ className={cn(
41
+ "py-2 hover:bg-muted w-full",
42
+ group === "optional" && "font-semibold",
43
+ group === "deprecated" && "text-muted-foreground",
44
+ )}
45
+ >
46
+ {properties.length} {group} fields
47
+ </Collapsible.Trigger>
48
+ )}
49
+
50
+ <Collapsible.Content className="divide-y divide-border">
51
+ {properties.map(([propertyName, property]) => (
52
+ <SchemaListViewItem
53
+ key={propertyName}
54
+ property={property}
55
+ propertyName={propertyName}
56
+ nestingLevel={nestingLevel}
57
+ isRequired={required.includes(propertyName)}
58
+ />
59
+ ))}
60
+ </Collapsible.Content>
61
+ </Collapsible.Root>
62
+ );
63
+ };
@@ -1,16 +1,17 @@
1
1
  import { HTTPSnippet } from "@zudoku/httpsnippet";
2
- import { Fragment, useMemo, useState } from "react";
2
+ import { Fragment, useMemo } from "react";
3
+ import { useSearchParams } from "react-router-dom";
3
4
  import { SyntaxHighlight } from "../../components/SyntaxHighlight.js";
4
5
  import type { SchemaObject } from "../../oas/parser/index.js";
5
6
  import { cn } from "../../util/cn.js";
6
7
  import { ColorizedParam } from "./ColorizedParam.js";
7
- import { MakeRequest } from "./MakeRequest.js";
8
8
  import { MethodTextColorMap } from "./MethodBadge.js";
9
9
  import type { OperationListItemResult } from "./OperationList.js";
10
+ import { PlaygroundDialogWrapper } from "./PlaygroundDialogWrapper.js";
10
11
  import { RequestBodySidecarBox } from "./RequestBodySidecarBox.js";
11
12
  import { ResponsesSidecarBox } from "./ResponsesSidecarBox.js";
12
- import { Select } from "./Select.js";
13
13
  import * as SidecarBox from "./SidecarBox.js";
14
+ import { SimpleSelect } from "./SimpleSelect.js";
14
15
  import { generateSchemaExample } from "./util/generateSchemaExample.js";
15
16
 
16
17
  const getConverted = (snippet: HTTPSnippet, option: string) => {
@@ -64,7 +65,10 @@ export const Sidecar = ({
64
65
  }) => {
65
66
  const methodTextColor =
66
67
  MethodTextColorMap[operation.method as keyof typeof MethodTextColorMap];
67
- const [option, setOption] = useState("curl");
68
+
69
+ const [searchParams, setSearchParams] = useSearchParams();
70
+ const selectedLang = searchParams.get("lang") ?? "shell";
71
+
68
72
  const requestBodyContent = operation.requestBody?.content;
69
73
 
70
74
  const path = operation.path.split("/").map((part) => (
@@ -105,8 +109,8 @@ export const Sidecar = ({
105
109
  } as never, // 👈 never touch this
106
110
  );
107
111
 
108
- return getConverted(snippet, option);
109
- }, [option, operation.method, operation.path, requestBodyContent]);
112
+ return getConverted(snippet, selectedLang);
113
+ }, [selectedLang, operation.method, operation.path, requestBodyContent]);
110
114
 
111
115
  return (
112
116
  <aside className="flex flex-col overflow-hidden sticky top-[--scroll-padding] gap-4">
@@ -120,9 +124,10 @@ export const Sidecar = ({
120
124
  {path}
121
125
  </span>
122
126
  <div className="flex gap-2 items-center">
123
- <Select
127
+ <SimpleSelect
124
128
  className="self-start"
125
- onChange={(e) => setOption(e.target.value)}
129
+ value={selectedLang}
130
+ onChange={(e) => setSearchParams({ lang: e.target.value })}
126
131
  options={[
127
132
  { value: "shell", label: "cURL" },
128
133
  { value: "js", label: "Javascript" },
@@ -137,12 +142,12 @@ export const Sidecar = ({
137
142
  { value: "swift", label: "Swift" },
138
143
  ]}
139
144
  />
140
- <MakeRequest operation={operation} />
145
+ <PlaygroundDialogWrapper operation={operation} />
141
146
  </div>
142
147
  </SidecarBox.Head>
143
148
  <SidecarBox.Body>
144
149
  <SyntaxHighlight
145
- language={option}
150
+ language={selectedLang}
146
151
  noBackground
147
152
  className="text-xs"
148
153
  code={code}
@@ -2,12 +2,14 @@ import type { ChangeEventHandler } from "react";
2
2
  import { ChevronsUpDownIcon } from "../../core/icons.js";
3
3
  import { cn } from "../../util/cn.js";
4
4
 
5
- export const Select = ({
5
+ export const SimpleSelect = ({
6
+ value,
6
7
  onChange,
7
8
  className,
8
9
  options,
9
10
  }: {
10
- onChange?: ChangeEventHandler<HTMLSelectElement>;
11
+ value: string;
12
+ onChange: ChangeEventHandler<HTMLSelectElement>;
11
13
  className?: string;
12
14
  options: {
13
15
  value: string;
@@ -20,6 +22,7 @@ export const Select = ({
20
22
  "row-start-1 col-start-1 border border-input text-foreground px-2 py-1 pe-6",
21
23
  "rounded-md appearance-none bg-zinc-50 hover:bg-white dark:bg-zinc-800 hover:dark:bg-zinc-800/75",
22
24
  )}
25
+ value={value}
23
26
  onChange={onChange}
24
27
  >
25
28
  {options.map((option) => (
@@ -15,7 +15,6 @@ import {
15
15
  } from "./util/urql.js";
16
16
 
17
17
  import { createSharedWorkerClient } from "virtual:zudoku-openapi-worker";
18
- import type { createSharedWorkerClient as createSharedWorkerClientType } from "./worker/createSharedWorkerClient.js";
19
18
 
20
19
  const OasContext = createContext<{ config: OasPluginConfig } | undefined>(
21
20
  undefined,
@@ -85,11 +84,25 @@ export const openApiPlugin = (config: OasPluginConfig): DevPortalPlugin => {
85
84
  url: config.server,
86
85
  exchanges: [cacheExchange, fetchExchange],
87
86
  })
88
- : (createSharedWorkerClient() as ReturnType<
89
- typeof createSharedWorkerClientType
90
- >);
87
+ : createSharedWorkerClient();
91
88
 
92
89
  return {
90
+ getHead: () => {
91
+ if (config.type === "url") {
92
+ return (
93
+ <link
94
+ rel="preload"
95
+ href={config.input}
96
+ as="fetch"
97
+ crossOrigin="anonymous"
98
+ />
99
+ );
100
+ }
101
+
102
+ if (config.server) {
103
+ return <link rel="preconnect" href={config.server} />;
104
+ }
105
+ },
93
106
  getNavigation: async (path: string) => {
94
107
  if (!matchPath({ path: basePath, end: false }, path)) {
95
108
  return [];
@@ -1,53 +1,80 @@
1
- import { XIcon } from "lucide-react";
2
- import { Control, useFieldArray, UseFormRegister } from "react-hook-form";
1
+ import { TriangleAlertIcon, XIcon } from "lucide-react";
2
+ import {
3
+ Control,
4
+ useFieldArray,
5
+ UseFormRegister,
6
+ useWatch,
7
+ } from "react-hook-form";
3
8
  import { Button } from "../../../ui/Button.js";
9
+ import { cn } from "../../../util/cn.js";
4
10
  import { InlineInput } from "./InlineInput.js";
5
- import type { Header, PlaygroundForm } from "./Playground.js";
11
+ import { NO_IDENTITY, type PlaygroundForm } from "./Playground.js";
6
12
 
7
13
  export const Headers = ({
8
14
  control,
9
15
  register,
10
- headers,
11
16
  }: {
12
17
  register: UseFormRegister<PlaygroundForm>;
13
18
  control: Control<PlaygroundForm>;
14
- headers: Header[];
15
19
  }) => {
16
20
  const { fields, append, remove } = useFieldArray<PlaygroundForm>({
17
21
  control,
18
22
  name: "headers",
19
23
  });
24
+ const selectedIdentity = useWatch({ name: "identity", control });
25
+ const liveHeaders = useWatch({ name: "headers", control });
26
+
27
+ const disableAuth = selectedIdentity !== NO_IDENTITY;
28
+
20
29
  return (
21
30
  <div className="grid grid-cols-[1fr_1fr_auto]">
22
- {fields.map((header, i) => (
23
- <div
24
- key={header.id}
25
- className="grid-cols-subgrid col-span-full grid items-center gap-x-2 has-[:focus]:bg-muted hover:bg-muted rounded overflow-hidden group"
26
- >
27
- <InlineInput
28
- {...register(`headers.${i}.name`)}
29
- placeholder="Name"
30
- className="peer"
31
- autoComplete="off"
32
- />
33
- <InlineInput
34
- placeholder={"Value"}
35
- className="peer"
36
- {...register(`headers.${i}.value`)}
37
- autoComplete="off"
38
- />
39
- <button
40
- className="hover:bg-black/5 p-1 rounded mr-2 text-muted-foreground invisible group-hover:visible peer-focus:visible"
41
- onClick={() => {
42
- remove(i);
43
- }}
44
- type="button"
31
+ {fields.map((header, i) => {
32
+ const isDisabledByAuth =
33
+ disableAuth && liveHeaders.at(i)?.name === "Authorization";
34
+
35
+ return (
36
+ <div
37
+ key={header.id}
38
+ className={cn(
39
+ "grid-cols-subgrid col-span-full grid items-center gap-x-2 has-[:focus]:bg-muted hover:bg-muted rounded overflow-hidden group",
40
+ isDisabledByAuth && "line-through",
41
+ )}
42
+ title={
43
+ isDisabledByAuth
44
+ ? "This header is disabled because authentication was selected"
45
+ : undefined
46
+ }
45
47
  >
46
- <XIcon size={16} />
47
- </button>
48
- <div className="col-span-full border-b border-border"></div>
49
- </div>
50
- ))}
48
+ <div className="flex gap-2 items-center">
49
+ <InlineInput
50
+ {...register(`headers.${i}.name`)}
51
+ placeholder="Name"
52
+ className="peer"
53
+ autoComplete="off"
54
+ />
55
+ {isDisabledByAuth && (
56
+ <TriangleAlertIcon size={16} className="text-amber-500" />
57
+ )}
58
+ </div>
59
+ <InlineInput
60
+ placeholder={"Value"}
61
+ className="peer"
62
+ {...register(`headers.${i}.value`)}
63
+ autoComplete="off"
64
+ />
65
+ <button
66
+ className="hover:bg-black/5 p-1 rounded mr-2 text-muted-foreground invisible group-hover:visible peer-focus:visible"
67
+ onClick={() => {
68
+ remove(i);
69
+ }}
70
+ type="button"
71
+ >
72
+ <XIcon size={16} />
73
+ </button>
74
+ <div className="col-span-full border-b border-border"></div>
75
+ </div>
76
+ );
77
+ })}
51
78
  <Button
52
79
  className="col-span-full mt-4"
53
80
  onClick={() => append({ name: "", value: "" })}