zudoku 0.37.1 → 0.39.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.
Files changed (260) hide show
  1. package/dist/app/main.js +2 -0
  2. package/dist/app/main.js.map +1 -1
  3. package/dist/app/tailwind.js +14 -0
  4. package/dist/app/tailwind.js.map +1 -1
  5. package/dist/config/validators/common.d.ts +287 -18
  6. package/dist/config/validators/common.js +2 -0
  7. package/dist/config/validators/common.js.map +1 -1
  8. package/dist/config/validators/validate.d.ts +107 -7
  9. package/dist/lib/authentication/authentication.d.ts +1 -0
  10. package/dist/lib/authentication/providers/clerk.js +19 -0
  11. package/dist/lib/authentication/providers/clerk.js.map +1 -1
  12. package/dist/lib/authentication/providers/openid.d.ts +1 -0
  13. package/dist/lib/authentication/providers/openid.js +5 -0
  14. package/dist/lib/authentication/providers/openid.js.map +1 -1
  15. package/dist/lib/authentication/providers/supabase.js +5 -0
  16. package/dist/lib/authentication/providers/supabase.js.map +1 -1
  17. package/dist/lib/authentication/state.d.ts +0 -26
  18. package/dist/lib/authentication/state.js +1 -16
  19. package/dist/lib/authentication/state.js.map +1 -1
  20. package/dist/lib/components/Heading.d.ts +1 -1
  21. package/dist/lib/components/Layout.js +5 -10
  22. package/dist/lib/components/Layout.js.map +1 -1
  23. package/dist/lib/components/Main.js +3 -1
  24. package/dist/lib/components/Main.js.map +1 -1
  25. package/dist/lib/components/Pagination.d.ts +10 -0
  26. package/dist/lib/components/Pagination.js +10 -0
  27. package/dist/lib/components/Pagination.js.map +1 -0
  28. package/dist/lib/components/TopNavigation.js +18 -2
  29. package/dist/lib/components/TopNavigation.js.map +1 -1
  30. package/dist/lib/components/navigation/SidebarItem.d.ts +1 -0
  31. package/dist/lib/components/navigation/SidebarItem.js +7 -3
  32. package/dist/lib/components/navigation/SidebarItem.js.map +1 -1
  33. package/dist/lib/{plugins/markdown → components/navigation}/Toc.js +5 -7
  34. package/dist/lib/components/navigation/Toc.js.map +1 -0
  35. package/dist/lib/core/ZudokuContext.d.ts +7 -0
  36. package/dist/lib/core/ZudokuContext.js +8 -3
  37. package/dist/lib/core/ZudokuContext.js.map +1 -1
  38. package/dist/lib/core/plugins.d.ts +1 -1
  39. package/dist/lib/oas/graphql/index.d.ts +2 -1
  40. package/dist/lib/oas/graphql/index.js +74 -14
  41. package/dist/lib/oas/graphql/index.js.map +1 -1
  42. package/dist/lib/oas/parser/dereference/index.js +2 -0
  43. package/dist/lib/oas/parser/dereference/index.js.map +1 -1
  44. package/dist/lib/oas/parser/index.d.ts +5 -3
  45. package/dist/lib/oas/parser/index.js +0 -22
  46. package/dist/lib/oas/parser/index.js.map +1 -1
  47. package/dist/lib/plugins/api-catalog/index.js +19 -17
  48. package/dist/lib/plugins/api-catalog/index.js.map +1 -1
  49. package/dist/lib/plugins/markdown/MdxPage.js +3 -9
  50. package/dist/lib/plugins/markdown/MdxPage.js.map +1 -1
  51. package/dist/lib/plugins/openapi/ColorizedParam.js +1 -1
  52. package/dist/lib/plugins/openapi/ColorizedParam.js.map +1 -1
  53. package/dist/lib/plugins/openapi/Endpoint.js +1 -1
  54. package/dist/lib/plugins/openapi/Endpoint.js.map +1 -1
  55. package/dist/lib/plugins/openapi/OperationList.d.ts +1 -1
  56. package/dist/lib/plugins/openapi/OperationList.js +29 -9
  57. package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
  58. package/dist/lib/plugins/openapi/OperationListItem.js +1 -1
  59. package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
  60. package/dist/lib/plugins/openapi/ParameterListItem.js +2 -1
  61. package/dist/lib/plugins/openapi/ParameterListItem.js.map +1 -1
  62. package/dist/lib/plugins/openapi/SchemaList.d.ts +1 -0
  63. package/dist/lib/plugins/openapi/SchemaList.js +52 -0
  64. package/dist/lib/plugins/openapi/SchemaList.js.map +1 -0
  65. package/dist/lib/plugins/openapi/Sidecar.js +29 -5
  66. package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
  67. package/dist/lib/plugins/openapi/client/GraphQLClient.d.ts +1 -1
  68. package/dist/lib/plugins/openapi/client/GraphQLClient.js +1 -1
  69. package/dist/lib/plugins/openapi/client/GraphQLClient.js.map +1 -1
  70. package/dist/lib/plugins/openapi/client/useCreateQuery.d.ts +6 -2
  71. package/dist/lib/plugins/openapi/client/useCreateQuery.js +5 -5
  72. package/dist/lib/plugins/openapi/client/useCreateQuery.js.map +1 -1
  73. package/dist/lib/plugins/openapi/components/EnumValues.js +1 -1
  74. package/dist/lib/plugins/openapi/components/EnumValues.js.map +1 -1
  75. package/dist/lib/plugins/openapi/graphql/gql.d.ts +6 -2
  76. package/dist/lib/plugins/openapi/graphql/gql.js +3 -2
  77. package/dist/lib/plugins/openapi/graphql/gql.js.map +1 -1
  78. package/dist/lib/plugins/openapi/graphql/graphql.d.ts +67 -11
  79. package/dist/lib/plugins/openapi/graphql/graphql.js +34 -5
  80. package/dist/lib/plugins/openapi/graphql/graphql.js.map +1 -1
  81. package/dist/lib/plugins/openapi/index.js +12 -0
  82. package/dist/lib/plugins/openapi/index.js.map +1 -1
  83. package/dist/lib/plugins/openapi/interfaces.d.ts +26 -0
  84. package/dist/lib/plugins/openapi/playground/Playground.js +1 -1
  85. package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
  86. package/dist/lib/plugins/openapi/playground/result-panel/ResultPanel.js +2 -2
  87. package/dist/lib/plugins/openapi/playground/result-panel/ResultPanel.js.map +1 -1
  88. package/dist/lib/plugins/openapi/schema/LogicalGroup/LogicalGroup.d.ts +1 -2
  89. package/dist/lib/plugins/openapi/schema/LogicalGroup/LogicalGroup.js +2 -2
  90. package/dist/lib/plugins/openapi/schema/LogicalGroup/LogicalGroup.js.map +1 -1
  91. package/dist/lib/plugins/openapi/schema/LogicalGroup/LogicalGroupItem.d.ts +0 -1
  92. package/dist/lib/plugins/openapi/schema/LogicalGroup/LogicalGroupItem.js +1 -1
  93. package/dist/lib/plugins/openapi/schema/LogicalGroup/LogicalGroupItem.js.map +1 -1
  94. package/dist/lib/plugins/openapi/schema/SchemaExampleAndDefault.d.ts +4 -0
  95. package/dist/lib/plugins/openapi/schema/SchemaExampleAndDefault.js +12 -0
  96. package/dist/lib/plugins/openapi/schema/SchemaExampleAndDefault.js.map +1 -0
  97. package/dist/lib/plugins/openapi/schema/SchemaPropertyItem.d.ts +2 -4
  98. package/dist/lib/plugins/openapi/schema/SchemaPropertyItem.js +12 -9
  99. package/dist/lib/plugins/openapi/schema/SchemaPropertyItem.js.map +1 -1
  100. package/dist/lib/plugins/openapi/schema/SchemaView.d.ts +1 -2
  101. package/dist/lib/plugins/openapi/schema/SchemaView.js +30 -52
  102. package/dist/lib/plugins/openapi/schema/SchemaView.js.map +1 -1
  103. package/dist/lib/plugins/openapi/schema/utils.d.ts +1 -0
  104. package/dist/lib/plugins/openapi/schema/utils.js +3 -1
  105. package/dist/lib/plugins/openapi/schema/utils.js.map +1 -1
  106. package/dist/lib/plugins/openapi/state.d.ts +25 -0
  107. package/dist/lib/plugins/openapi/state.js +18 -0
  108. package/dist/lib/plugins/openapi/state.js.map +1 -0
  109. package/dist/lib/plugins/openapi/util/getRoutes.js +9 -3
  110. package/dist/lib/plugins/openapi/util/getRoutes.js.map +1 -1
  111. package/dist/lib/plugins/search-pagefind/PagefindSearch.js +13 -4
  112. package/dist/lib/plugins/search-pagefind/PagefindSearch.js.map +1 -1
  113. package/dist/lib/plugins/search-pagefind/ResultList.js +19 -12
  114. package/dist/lib/plugins/search-pagefind/ResultList.js.map +1 -1
  115. package/dist/lib/plugins/search-pagefind/get-results.d.ts +8 -1
  116. package/dist/lib/plugins/search-pagefind/get-results.js +9 -4
  117. package/dist/lib/plugins/search-pagefind/get-results.js.map +1 -1
  118. package/dist/lib/util/traverse.d.ts +2 -8
  119. package/dist/lib/util/traverse.js.map +1 -1
  120. package/dist/lib/util/types.d.ts +7 -0
  121. package/dist/lib/util/types.js +2 -0
  122. package/dist/lib/util/types.js.map +1 -0
  123. package/dist/lib/util/useOnScreen.d.ts +3 -2
  124. package/dist/lib/util/useOnScreen.js +3 -3
  125. package/dist/lib/util/useOnScreen.js.map +1 -1
  126. package/dist/lib/util/useScrollToAnchor.js +18 -12
  127. package/dist/lib/util/useScrollToAnchor.js.map +1 -1
  128. package/dist/vite/api/schema-codegen.js +2 -2
  129. package/dist/vite/api/schema-codegen.js.map +1 -1
  130. package/dist/vite/api/schema-codegen.test.js +5 -0
  131. package/dist/vite/api/schema-codegen.test.js.map +1 -1
  132. package/dist/vite/plugin-api.js +12 -8
  133. package/dist/vite/plugin-api.js.map +1 -1
  134. package/lib/{AuthenticationPlugin-Cij2tPWa.js → AuthenticationPlugin-foqdvvkf.js} +3 -3
  135. package/lib/{AuthenticationPlugin-Cij2tPWa.js.map → AuthenticationPlugin-foqdvvkf.js.map} +1 -1
  136. package/lib/{Callout-B2vsR09t.js → Callout-D5frCCJ0.js} +2 -2
  137. package/lib/{Callout-B2vsR09t.js.map → Callout-D5frCCJ0.js.map} +1 -1
  138. package/lib/{Dialog-sbgekbjb.js → Dialog-Dv6WG8RN.js} +5 -5
  139. package/lib/{Dialog-sbgekbjb.js.map → Dialog-Dv6WG8RN.js.map} +1 -1
  140. package/lib/{Markdown-DT5Rrq8_.js → Markdown-aF5FdsNi.js} +1945 -1937
  141. package/lib/{Markdown-DT5Rrq8_.js.map → Markdown-aF5FdsNi.js.map} +1 -1
  142. package/lib/MdxPage-ZW1StNhp.js +83 -0
  143. package/lib/MdxPage-ZW1StNhp.js.map +1 -0
  144. package/lib/{OasProvider-DdEBf2qS.js → OasProvider-Cld9RAMQ.js} +4 -4
  145. package/lib/{OasProvider-DdEBf2qS.js.map → OasProvider-Cld9RAMQ.js.map} +1 -1
  146. package/lib/OperationList-D-OfzJm6.js +5065 -0
  147. package/lib/OperationList-D-OfzJm6.js.map +1 -0
  148. package/lib/Pagination-CYB3nVYx.js +46 -0
  149. package/lib/Pagination-CYB3nVYx.js.map +1 -0
  150. package/lib/SchemaList-Ci1WxRh0.js +148 -0
  151. package/lib/SchemaList-Ci1WxRh0.js.map +1 -0
  152. package/lib/SchemaView-Brn-YxHY.js +345 -0
  153. package/lib/SchemaView-Brn-YxHY.js.map +1 -0
  154. package/lib/{Select-z1Lwl0-J.js → Select-DVFRKf1R.js} +8 -8
  155. package/lib/{Select-z1Lwl0-J.js.map → Select-DVFRKf1R.js.map} +1 -1
  156. package/lib/{SlotletProvider-D8OBnr77.js → SlotletProvider-DXvc0aY6.js} +4 -4
  157. package/lib/{SlotletProvider-D8OBnr77.js.map → SlotletProvider-DXvc0aY6.js.map} +1 -1
  158. package/lib/Toc-YBsgI72s.js +92 -0
  159. package/lib/Toc-YBsgI72s.js.map +1 -0
  160. package/lib/{chunk-HA7DTUK3-ZGg2W6yV.js → chunk-HA7DTUK3-C4gP41vD.js} +5 -5
  161. package/lib/{chunk-HA7DTUK3-ZGg2W6yV.js.map → chunk-HA7DTUK3-C4gP41vD.js.map} +1 -1
  162. package/lib/{createServer-DjgKDpGV.js → createServer-mMau3eV_.js} +1732 -1664
  163. package/lib/{createServer-DjgKDpGV.js.map → createServer-mMau3eV_.js.map} +1 -1
  164. package/lib/hook-CqpVYDqN.js +1483 -0
  165. package/lib/hook-CqpVYDqN.js.map +1 -0
  166. package/lib/index-Bt7MKhZq.js +2514 -0
  167. package/lib/index-Bt7MKhZq.js.map +1 -0
  168. package/lib/{index-DdQSV2RF.js → index-CjPMxpOV.js} +809 -750
  169. package/lib/index-CjPMxpOV.js.map +1 -0
  170. package/lib/{mutation-_Z5C2wFZ.js → mutation-8LjrN7uz.js} +2 -2
  171. package/lib/{mutation-_Z5C2wFZ.js.map → mutation-8LjrN7uz.js.map} +1 -1
  172. package/lib/post-processors/traverse.js.map +1 -1
  173. package/lib/ui/Command.js +1 -1
  174. package/lib/{useExposedProps-BslIn-FE.js → useExposedProps-B9qXJedG.js} +2 -2
  175. package/lib/{useExposedProps-BslIn-FE.js.map → useExposedProps-B9qXJedG.js.map} +1 -1
  176. package/lib/zudoku.auth-auth0.js +1 -1
  177. package/lib/zudoku.auth-clerk.js +59 -41
  178. package/lib/zudoku.auth-clerk.js.map +1 -1
  179. package/lib/zudoku.auth-openid.js +76 -73
  180. package/lib/zudoku.auth-openid.js.map +1 -1
  181. package/lib/zudoku.components.js +31 -1440
  182. package/lib/zudoku.components.js.map +1 -1
  183. package/lib/zudoku.hooks.js +1 -1
  184. package/lib/zudoku.plugin-api-catalog.js +81 -79
  185. package/lib/zudoku.plugin-api-catalog.js.map +1 -1
  186. package/lib/zudoku.plugin-api-keys.js +15 -16
  187. package/lib/zudoku.plugin-api-keys.js.map +1 -1
  188. package/lib/zudoku.plugin-custom-pages.js +2 -2
  189. package/lib/zudoku.plugin-markdown.js +1 -1
  190. package/lib/zudoku.plugin-openapi.js +5 -6
  191. package/lib/zudoku.plugin-openapi.js.map +1 -1
  192. package/lib/zudoku.plugin-redirect.js +1 -1
  193. package/lib/zudoku.plugin-search-pagefind.js +133 -98
  194. package/lib/zudoku.plugin-search-pagefind.js.map +1 -1
  195. package/lib/zudoku.plugins.js.map +1 -1
  196. package/package.json +4 -3
  197. package/src/app/main.tsx +2 -0
  198. package/src/app/tailwind.ts +14 -0
  199. package/src/lib/authentication/authentication.ts +2 -0
  200. package/src/lib/authentication/providers/clerk.tsx +20 -0
  201. package/src/lib/authentication/providers/openid.tsx +6 -0
  202. package/src/lib/authentication/providers/supabase.tsx +6 -0
  203. package/src/lib/authentication/state.ts +1 -35
  204. package/src/lib/components/Layout.tsx +17 -17
  205. package/src/lib/components/Main.tsx +3 -1
  206. package/src/lib/components/Pagination.tsx +47 -0
  207. package/src/lib/components/TopNavigation.tsx +29 -2
  208. package/src/lib/components/navigation/SidebarItem.tsx +10 -4
  209. package/src/lib/{plugins/markdown → components/navigation}/Toc.tsx +5 -14
  210. package/src/lib/core/ZudokuContext.ts +13 -6
  211. package/src/lib/core/plugins.ts +1 -1
  212. package/src/lib/oas/graphql/index.ts +118 -45
  213. package/src/lib/oas/parser/dereference/index.ts +2 -0
  214. package/src/lib/oas/parser/index.ts +7 -29
  215. package/src/lib/plugins/api-catalog/index.tsx +40 -35
  216. package/src/lib/plugins/markdown/MdxPage.tsx +6 -43
  217. package/src/lib/plugins/openapi/ColorizedParam.tsx +1 -1
  218. package/src/lib/plugins/openapi/Endpoint.tsx +1 -1
  219. package/src/lib/plugins/openapi/OperationList.tsx +37 -16
  220. package/src/lib/plugins/openapi/OperationListItem.tsx +7 -2
  221. package/src/lib/plugins/openapi/ParameterListItem.tsx +2 -0
  222. package/src/lib/plugins/openapi/SchemaList.tsx +151 -0
  223. package/src/lib/plugins/openapi/Sidecar.tsx +36 -7
  224. package/src/lib/plugins/openapi/client/GraphQLClient.tsx +1 -1
  225. package/src/lib/plugins/openapi/client/useCreateQuery.ts +12 -5
  226. package/src/lib/plugins/openapi/components/EnumValues.tsx +1 -1
  227. package/src/lib/plugins/openapi/graphql/gql.ts +15 -6
  228. package/src/lib/plugins/openapi/graphql/graphql.ts +104 -15
  229. package/src/lib/plugins/openapi/index.tsx +13 -0
  230. package/src/lib/plugins/openapi/interfaces.ts +29 -0
  231. package/src/lib/plugins/openapi/playground/Playground.tsx +1 -1
  232. package/src/lib/plugins/openapi/playground/result-panel/ResultPanel.tsx +2 -1
  233. package/src/lib/plugins/openapi/schema/LogicalGroup/LogicalGroup.tsx +1 -8
  234. package/src/lib/plugins/openapi/schema/LogicalGroup/LogicalGroupItem.tsx +1 -2
  235. package/src/lib/plugins/openapi/schema/SchemaExampleAndDefault.tsx +36 -0
  236. package/src/lib/plugins/openapi/schema/SchemaPropertyItem.tsx +20 -21
  237. package/src/lib/plugins/openapi/schema/SchemaView.tsx +69 -141
  238. package/src/lib/plugins/openapi/schema/utils.ts +7 -1
  239. package/src/lib/plugins/openapi/state.ts +36 -0
  240. package/src/lib/plugins/openapi/util/getRoutes.tsx +9 -6
  241. package/src/lib/plugins/search-pagefind/PagefindSearch.tsx +26 -4
  242. package/src/lib/plugins/search-pagefind/ResultList.tsx +59 -47
  243. package/src/lib/plugins/search-pagefind/get-results.tsx +31 -10
  244. package/src/lib/util/traverse.ts +2 -6
  245. package/src/lib/util/types.ts +7 -0
  246. package/src/lib/util/useOnScreen.ts +6 -4
  247. package/src/lib/util/useScrollToAnchor.ts +20 -12
  248. package/dist/lib/plugins/markdown/Toc.js.map +0 -1
  249. package/lib/MdxPage-D2rD1vC4.js +0 -200
  250. package/lib/MdxPage-D2rD1vC4.js.map +0 -1
  251. package/lib/OperationList-DT4-gm_S.js +0 -5363
  252. package/lib/OperationList-DT4-gm_S.js.map +0 -1
  253. package/lib/hook-DzQC8PzJ.js +0 -355
  254. package/lib/hook-DzQC8PzJ.js.map +0 -1
  255. package/lib/index-DdQSV2RF.js.map +0 -1
  256. package/lib/index.esm-CltAN0Tf.js +0 -711
  257. package/lib/index.esm-CltAN0Tf.js.map +0 -1
  258. package/lib/joinUrl-BjDooT-T.js +0 -1154
  259. package/lib/joinUrl-BjDooT-T.js.map +0 -1
  260. /package/dist/lib/{plugins/markdown → components/navigation}/Toc.d.ts +0 -0
@@ -3,11 +3,15 @@ import { OpenAPIV3, type OpenAPIV3_1 } from "openapi-types";
3
3
  import { dereference, type JSONSchema } from "./dereference/index.js";
4
4
  import { upgradeSchema } from "./upgrade/index.js";
5
5
 
6
- type ReferenceObject = OpenAPIV3_1.ReferenceObject;
7
- type DeepOmitReference<T> = T extends ReferenceObject
6
+ // Must be an interface (not a type) to allow merging with OpenAPI types with index signatures
7
+ interface WithRef {
8
+ __$ref?: string;
9
+ }
10
+
11
+ type DeepOmitReference<T> = T extends OpenAPIV3_1.ReferenceObject
8
12
  ? never
9
13
  : T extends object
10
- ? { [K in keyof T]: DeepOmitReference<T[K]> }
14
+ ? { [K in keyof T]: DeepOmitReference<T[K]> } & WithRef
11
15
  : T;
12
16
 
13
17
  export type OpenAPIDocument = DeepOmitReference<OpenAPIV3_1.Document>;
@@ -24,25 +28,6 @@ export type ServerObject = DeepOmitReference<OpenAPIV3_1.ServerObject>;
24
28
 
25
29
  export const HttpMethods = Object.values(OpenAPIV3.HttpMethods);
26
30
 
27
- // class ValidationError extends Error {
28
- // constructor(public errors: OutputUnit[]) {
29
- // super("Validation error");
30
- // }
31
- // }
32
-
33
- // const getValidator = async (openApiVersion: string) => {
34
- // if (openApiVersion.startsWith("3.0")) {
35
- // const schema = (await import("./schemas/v3.0.json")) as any;
36
- // return new Validator(schema, "4");
37
- // }
38
- // if (openApiVersion.startsWith("3.1")) {
39
- // const schema = (await import("./schemas/v3.1.json")) as any;
40
- // return new Validator(schema as any, "2020-12");
41
- // }
42
-
43
- // throw new Error(`Unsupported OpenAPI version: ${openApiVersion}`);
44
- // };
45
-
46
31
  const parseSchemaInput = async (
47
32
  schemaInput: unknown,
48
33
  ): Promise<JSONSchema & { openapi?: string }> => {
@@ -110,13 +95,6 @@ export const validate = async (schemaInput: unknown) => {
110
95
  throw new GraphQLError("OpenAPI version is not defined");
111
96
  }
112
97
 
113
- // const validator = await getValidator(schema.openapi);
114
- // const result = validator.validate(schema);
115
- //
116
- // if (!result.valid) {
117
- // throw new ValidationError(result.errors);
118
- // }
119
-
120
98
  const dereferenced = await dereference(schema);
121
99
 
122
100
  return upgradeSchema(dereferenced);
@@ -51,9 +51,22 @@ export const apiCatalogPlugin = ({
51
51
  items: ApiCatalogItem[];
52
52
  filterCatalogItems?: filterCatalogItems;
53
53
  }): ZudokuPlugin => {
54
+ const paths = Object.fromEntries(
55
+ categories.flatMap((category) =>
56
+ [undefined, ...category.tags].map((tag) => [
57
+ joinUrl(navigationId, tag ? getKey(category.label, tag) : undefined),
58
+ tag,
59
+ ]),
60
+ ),
61
+ );
62
+
54
63
  return {
55
- getSidebar: async function Sidebar(path) {
56
- if (!matchPath({ path: joinUrl(navigationId), end: false }, path)) {
64
+ getSidebar: async (currentPath) => {
65
+ const matches = Object.keys(paths).some((path) =>
66
+ matchPath(path, currentPath),
67
+ );
68
+
69
+ if (!matches) {
57
70
  return [];
58
71
  }
59
72
 
@@ -61,22 +74,19 @@ export const apiCatalogPlugin = ({
61
74
  type: "category" as const,
62
75
  label: category.label,
63
76
  collapsible: false,
64
- items: category.tags.map((tag) => {
65
- const tagPath = getKey(category.label, tag);
66
- return {
67
- type: "doc" as const,
68
- id: joinUrl(navigationId, tagPath),
69
- label: tag,
70
- badge: {
71
- label: String(
72
- items.filter((api) =>
73
- api.categories.find((c) => c.tags.includes(tag)),
74
- ).length,
75
- ),
76
- color: "outline" as const,
77
- },
78
- };
79
- }),
77
+ items: category.tags.map((tag) => ({
78
+ type: "doc" as const,
79
+ id: joinUrl(navigationId, getKey(category.label, tag)),
80
+ label: tag,
81
+ badge: {
82
+ label: String(
83
+ items.filter((api) =>
84
+ api.categories.find((c) => c.tags.includes(tag)),
85
+ ).length,
86
+ ),
87
+ color: "outline" as const,
88
+ },
89
+ })),
80
90
  }));
81
91
 
82
92
  sidebar.unshift({
@@ -89,22 +99,17 @@ export const apiCatalogPlugin = ({
89
99
  return sidebar;
90
100
  },
91
101
  getRoutes: () =>
92
- categories.flatMap((category) =>
93
- [undefined, ...category.tags].map((tag) => ({
94
- path: joinUrl(
95
- navigationId,
96
- tag ? getKey(category.label, tag) : undefined,
97
- ),
98
- element: (
99
- <Catalog
100
- label={label}
101
- categoryLabel={tag}
102
- items={items}
103
- filterCatalogItems={filterCatalogItems}
104
- categories={categories}
105
- />
106
- ),
107
- })),
108
- ),
102
+ Object.entries(paths).map(([path, tag]) => ({
103
+ path,
104
+ element: (
105
+ <Catalog
106
+ label={label}
107
+ categoryLabel={tag}
108
+ items={items}
109
+ filterCatalogItems={filterCatalogItems}
110
+ categories={categories}
111
+ />
112
+ ),
113
+ })),
109
114
  };
110
115
  };
@@ -2,17 +2,17 @@ import { useMDXComponents } from "@mdx-js/react";
2
2
  import slugify from "@sindresorhus/slugify";
3
3
  import { Helmet } from "@zudoku/react-helmet-async";
4
4
  import { type PropsWithChildren, useEffect } from "react";
5
- import { Link, useHref } from "react-router";
6
5
  import { CategoryHeading } from "../../components/CategoryHeading.js";
7
6
  import { Heading } from "../../components/Heading.js";
8
7
  import { ProseClasses } from "../../components/Markdown.js";
8
+ import { Pagination } from "../../components/Pagination.js";
9
+ import { Toc } from "../../components/navigation/Toc.js";
9
10
  import {
10
11
  useCurrentItem,
11
12
  usePrevNext,
12
13
  } from "../../components/navigation/utils.js";
13
14
  import type { MdxComponentsType } from "../../util/MdxComponents.js";
14
15
  import { cn } from "../../util/cn.js";
15
- import { Toc } from "./Toc.js";
16
16
  import { type MarkdownPluginDefaultOptions, type MDXImport } from "./index.js";
17
17
 
18
18
  declare global {
@@ -51,12 +51,6 @@ export const MdxPage = ({
51
51
  }
52
52
  >) => {
53
53
  const categoryTitle = useCurrentItem()?.categoryLabel;
54
- let canonicalUrl = null;
55
- const path = useHref("");
56
- if (typeof window !== "undefined") {
57
- const domain = window.location.origin;
58
- canonicalUrl = `${domain}${path}`;
59
- }
60
54
 
61
55
  const title = frontmatter.title;
62
56
  const category = frontmatter.category ?? categoryTitle;
@@ -98,7 +92,6 @@ export const MdxPage = ({
98
92
  <Helmet>
99
93
  <title>{pageTitle}</title>
100
94
  {excerpt && <meta name="description" content={excerpt} />}
101
- {canonicalUrl && <link rel="canonical" href={canonicalUrl} />}
102
95
  </Helmet>
103
96
  <div
104
97
  className={cn(
@@ -122,40 +115,10 @@ export const MdxPage = ({
122
115
  {!hidePager && (
123
116
  <>
124
117
  <hr />
125
- <div className="not-prose flex flex-wrap items-center justify-between gap-2 lg:gap-8">
126
- {prev ? (
127
- <Link
128
- to={prev.id}
129
- className="flex flex-col items-stretch gap-2 flex-1 min-w-max border rounded px-6 py-4 text-start hover:border-primary/85 transition shadow-sm hover:shadow-md"
130
- title={prev.label}
131
- >
132
- <div className="text-sm text-muted-foreground">
133
- ← Previous page
134
- </div>
135
- <div className="text-lg text-primary truncate">
136
- {prev.label}
137
- </div>
138
- </Link>
139
- ) : (
140
- <div className="flex-1" />
141
- )}
142
- {next ? (
143
- <Link
144
- to={next.id}
145
- className="flex flex-col items-stretch gap-2 flex-1 min-w-max border rounded px-6 py-4 text-end hover:border-primary/85 transition shadow-sm hover:shadow-md"
146
- title={next.label}
147
- >
148
- <div className="text-sm text-muted-foreground">
149
- Next page →
150
- </div>
151
- <div className="text-lg text-primary truncate">
152
- {next.label}
153
- </div>
154
- </Link>
155
- ) : (
156
- <div className="flex-1" />
157
- )}
158
- </div>
118
+ <Pagination
119
+ prev={prev ? { to: prev.id, label: prev.label } : undefined}
120
+ next={next ? { to: next.id, label: next.label } : undefined}
121
+ />
159
122
  </>
160
123
  )}
161
124
  </div>
@@ -90,7 +90,7 @@ export const ColorizedParam = ({
90
90
  {...{ [DATA_ATTR]: normalizedSlug }}
91
91
  className={cn(
92
92
  // This may not contain (inline-)flex or (inline-)block otherwise it breaks the browser's full text search
93
- "relative rounded transition-all duration-100 rounded-lg",
93
+ "relative transition-all duration-100 rounded-lg",
94
94
  "border border-[--border-color] p-0.5 text-[--param-color] bg-[--background-color]",
95
95
  "data-[active=true]:border-[--param-color] data-[active=true]:shadow data-[active=true]:bottom-px",
96
96
  className,
@@ -1,13 +1,13 @@
1
1
  import { useSuspenseQuery } from "@tanstack/react-query";
2
2
  import { CheckIcon, CopyIcon } from "lucide-react";
3
3
  import { useState, useTransition } from "react";
4
- import { useSelectedServer } from "../../authentication/state.js";
5
4
  import { InlineCode } from "../../components/InlineCode.js";
6
5
  import { Button } from "../../ui/Button.js";
7
6
  import { useCreateQuery } from "./client/useCreateQuery.js";
8
7
  import { useOasConfig } from "./context.js";
9
8
  import { graphql } from "./graphql/index.js";
10
9
  import { SimpleSelect } from "./SimpleSelect.js";
10
+ import { useSelectedServer } from "./state.js";
11
11
 
12
12
  const ServersQuery = graphql(/* GraphQL */ `
13
13
  query ServersQuery($input: JSON!, $type: SchemaType!) {
@@ -15,10 +15,10 @@ import {
15
15
  SelectTrigger,
16
16
  SelectValue,
17
17
  } from "zudoku/ui/Select.js";
18
- import { useSelectedServer } from "../../authentication/state.js";
19
18
  import { CategoryHeading } from "../../components/CategoryHeading.js";
20
19
  import { Heading } from "../../components/Heading.js";
21
20
  import { Markdown, ProseClasses } from "../../components/Markdown.js";
21
+ import { Pagination } from "../../components/Pagination.js";
22
22
  import { useApiIdentities } from "../../components/context/ZudokuContext.js";
23
23
  import { cn } from "../../util/cn.js";
24
24
  import { Endpoint } from "./Endpoint.js";
@@ -26,6 +26,8 @@ import { OperationListItem } from "./OperationListItem.js";
26
26
  import { useCreateQuery } from "./client/useCreateQuery.js";
27
27
  import { useOasConfig } from "./context.js";
28
28
  import { graphql } from "./graphql/index.js";
29
+ import { UNTAGGED_PATH } from "./index.js";
30
+ import { useSelectedServer } from "./state.js";
29
31
  import { sanitizeMarkdownForMetatag } from "./util/sanitizeMarkdownForMetatag.js";
30
32
 
31
33
  export const OperationsFragment = graphql(/* GraphQL */ `
@@ -121,13 +123,21 @@ const OperationsForTagQuery = graphql(/* GraphQL */ `
121
123
  title
122
124
  url
123
125
  version
124
- tags(name: $tag) {
126
+ tag(slug: $tag, untagged: $untagged) {
125
127
  name
126
128
  description
127
- }
128
- operations(tag: $tag, untagged: $untagged) {
129
- slug
130
- ...OperationsFragment
129
+ operations {
130
+ slug
131
+ ...OperationsFragment
132
+ }
133
+ next {
134
+ name
135
+ slug
136
+ }
137
+ prev {
138
+ name
139
+ slug
140
+ }
131
141
  }
132
142
  }
133
143
  }
@@ -156,8 +166,6 @@ export const OperationList = ({
156
166
  const summary = schema.summary;
157
167
  const description = schema.description;
158
168
  const navigate = useNavigate();
159
- const operations = schema.operations;
160
- const tagDescription = schema.tags.find((t) => t.name === tag)?.description;
161
169
 
162
170
  // This is to warmup (i.e. load the schema in the background) the schema on the client, if the page has been rendered on the server
163
171
  const warmupQuery = useCreateQuery(SchemaWarmupQuery, { input, type });
@@ -170,6 +178,10 @@ export const OperationList = ({
170
178
  // Prefetch for Playground
171
179
  useApiIdentities();
172
180
 
181
+ if (!schema.tag) return null;
182
+
183
+ const { operations, next, prev, description: tagDescription } = schema.tag;
184
+
173
185
  // The summary property is preferable here as it is a short description of
174
186
  // the API, whereas the description property is typically longer and supports
175
187
  // commonmark formatting, making it ill-suited for use in the meta description
@@ -187,6 +199,16 @@ export const OperationList = ({
187
199
  options?.showVersionSelect === "always" ||
188
200
  (hasMultipleVersions && options?.showVersionSelect !== "hide");
189
201
 
202
+ const paginationProps = {
203
+ prev: prev?.name ? { to: `../${prev.slug}`, label: prev.name } : undefined,
204
+ next: next
205
+ ? {
206
+ to: `../${next.slug ?? UNTAGGED_PATH}`,
207
+ label: next.name ?? "Other endpoints",
208
+ }
209
+ : undefined,
210
+ };
211
+
190
212
  return (
191
213
  <div
192
214
  className="pt-[--padding-content-top]"
@@ -194,7 +216,7 @@ export const OperationList = ({
194
216
  data-pagefind-meta="section:openapi"
195
217
  >
196
218
  <Helmet>
197
- <title>{[tag, title].filter(Boolean).join(" - ")}</title>
219
+ <title>{[schema.tag.name, title].filter(Boolean).join(" - ")}</title>
198
220
  {metaDescription && (
199
221
  <meta name="description" content={metaDescription} />
200
222
  )}
@@ -202,7 +224,7 @@ export const OperationList = ({
202
224
  <div className="mb-8">
203
225
  <Collapsible className="w-full">
204
226
  <div className="flex flex-col gap-y-4 sm:flex-row justify-around items-start sm:items-end">
205
- <div className="flex-1">
227
+ <div className="flex flex-col flex-1 gap-2">
206
228
  <CategoryHeading>{title}</CategoryHeading>
207
229
  <Heading
208
230
  level={1}
@@ -210,7 +232,7 @@ export const OperationList = ({
210
232
  registerSidebarAnchor
211
233
  className="mb-0"
212
234
  >
213
- {tag ?? "Other endpoints"}
235
+ {schema.tag.name ?? "Other endpoints"}
214
236
  {showVersions && (
215
237
  <span className="text-xl text-muted-foreground ml-1.5">
216
238
  {" "}
@@ -218,6 +240,7 @@ export const OperationList = ({
218
240
  </span>
219
241
  )}
220
242
  </Heading>
243
+ <Endpoint />
221
244
  </div>
222
245
  <div className="flex flex-col gap-4 sm:items-end">
223
246
  {showVersions && (
@@ -240,7 +263,7 @@ export const OperationList = ({
240
263
  )}
241
264
  {schema.description && (
242
265
  <CollapsibleTrigger className="flex items-center gap-1 text-sm font-medium text-muted-foreground group">
243
- <span>Schema description</span>
266
+ <span>API information</span>
244
267
 
245
268
  <ChevronsUpDownIcon
246
269
  className="group-data-[state=open]:hidden translate-y-px"
@@ -282,11 +305,8 @@ export const OperationList = ({
282
305
  )}
283
306
  </div>
284
307
  <hr />
285
- <div className="my-4 flex items-center justify-end gap-4">
286
- <Endpoint />
287
- </div>
288
308
  {/* px, -mx is so that `content-visibility` doesn't cut off overflown heading anchor links '#' */}
289
- <div className="px-6 -mx-6 [content-visibility:auto]">
309
+ <div className="px-6 mt-6 -mx-6 [content-visibility:auto]">
290
310
  {operations.map((fragment) => (
291
311
  <OperationListItem
292
312
  serverUrl={selectedServer}
@@ -294,6 +314,7 @@ export const OperationList = ({
294
314
  operationFragment={fragment}
295
315
  />
296
316
  ))}
317
+ <Pagination {...paginationProps} />
297
318
  </div>
298
319
  </div>
299
320
  );
@@ -100,13 +100,18 @@ export const OperationListItem = ({
100
100
  <div className="mt-4 flex flex-col gap-4">
101
101
  <Heading
102
102
  level={3}
103
- className="capitalize"
103
+ className="capitalize flex items-center gap-2"
104
104
  id={`${operation.slug}/request-body`}
105
105
  >
106
106
  {operation.summary && (
107
107
  <VisuallyHidden>{operation.summary} &rsaquo; </VisuallyHidden>
108
108
  )}
109
- Request Body
109
+ Request Body{" "}
110
+ {operation.requestBody?.required === false ? (
111
+ <Badge variant="muted">optional</Badge>
112
+ ) : (
113
+ ""
114
+ )}
110
115
  </Heading>
111
116
  <SchemaView schema={schema} />
112
117
  </div>
@@ -6,6 +6,7 @@ import type { ParameterGroup } from "./OperationListItem.js";
6
6
  import { ParamInfos } from "./ParamInfos.js";
7
7
  import { EnumValues } from "./components/EnumValues.js";
8
8
  import { SelectOnClick } from "./components/SelectOnClick.js";
9
+ import { SchemaExampleAndDefault } from "./schema/SchemaExampleAndDefault.js";
9
10
 
10
11
  const getParameterSchema = (
11
12
  parameter: ParameterListItemResult,
@@ -72,6 +73,7 @@ export const ParameterListItem = ({
72
73
  ) : (
73
74
  paramSchema.enum && <EnumValues values={paramSchema.enum} />
74
75
  )}
76
+ <SchemaExampleAndDefault schema={paramSchema} />
75
77
  </li>
76
78
  );
77
79
  };
@@ -0,0 +1,151 @@
1
+ import slugify from "@sindresorhus/slugify";
2
+ import { useSuspenseQuery } from "@tanstack/react-query";
3
+ import {
4
+ ChevronRightIcon,
5
+ ChevronsDownUpIcon,
6
+ ChevronsUpDownIcon,
7
+ } from "lucide-react";
8
+ import { Button } from "zudoku/ui/Button.js";
9
+ import {
10
+ Collapsible,
11
+ CollapsibleContent,
12
+ CollapsibleTrigger,
13
+ } from "zudoku/ui/Collapsible.js";
14
+ import { CategoryHeading } from "../../components/CategoryHeading.js";
15
+ import { Heading } from "../../components/Heading.js";
16
+ import { Markdown, ProseClasses } from "../../components/Markdown.js";
17
+ import { Toc } from "../../components/navigation/Toc.js";
18
+ import { cn } from "../../util/cn.js";
19
+ import { useCreateQuery } from "./client/useCreateQuery.js";
20
+ import { useOasConfig } from "./context.js";
21
+ import { graphql } from "./graphql/gql.js";
22
+ import { SchemaView } from "./schema/SchemaView.js";
23
+
24
+ const GET_SCHEMAS = graphql(/* GraphQL */ `
25
+ query GetSchemas($input: JSON!, $type: SchemaType!) {
26
+ schema(input: $input, type: $type) {
27
+ title
28
+ description
29
+ summary
30
+ components {
31
+ schemas {
32
+ name
33
+ schema
34
+ extensions
35
+ }
36
+ }
37
+ }
38
+ }
39
+ `);
40
+
41
+ export function SchemaList() {
42
+ const { input, type, versions, version, options } = useOasConfig();
43
+ const schemasQuery = useCreateQuery(GET_SCHEMAS, {
44
+ input,
45
+ type,
46
+ });
47
+ const { data } = useSuspenseQuery(schemasQuery);
48
+
49
+ const schemas = data.schema.components?.schemas ?? [];
50
+
51
+ if (!schemas.length) {
52
+ return <div>No schemas found</div>;
53
+ }
54
+
55
+ const hasMultipleVersions = Object.entries(versions).length > 1;
56
+ const showVersions =
57
+ options?.showVersionSelect === "always" ||
58
+ (hasMultipleVersions && options?.showVersionSelect !== "hide");
59
+
60
+ return (
61
+ <div
62
+ className="grid grid-cols-[--sidecar-grid-cols] gap-8 justify-between"
63
+ data-pagefind-filter="section:openapi"
64
+ data-pagefind-meta="section:openapi"
65
+ >
66
+ <div className="pt-[--padding-content-top] pb-[--padding-content-bottom]">
67
+ <Collapsible className="w-full">
68
+ <div className="flex flex-col gap-y-4 sm:flex-row justify-around items-start sm:items-end">
69
+ <div className="flex-1">
70
+ <CategoryHeading>{data.schema.title}</CategoryHeading>
71
+ <Heading
72
+ level={1}
73
+ id="schemas"
74
+ registerSidebarAnchor
75
+ className="mb-0"
76
+ >
77
+ Schemas
78
+ {showVersions && (
79
+ <span className="text-xl text-muted-foreground ml-1.5">
80
+ ({version})
81
+ </span>
82
+ )}
83
+ </Heading>
84
+ </div>
85
+ {data.schema.description && (
86
+ <CollapsibleTrigger className="flex items-center gap-1 text-sm font-medium text-muted-foreground group">
87
+ <span>API information</span>
88
+ <ChevronsUpDownIcon
89
+ className="group-data-[state=open]:hidden translate-y-px"
90
+ size={14}
91
+ />
92
+ <ChevronsDownUpIcon
93
+ className="group-data-[state=closed]:hidden translate-y-px"
94
+ size={13}
95
+ />
96
+ </CollapsibleTrigger>
97
+ )}
98
+ </div>
99
+ {data.schema.description && (
100
+ <CollapsibleContent className="CollapsibleContent">
101
+ <div
102
+ className={cn(
103
+ ProseClasses,
104
+ "pt-4 max-w-full prose-img:max-w-prose",
105
+ )}
106
+ >
107
+ <Markdown
108
+ className="border rounded bg-muted/25 border-border px-2.5 md:px-4"
109
+ content={data.schema.description}
110
+ />
111
+ </div>
112
+ </CollapsibleContent>
113
+ )}
114
+ </Collapsible>
115
+ <hr className="my-8" />
116
+ <div className="flex flex-col gap-y-5">
117
+ {schemas.map((schema) => (
118
+ <Collapsible key={schema.name} className="group" defaultOpen>
119
+ <Heading
120
+ registerSidebarAnchor
121
+ level={2}
122
+ className="flex items-center gap-1 justify-between w-fit"
123
+ id={slugify(schema.name)}
124
+ >
125
+ {schema.name}{" "}
126
+ <CollapsibleTrigger asChild>
127
+ <Button variant="ghost" size="icon" className="size-6">
128
+ <ChevronRightIcon
129
+ size={16}
130
+ className="group-data-[state=open]:rotate-90 transition cursor-pointer"
131
+ />
132
+ </Button>
133
+ </CollapsibleTrigger>
134
+ </Heading>
135
+ <CollapsibleContent className="mt-4 CollapsibleContent">
136
+ <SchemaView schema={schema.schema} />
137
+ </CollapsibleContent>
138
+ </Collapsible>
139
+ ))}
140
+ </div>
141
+ </div>
142
+ <Toc
143
+ entries={schemas.map((schema) => ({
144
+ id: slugify(schema.name),
145
+ value: schema.name,
146
+ depth: 1,
147
+ }))}
148
+ />
149
+ </div>
150
+ );
151
+ }