zudoku 0.35.5 → 0.36.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/app/entry.server.js +5 -1
- package/dist/app/entry.server.js.map +1 -1
- package/dist/config/validators/common.d.ts +176 -176
- package/dist/config/validators/common.js +8 -6
- package/dist/config/validators/common.js.map +1 -1
- package/dist/config/validators/validate.d.ts +63 -63
- package/dist/lib/authentication/providers/openid.js +11 -7
- package/dist/lib/authentication/providers/openid.js.map +1 -1
- package/dist/lib/components/AnchorLink.js +3 -2
- package/dist/lib/components/AnchorLink.js.map +1 -1
- package/dist/lib/components/Layout.js +3 -14
- package/dist/lib/components/Layout.js.map +1 -1
- package/dist/lib/components/Zudoku.js +3 -1
- package/dist/lib/components/Zudoku.js.map +1 -1
- package/dist/lib/components/cache.d.ts +7 -0
- package/dist/lib/components/cache.js +7 -0
- package/dist/lib/components/cache.js.map +1 -1
- package/dist/lib/components/context/ViewportAnchorContext.js +3 -6
- package/dist/lib/components/context/ViewportAnchorContext.js.map +1 -1
- package/dist/lib/components/context/ZudokuContext.d.ts +1 -1
- package/dist/lib/components/context/ZudokuContext.js +4 -3
- package/dist/lib/components/context/ZudokuContext.js.map +1 -1
- package/dist/lib/components/navigation/SidebarItem.js +3 -2
- package/dist/lib/components/navigation/SidebarItem.js.map +1 -1
- package/dist/lib/core/ZudokuContext.d.ts +8 -6
- package/dist/lib/core/ZudokuContext.js +4 -2
- package/dist/lib/core/ZudokuContext.js.map +1 -1
- package/dist/lib/core/plugins.d.ts +3 -3
- package/dist/lib/hooks/useEvent.test.js +1 -1
- package/dist/lib/hooks/useEvent.test.js.map +1 -1
- package/dist/lib/oas/graphql/index.d.ts +16 -4
- package/dist/lib/oas/graphql/index.js +59 -43
- package/dist/lib/oas/graphql/index.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationList.js +19 -5
- package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationListItem.js +1 -1
- package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js +2 -2
- package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
- package/dist/lib/plugins/openapi/client/useCreateQuery.d.ts +1 -1
- package/dist/lib/plugins/openapi/client/useCreateQuery.js +2 -1
- package/dist/lib/plugins/openapi/client/useCreateQuery.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/gql.d.ts +4 -4
- package/dist/lib/plugins/openapi/graphql/gql.js +3 -3
- package/dist/lib/plugins/openapi/graphql/gql.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/graphql.d.ts +34 -45
- package/dist/lib/plugins/openapi/graphql/graphql.js +20 -30
- package/dist/lib/plugins/openapi/graphql/graphql.js.map +1 -1
- package/dist/lib/plugins/openapi/index.d.ts +5 -10
- package/dist/lib/plugins/openapi/index.js +29 -60
- package/dist/lib/plugins/openapi/index.js.map +1 -1
- package/dist/lib/plugins/openapi/interfaces.d.ts +3 -1
- package/dist/lib/plugins/openapi/util/createSidebarCategory.js +5 -7
- package/dist/lib/plugins/openapi/util/createSidebarCategory.js.map +1 -1
- package/dist/lib/util/traverse.js +2 -2
- package/dist/lib/util/traverse.js.map +1 -1
- package/dist/lib/util/useScrollToAnchor.js +2 -0
- package/dist/lib/util/useScrollToAnchor.js.map +1 -1
- package/dist/vite/api/schema-codegen.js +19 -4
- package/dist/vite/api/schema-codegen.js.map +1 -1
- package/dist/vite/api/schema-codegen.test.js +61 -0
- package/dist/vite/api/schema-codegen.test.js.map +1 -1
- package/dist/vite/plugin-api.js +3 -11
- package/dist/vite/plugin-api.js.map +1 -1
- package/lib/{AuthenticationPlugin-4ip08maU.js → AuthenticationPlugin-Cr6xjOJD.js} +2 -2
- package/lib/{AuthenticationPlugin-4ip08maU.js.map → AuthenticationPlugin-Cr6xjOJD.js.map} +1 -1
- package/lib/{Markdown-hBN9vkm5.js → Markdown-BlioIqkZ.js} +313 -311
- package/lib/Markdown-BlioIqkZ.js.map +1 -0
- package/lib/{MdxPage-UCWwxhzC.js → MdxPage-7XnN9J9R.js} +3 -3
- package/lib/{MdxPage-UCWwxhzC.js.map → MdxPage-7XnN9J9R.js.map} +1 -1
- package/lib/{OasProvider-CJ8KOnsH.js → OasProvider-BaRRMSsD.js} +3 -3
- package/lib/{OasProvider-CJ8KOnsH.js.map → OasProvider-BaRRMSsD.js.map} +1 -1
- package/lib/{OperationList-C4rpJdcE.js → OperationList-BjL1hzSx.js} +988 -961
- package/lib/OperationList-BjL1hzSx.js.map +1 -0
- package/lib/{SlotletProvider-D-XPr1Wg.js → SlotletProvider-CXb3wQiR.js} +2 -2
- package/lib/{SlotletProvider-D-XPr1Wg.js.map → SlotletProvider-CXb3wQiR.js.map} +1 -1
- package/lib/{circular-v7K6lDDh.js → circular-ByJI6Mci.js} +4887 -4419
- package/lib/circular-ByJI6Mci.js.map +1 -0
- package/lib/{createServer-BEFAOb-x.js → createServer-DjgKDpGV.js} +3887 -4291
- package/lib/createServer-DjgKDpGV.js.map +1 -0
- package/lib/{hook-CfCFKZ-2.js → hook-Bo80UX00.js} +75 -74
- package/lib/hook-Bo80UX00.js.map +1 -0
- package/lib/{index-Dowg8c_k.js → index-D5m8_oyY.js} +612 -650
- package/lib/index-D5m8_oyY.js.map +1 -0
- package/lib/post-processors/traverse.js +2 -2
- package/lib/post-processors/traverse.js.map +1 -1
- package/lib/zudoku.auth-auth0.js +1 -1
- package/lib/zudoku.auth-clerk.js +2 -2
- package/lib/zudoku.auth-openid.js +283 -282
- package/lib/zudoku.auth-openid.js.map +1 -1
- package/lib/zudoku.components.js +395 -397
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.hooks.js +1 -1
- package/lib/zudoku.plugin-api-catalog.js +2 -2
- package/lib/zudoku.plugin-api-keys.js +2 -2
- package/lib/zudoku.plugin-custom-pages.js +1 -1
- package/lib/zudoku.plugin-markdown.js +1 -1
- package/lib/zudoku.plugin-openapi.js +4 -5
- package/lib/zudoku.plugin-openapi.js.map +1 -1
- package/lib/zudoku.plugins.js.map +1 -1
- package/package.json +5 -5
- package/src/app/entry.server.tsx +7 -1
- package/src/lib/authentication/providers/openid.tsx +12 -9
- package/src/lib/components/AnchorLink.tsx +4 -2
- package/src/lib/components/Layout.tsx +3 -16
- package/src/lib/components/Zudoku.tsx +5 -1
- package/src/lib/components/cache.ts +8 -0
- package/src/lib/components/context/ViewportAnchorContext.tsx +3 -6
- package/src/lib/components/context/ZudokuContext.ts +5 -4
- package/src/lib/components/navigation/SidebarItem.tsx +3 -2
- package/src/lib/core/ZudokuContext.ts +11 -8
- package/src/lib/core/plugins.ts +4 -4
- package/src/lib/hooks/useEvent.test.tsx +1 -1
- package/src/lib/oas/graphql/index.ts +116 -76
- package/src/lib/plugins/openapi/OperationList.tsx +31 -37
- package/src/lib/plugins/openapi/OperationListItem.tsx +1 -1
- package/src/lib/plugins/openapi/Sidecar.tsx +2 -2
- package/src/lib/plugins/openapi/client/useCreateQuery.ts +2 -1
- package/src/lib/plugins/openapi/graphql/gql.ts +17 -17
- package/src/lib/plugins/openapi/graphql/graphql.ts +62 -79
- package/src/lib/plugins/openapi/index.tsx +40 -84
- package/src/lib/plugins/openapi/interfaces.ts +4 -1
- package/src/lib/plugins/openapi/util/createSidebarCategory.tsx +5 -7
- package/src/lib/util/traverse.ts +2 -2
- package/src/lib/util/useScrollToAnchor.ts +2 -0
- package/lib/Markdown-hBN9vkm5.js.map +0 -1
- package/lib/OperationList-C4rpJdcE.js.map +0 -1
- package/lib/circular-v7K6lDDh.js.map +0 -1
- package/lib/createServer-BEFAOb-x.js.map +0 -1
- package/lib/hook-CfCFKZ-2.js.map +0 -1
- package/lib/index-Dowg8c_k.js.map +0 -1
|
@@ -42,21 +42,29 @@ type OperationLike = {
|
|
|
42
42
|
export const createOperationSlug = (
|
|
43
43
|
slugify: CountableSlugify,
|
|
44
44
|
operation: OperationLike,
|
|
45
|
-
tag?: string,
|
|
46
45
|
) => {
|
|
47
46
|
const summary =
|
|
48
47
|
operation.summary ||
|
|
49
48
|
operation.operationId ||
|
|
50
49
|
`${operation.method}-${operation.path}`;
|
|
51
|
-
const prefix = tag ? `${tag}-` : "";
|
|
52
50
|
|
|
53
|
-
return slugify(
|
|
51
|
+
return slugify(summary);
|
|
54
52
|
};
|
|
55
53
|
|
|
56
|
-
export type
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
>;
|
|
54
|
+
export type SchemaImport = () => Promise<{
|
|
55
|
+
schema: OpenAPIDocument;
|
|
56
|
+
slugs: ReturnType<typeof getAllSlugs>;
|
|
57
|
+
}>;
|
|
58
|
+
|
|
59
|
+
export type SchemaImports = Record<string, SchemaImport>;
|
|
60
|
+
|
|
61
|
+
type Context = {
|
|
62
|
+
schema: OpenAPIDocument;
|
|
63
|
+
operations: GraphQLOperationObject[];
|
|
64
|
+
schemaImports?: SchemaImports;
|
|
65
|
+
tags: ReturnType<typeof getAllTags>;
|
|
66
|
+
slugs: ReturnType<typeof getAllSlugs>;
|
|
67
|
+
};
|
|
60
68
|
|
|
61
69
|
const builder = new SchemaBuilder<{
|
|
62
70
|
DefaultFieldNullability: false;
|
|
@@ -65,14 +73,7 @@ const builder = new SchemaBuilder<{
|
|
|
65
73
|
JSONObject: any;
|
|
66
74
|
JSONSchema: any;
|
|
67
75
|
};
|
|
68
|
-
Context:
|
|
69
|
-
schema: OpenAPIDocument;
|
|
70
|
-
operations: GraphQLOperationObject[];
|
|
71
|
-
tags: TagObject[];
|
|
72
|
-
schemaImports?: SchemaImports;
|
|
73
|
-
currentTag?: string;
|
|
74
|
-
slugify: CountableSlugify;
|
|
75
|
-
};
|
|
76
|
+
Context: Context;
|
|
76
77
|
}>({
|
|
77
78
|
defaultFieldNullability: false,
|
|
78
79
|
});
|
|
@@ -88,17 +89,15 @@ const JSONScalar = builder.addScalarType("JSON", GraphQLJSON);
|
|
|
88
89
|
const JSONObjectScalar = builder.addScalarType("JSONObject", GraphQLJSONObject);
|
|
89
90
|
const JSONSchemaScalar = builder.addScalarType("JSONSchema", GraphQLJSONSchema);
|
|
90
91
|
|
|
91
|
-
const resolveExtensions = (obj: Record<string, any>) =>
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
extensions[key] = value;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return extensions;
|
|
99
|
-
};
|
|
92
|
+
const resolveExtensions = (obj: Record<string, any>) =>
|
|
93
|
+
Object.fromEntries(
|
|
94
|
+
Object.entries(obj).filter(([key]) => key.startsWith("x-")),
|
|
95
|
+
);
|
|
100
96
|
|
|
101
|
-
export const getAllTags = (
|
|
97
|
+
export const getAllTags = (
|
|
98
|
+
schema: OpenAPIDocument,
|
|
99
|
+
slugs: ReturnType<typeof getAllSlugs>["tags"],
|
|
100
|
+
): Array<TagObject & { slug?: string }> => {
|
|
102
101
|
const rootTags = schema.tags ?? [];
|
|
103
102
|
const operationTags = new Set(
|
|
104
103
|
Object.values(schema.paths ?? {})
|
|
@@ -108,14 +107,43 @@ export const getAllTags = (schema: OpenAPIDocument): TagObject[] => {
|
|
|
108
107
|
|
|
109
108
|
return [
|
|
110
109
|
// Keep root tags that are actually used in operations
|
|
111
|
-
...rootTags
|
|
110
|
+
...rootTags
|
|
111
|
+
.filter((tag) => operationTags.has(tag.name))
|
|
112
|
+
.map((tag) => ({ ...tag, slug: slugs[tag.name] })),
|
|
112
113
|
// Add tags found in operations but not defined in root tags
|
|
113
114
|
...[...operationTags]
|
|
114
115
|
.filter((tag) => !rootTags.some((rt) => rt.name === tag))
|
|
115
|
-
.map((tag) => ({ name: tag })),
|
|
116
|
+
.map((tag) => ({ name: tag, slug: slugs[tag] })),
|
|
116
117
|
];
|
|
117
118
|
};
|
|
118
119
|
|
|
120
|
+
export const getAllSlugs = (
|
|
121
|
+
ops: GraphQLOperationObject[],
|
|
122
|
+
schemaTags: TagObject[] = [],
|
|
123
|
+
) => {
|
|
124
|
+
const slugify = slugifyWithCounter();
|
|
125
|
+
|
|
126
|
+
const tags = Array.from(
|
|
127
|
+
new Set([
|
|
128
|
+
...ops.flatMap((op) => op.tags ?? []),
|
|
129
|
+
...schemaTags.map((tag) => tag.name),
|
|
130
|
+
]),
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
operations: Object.fromEntries(
|
|
135
|
+
ops.map((op) => [
|
|
136
|
+
getOperationSlugKey(op),
|
|
137
|
+
createOperationSlug(slugify, op),
|
|
138
|
+
]),
|
|
139
|
+
),
|
|
140
|
+
tags: Object.fromEntries(tags.map((tag) => [tag, slugify(tag)])),
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const getOperationSlugKey = (op: GraphQLOperationObject) =>
|
|
145
|
+
[op.path, op.method, op.operationId, op.summary].filter(Boolean).join("-");
|
|
146
|
+
|
|
119
147
|
export const getAllOperations = (
|
|
120
148
|
paths?: PathsObject,
|
|
121
149
|
): GraphQLOperationObject[] => {
|
|
@@ -153,30 +181,38 @@ export const getAllOperations = (
|
|
|
153
181
|
return operations;
|
|
154
182
|
};
|
|
155
183
|
|
|
156
|
-
const SchemaTag = builder
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
184
|
+
const SchemaTag = builder
|
|
185
|
+
.objectRef<
|
|
186
|
+
Omit<TagObject, "name"> & { name?: string; slug?: string }
|
|
187
|
+
>("SchemaTag")
|
|
188
|
+
.implement({
|
|
189
|
+
fields: (t) => ({
|
|
190
|
+
name: t.exposeString("name", { nullable: true }),
|
|
191
|
+
slug: t.exposeString("slug", { nullable: true }),
|
|
192
|
+
description: t.exposeString("description", { nullable: true }),
|
|
193
|
+
operations: t.field({
|
|
194
|
+
type: [OperationItem],
|
|
195
|
+
resolve: (parent, _args, ctx) => {
|
|
196
|
+
const rootTags = ctx.tags.map((tag) => tag.name);
|
|
197
|
+
|
|
198
|
+
return ctx.operations
|
|
199
|
+
.filter((item) =>
|
|
200
|
+
parent.name
|
|
201
|
+
? item.tags?.includes(parent.name)
|
|
202
|
+
: item.tags?.length === 0 ||
|
|
203
|
+
// If none of the tags are present in the root tags, then show them here
|
|
204
|
+
item.tags?.every((tag) => !rootTags.includes(tag)),
|
|
205
|
+
)
|
|
206
|
+
.map((item) => ({ ...item, parentTag: parent.name }));
|
|
207
|
+
},
|
|
208
|
+
}),
|
|
209
|
+
extensions: t.field({
|
|
210
|
+
type: JSONObjectScalar,
|
|
211
|
+
resolve: (parent) => resolveExtensions(parent),
|
|
212
|
+
nullable: true,
|
|
213
|
+
}),
|
|
177
214
|
}),
|
|
178
|
-
})
|
|
179
|
-
});
|
|
215
|
+
});
|
|
180
216
|
|
|
181
217
|
const ServerItem = builder.objectRef<ServerObject>("Server").implement({
|
|
182
218
|
fields: (t) => ({
|
|
@@ -341,18 +377,16 @@ const OperationItem = builder
|
|
|
341
377
|
slug: t.field({
|
|
342
378
|
type: "String",
|
|
343
379
|
resolve: (parent, _, ctx) => {
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
return createOperationSlug(ctx.slugify, slugData, parent.parentTag);
|
|
380
|
+
const slug = ctx.slugs.operations[getOperationSlugKey(parent)];
|
|
381
|
+
|
|
382
|
+
if (!slug) {
|
|
383
|
+
throw new Error(
|
|
384
|
+
`No slug found for operation: ${getOperationSlugKey(parent)}`,
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
return slug;
|
|
353
388
|
},
|
|
354
389
|
}),
|
|
355
|
-
|
|
356
390
|
path: t.exposeString("path"),
|
|
357
391
|
method: t.exposeString("method"),
|
|
358
392
|
operationId: t.exposeString("operationId", { nullable: true }),
|
|
@@ -466,10 +500,17 @@ const Schema = builder.objectRef<OpenAPIDocument>("Schema").implement({
|
|
|
466
500
|
name: t.arg.string(),
|
|
467
501
|
},
|
|
468
502
|
type: [SchemaTag],
|
|
469
|
-
resolve: (
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
503
|
+
resolve: (_root, args, ctx) => {
|
|
504
|
+
if (args.name) {
|
|
505
|
+
return ctx.tags.filter((tag) => tag.name === args.name);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Append empty tag which will be used to display untagged operations
|
|
509
|
+
if (ctx.operations.some((op) => !op.tags?.length)) {
|
|
510
|
+
return [...ctx.tags, { name: undefined, slug: undefined }];
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
return ctx.tags;
|
|
473
514
|
},
|
|
474
515
|
}),
|
|
475
516
|
operations: t.field({
|
|
@@ -513,26 +554,25 @@ builder.queryType({
|
|
|
513
554
|
input: t.arg({ type: JSONScalar, required: true }),
|
|
514
555
|
},
|
|
515
556
|
resolve: async (_, args, ctx) => {
|
|
516
|
-
let schema: OpenAPIDocument;
|
|
517
|
-
|
|
518
557
|
if (args.type === "file" && typeof args.input === "string") {
|
|
519
558
|
const loadSchema = ctx.schemaImports?.[args.input];
|
|
520
559
|
|
|
521
560
|
if (!loadSchema) {
|
|
522
561
|
throw new Error(`No schema loader found for path: ${args.input}`);
|
|
523
562
|
}
|
|
524
|
-
const
|
|
525
|
-
schema =
|
|
563
|
+
const { schema, slugs } = await loadSchema();
|
|
564
|
+
ctx.schema = schema;
|
|
565
|
+
ctx.operations = getAllOperations(schema.paths);
|
|
566
|
+
ctx.slugs = slugs;
|
|
567
|
+
ctx.tags = getAllTags(schema, ctx.slugs.tags);
|
|
526
568
|
} else {
|
|
527
|
-
schema = await validate(args.input as string);
|
|
569
|
+
ctx.schema = await validate(args.input as string);
|
|
570
|
+
ctx.operations = getAllOperations(ctx.schema.paths);
|
|
571
|
+
ctx.slugs = getAllSlugs(ctx.operations);
|
|
572
|
+
ctx.tags = getAllTags(ctx.schema, ctx.slugs.tags);
|
|
528
573
|
}
|
|
529
574
|
|
|
530
|
-
ctx.schema
|
|
531
|
-
ctx.operations = getAllOperations(schema.paths);
|
|
532
|
-
ctx.slugify = slugifyWithCounter();
|
|
533
|
-
ctx.tags = getAllTags(schema);
|
|
534
|
-
|
|
535
|
-
return schema;
|
|
575
|
+
return ctx.schema;
|
|
536
576
|
},
|
|
537
577
|
}),
|
|
538
578
|
}),
|
|
@@ -542,4 +582,4 @@ export const schema = builder.toSchema();
|
|
|
542
582
|
|
|
543
583
|
export const createGraphQLServer = (
|
|
544
584
|
options?: Omit<YogaServerOptions<any, any>, "schema">,
|
|
545
|
-
) => createYoga({ schema, ...options });
|
|
585
|
+
) => createYoga({ schema, batching: true, ...options });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ResultOf } from "@graphql-typed-document-node/core";
|
|
2
|
-
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
2
|
+
import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
|
|
3
3
|
import { Helmet } from "@zudoku/react-helmet-async";
|
|
4
4
|
import { ChevronsDownUpIcon, ChevronsUpDownIcon } from "lucide-react";
|
|
5
5
|
import { useNavigate } from "react-router";
|
|
@@ -97,8 +97,16 @@ export const OperationsFragment = graphql(/* GraphQL */ `
|
|
|
97
97
|
|
|
98
98
|
export type OperationListItemResult = ResultOf<typeof OperationsFragment>;
|
|
99
99
|
|
|
100
|
-
const
|
|
101
|
-
query
|
|
100
|
+
const SchemaWarmupQuery = graphql(/* GraphQL */ `
|
|
101
|
+
query SchemaWarmup($input: JSON!, $type: SchemaType!) {
|
|
102
|
+
schema(input: $input, type: $type) {
|
|
103
|
+
openapi
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
`);
|
|
107
|
+
|
|
108
|
+
const OperationsForTagQuery = graphql(/* GraphQL */ `
|
|
109
|
+
query OperationsForTag(
|
|
102
110
|
$input: JSON!
|
|
103
111
|
$type: SchemaType!
|
|
104
112
|
$tag: String
|
|
@@ -133,7 +141,7 @@ export const OperationList = ({
|
|
|
133
141
|
untagged?: boolean;
|
|
134
142
|
}) => {
|
|
135
143
|
const { input, type, versions, version, options } = useOasConfig();
|
|
136
|
-
const query = useCreateQuery(
|
|
144
|
+
const query = useCreateQuery(OperationsForTagQuery, {
|
|
137
145
|
input,
|
|
138
146
|
type,
|
|
139
147
|
tag,
|
|
@@ -151,6 +159,14 @@ export const OperationList = ({
|
|
|
151
159
|
const operations = schema.operations;
|
|
152
160
|
const tagDescription = schema.tags.find((t) => t.name === tag)?.description;
|
|
153
161
|
|
|
162
|
+
// 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
|
+
const warmupQuery = useCreateQuery(SchemaWarmupQuery, { input, type });
|
|
164
|
+
useQuery({
|
|
165
|
+
...warmupQuery,
|
|
166
|
+
enabled: typeof window !== "undefined",
|
|
167
|
+
notifyOnChangeProps: [],
|
|
168
|
+
});
|
|
169
|
+
|
|
154
170
|
// Prefetch for Playground
|
|
155
171
|
useApiIdentities();
|
|
156
172
|
|
|
@@ -194,7 +210,7 @@ export const OperationList = ({
|
|
|
194
210
|
registerSidebarAnchor
|
|
195
211
|
className="mb-0"
|
|
196
212
|
>
|
|
197
|
-
{tag}
|
|
213
|
+
{tag ?? "Other endpoints"}
|
|
198
214
|
{showVersions && (
|
|
199
215
|
<span className="text-xl text-muted-foreground ml-1.5">
|
|
200
216
|
{" "}
|
|
@@ -269,38 +285,16 @@ export const OperationList = ({
|
|
|
269
285
|
<div className="my-4 flex items-center justify-end gap-4">
|
|
270
286
|
<Endpoint />
|
|
271
287
|
</div>
|
|
272
|
-
{
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
// px, -mx is so that `content-visibility` doesn't cut off overflown heading anchor links '#'
|
|
283
|
-
<div key={tag.name} className="px-6 -mx-6 [content-visibility:auto]">
|
|
284
|
-
{tag.name && <CategoryHeading>{tag.name}</CategoryHeading>}
|
|
285
|
-
{tag.description && (
|
|
286
|
-
<Markdown
|
|
287
|
-
className={`${ProseClasses} max-w-full prose-img:max-w-prose w-full mt-2 mb-12`}
|
|
288
|
-
content={tag.description}
|
|
289
|
-
/>
|
|
290
|
-
)}
|
|
291
|
-
<div className="operation mb-12">
|
|
292
|
-
<StaggeredRender>
|
|
293
|
-
{tag.operations.map((fragment) => (
|
|
294
|
-
<OperationListItem
|
|
295
|
-
serverUrl={selectedServer ?? schema.url}
|
|
296
|
-
key={fragment.slug}
|
|
297
|
-
operationFragment={fragment}
|
|
298
|
-
/>
|
|
299
|
-
))}
|
|
300
|
-
</StaggeredRender>
|
|
301
|
-
</div>
|
|
302
|
-
</div>
|
|
303
|
-
))} */}
|
|
288
|
+
{/* 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]">
|
|
290
|
+
{operations.map((fragment) => (
|
|
291
|
+
<OperationListItem
|
|
292
|
+
serverUrl={selectedServer}
|
|
293
|
+
key={fragment.slug}
|
|
294
|
+
operationFragment={fragment}
|
|
295
|
+
/>
|
|
296
|
+
))}
|
|
297
|
+
</div>
|
|
304
298
|
</div>
|
|
305
299
|
);
|
|
306
300
|
};
|
|
@@ -63,7 +63,7 @@ export const OperationListItem = ({
|
|
|
63
63
|
<SelectOnClick className="max-w-full truncate flex cursor-pointer">
|
|
64
64
|
{serverUrl && (
|
|
65
65
|
<div className="text-neutral-400 dark:text-neutral-500 truncate">
|
|
66
|
-
{serverUrl}
|
|
66
|
+
{serverUrl.replace(/\/$/, "")}
|
|
67
67
|
</div>
|
|
68
68
|
)}
|
|
69
69
|
<div className="text-neutral-900 dark:text-neutral-200">
|
|
@@ -173,9 +173,9 @@ export const Sidecar = ({
|
|
|
173
173
|
const showPlayground =
|
|
174
174
|
isOnScreen &&
|
|
175
175
|
(operation.extensions["x-explorer-enabled"] === true ||
|
|
176
|
-
operation.extensions["x-playground-enabled"] === true ||
|
|
176
|
+
operation.extensions["x-zudoku-playground-enabled"] === true ||
|
|
177
177
|
(operation.extensions["x-explorer-enabled"] === undefined &&
|
|
178
|
-
operation.extensions["x-playground-enabled"] === undefined &&
|
|
178
|
+
operation.extensions["x-zudoku-playground-enabled"] === undefined &&
|
|
179
179
|
!options?.disablePlayground));
|
|
180
180
|
|
|
181
181
|
return (
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { stripIgnoredCharacters } from "graphql";
|
|
1
2
|
import { useContext } from "react";
|
|
2
3
|
import type { TypedDocumentString } from "../graphql/graphql.js";
|
|
3
4
|
import { GraphQLContext } from "./GraphQLContext.js";
|
|
@@ -13,6 +14,6 @@ export const useCreateQuery = <TResult, TVariables>(
|
|
|
13
14
|
|
|
14
15
|
return {
|
|
15
16
|
queryFn: () => graphQLClient.fetch(query, ...variables),
|
|
16
|
-
queryKey: [query, variables[0]],
|
|
17
|
+
queryKey: [stripIgnoredCharacters(query.toString()), variables[0]],
|
|
17
18
|
} as const;
|
|
18
19
|
};
|
|
@@ -15,24 +15,24 @@ import * as types from "./graphql.js";
|
|
|
15
15
|
type Documents = {
|
|
16
16
|
"\n query ServersQuery($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n url\n servers {\n url\n }\n }\n }\n": typeof types.ServersQueryDocument;
|
|
17
17
|
"\n fragment OperationsFragment on OperationItem {\n slug\n summary\n method\n description\n operationId\n contentTypes\n path\n deprecated\n extensions\n parameters {\n name\n in\n description\n required\n schema\n style\n explode\n examples {\n name\n description\n externalValue\n value\n summary\n }\n }\n requestBody {\n content {\n mediaType\n encoding {\n name\n }\n examples {\n name\n description\n externalValue\n value\n summary\n }\n schema\n }\n description\n required\n }\n responses {\n statusCode\n links\n description\n content {\n examples {\n name\n description\n externalValue\n value\n summary\n }\n mediaType\n encoding {\n name\n }\n schema\n }\n }\n }\n": typeof types.OperationsFragmentFragmentDoc;
|
|
18
|
-
"\n query
|
|
18
|
+
"\n query SchemaWarmup($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n openapi\n }\n }\n": typeof types.SchemaWarmupDocument;
|
|
19
|
+
"\n query OperationsForTag(\n $input: JSON!\n $type: SchemaType!\n $tag: String\n $untagged: Boolean\n ) {\n schema(input: $input, type: $type) {\n servers {\n url\n }\n description\n summary\n title\n url\n version\n tags(name: $tag) {\n name\n description\n }\n operations(tag: $tag, untagged: $untagged) {\n slug\n ...OperationsFragment\n }\n }\n }\n": typeof types.OperationsForTagDocument;
|
|
19
20
|
"\n query getServerQuery($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n url\n servers {\n url\n }\n }\n }\n": typeof types.GetServerQueryDocument;
|
|
20
|
-
"\n query
|
|
21
|
-
"\n query GetOperations($input: JSON!, $type: SchemaType!, $tag: String) {\n schema(input: $input, type: $type) {\n operations(tag: $tag) {\n slug\n deprecated\n method\n summary\n operationId\n path\n tags {\n name\n }\n }\n untagged: operations(untagged: true) {\n slug\n deprecated\n method\n summary\n operationId\n path\n }\n }\n }\n": typeof types.GetOperationsDocument;
|
|
21
|
+
"\n query GetSidebarOperations($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n tags {\n slug\n name\n extensions\n operations {\n summary\n slug\n method\n operationId\n path\n }\n }\n }\n }\n": typeof types.GetSidebarOperationsDocument;
|
|
22
22
|
};
|
|
23
23
|
const documents: Documents = {
|
|
24
24
|
"\n query ServersQuery($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n url\n servers {\n url\n }\n }\n }\n":
|
|
25
25
|
types.ServersQueryDocument,
|
|
26
26
|
"\n fragment OperationsFragment on OperationItem {\n slug\n summary\n method\n description\n operationId\n contentTypes\n path\n deprecated\n extensions\n parameters {\n name\n in\n description\n required\n schema\n style\n explode\n examples {\n name\n description\n externalValue\n value\n summary\n }\n }\n requestBody {\n content {\n mediaType\n encoding {\n name\n }\n examples {\n name\n description\n externalValue\n value\n summary\n }\n schema\n }\n description\n required\n }\n responses {\n statusCode\n links\n description\n content {\n examples {\n name\n description\n externalValue\n value\n summary\n }\n mediaType\n encoding {\n name\n }\n schema\n }\n }\n }\n":
|
|
27
27
|
types.OperationsFragmentFragmentDoc,
|
|
28
|
-
"\n query
|
|
29
|
-
types.
|
|
28
|
+
"\n query SchemaWarmup($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n openapi\n }\n }\n":
|
|
29
|
+
types.SchemaWarmupDocument,
|
|
30
|
+
"\n query OperationsForTag(\n $input: JSON!\n $type: SchemaType!\n $tag: String\n $untagged: Boolean\n ) {\n schema(input: $input, type: $type) {\n servers {\n url\n }\n description\n summary\n title\n url\n version\n tags(name: $tag) {\n name\n description\n }\n operations(tag: $tag, untagged: $untagged) {\n slug\n ...OperationsFragment\n }\n }\n }\n":
|
|
31
|
+
types.OperationsForTagDocument,
|
|
30
32
|
"\n query getServerQuery($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n url\n servers {\n url\n }\n }\n }\n":
|
|
31
33
|
types.GetServerQueryDocument,
|
|
32
|
-
"\n query
|
|
33
|
-
types.
|
|
34
|
-
"\n query GetOperations($input: JSON!, $type: SchemaType!, $tag: String) {\n schema(input: $input, type: $type) {\n operations(tag: $tag) {\n slug\n deprecated\n method\n summary\n operationId\n path\n tags {\n name\n }\n }\n untagged: operations(untagged: true) {\n slug\n deprecated\n method\n summary\n operationId\n path\n }\n }\n }\n":
|
|
35
|
-
types.GetOperationsDocument,
|
|
34
|
+
"\n query GetSidebarOperations($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n tags {\n slug\n name\n extensions\n operations {\n summary\n slug\n method\n operationId\n path\n }\n }\n }\n }\n":
|
|
35
|
+
types.GetSidebarOperationsDocument,
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
/**
|
|
@@ -51,26 +51,26 @@ export function graphql(
|
|
|
51
51
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
|
52
52
|
*/
|
|
53
53
|
export function graphql(
|
|
54
|
-
source: "\n query
|
|
55
|
-
): typeof import("./graphql.js").
|
|
54
|
+
source: "\n query SchemaWarmup($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n openapi\n }\n }\n",
|
|
55
|
+
): typeof import("./graphql.js").SchemaWarmupDocument;
|
|
56
56
|
/**
|
|
57
57
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
|
58
58
|
*/
|
|
59
59
|
export function graphql(
|
|
60
|
-
source: "\n query
|
|
61
|
-
): typeof import("./graphql.js").
|
|
60
|
+
source: "\n query OperationsForTag(\n $input: JSON!\n $type: SchemaType!\n $tag: String\n $untagged: Boolean\n ) {\n schema(input: $input, type: $type) {\n servers {\n url\n }\n description\n summary\n title\n url\n version\n tags(name: $tag) {\n name\n description\n }\n operations(tag: $tag, untagged: $untagged) {\n slug\n ...OperationsFragment\n }\n }\n }\n",
|
|
61
|
+
): typeof import("./graphql.js").OperationsForTagDocument;
|
|
62
62
|
/**
|
|
63
63
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
|
64
64
|
*/
|
|
65
65
|
export function graphql(
|
|
66
|
-
source: "\n query
|
|
67
|
-
): typeof import("./graphql.js").
|
|
66
|
+
source: "\n query getServerQuery($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n url\n servers {\n url\n }\n }\n }\n",
|
|
67
|
+
): typeof import("./graphql.js").GetServerQueryDocument;
|
|
68
68
|
/**
|
|
69
69
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
|
70
70
|
*/
|
|
71
71
|
export function graphql(
|
|
72
|
-
source: "\n query
|
|
73
|
-
): typeof import("./graphql.js").
|
|
72
|
+
source: "\n query GetSidebarOperations($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n tags {\n slug\n name\n extensions\n operations {\n summary\n slug\n method\n operationId\n path\n }\n }\n }\n }\n",
|
|
73
|
+
): typeof import("./graphql.js").GetSidebarOperationsDocument;
|
|
74
74
|
|
|
75
75
|
export function graphql(source: string) {
|
|
76
76
|
return (documents as any)[source] ?? {};
|