zudoku 0.31.2 → 0.32.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 (129) hide show
  1. package/dist/cli/common/utils/ports.d.ts +1 -1
  2. package/dist/cli/common/utils/ports.js +16 -15
  3. package/dist/cli/common/utils/ports.js.map +1 -1
  4. package/dist/cli/dev/handler.js +9 -12
  5. package/dist/cli/dev/handler.js.map +1 -1
  6. package/dist/config/validators/common.d.ts +90 -0
  7. package/dist/config/validators/common.js +8 -0
  8. package/dist/config/validators/common.js.map +1 -1
  9. package/dist/config/validators/validate.d.ts +38 -0
  10. package/dist/lib/MissingIcon.d.ts +2 -0
  11. package/dist/lib/MissingIcon.js +7 -0
  12. package/dist/lib/MissingIcon.js.map +1 -0
  13. package/dist/lib/core/ZudokuContext.d.ts +1 -1
  14. package/dist/lib/core/plugins.d.ts +2 -0
  15. package/dist/lib/core/plugins.js +2 -0
  16. package/dist/lib/core/plugins.js.map +1 -1
  17. package/dist/lib/icons.d.ts +1 -0
  18. package/dist/lib/icons.js +1 -0
  19. package/dist/lib/icons.js.map +1 -1
  20. package/dist/lib/oas/graphql/index.js +3 -2
  21. package/dist/lib/oas/graphql/index.js.map +1 -1
  22. package/dist/lib/plugins/api-keys/index.d.ts +1 -0
  23. package/dist/lib/plugins/api-keys/index.js +1 -0
  24. package/dist/lib/plugins/api-keys/index.js.map +1 -1
  25. package/dist/lib/plugins/openapi/{OpenApiRoute.d.ts → OasProvider.d.ts} +1 -2
  26. package/dist/lib/plugins/openapi/OasProvider.js +29 -0
  27. package/dist/lib/plugins/openapi/OasProvider.js.map +1 -0
  28. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.d.ts +1 -1
  29. package/dist/lib/plugins/openapi/Sidecar.js +1 -1
  30. package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
  31. package/dist/lib/plugins/openapi/index.d.ts +8 -0
  32. package/dist/lib/plugins/openapi/index.js +46 -113
  33. package/dist/lib/plugins/openapi/index.js.map +1 -1
  34. package/dist/lib/plugins/openapi/playground/Playground.d.ts +1 -1
  35. package/dist/lib/plugins/openapi/playground/Playground.js +5 -5
  36. package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
  37. package/dist/lib/plugins/openapi/playground/result-panel/RequestTab.js +1 -1
  38. package/dist/lib/plugins/openapi/playground/result-panel/RequestTab.js.map +1 -1
  39. package/dist/lib/plugins/openapi/util/createSidebarCategory.d.ts +9 -0
  40. package/dist/lib/plugins/openapi/util/createSidebarCategory.js +25 -0
  41. package/dist/lib/plugins/openapi/util/createSidebarCategory.js.map +1 -0
  42. package/dist/lib/plugins/openapi/util/getRoutes.d.ts +10 -0
  43. package/dist/lib/plugins/openapi/util/getRoutes.js +74 -0
  44. package/dist/lib/plugins/openapi/util/getRoutes.js.map +1 -0
  45. package/dist/lib/plugins/openapi/util/methodColorMap.d.ts +2 -0
  46. package/dist/lib/plugins/openapi/util/methodColorMap.js +10 -0
  47. package/dist/lib/plugins/openapi/util/methodColorMap.js.map +1 -0
  48. package/dist/vite/build.js +20 -14
  49. package/dist/vite/build.js.map +1 -1
  50. package/dist/vite/config.js +2 -6
  51. package/dist/vite/config.js.map +1 -1
  52. package/dist/vite/dev-server.d.ts +4 -2
  53. package/dist/vite/dev-server.js +30 -8
  54. package/dist/vite/dev-server.js.map +1 -1
  55. package/dist/vite/error-handler.d.ts +1 -1
  56. package/dist/vite/error-handler.js +1 -1
  57. package/dist/vite/error-handler.js.map +1 -1
  58. package/dist/vite/output.d.ts +14 -2
  59. package/dist/vite/output.js +12 -14
  60. package/dist/vite/output.js.map +1 -1
  61. package/dist/vite/plugin-api-keys.js +2 -2
  62. package/dist/vite/plugin-api-keys.js.map +1 -1
  63. package/dist/vite/plugin-sidebar.js +17 -2
  64. package/dist/vite/plugin-sidebar.js.map +1 -1
  65. package/dist/vite/prerender/FileWritingResponse.d.ts +7 -3
  66. package/dist/vite/prerender/FileWritingResponse.js +15 -9
  67. package/dist/vite/prerender/FileWritingResponse.js.map +1 -1
  68. package/dist/vite/prerender/prerender.d.ts +10 -2
  69. package/dist/vite/prerender/prerender.js +5 -4
  70. package/dist/vite/prerender/prerender.js.map +1 -1
  71. package/dist/vite/prerender/worker.d.ts +3 -1
  72. package/dist/vite/prerender/worker.js +11 -4
  73. package/dist/vite/prerender/worker.js.map +1 -1
  74. package/lib/{AuthenticationPlugin-DjnQ5hs7.js → AuthenticationPlugin-_YVa673u.js} +2 -2
  75. package/lib/{AuthenticationPlugin-DjnQ5hs7.js.map → AuthenticationPlugin-_YVa673u.js.map} +1 -1
  76. package/lib/{MdxPage-ZX2oquWw.js → MdxPage-GM1T5jmO.js} +3 -3
  77. package/lib/{MdxPage-ZX2oquWw.js.map → MdxPage-GM1T5jmO.js.map} +1 -1
  78. package/lib/OasProvider-IS9wBrb7.js +34 -0
  79. package/lib/OasProvider-IS9wBrb7.js.map +1 -0
  80. package/lib/{OperationList-c72qPMtm.js → OperationList-BTmRbbXk.js} +4 -5
  81. package/lib/{OperationList-c72qPMtm.js.map → OperationList-BTmRbbXk.js.map} +1 -1
  82. package/lib/{Select-NSz0gku6.js → Select-D9CKL33X.js} +3 -3
  83. package/lib/{Select-NSz0gku6.js.map → Select-D9CKL33X.js.map} +1 -1
  84. package/lib/{createServer-ZDNGmPfQ.js → createServer-DSQiPwjN.js} +2 -5
  85. package/lib/{createServer-ZDNGmPfQ.js.map → createServer-DSQiPwjN.js.map} +1 -1
  86. package/lib/{hook-Dnj3SwPC.js → hook-C_t2ISLC.js} +22 -22
  87. package/lib/{hook-Dnj3SwPC.js.map → hook-C_t2ISLC.js.map} +1 -1
  88. package/lib/{index-CZjcfK-H.js → index-BANyVRgL.js} +806 -771
  89. package/lib/index-BANyVRgL.js.map +1 -0
  90. package/lib/{mutation-ByGtmi0-.js → mutation-Cm3O9f3X.js} +2 -2
  91. package/lib/{mutation-ByGtmi0-.js.map → mutation-Cm3O9f3X.js.map} +1 -1
  92. package/lib/{useScrollToAnchor-DkVfWsxe.js → useScrollToAnchor-BGEcH3HM.js} +2 -2
  93. package/lib/{useScrollToAnchor-DkVfWsxe.js.map → useScrollToAnchor-BGEcH3HM.js.map} +1 -1
  94. package/lib/zudoku.auth-auth0.js +1 -1
  95. package/lib/zudoku.auth-clerk.js +2 -2
  96. package/lib/zudoku.auth-openid.js +2 -2
  97. package/lib/zudoku.components.js +141 -140
  98. package/lib/zudoku.components.js.map +1 -1
  99. package/lib/zudoku.icons.js +10 -0
  100. package/lib/zudoku.icons.js.map +1 -1
  101. package/lib/zudoku.plugin-api-catalog.js +1 -1
  102. package/lib/zudoku.plugin-api-keys.js +10 -9
  103. package/lib/zudoku.plugin-api-keys.js.map +1 -1
  104. package/lib/zudoku.plugin-markdown.js +1 -1
  105. package/lib/zudoku.plugin-openapi.js +4 -3
  106. package/lib/zudoku.plugins.js +13 -0
  107. package/lib/zudoku.plugins.js.map +1 -0
  108. package/package.json +5 -1
  109. package/src/lib/MissingIcon.tsx +22 -0
  110. package/src/lib/core/ZudokuContext.ts +1 -1
  111. package/src/lib/core/plugins.ts +8 -0
  112. package/src/lib/icons.ts +1 -0
  113. package/src/lib/oas/graphql/index.ts +3 -2
  114. package/src/lib/plugins/api-keys/index.tsx +3 -0
  115. package/src/lib/plugins/openapi/OasProvider.tsx +51 -0
  116. package/src/lib/plugins/openapi/PlaygroundDialogWrapper.tsx +1 -1
  117. package/src/lib/plugins/openapi/Sidecar.tsx +0 -1
  118. package/src/lib/plugins/openapi/index.tsx +80 -143
  119. package/src/lib/plugins/openapi/playground/Playground.tsx +26 -24
  120. package/src/lib/plugins/openapi/playground/result-panel/RequestTab.tsx +1 -1
  121. package/src/lib/plugins/openapi/util/createSidebarCategory.tsx +39 -0
  122. package/src/lib/plugins/openapi/util/getRoutes.tsx +123 -0
  123. package/src/lib/plugins/openapi/util/methodColorMap.tsx +11 -0
  124. package/dist/lib/plugins/openapi/OpenApiRoute.js +0 -25
  125. package/dist/lib/plugins/openapi/OpenApiRoute.js.map +0 -1
  126. package/lib/OpenApiRoute-BP9kzG5k.js +0 -36
  127. package/lib/OpenApiRoute-BP9kzG5k.js.map +0 -1
  128. package/lib/index-CZjcfK-H.js.map +0 -1
  129. package/src/lib/plugins/openapi/OpenApiRoute.tsx +0 -51
@@ -1,9 +1,9 @@
1
+ import type { ResultOf } from "@graphql-typed-document-node/core";
1
2
  import slugify from "@sindresorhus/slugify";
2
3
  import { CirclePlayIcon, LogInIcon } from "lucide-react";
3
- import { matchPath, redirect, RouteObject } from "react-router";
4
- import type { SidebarItem } from "../../../config/validators/SidebarSchema.js";
4
+ import { ReactNode } from "react";
5
+ import { matchPath } from "react-router";
5
6
  import { useAuth } from "../../authentication/hook.js";
6
- import { ColorMap } from "../../components/navigation/SidebarBadge.js";
7
7
  import { type ZudokuPlugin } from "../../core/plugins.js";
8
8
  import type { SchemaImports } from "../../oas/graphql/index.js";
9
9
  import { Button } from "../../ui/Button.js";
@@ -13,6 +13,8 @@ import { graphql } from "./graphql/index.js";
13
13
  import { OasPluginConfig } from "./interfaces.js";
14
14
  import type { PlaygroundContentProps } from "./playground/Playground.js";
15
15
  import { PlaygroundDialog } from "./playground/PlaygroundDialog.js";
16
+ import { createSidebarCategory } from "./util/createSidebarCategory.js";
17
+ import { getRoutes, getVersions } from "./util/getRoutes.js";
16
18
 
17
19
  const GetCategoriesQuery = graphql(`
18
20
  query GetCategories($input: JSON!, $type: SchemaType!) {
@@ -51,26 +53,18 @@ const GetOperationsQuery = graphql(`
51
53
  }
52
54
  `);
53
55
 
54
- type InternalOasPluginConfig = { schemaImports?: SchemaImports };
56
+ export type OperationResult = ResultOf<
57
+ typeof GetOperationsQuery
58
+ >["schema"]["operations"][number];
55
59
 
56
- const MethodColorMap: Record<string, keyof typeof ColorMap> = {
57
- get: "green",
58
- post: "blue",
59
- put: "yellow",
60
- delete: "red",
61
- patch: "purple",
62
- options: "gray",
63
- head: "gray",
64
- };
60
+ type InternalOasPluginConfig = { schemaImports?: SchemaImports };
65
61
 
66
62
  export type OpenApiPluginOptions = OasPluginConfig & InternalOasPluginConfig;
67
63
 
68
- const UNTAGGED_PATH = "~endpoints";
64
+ export const UNTAGGED_PATH = "~endpoints";
69
65
 
70
66
  export const openApiPlugin = (config: OpenApiPluginOptions): ZudokuPlugin => {
71
67
  const basePath = joinUrl(config.navigationId ?? "/reference");
72
- const versions = config.type === "file" ? Object.keys(config.input) : [];
73
-
74
68
  const client = new GraphQLClient(config);
75
69
 
76
70
  return {
@@ -96,9 +90,12 @@ export const openApiPlugin = (config: OpenApiPluginOptions): ZudokuPlugin => {
96
90
  server,
97
91
  method,
98
92
  url,
93
+ children,
99
94
  ...props
100
- }: Partial<PlaygroundContentProps> &
101
- Pick<PlaygroundContentProps, "server"> & {
95
+ }: Partial<PlaygroundContentProps> & { children: ReactNode } & Pick<
96
+ PlaygroundContentProps,
97
+ "server"
98
+ > & {
102
99
  requireAuth: boolean;
103
100
  }) => {
104
101
  const auth = useAuth();
@@ -127,7 +124,11 @@ export const openApiPlugin = (config: OpenApiPluginOptions): ZudokuPlugin => {
127
124
  {...props}
128
125
  >
129
126
  <Button className="gap-2 items-center" variant="outline">
130
- Open in Playground <CirclePlayIcon size={16} />
127
+ {children ?? (
128
+ <>
129
+ Open in Playground <CirclePlayIcon size={16} />
130
+ </>
131
+ )}
131
132
  </Button>
132
133
  </PlaygroundDialog>
133
134
  );
@@ -138,86 +139,78 @@ export const openApiPlugin = (config: OpenApiPluginOptions): ZudokuPlugin => {
138
139
  return [];
139
140
  }
140
141
 
141
- try {
142
- const urlVersion = versions.find((v) =>
143
- path.startsWith(joinUrl(basePath, v)),
144
- );
145
- const version = urlVersion ?? Object.keys(config.input).at(0);
146
-
147
- const tagData = await client.fetch(GetCategoriesQuery, {
148
- type: config.type,
149
- input: config.type === "file" ? config.input[version!] : config.input,
150
- });
142
+ const match = matchPath(
143
+ { path: `${basePath}/:version?/:tag`, end: true },
144
+ path,
145
+ );
151
146
 
152
- const tag = config.tagPages?.find(
153
- (tag) => path.split("/").at(-1) === slugify(tag),
147
+ try {
148
+ const versionParam = match?.params.version;
149
+ const version = versionParam ?? getVersions(config).at(0);
150
+ const type = config.type;
151
+ const input =
152
+ config.type === "file" ? config.input[version!] : config.input;
153
+
154
+ const collapsible = config.loadTags === true || config.type === "url";
155
+ const collapsed = !config.loadTags && config.type !== "url";
156
+
157
+ // find tag name by slug in config.tagPages
158
+ const tagName = config.tagPages?.find(
159
+ (tag) => slugify(tag) === match?.params.tag,
154
160
  );
155
161
 
156
- const operationsData = await client.fetch(GetOperationsQuery, {
157
- type: config.type,
158
- input: config.type === "file" ? config.input[version!] : config.input,
159
- tag: !config.loadTags ? tag : undefined,
160
- });
161
-
162
- const categories = tagData.schema.tags.flatMap<SidebarItem>((tag) => {
163
- const categoryLink = joinUrl(basePath, urlVersion, slugify(tag.name));
162
+ const [tagData, operationsData] = await Promise.all([
163
+ client.fetch(GetCategoriesQuery, { type, input }),
164
+ client.fetch(GetOperationsQuery, {
165
+ type,
166
+ input,
167
+ tag: !config.loadTags ? tagName : undefined,
168
+ }),
169
+ ]);
170
+
171
+ const categories = tagData.schema.tags.flatMap((tag) => {
172
+ const categoryPath = joinUrl(
173
+ basePath,
174
+ versionParam,
175
+ slugify(tag.name),
176
+ );
164
177
 
165
- const operations = operationsData.schema.operations
166
- .filter(
167
- (operation) =>
168
- operation.tags?.length !== 0 &&
169
- operation.tags?.map((t) => t.name).includes(tag.name),
170
- )
171
- .map((operation) => ({
172
- type: "link" as const,
173
- label: operation.summary ?? operation.path,
174
- href: `${categoryLink}#${operation.slug}`,
175
- badge: {
176
- label: operation.method,
177
- color: MethodColorMap[operation.method.toLowerCase()]!,
178
- invert: true,
179
- } as const,
180
- }));
178
+ const operations = operationsData.schema.operations.filter(
179
+ (operation) =>
180
+ operation.tags?.length !== 0 &&
181
+ operation.tags?.map((t) => t.name).includes(tag.name),
182
+ );
181
183
 
184
+ // skip empty categories
182
185
  if (config.loadTags && operations.length === 0) {
183
186
  return [];
184
187
  }
185
188
 
186
- return {
187
- type: "category",
189
+ return createSidebarCategory({
188
190
  label: tag.name,
189
- link: {
190
- type: "doc" as const,
191
- id: categoryLink,
192
- label: tag.name,
193
- },
194
- collapsible: config.loadTags,
195
- collapsed: !config.loadTags,
196
- items: operations,
197
- };
191
+ path: categoryPath,
192
+ operations:
193
+ match?.params.tag !== UNTAGGED_PATH || config.loadTags
194
+ ? operations
195
+ : [],
196
+ collapsible,
197
+ collapsed,
198
+ });
198
199
  });
199
200
 
200
- const { untagged } = operationsData.schema;
201
-
202
- if (untagged.length > 0) {
203
- const categoryLink = joinUrl(basePath, urlVersion, UNTAGGED_PATH);
204
-
205
- categories.push({
206
- type: "category",
207
- label: "Other endpoints",
208
- link: {
209
- type: "doc" as const,
210
- id: categoryLink,
201
+ if (operationsData.schema.untagged.length > 0) {
202
+ categories.push(
203
+ createSidebarCategory({
211
204
  label: "Other endpoints",
212
- },
213
- collapsible: config.loadTags,
214
- collapsed: !config.loadTags,
215
- items: untagged.map((operation) => ({
216
- type: "link" as const,
217
- label: operation.summary ?? operation.path,
218
- href: `${categoryLink}#${operation.slug}`,
219
- })),
220
- });
205
+ path: joinUrl(basePath, versionParam, UNTAGGED_PATH),
206
+ operations:
207
+ match?.params.tag === UNTAGGED_PATH || config.loadTags
208
+ ? operationsData.schema.untagged
209
+ : [],
210
+ collapsible,
211
+ collapsed,
212
+ }),
213
+ );
221
214
  }
222
215
 
223
216
  return categories;
@@ -225,62 +218,6 @@ export const openApiPlugin = (config: OpenApiPluginOptions): ZudokuPlugin => {
225
218
  return [];
226
219
  }
227
220
  },
228
- getRoutes: () => {
229
- const versionsInPath = versions.length > 1 ? [null, ...versions] : [null];
230
-
231
- const tagPages = (config.tagPages ?? []).map((tag) => ({
232
- tag,
233
- path: slugify(tag),
234
- }));
235
-
236
- return versionsInPath.map((version) => {
237
- const versionPath = joinUrl(basePath, version);
238
-
239
- return {
240
- path: versionPath,
241
- async lazy() {
242
- const { OpenApiRoute } = await import("./OpenApiRoute.js");
243
- return {
244
- element: (
245
- <OpenApiRoute
246
- version={version ?? undefined}
247
- basePath={basePath}
248
- versions={versions}
249
- client={client}
250
- config={config}
251
- />
252
- ),
253
- };
254
- },
255
- children: [
256
- {
257
- index: true,
258
- loader: () =>
259
- redirect(
260
- joinUrl(versionPath, tagPages.at(0)?.path ?? UNTAGGED_PATH),
261
- ),
262
- },
263
- {
264
- path: joinUrl(versionPath, UNTAGGED_PATH),
265
- async lazy() {
266
- const { OperationList } = await import("./OperationList.js");
267
- return { element: <OperationList untagged={true} /> };
268
- },
269
- },
270
- ...tagPages.map<RouteObject>((tag) => {
271
- return {
272
- path: joinUrl(versionPath, tag.path),
273
- async lazy() {
274
- const { OperationList } = await import("./OperationList.js");
275
- return {
276
- element: <OperationList tag={tag.tag} />,
277
- };
278
- },
279
- };
280
- }),
281
- ],
282
- };
283
- });
284
- },
221
+ getRoutes: () => getRoutes({ basePath, config, client }),
285
222
  };
286
223
  };
@@ -88,7 +88,7 @@ export type PlaygroundResult = {
88
88
  };
89
89
 
90
90
  export type PlaygroundContentProps = {
91
- server: string;
91
+ server?: string;
92
92
  servers?: string[];
93
93
  url: string;
94
94
  method: string;
@@ -111,7 +111,7 @@ export const Playground = ({
111
111
  examples,
112
112
  }: PlaygroundContentProps) => {
113
113
  const { selectedServer, setSelectedServer } = useSelectedServer(
114
- servers.map((server) => ({ url: server })),
114
+ servers.map((url) => ({ url })),
115
115
  );
116
116
  const [, startTransition] = useTransition();
117
117
  const { register, control, handleSubmit, watch, setValue, ...form } =
@@ -172,7 +172,7 @@ export const Playground = ({
172
172
  mutationFn: async (data: PlaygroundForm) => {
173
173
  const start = performance.now();
174
174
  const request = new Request(
175
- createUrl(selectedServer ?? server, url, data),
175
+ createUrl(server ?? selectedServer, url, data),
176
176
  {
177
177
  method: method.toUpperCase(),
178
178
  headers: Object.fromEntries(
@@ -185,7 +185,7 @@ export const Playground = ({
185
185
  );
186
186
 
187
187
  if (data.identity !== NO_IDENTITY) {
188
- identities.data
188
+ await identities.data
189
189
  ?.find((i) => i.id === data.identity)
190
190
  ?.authorizeRequest(request);
191
191
  }
@@ -263,27 +263,29 @@ export const Playground = ({
263
263
 
264
264
  const serverSelect = (
265
265
  <div className="inline-block opacity-50 hover:opacity-100 transition">
266
- {servers && servers.length > 1 ? (
267
- <Select
268
- onValueChange={(value) => {
269
- startTransition(() => setSelectedServer(value));
270
- }}
271
- value={selectedServer}
272
- defaultValue={selectedServer}
273
- >
274
- <SelectTrigger className="p-0 border-none flex-row-reverse bg-transparent text-xs gap-0.5 h-auto">
275
- <SelectValue />
276
- </SelectTrigger>
277
- <SelectContent>
278
- {servers.map((s) => (
279
- <SelectItem key={s} value={s}>
280
- {s.replace(/^https?:\/\//, "")}
281
- </SelectItem>
282
- ))}
283
- </SelectContent>
284
- </Select>
285
- ) : (
266
+ {server ? (
286
267
  <span>{server.replace(/^https?:\/\//, "")}</span>
268
+ ) : (
269
+ servers.length > 1 && (
270
+ <Select
271
+ onValueChange={(value) => {
272
+ startTransition(() => setSelectedServer(value));
273
+ }}
274
+ value={selectedServer}
275
+ defaultValue={selectedServer}
276
+ >
277
+ <SelectTrigger className="p-0 border-none flex-row-reverse bg-transparent text-xs gap-0.5 h-auto">
278
+ <SelectValue />
279
+ </SelectTrigger>
280
+ <SelectContent>
281
+ {servers.map((s) => (
282
+ <SelectItem key={s} value={s}>
283
+ {s.replace(/^https?:\/\//, "")}
284
+ </SelectItem>
285
+ ))}
286
+ </SelectContent>
287
+ </Select>
288
+ )
287
289
  )}
288
290
  </div>
289
291
  );
@@ -40,7 +40,7 @@ export const RequestTab = ({
40
40
  {headers.map(([key, value]) => (
41
41
  <Fragment key={key}>
42
42
  <div className="text-primary">{key}</div>
43
- <div className="break-words">{value}</div>
43
+ <div className="break-all">{value}</div>
44
44
  </Fragment>
45
45
  ))}
46
46
  </div>
@@ -0,0 +1,39 @@
1
+ import type { SidebarItem } from "../../../../config/validators/SidebarSchema.js";
2
+ import type { OperationResult } from "../index.js";
3
+ import { MethodColorMap } from "./methodColorMap.js";
4
+
5
+ export const createSidebarCategory = ({
6
+ label,
7
+ path,
8
+ operations,
9
+ collapsible,
10
+ collapsed,
11
+ }: {
12
+ label: string;
13
+ path: string;
14
+ operations: OperationResult[];
15
+ collapsible?: boolean;
16
+ collapsed?: boolean;
17
+ }): SidebarItem => ({
18
+ type: "category",
19
+ label,
20
+ link: {
21
+ type: "doc" as const,
22
+ id: path,
23
+ label,
24
+ },
25
+ collapsible,
26
+ collapsed,
27
+ items: operations.map((operation) => ({
28
+ type: "link" as const,
29
+ label: operation.summary ?? operation.path,
30
+ href: `${path}#${operation.slug}`,
31
+ ...(operation.method && {
32
+ badge: {
33
+ label: operation.method,
34
+ color: MethodColorMap[operation.method.toLowerCase()]!,
35
+ invert: true,
36
+ } as const,
37
+ }),
38
+ })),
39
+ });
@@ -0,0 +1,123 @@
1
+ import slugify from "@sindresorhus/slugify";
2
+ import { redirect, type RouteObject } from "react-router";
3
+ import { joinUrl } from "../../../util/joinUrl.js";
4
+ import type { GraphQLClient } from "../client/GraphQLClient.js";
5
+ import { type OpenApiPluginOptions, UNTAGGED_PATH } from "../index.js";
6
+ import type { OasPluginConfig } from "../interfaces.js";
7
+
8
+ // Creates the main provider route that wraps operation routes.
9
+ const createOasProvider = (opts: {
10
+ routePath: string;
11
+ basePath: string;
12
+ version?: string;
13
+ routes: RouteObject[];
14
+ client: GraphQLClient;
15
+ config: OpenApiPluginOptions;
16
+ }): RouteObject => ({
17
+ path: opts.routePath,
18
+ async lazy() {
19
+ const { OasProvider } = await import("../OasProvider.js");
20
+ return {
21
+ element: (
22
+ <OasProvider
23
+ basePath={opts.basePath}
24
+ version={opts.version}
25
+ client={opts.client}
26
+ config={opts.config}
27
+ />
28
+ ),
29
+ };
30
+ },
31
+ children: opts.routes,
32
+ });
33
+
34
+ // Creates a route for displaying the operation list used for both tagged and untagged operations.
35
+ const createRoute = ({
36
+ path,
37
+ tag,
38
+ untagged,
39
+ }: {
40
+ path: string;
41
+ tag?: string;
42
+ untagged?: boolean;
43
+ }): RouteObject => ({
44
+ path,
45
+ async lazy() {
46
+ const { OperationList } = await import("../OperationList.js");
47
+ return { element: <OperationList tag={tag} untagged={untagged} /> };
48
+ },
49
+ });
50
+
51
+ // Creates routes for a specific version, including tag-based routes and the untagged operations route.
52
+ const createVersionRoutes = (
53
+ versionPath: string,
54
+ tagPages: string[],
55
+ ): RouteObject[] => {
56
+ const firstTagRoute = joinUrl(
57
+ versionPath,
58
+ tagPages[0] ? slugify(tagPages[0]) : UNTAGGED_PATH,
59
+ );
60
+
61
+ return [
62
+ // Redirect to first tag on the index route
63
+ { index: true, loader: () => redirect(firstTagRoute) },
64
+ // Create routes for each tag
65
+ ...tagPages.map((tag) =>
66
+ createRoute({
67
+ path: joinUrl(versionPath, slugify(tag)),
68
+ tag,
69
+ }),
70
+ ),
71
+ // Category without tagged operations
72
+ createRoute({
73
+ path: joinUrl(versionPath, UNTAGGED_PATH),
74
+ untagged: true,
75
+ }),
76
+ ];
77
+ };
78
+
79
+ export const getVersions = (config: OasPluginConfig) =>
80
+ config.type === "file" ? Object.keys(config.input) : [];
81
+
82
+ export const getRoutes = ({
83
+ basePath,
84
+ config,
85
+ client,
86
+ }: {
87
+ client: GraphQLClient;
88
+ config: OpenApiPluginOptions;
89
+ basePath: string;
90
+ }): RouteObject[] => {
91
+ const tagPages = config.tagPages;
92
+
93
+ // If the config does not provide tag pages the catch-all
94
+ // route handles all operations on a single page
95
+ if (!tagPages) {
96
+ return [
97
+ createOasProvider({
98
+ basePath,
99
+ routePath: basePath,
100
+ routes: [createRoute({ path: basePath + "/:tag?" })],
101
+ client,
102
+ config,
103
+ }),
104
+ ];
105
+ }
106
+
107
+ const versions = getVersions(config);
108
+ // The latest version always is added as index path
109
+ const versionsInPath =
110
+ versions.length > 1 ? [undefined, ...versions] : [undefined];
111
+
112
+ return versionsInPath.map((version) => {
113
+ const versionPath = joinUrl(basePath, version);
114
+ return createOasProvider({
115
+ basePath,
116
+ version,
117
+ routePath: versionPath,
118
+ routes: createVersionRoutes(versionPath, tagPages),
119
+ client,
120
+ config,
121
+ });
122
+ });
123
+ };
@@ -0,0 +1,11 @@
1
+ import { ColorMap } from "../../../components/navigation/SidebarBadge.js";
2
+
3
+ export const MethodColorMap: Record<string, keyof typeof ColorMap> = {
4
+ get: "green",
5
+ post: "blue",
6
+ put: "yellow",
7
+ delete: "red",
8
+ patch: "purple",
9
+ options: "gray",
10
+ head: "gray",
11
+ };
@@ -1,25 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Outlet } from "react-router";
3
- import { joinPath } from "../../util/joinPath.js";
4
- import { GraphQLProvider } from "./client/GraphQLContext.js";
5
- import { OasConfigProvider } from "./context.js";
6
- export const OpenApiRoute = ({ basePath, versions, version, config, client, }) => {
7
- const input = config.type === "file"
8
- ? {
9
- type: config.type,
10
- input: version
11
- ? config.input[version]
12
- : Object.values(config.input).at(0),
13
- }
14
- : { type: config.type, input: config.input };
15
- const currentVersion = version ?? versions.at(0);
16
- return (_jsx(OasConfigProvider, { value: {
17
- config: {
18
- ...config,
19
- version: currentVersion,
20
- versions: Object.fromEntries(versions.map((version) => [version, joinPath(basePath, version)])),
21
- ...input,
22
- },
23
- }, children: _jsx(GraphQLProvider, { client: client, children: _jsx(Outlet, {}) }) }));
24
- };
25
- //# sourceMappingURL=OpenApiRoute.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"OpenApiRoute.js","sourceRoot":"","sources":["../../../../src/lib/plugins/openapi/OpenApiRoute.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGjD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAC3B,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,MAAM,EACN,MAAM,GAOP,EAAE,EAAE;IACH,MAAM,KAAK,GACT,MAAM,CAAC,IAAI,KAAK,MAAM;QACpB,CAAC,CAAC;YACE,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,KAAK,EAAE,OAAO;gBACZ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAE;gBACxB,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAE;SACvC;QACH,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;IAEjD,MAAM,cAAc,GAAG,OAAO,IAAI,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAEjD,OAAO,CACL,KAAC,iBAAiB,IAChB,KAAK,EAAE;YACL,MAAM,EAAE;gBACN,GAAG,MAAM;gBACT,OAAO,EAAE,cAAc;gBACvB,QAAQ,EAAE,MAAM,CAAC,WAAW,CAC1B,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,CAClE;gBACD,GAAG,KAAK;aACT;SACF,YAED,KAAC,eAAe,IAAC,MAAM,EAAE,MAAM,YAC7B,KAAC,MAAM,KAAG,GACM,GACA,CACrB,CAAC;AACJ,CAAC,CAAC"}
@@ -1,36 +0,0 @@
1
- import { j as e } from "./jsx-runtime-Bdg6XQ1m.js";
2
- import { O as n } from "./chunk-SYFQ2XB5-QijJrSf0.js";
3
- import { j as m } from "./hook-Dnj3SwPC.js";
4
- import { O as j, G as O } from "./context-rwLGh-6_.js";
5
- const h = ({
6
- basePath: i,
7
- versions: p,
8
- version: r,
9
- config: t,
10
- client: a
11
- }) => {
12
- const o = t.type === "file" ? {
13
- type: t.type,
14
- input: r ? t.input[r] : Object.values(t.input).at(0)
15
- } : { type: t.type, input: t.input }, u = r ?? p.at(0);
16
- return /* @__PURE__ */ e.jsx(
17
- j,
18
- {
19
- value: {
20
- config: {
21
- ...t,
22
- version: u,
23
- versions: Object.fromEntries(
24
- p.map((s) => [s, m(i, s)])
25
- ),
26
- ...o
27
- }
28
- },
29
- children: /* @__PURE__ */ e.jsx(O, { client: a, children: /* @__PURE__ */ e.jsx(n, {}) })
30
- }
31
- );
32
- };
33
- export {
34
- h as OpenApiRoute
35
- };
36
- //# sourceMappingURL=OpenApiRoute-BP9kzG5k.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"OpenApiRoute-BP9kzG5k.js","sources":["../src/lib/plugins/openapi/OpenApiRoute.tsx"],"sourcesContent":["import { Outlet } from \"react-router\";\nimport { joinPath } from \"../../util/joinPath.js\";\nimport type { GraphQLClient } from \"./client/GraphQLClient.js\";\nimport { GraphQLProvider } from \"./client/GraphQLContext.js\";\nimport { OasConfigProvider } from \"./context.js\";\nimport { type OasPluginConfig } from \"./interfaces.js\";\n\nexport const OpenApiRoute = ({\n basePath,\n versions,\n version,\n config,\n client,\n}: {\n basePath: string;\n version?: string;\n versions: string[];\n config: OasPluginConfig;\n client: GraphQLClient;\n}) => {\n const input =\n config.type === \"file\"\n ? {\n type: config.type,\n input: version\n ? config.input[version]!\n : Object.values(config.input).at(0)!,\n }\n : { type: config.type, input: config.input };\n\n const currentVersion = version ?? versions.at(0);\n\n return (\n <OasConfigProvider\n value={{\n config: {\n ...config,\n version: currentVersion,\n versions: Object.fromEntries(\n versions.map((version) => [version, joinPath(basePath, version)]),\n ),\n ...input,\n },\n }}\n >\n <GraphQLProvider client={client}>\n <Outlet />\n </GraphQLProvider>\n </OasConfigProvider>\n );\n};\n"],"names":["OpenApiRoute","basePath","versions","version","config","client","input","currentVersion","jsx","OasConfigProvider","joinPath","GraphQLProvider","Outlet"],"mappings":";;;;AAOO,MAAMA,IAAe,CAAC;AAAA,EAC3B,UAAAC;AAAA,EACA,UAAAC;AAAA,EACA,SAAAC;AAAA,EACA,QAAAC;AAAA,EACA,QAAAC;AACF,MAMM;AACE,QAAAC,IACJF,EAAO,SAAS,SACZ;AAAA,IACE,MAAMA,EAAO;AAAA,IACb,OAAOD,IACHC,EAAO,MAAMD,CAAO,IACpB,OAAO,OAAOC,EAAO,KAAK,EAAE,GAAG,CAAC;AAAA,EAAA,IAEtC,EAAE,MAAMA,EAAO,MAAM,OAAOA,EAAO,MAAM,GAEzCG,IAAiBJ,KAAWD,EAAS,GAAG,CAAC;AAG7C,SAAAM,gBAAAA,EAAA;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,OAAO;AAAA,QACL,QAAQ;AAAA,UACN,GAAGL;AAAA,UACH,SAASG;AAAA,UACT,UAAU,OAAO;AAAA,YACfL,EAAS,IAAI,CAACC,MAAY,CAACA,GAASO,EAAST,GAAUE,CAAO,CAAC,CAAC;AAAA,UAClE;AAAA,UACA,GAAGG;AAAA,QAAA;AAAA,MAEP;AAAA,MAEA,UAACE,gBAAAA,EAAAA,IAAAG,GAAA,EAAgB,QAAAN,GACf,UAAAG,gBAAAA,EAAA,IAACI,KAAO,EACV,CAAA;AAAA,IAAA;AAAA,EACF;AAEJ;"}