zudoku 0.27.0 → 0.28.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.
- package/dist/lib/components/navigation/SidebarCategory.js +3 -3
- package/dist/lib/components/navigation/SidebarCategory.js.map +1 -1
- package/dist/lib/oas/graphql/index.d.ts +1 -0
- package/dist/lib/oas/graphql/index.js +41 -23
- package/dist/lib/oas/graphql/index.js.map +1 -1
- package/dist/lib/plugins/openapi/Endpoint.js +2 -2
- package/dist/lib/plugins/openapi/Endpoint.js.map +1 -1
- package/dist/lib/plugins/openapi/{Route.d.ts → OpenApiRoute.d.ts} +2 -1
- package/dist/lib/plugins/openapi/{Route.js → OpenApiRoute.js} +3 -4
- package/dist/lib/plugins/openapi/OpenApiRoute.js.map +1 -0
- package/dist/lib/plugins/openapi/OperationList.d.ts +4 -1
- package/dist/lib/plugins/openapi/OperationList.js +20 -14
- package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
- package/dist/lib/plugins/openapi/RequestBodySidecarBox.d.ts +1 -1
- package/dist/lib/plugins/openapi/RequestBodySidecarBox.js +2 -0
- package/dist/lib/plugins/openapi/RequestBodySidecarBox.js.map +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
- package/dist/lib/plugins/openapi/SidecarExamples.js +17 -14
- package/dist/lib/plugins/openapi/SidecarExamples.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/gql.d.ts +6 -2
- package/dist/lib/plugins/openapi/graphql/gql.js +3 -2
- package/dist/lib/plugins/openapi/graphql/gql.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/graphql.d.ts +47 -26
- package/dist/lib/plugins/openapi/graphql/graphql.js +20 -16
- package/dist/lib/plugins/openapi/graphql/graphql.js.map +1 -1
- package/dist/lib/plugins/openapi/index.js +97 -54
- package/dist/lib/plugins/openapi/index.js.map +1 -1
- package/dist/lib/plugins/openapi/interfaces.d.ts +1 -0
- package/dist/lib/util/joinUrl.js +1 -1
- package/dist/lib/util/joinUrl.js.map +1 -1
- package/dist/lib/util/joinUrl.test.d.ts +1 -0
- package/dist/lib/util/joinUrl.test.js +43 -0
- package/dist/lib/util/joinUrl.test.js.map +1 -0
- package/dist/vite/plugin-api.js +7 -1
- package/dist/vite/plugin-api.js.map +1 -1
- package/lib/{AuthenticationPlugin-CO_YCd2x.js → AuthenticationPlugin-Du8cLBSr.js} +2 -2
- package/lib/{AuthenticationPlugin-CO_YCd2x.js.map → AuthenticationPlugin-Du8cLBSr.js.map} +1 -1
- package/lib/{Markdown-B8o9Qz4q.js → Markdown-Cyrx_JrO.js} +8 -9
- package/lib/{Markdown-B8o9Qz4q.js.map → Markdown-Cyrx_JrO.js.map} +1 -1
- package/lib/{MdxPage-BxRt3Ly7.js → MdxPage-DewragjB.js} +5 -5
- package/lib/{MdxPage-BxRt3Ly7.js.map → MdxPage-DewragjB.js.map} +1 -1
- package/lib/OpenApiRoute-UrC_t0e5.js +36 -0
- package/lib/OpenApiRoute-UrC_t0e5.js.map +1 -0
- package/lib/{OperationList-DH-zIgtq.js → OperationList-D_ejrepA.js} +1373 -1372
- package/lib/OperationList-D_ejrepA.js.map +1 -0
- package/lib/{Select-B7UXR0SB.js → Select-CnCZ4WhS.js} +3 -3
- package/lib/{Select-B7UXR0SB.js.map → Select-CnCZ4WhS.js.map} +1 -1
- package/lib/{SlotletProvider-CtIp8rP3.js → SlotletProvider-mQiPDQIH.js} +2 -2
- package/lib/{SlotletProvider-CtIp8rP3.js.map → SlotletProvider-mQiPDQIH.js.map} +1 -1
- package/lib/{SyntaxHighlight-C1w1QPdY.js → SyntaxHighlight-B0L4SC_N.js} +11 -5
- package/lib/SyntaxHighlight-B0L4SC_N.js.map +1 -0
- package/lib/{ZudokuContext-8jts0fF3.js → ZudokuContext-BTUJPpQl.js} +21 -21
- package/lib/{ZudokuContext-8jts0fF3.js.map → ZudokuContext-BTUJPpQl.js.map} +1 -1
- package/lib/{createServer-BV0tHzLK.js → createServer-BydbkTsd.js} +821 -808
- package/lib/{createServer-BV0tHzLK.js.map → createServer-BydbkTsd.js.map} +1 -1
- package/lib/{hook-BG02esyv.js → hook-FT3SJLe_.js} +2 -2
- package/lib/{hook-BG02esyv.js.map → hook-FT3SJLe_.js.map} +1 -1
- package/lib/{index-LNp6rxyU.js → index-CjJS0l4l.js} +2 -2
- package/lib/{index-LNp6rxyU.js.map → index-CjJS0l4l.js.map} +1 -1
- package/lib/{index-DmqsUPcm.js → index-DGugJOLc.js} +836 -777
- package/lib/index-DGugJOLc.js.map +1 -0
- package/lib/{joinUrl-BTy9bvoK.js → joinUrl-nLx9pD-Z.js} +2 -2
- package/lib/joinUrl-nLx9pD-Z.js.map +1 -0
- package/lib/{useScrollToAnchor-Bl6mz9_x.js → useScrollToAnchor-eRM9tVvD.js} +10 -9
- package/lib/useScrollToAnchor-eRM9tVvD.js.map +1 -0
- package/lib/zudoku.auth-clerk.js +1 -1
- package/lib/zudoku.auth-openid.js +3 -3
- package/lib/zudoku.components.js +153 -154
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.plugin-api-catalog.js +3 -3
- package/lib/zudoku.plugin-api-keys.js +4 -4
- package/lib/zudoku.plugin-custom-pages.js +1 -1
- package/lib/zudoku.plugin-markdown.js +1 -1
- package/lib/zudoku.plugin-openapi.js +6 -5
- package/lib/zudoku.plugin-openapi.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/components/navigation/SidebarCategory.tsx +3 -2
- package/src/lib/oas/graphql/index.ts +63 -35
- package/src/lib/plugins/openapi/Endpoint.tsx +2 -2
- package/src/lib/plugins/openapi/{Route.tsx → OpenApiRoute.tsx} +3 -3
- package/src/lib/plugins/openapi/OperationList.tsx +34 -12
- package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +2 -0
- package/src/lib/plugins/openapi/Sidecar.tsx +1 -1
- package/src/lib/plugins/openapi/SidecarExamples.tsx +24 -24
- package/src/lib/plugins/openapi/graphql/gql.ts +12 -4
- package/src/lib/plugins/openapi/graphql/graphql.ts +66 -43
- package/src/lib/plugins/openapi/index.tsx +125 -67
- package/src/lib/plugins/openapi/interfaces.ts +1 -0
- package/src/lib/util/joinUrl.test.ts +62 -0
- package/src/lib/util/joinUrl.ts +1 -1
- package/dist/lib/plugins/openapi/Route.js.map +0 -1
- package/lib/OperationList-DH-zIgtq.js.map +0 -1
- package/lib/Route-DJ0ZlVq1.js +0 -35
- package/lib/Route-DJ0ZlVq1.js.map +0 -1
- package/lib/StaggeredRender-DgsamH_G.js +0 -17
- package/lib/StaggeredRender-DgsamH_G.js.map +0 -1
- package/lib/SyntaxHighlight-C1w1QPdY.js.map +0 -1
- package/lib/index-Bn6Lc9tq.js +0 -9
- package/lib/index-Bn6Lc9tq.js.map +0 -1
- package/lib/index-DmqsUPcm.js.map +0 -1
- package/lib/joinUrl-BTy9bvoK.js.map +0 -1
- package/lib/useScrollToAnchor-Bl6mz9_x.js.map +0 -1
|
@@ -31,6 +31,8 @@ export type Scalars = {
|
|
|
31
31
|
JSON: { input: any; output: any };
|
|
32
32
|
/** The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */
|
|
33
33
|
JSONObject: { input: any; output: any };
|
|
34
|
+
/** OpenAPI schema scalar type that handles circular references */
|
|
35
|
+
JSONSchema: { input: any; output: any };
|
|
34
36
|
};
|
|
35
37
|
|
|
36
38
|
export type EncodingItem = {
|
|
@@ -57,7 +59,7 @@ export type MediaTypeObject = {
|
|
|
57
59
|
encoding?: Maybe<Array<EncodingItem>>;
|
|
58
60
|
examples?: Maybe<Array<ExampleItem>>;
|
|
59
61
|
mediaType: Scalars["String"]["output"];
|
|
60
|
-
schema?: Maybe<Scalars["
|
|
62
|
+
schema?: Maybe<Scalars["JSONSchema"]["output"]>;
|
|
61
63
|
};
|
|
62
64
|
|
|
63
65
|
export type OperationItem = {
|
|
@@ -89,7 +91,7 @@ export type ParameterItem = {
|
|
|
89
91
|
in: ParameterIn;
|
|
90
92
|
name: Scalars["String"]["output"];
|
|
91
93
|
required?: Maybe<Scalars["Boolean"]["output"]>;
|
|
92
|
-
schema?: Maybe<Scalars["
|
|
94
|
+
schema?: Maybe<Scalars["JSONSchema"]["output"]>;
|
|
93
95
|
style?: Maybe<Scalars["String"]["output"]>;
|
|
94
96
|
};
|
|
95
97
|
|
|
@@ -132,11 +134,11 @@ export type Schema = {
|
|
|
132
134
|
operations: Array<OperationItem>;
|
|
133
135
|
paths: Array<PathItem>;
|
|
134
136
|
servers: Array<Server>;
|
|
137
|
+
summary?: Maybe<Scalars["String"]["output"]>;
|
|
135
138
|
tags: Array<SchemaTag>;
|
|
136
139
|
title: Scalars["String"]["output"];
|
|
137
|
-
url
|
|
140
|
+
url?: Maybe<Scalars["String"]["output"]>;
|
|
138
141
|
version: Scalars["String"]["output"];
|
|
139
|
-
summary?: Maybe<Scalars["String"]["output"]>;
|
|
140
142
|
};
|
|
141
143
|
|
|
142
144
|
export type SchemaOperationsArgs = {
|
|
@@ -144,6 +146,7 @@ export type SchemaOperationsArgs = {
|
|
|
144
146
|
operationId?: InputMaybe<Scalars["String"]["input"]>;
|
|
145
147
|
path?: InputMaybe<Scalars["String"]["input"]>;
|
|
146
148
|
tag?: InputMaybe<Scalars["String"]["input"]>;
|
|
149
|
+
untagged?: InputMaybe<Scalars["Boolean"]["input"]>;
|
|
147
150
|
};
|
|
148
151
|
|
|
149
152
|
export type SchemaTagsArgs = {
|
|
@@ -180,7 +183,7 @@ export type ServersQueryQuery = {
|
|
|
180
183
|
__typename?: "Query";
|
|
181
184
|
schema: {
|
|
182
185
|
__typename?: "Schema";
|
|
183
|
-
url
|
|
186
|
+
url?: string | null;
|
|
184
187
|
servers: Array<{ __typename?: "Server"; url: string }>;
|
|
185
188
|
};
|
|
186
189
|
};
|
|
@@ -255,6 +258,8 @@ export type OperationsFragmentFragment = {
|
|
|
255
258
|
export type AllOperationsQueryVariables = Exact<{
|
|
256
259
|
input: Scalars["JSON"]["input"];
|
|
257
260
|
type: SchemaType;
|
|
261
|
+
tag?: InputMaybe<Scalars["String"]["input"]>;
|
|
262
|
+
untagged?: InputMaybe<Scalars["Boolean"]["input"]>;
|
|
258
263
|
}>;
|
|
259
264
|
|
|
260
265
|
export type AllOperationsQuery = {
|
|
@@ -264,20 +269,20 @@ export type AllOperationsQuery = {
|
|
|
264
269
|
description?: string | null;
|
|
265
270
|
summary?: string | null;
|
|
266
271
|
title: string;
|
|
267
|
-
url
|
|
272
|
+
url?: string | null;
|
|
268
273
|
version: string;
|
|
269
274
|
tags: Array<{
|
|
270
275
|
__typename?: "SchemaTag";
|
|
271
276
|
name?: string | null;
|
|
272
277
|
description?: string | null;
|
|
273
|
-
operations: Array<
|
|
274
|
-
{ __typename?: "OperationItem"; slug: string } & {
|
|
275
|
-
" $fragmentRefs"?: {
|
|
276
|
-
OperationsFragmentFragment: OperationsFragmentFragment;
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
>;
|
|
280
278
|
}>;
|
|
279
|
+
operations: Array<
|
|
280
|
+
{ __typename?: "OperationItem"; slug: string } & {
|
|
281
|
+
" $fragmentRefs"?: {
|
|
282
|
+
OperationsFragmentFragment: OperationsFragmentFragment;
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
>;
|
|
281
286
|
};
|
|
282
287
|
};
|
|
283
288
|
|
|
@@ -290,7 +295,7 @@ export type GetServerQueryQuery = {
|
|
|
290
295
|
__typename?: "Query";
|
|
291
296
|
schema: {
|
|
292
297
|
__typename?: "Schema";
|
|
293
|
-
url
|
|
298
|
+
url?: string | null;
|
|
294
299
|
servers: Array<{ __typename?: "Server"; url: string }>;
|
|
295
300
|
};
|
|
296
301
|
};
|
|
@@ -304,19 +309,30 @@ export type GetCategoriesQuery = {
|
|
|
304
309
|
__typename?: "Query";
|
|
305
310
|
schema: {
|
|
306
311
|
__typename?: "Schema";
|
|
307
|
-
url
|
|
308
|
-
tags: Array<{
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
312
|
+
url?: string | null;
|
|
313
|
+
tags: Array<{ __typename?: "SchemaTag"; name?: string | null }>;
|
|
314
|
+
};
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
export type GetOperationsQueryVariables = Exact<{
|
|
318
|
+
input: Scalars["JSON"]["input"];
|
|
319
|
+
type: SchemaType;
|
|
320
|
+
tag?: InputMaybe<Scalars["String"]["input"]>;
|
|
321
|
+
untagged?: InputMaybe<Scalars["Boolean"]["input"]>;
|
|
322
|
+
}>;
|
|
323
|
+
|
|
324
|
+
export type GetOperationsQuery = {
|
|
325
|
+
__typename?: "Query";
|
|
326
|
+
schema: {
|
|
327
|
+
__typename?: "Schema";
|
|
328
|
+
operations: Array<{
|
|
329
|
+
__typename?: "OperationItem";
|
|
330
|
+
slug: string;
|
|
331
|
+
deprecated?: boolean | null;
|
|
332
|
+
method: string;
|
|
333
|
+
summary?: string | null;
|
|
334
|
+
operationId?: string | null;
|
|
335
|
+
path: string;
|
|
320
336
|
}>;
|
|
321
337
|
};
|
|
322
338
|
};
|
|
@@ -418,20 +434,20 @@ export const ServersQueryDocument = new TypedDocumentString(`
|
|
|
418
434
|
ServersQueryQueryVariables
|
|
419
435
|
>;
|
|
420
436
|
export const AllOperationsDocument = new TypedDocumentString(`
|
|
421
|
-
query AllOperations($input: JSON!, $type: SchemaType
|
|
437
|
+
query AllOperations($input: JSON!, $type: SchemaType!, $tag: String, $untagged: Boolean) {
|
|
422
438
|
schema(input: $input, type: $type) {
|
|
423
439
|
description
|
|
424
440
|
summary
|
|
425
441
|
title
|
|
426
442
|
url
|
|
427
443
|
version
|
|
428
|
-
tags {
|
|
444
|
+
tags(name: $tag) {
|
|
429
445
|
name
|
|
430
446
|
description
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
447
|
+
}
|
|
448
|
+
operations(tag: $tag, untagged: $untagged) {
|
|
449
|
+
slug
|
|
450
|
+
...OperationsFragment
|
|
435
451
|
}
|
|
436
452
|
}
|
|
437
453
|
}
|
|
@@ -517,17 +533,7 @@ export const GetCategoriesDocument = new TypedDocumentString(`
|
|
|
517
533
|
schema(input: $input, type: $type) {
|
|
518
534
|
url
|
|
519
535
|
tags {
|
|
520
|
-
__typename
|
|
521
536
|
name
|
|
522
|
-
operations {
|
|
523
|
-
__typename
|
|
524
|
-
slug
|
|
525
|
-
deprecated
|
|
526
|
-
method
|
|
527
|
-
summary
|
|
528
|
-
operationId
|
|
529
|
-
path
|
|
530
|
-
}
|
|
531
537
|
}
|
|
532
538
|
}
|
|
533
539
|
}
|
|
@@ -535,3 +541,20 @@ export const GetCategoriesDocument = new TypedDocumentString(`
|
|
|
535
541
|
GetCategoriesQuery,
|
|
536
542
|
GetCategoriesQueryVariables
|
|
537
543
|
>;
|
|
544
|
+
export const GetOperationsDocument = new TypedDocumentString(`
|
|
545
|
+
query GetOperations($input: JSON!, $type: SchemaType!, $tag: String, $untagged: Boolean) {
|
|
546
|
+
schema(input: $input, type: $type) {
|
|
547
|
+
operations(tag: $tag, untagged: $untagged) {
|
|
548
|
+
slug
|
|
549
|
+
deprecated
|
|
550
|
+
method
|
|
551
|
+
summary
|
|
552
|
+
operationId
|
|
553
|
+
path
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
`) as unknown as TypedDocumentString<
|
|
558
|
+
GetOperationsQuery,
|
|
559
|
+
GetOperationsQueryVariables
|
|
560
|
+
>;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { type ZudokuPlugin } from "../../core/plugins.js";
|
|
3
|
-
import { graphql } from "./graphql/index.js";
|
|
4
|
-
|
|
1
|
+
import slugify from "@sindresorhus/slugify";
|
|
5
2
|
import { CirclePlayIcon, LogInIcon } from "lucide-react";
|
|
3
|
+
import { matchPath, redirect, RouteObject } from "react-router";
|
|
6
4
|
import type { SidebarItem } from "../../../config/validators/SidebarSchema.js";
|
|
7
5
|
import { useAuth } from "../../authentication/hook.js";
|
|
8
6
|
import { ColorMap } from "../../components/navigation/SidebarBadge.js";
|
|
7
|
+
import { type ZudokuPlugin } from "../../core/plugins.js";
|
|
9
8
|
import type { SchemaImports } from "../../oas/graphql/index.js";
|
|
10
9
|
import { Button } from "../../ui/Button.js";
|
|
11
|
-
import {
|
|
10
|
+
import { joinUrl } from "../../util/joinUrl.js";
|
|
12
11
|
import { GraphQLClient } from "./client/GraphQLClient.js";
|
|
12
|
+
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";
|
|
@@ -19,17 +19,27 @@ const GetCategoriesQuery = graphql(`
|
|
|
19
19
|
schema(input: $input, type: $type) {
|
|
20
20
|
url
|
|
21
21
|
tags {
|
|
22
|
-
__typename
|
|
23
22
|
name
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
`);
|
|
27
|
+
|
|
28
|
+
const GetOperationsQuery = graphql(`
|
|
29
|
+
query GetOperations(
|
|
30
|
+
$input: JSON!
|
|
31
|
+
$type: SchemaType!
|
|
32
|
+
$tag: String
|
|
33
|
+
$untagged: Boolean
|
|
34
|
+
) {
|
|
35
|
+
schema(input: $input, type: $type) {
|
|
36
|
+
operations(tag: $tag, untagged: $untagged) {
|
|
37
|
+
slug
|
|
38
|
+
deprecated
|
|
39
|
+
method
|
|
40
|
+
summary
|
|
41
|
+
operationId
|
|
42
|
+
path
|
|
33
43
|
}
|
|
34
44
|
}
|
|
35
45
|
}
|
|
@@ -49,9 +59,10 @@ const MethodColorMap: Record<string, keyof typeof ColorMap> = {
|
|
|
49
59
|
|
|
50
60
|
export type OpenApiPluginOptions = OasPluginConfig & InternalOasPluginConfig;
|
|
51
61
|
|
|
52
|
-
|
|
53
|
-
const basePath = joinPath(config.navigationId ?? "/reference");
|
|
62
|
+
const UNTAGGED_PATH = "~endpoints";
|
|
54
63
|
|
|
64
|
+
export const openApiPlugin = (config: OpenApiPluginOptions): ZudokuPlugin => {
|
|
65
|
+
const basePath = joinUrl(config.navigationId ?? "/reference");
|
|
55
66
|
const versions = config.type === "file" ? Object.keys(config.input) : [];
|
|
56
67
|
|
|
57
68
|
const client = new GraphQLClient(config);
|
|
@@ -122,41 +133,60 @@ export const openApiPlugin = (config: OpenApiPluginOptions): ZudokuPlugin => {
|
|
|
122
133
|
}
|
|
123
134
|
|
|
124
135
|
try {
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
136
|
+
const urlVersion = versions.find((v) =>
|
|
137
|
+
path.startsWith(joinUrl(basePath, v)),
|
|
138
|
+
);
|
|
139
|
+
const version = urlVersion ?? Object.keys(config.input).at(0);
|
|
128
140
|
|
|
129
141
|
const data = await client.fetch(GetCategoriesQuery, {
|
|
130
142
|
type: config.type,
|
|
131
143
|
input: config.type === "file" ? config.input[version!] : config.input,
|
|
132
|
-
version,
|
|
133
144
|
});
|
|
134
145
|
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
type: "category",
|
|
139
|
-
label: tag.name || "Other endpoints",
|
|
140
|
-
collapsible: true,
|
|
141
|
-
collapsed: false,
|
|
142
|
-
items: tag.operations.map((operation) => ({
|
|
143
|
-
type: "link",
|
|
144
|
-
label: operation.summary ?? operation.path,
|
|
145
|
-
href: `#${operation.slug}`,
|
|
146
|
-
badge: {
|
|
147
|
-
label: operation.method,
|
|
148
|
-
color: MethodColorMap[operation.method.toLowerCase()]!,
|
|
149
|
-
invert: true,
|
|
150
|
-
},
|
|
151
|
-
})),
|
|
152
|
-
}));
|
|
146
|
+
const tag = config.tagPages?.find(
|
|
147
|
+
(tag) => path.split("/").at(-1) === slugify(tag),
|
|
148
|
+
);
|
|
153
149
|
|
|
154
|
-
|
|
155
|
-
type:
|
|
156
|
-
|
|
157
|
-
|
|
150
|
+
const operationsData = await client.fetch(GetOperationsQuery, {
|
|
151
|
+
type: config.type,
|
|
152
|
+
input: config.type === "file" ? config.input[version!] : config.input,
|
|
153
|
+
tag,
|
|
154
|
+
untagged: tag === undefined,
|
|
158
155
|
});
|
|
159
156
|
|
|
157
|
+
const items = operationsData.schema.operations.map((operation) => ({
|
|
158
|
+
type: "link" as const,
|
|
159
|
+
label: operation.summary ?? operation.path,
|
|
160
|
+
href: `#${operation.slug}`,
|
|
161
|
+
badge: {
|
|
162
|
+
label: operation.method,
|
|
163
|
+
color: MethodColorMap[operation.method.toLowerCase()]!,
|
|
164
|
+
invert: true,
|
|
165
|
+
} as const,
|
|
166
|
+
}));
|
|
167
|
+
|
|
168
|
+
const categories = data.schema.tags
|
|
169
|
+
// .filter((tag) => tag.operations.length > 0)
|
|
170
|
+
.map<SidebarItem>((tag) => {
|
|
171
|
+
const categoryLink = joinUrl(
|
|
172
|
+
basePath,
|
|
173
|
+
urlVersion,
|
|
174
|
+
tag.name ? slugify(tag.name) : UNTAGGED_PATH,
|
|
175
|
+
);
|
|
176
|
+
return {
|
|
177
|
+
type: "category",
|
|
178
|
+
label: tag.name || "Other endpoints",
|
|
179
|
+
link: {
|
|
180
|
+
type: "doc" as const,
|
|
181
|
+
id: categoryLink,
|
|
182
|
+
label: tag.name!,
|
|
183
|
+
},
|
|
184
|
+
collapsible: false,
|
|
185
|
+
collapsed: true,
|
|
186
|
+
items: path === categoryLink ? items : [],
|
|
187
|
+
};
|
|
188
|
+
});
|
|
189
|
+
|
|
160
190
|
return categories;
|
|
161
191
|
} catch {
|
|
162
192
|
return [];
|
|
@@ -165,31 +195,59 @@ export const openApiPlugin = (config: OpenApiPluginOptions): ZudokuPlugin => {
|
|
|
165
195
|
getRoutes: () => {
|
|
166
196
|
const versionsInPath = [null, ...versions];
|
|
167
197
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const { OpenApiRoute } = await import("./Route.js");
|
|
172
|
-
return {
|
|
173
|
-
element: (
|
|
174
|
-
<OpenApiRoute
|
|
175
|
-
basePath={basePath}
|
|
176
|
-
versions={versions}
|
|
177
|
-
client={client}
|
|
178
|
-
config={config}
|
|
179
|
-
/>
|
|
180
|
-
),
|
|
181
|
-
};
|
|
182
|
-
},
|
|
183
|
-
children: [
|
|
184
|
-
{
|
|
185
|
-
index: true,
|
|
186
|
-
async lazy() {
|
|
187
|
-
const { OperationList } = await import("./OperationList.js");
|
|
188
|
-
return { element: <OperationList /> };
|
|
189
|
-
},
|
|
190
|
-
},
|
|
191
|
-
],
|
|
198
|
+
const tagPages = (config.tagPages ?? []).map((tag) => ({
|
|
199
|
+
tag,
|
|
200
|
+
path: slugify(tag),
|
|
192
201
|
}));
|
|
202
|
+
|
|
203
|
+
return versionsInPath.map((version) => {
|
|
204
|
+
const versionPath = joinUrl(basePath, version ? `/${version}` : "");
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
path: versionPath,
|
|
208
|
+
async lazy() {
|
|
209
|
+
const { OpenApiRoute } = await import("./OpenApiRoute.js");
|
|
210
|
+
return {
|
|
211
|
+
element: (
|
|
212
|
+
<OpenApiRoute
|
|
213
|
+
version={version ?? undefined}
|
|
214
|
+
basePath={basePath}
|
|
215
|
+
versions={versions}
|
|
216
|
+
client={client}
|
|
217
|
+
config={config}
|
|
218
|
+
/>
|
|
219
|
+
),
|
|
220
|
+
};
|
|
221
|
+
},
|
|
222
|
+
children: [
|
|
223
|
+
{
|
|
224
|
+
index: true,
|
|
225
|
+
loader: () =>
|
|
226
|
+
redirect(
|
|
227
|
+
joinUrl(versionPath, tagPages.at(0)?.path ?? UNTAGGED_PATH),
|
|
228
|
+
),
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
path: joinUrl(versionPath, UNTAGGED_PATH),
|
|
232
|
+
async lazy() {
|
|
233
|
+
const { OperationList } = await import("./OperationList.js");
|
|
234
|
+
return { element: <OperationList untagged={true} /> };
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
...tagPages.map<RouteObject>((tag) => {
|
|
238
|
+
return {
|
|
239
|
+
path: joinUrl(versionPath, tag.path),
|
|
240
|
+
async lazy() {
|
|
241
|
+
const { OperationList } = await import("./OperationList.js");
|
|
242
|
+
return {
|
|
243
|
+
element: <OperationList tag={tag.tag} />,
|
|
244
|
+
};
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
}),
|
|
248
|
+
],
|
|
249
|
+
};
|
|
250
|
+
});
|
|
193
251
|
},
|
|
194
252
|
};
|
|
195
253
|
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { joinUrl } from "./joinUrl.js";
|
|
3
|
+
|
|
4
|
+
describe("joinUrl", () => {
|
|
5
|
+
test("handles basic URL joining", () => {
|
|
6
|
+
expect(joinUrl("https://example.com", "path")).toBe(
|
|
7
|
+
"https://example.com/path",
|
|
8
|
+
);
|
|
9
|
+
expect(joinUrl("https://example.com/", "path")).toBe(
|
|
10
|
+
"https://example.com/path",
|
|
11
|
+
);
|
|
12
|
+
expect(joinUrl("https://example.com/", "/path")).toBe(
|
|
13
|
+
"https://example.com/path",
|
|
14
|
+
);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test("handles multiple path segments", () => {
|
|
18
|
+
expect(joinUrl("https://example.com", "api", "v1", "users")).toBe(
|
|
19
|
+
"https://example.com/api/v1/users",
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// test("handles query parameters", () => {
|
|
24
|
+
// expect(joinUrl("https://example.com", "path?query=1")).toBe(
|
|
25
|
+
// "https://example.com/path?query=1",
|
|
26
|
+
// );
|
|
27
|
+
// expect(joinUrl("https://example.com?base=1", "path?query=1")).toBe(
|
|
28
|
+
// "https://example.com/path?query=1",
|
|
29
|
+
// );
|
|
30
|
+
// });
|
|
31
|
+
|
|
32
|
+
// test("handles repeated dots and question marks", () => {
|
|
33
|
+
// expect(joinUrl("https://example.com", "path/../../../test")).toBe(
|
|
34
|
+
// "https://example.com/path/../../../test",
|
|
35
|
+
// );
|
|
36
|
+
// expect(joinUrl("https://example.com", "test????a=1")).toBe(
|
|
37
|
+
// "https://example.com/test????a=1",
|
|
38
|
+
// );
|
|
39
|
+
// });
|
|
40
|
+
|
|
41
|
+
test("handles falsy values", () => {
|
|
42
|
+
expect(joinUrl("https://example.com", null, undefined, false, "path")).toBe(
|
|
43
|
+
"https://example.com/path",
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("handles numeric values", () => {
|
|
48
|
+
expect(joinUrl("https://example.com", "api", 123, "test")).toBe(
|
|
49
|
+
"https://example.com/api/123/test",
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("handles relative paths", () => {
|
|
54
|
+
expect(joinUrl("/api", "v1", "users")).toBe("/api/v1/users");
|
|
55
|
+
expect(joinUrl("api", "v1", "users")).toBe("/api/v1/users");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("handles empty input", () => {
|
|
59
|
+
expect(joinUrl()).toBe("/");
|
|
60
|
+
expect(joinUrl("")).toBe("/");
|
|
61
|
+
});
|
|
62
|
+
});
|
package/src/lib/util/joinUrl.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Mostly adapted from https://github.com/moxystudio/js-proper-url-join
|
|
2
|
-
const defaultUrlRegExp = /^(\w+:\/\/[^/?]+)?(
|
|
2
|
+
const defaultUrlRegExp = /^(\w+:\/\/[^/?]+)?([^?]*)(\?.*)?$/;
|
|
3
3
|
|
|
4
4
|
const normalizeParts = (
|
|
5
5
|
parts: (string | number | null | undefined | false)[],
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Route.js","sourceRoot":"","sources":["../../../../src/lib/plugins/openapi/Route.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACjD,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,MAAM,EACN,MAAM,GAMP,EAAE,EAAE;IACH,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,EAAa,CAAC;IAE3C,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"}
|