zudoku 0.4.1 → 0.4.2-dev.1

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 (88) hide show
  1. package/dist/lib/components/Header.js +4 -3
  2. package/dist/lib/components/Header.js.map +1 -1
  3. package/dist/lib/components/SyntaxHighlight.js +1 -1
  4. package/dist/lib/components/SyntaxHighlight.js.map +1 -1
  5. package/dist/lib/plugins/api-keys/SettingsApiKeys.js +9 -3
  6. package/dist/lib/plugins/api-keys/SettingsApiKeys.js.map +1 -1
  7. package/dist/lib/plugins/openapi/RequestBodySidecarBox.js +1 -1
  8. package/dist/lib/plugins/openapi/RequestBodySidecarBox.js.map +1 -1
  9. package/dist/lib/plugins/openapi/ResponsesSidecarBox.js +1 -1
  10. package/dist/lib/plugins/openapi/ResponsesSidecarBox.js.map +1 -1
  11. package/dist/lib/plugins/openapi/Sidecar.js +8 -2
  12. package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
  13. package/dist/lib/plugins/openapi/playground/Headers.js +6 -16
  14. package/dist/lib/plugins/openapi/playground/Headers.js.map +1 -1
  15. package/dist/lib/plugins/openapi/playground/PathParams.js +1 -1
  16. package/dist/lib/plugins/openapi/playground/PathParams.js.map +1 -1
  17. package/dist/lib/plugins/openapi/playground/Playground.js +27 -28
  18. package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
  19. package/dist/lib/plugins/openapi/playground/ResponseTab.js +1 -1
  20. package/dist/lib/plugins/openapi/playground/ResponseTab.js.map +1 -1
  21. package/dist/lib/plugins/openapi/schema/SchemaView.js +3 -5
  22. package/dist/lib/plugins/openapi/schema/SchemaView.js.map +1 -1
  23. package/dist/lib/ui/Callout.js +1 -1
  24. package/dist/lib/ui/Callout.js.map +1 -1
  25. package/lib/{AuthenticationPlugin-owbEUimP.js → AuthenticationPlugin-DYnkydqa.js} +3 -3
  26. package/lib/{AuthenticationPlugin-owbEUimP.js.map → AuthenticationPlugin-DYnkydqa.js.map} +1 -1
  27. package/lib/{CategoryHeading-DnPprxtD.js → CategoryHeading-D7_Jy0Lx.js} +2 -2
  28. package/lib/{CategoryHeading-DnPprxtD.js.map → CategoryHeading-D7_Jy0Lx.js.map} +1 -1
  29. package/lib/{Combination-DruV0zX_.js → Combination-Ce1nWgn5.js} +3 -3
  30. package/lib/{Combination-DruV0zX_.js.map → Combination-Ce1nWgn5.js.map} +1 -1
  31. package/lib/{ErrorPage-PUg985n_.js → ErrorPage-uwQIn-3A.js} +4 -4
  32. package/lib/{ErrorPage-PUg985n_.js.map → ErrorPage-uwQIn-3A.js.map} +1 -1
  33. package/lib/{Input-CBfi9Yjc.js → Input-CBiLCRuK.js} +6 -7
  34. package/lib/{Input-CBfi9Yjc.js.map → Input-CBiLCRuK.js.map} +1 -1
  35. package/lib/{Markdown-Chb9VIBv.js → Markdown-h11bKkQ9.js} +5 -5
  36. package/lib/Markdown-h11bKkQ9.js.map +1 -0
  37. package/lib/{MdxPage-CIBHMwTd.js → MdxPage-AzVbIhda.js} +5 -5
  38. package/lib/{MdxPage-CIBHMwTd.js.map → MdxPage-AzVbIhda.js.map} +1 -1
  39. package/lib/{OperationList-CZiSz5JH.js → OperationList-DajrjZzx.js} +84 -85
  40. package/lib/OperationList-DajrjZzx.js.map +1 -0
  41. package/lib/{Route-Cle-r-bq.js → Route-D7sTrFzF.js} +3 -3
  42. package/lib/{Route-Cle-r-bq.js.map → Route-D7sTrFzF.js.map} +1 -1
  43. package/lib/{SidebarBadge-Ba0PhibA.js → SidebarBadge-djIXD1Pv.js} +3 -3
  44. package/lib/{SidebarBadge-Ba0PhibA.js.map → SidebarBadge-djIXD1Pv.js.map} +1 -1
  45. package/lib/{SlotletProvider-Dq80og6-.js → SlotletProvider-WwEUzQQ3.js} +4 -4
  46. package/lib/{SlotletProvider-Dq80og6-.js.map → SlotletProvider-WwEUzQQ3.js.map} +1 -1
  47. package/lib/{Spinner-CvXZ7QK4.js → Spinner-D4ifRVWf.js} +2 -2
  48. package/lib/{Spinner-CvXZ7QK4.js.map → Spinner-D4ifRVWf.js.map} +1 -1
  49. package/lib/{ZudokuContext-BQ45UjcB.js → ZudokuContext-BHNQL3XO.js} +2 -2
  50. package/lib/{ZudokuContext-BQ45UjcB.js.map → ZudokuContext-BHNQL3XO.js.map} +1 -1
  51. package/lib/{index-DCJ9wEIV.js → index-CZAFD5xN.js} +3 -3
  52. package/lib/{index-DCJ9wEIV.js.map → index-CZAFD5xN.js.map} +1 -1
  53. package/lib/{index-Yjb2PyPF.js → index-ChhUJhLT.js} +4 -4
  54. package/lib/{index-Yjb2PyPF.js.map → index-ChhUJhLT.js.map} +1 -1
  55. package/lib/{index-Br1MQPxy.js → index-D2SS6ne_.js} +1111 -1113
  56. package/lib/index-D2SS6ne_.js.map +1 -0
  57. package/lib/{utils-pDHePxa0.js → utils-BPHLKjns.js} +3 -3
  58. package/lib/{utils-pDHePxa0.js.map → utils-BPHLKjns.js.map} +1 -1
  59. package/lib/zudoku.auth-clerk.js +1 -1
  60. package/lib/zudoku.auth-openid.js +5 -5
  61. package/lib/zudoku.components.js +112 -111
  62. package/lib/zudoku.components.js.map +1 -1
  63. package/lib/zudoku.plugin-api-keys.js +58 -45
  64. package/lib/zudoku.plugin-api-keys.js.map +1 -1
  65. package/lib/zudoku.plugin-custom-page.js +1 -1
  66. package/lib/zudoku.plugin-markdown.js +1 -1
  67. package/lib/zudoku.plugin-openapi.js +6 -6
  68. package/package.json +1 -1
  69. package/src/app/main.css +3 -1
  70. package/src/lib/components/Header.tsx +4 -4
  71. package/src/lib/components/SyntaxHighlight.tsx +1 -1
  72. package/src/lib/plugins/api-keys/SettingsApiKeys.tsx +25 -5
  73. package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +1 -1
  74. package/src/lib/plugins/openapi/ResponsesSidecarBox.tsx +1 -1
  75. package/src/lib/plugins/openapi/Sidecar.tsx +18 -13
  76. package/src/lib/plugins/openapi/playground/Headers.tsx +53 -68
  77. package/src/lib/plugins/openapi/playground/PathParams.tsx +1 -3
  78. package/src/lib/plugins/openapi/playground/Playground.tsx +43 -34
  79. package/src/lib/plugins/openapi/playground/ResponseTab.tsx +1 -1
  80. package/src/lib/plugins/openapi/schema/SchemaView.tsx +3 -10
  81. package/src/lib/ui/Callout.tsx +1 -1
  82. package/dist/lib/util/fetchTimeout.d.ts +0 -1
  83. package/dist/lib/util/fetchTimeout.js +0 -14
  84. package/dist/lib/util/fetchTimeout.js.map +0 -1
  85. package/lib/Markdown-Chb9VIBv.js.map +0 -1
  86. package/lib/OperationList-CZiSz5JH.js.map +0 -1
  87. package/lib/index-Br1MQPxy.js.map +0 -1
  88. package/src/lib/util/fetchTimeout.tsx +0 -21
@@ -140,19 +140,24 @@ export const Sidecar = ({
140
140
  ? generateSchemaExample(requestBodyContent[0].schema as SchemaObject)
141
141
  : undefined;
142
142
 
143
- const snippet = new HTTPSnippet(
144
- {
145
- method: operation.method.toLocaleUpperCase(),
146
- url: operation.path.replaceAll("{", ":").replaceAll("}", ""),
147
- headers: [{ name: "Authorization", value: "Bearer <token>" }],
148
- postData: example
149
- ? {
150
- text: JSON.stringify(example, null, 2),
151
- mimeType: "application/json",
152
- }
153
- : {},
154
- } as never, // 👈 never touch this
155
- );
143
+ const snippet = new HTTPSnippet({
144
+ method: operation.method.toLocaleUpperCase(),
145
+ url:
146
+ (result.data?.schema.url ?? "") +
147
+ operation.path.replaceAll("{", ":").replaceAll("}", ""),
148
+ postData: example
149
+ ? {
150
+ text: JSON.stringify(example, null, 2),
151
+ mimeType: "application/json",
152
+ }
153
+ : ({} as any),
154
+ headers: [],
155
+ queryString: [],
156
+ httpVersion: "",
157
+ cookies: [],
158
+ headersSize: 0,
159
+ bodySize: 0,
160
+ });
156
161
 
157
162
  return getConverted(snippet, selectedLang);
158
163
  }, [selectedLang, operation.method, operation.path, requestBodyContent]);
@@ -1,14 +1,8 @@
1
- import { TriangleAlertIcon, XIcon } from "lucide-react";
2
- import {
3
- Control,
4
- useFieldArray,
5
- UseFormRegister,
6
- useWatch,
7
- } from "react-hook-form";
1
+ import { XIcon } from "lucide-react";
2
+ import { Control, useFieldArray, UseFormRegister } from "react-hook-form";
8
3
  import { Button } from "../../../ui/Button.js";
9
- import { cn } from "../../../util/cn.js";
10
- import { InlineInput } from "./InlineInput.js";
11
- import { NO_IDENTITY, type PlaygroundForm } from "./Playground.js";
4
+ import { Input } from "../../../ui/Input.js";
5
+ import { type PlaygroundForm } from "./Playground.js";
12
6
 
13
7
  export const Headers = ({
14
8
  control,
@@ -21,67 +15,58 @@ export const Headers = ({
21
15
  control,
22
16
  name: "headers",
23
17
  });
24
- const selectedIdentity = useWatch({ name: "identity", control });
25
- const liveHeaders = useWatch({ name: "headers", control });
26
-
27
- const disableAuth = selectedIdentity !== NO_IDENTITY;
28
18
 
29
19
  return (
30
- <div className="grid grid-cols-[1fr_1fr_auto]">
31
- {fields.map((header, i) => {
32
- const isDisabledByAuth =
33
- disableAuth && liveHeaders.at(i)?.name === "Authorization";
34
-
35
- return (
36
- <div
37
- key={header.id}
38
- className={cn(
39
- "grid-cols-subgrid col-span-full grid items-center gap-x-2 has-[:focus]:bg-muted hover:bg-muted rounded overflow-hidden group",
40
- isDisabledByAuth && "line-through",
41
- )}
42
- title={
43
- isDisabledByAuth
44
- ? "This header is disabled because authentication was selected"
45
- : undefined
46
- }
47
- >
48
- <div className="flex gap-2 items-center">
49
- <InlineInput
50
- {...register(`headers.${i}.name`)}
51
- placeholder="Name"
52
- className="peer"
53
- autoComplete="off"
54
- />
55
- {isDisabledByAuth && (
56
- <TriangleAlertIcon size={16} className="text-amber-500" />
57
- )}
58
- </div>
59
- <InlineInput
60
- placeholder={"Value"}
61
- className="peer"
62
- {...register(`headers.${i}.value`)}
63
- autoComplete="off"
64
- />
65
- <button
66
- className="hover:bg-black/5 p-1 rounded mr-2 text-muted-foreground invisible group-hover:visible peer-focus:visible"
67
- onClick={() => {
68
- remove(i);
69
- }}
70
- type="button"
20
+ <div className="flex flex-col gap-2">
21
+ <table className="w-full [&_td]:border [&_td]:p-1.5 [&_td]:px-2">
22
+ <tbody>
23
+ {fields.map((header, i) => (
24
+ <tr
25
+ key={header.id}
26
+ className="group has-[:focus]:bg-muted/50 hover:bg-muted/50"
71
27
  >
72
- <XIcon size={16} />
73
- </button>
74
- <div className="col-span-full border-b"></div>
75
- </div>
76
- );
77
- })}
78
- <Button
79
- className="col-span-full mt-4"
80
- onClick={() => append({ name: "", value: "" })}
81
- type="button"
82
- >
83
- Add header
84
- </Button>
28
+ <td className="flex gap-2 items-center">
29
+ <Input
30
+ {...register(`headers.${i}.name`)}
31
+ placeholder="Name"
32
+ className="border-0 shadow-none text-xs font-mono"
33
+ autoComplete="off"
34
+ />
35
+ </td>
36
+ <td>
37
+ <div className="flex items-center gap-2">
38
+ <Input
39
+ placeholder={"Value"}
40
+ className="border-0 shadow-none text-xs font-mono"
41
+ {...register(`headers.${i}.value`)}
42
+ autoComplete="off"
43
+ />
44
+ <Button
45
+ size="icon"
46
+ variant="ghost"
47
+ className="text-muted-foreground opacity-0 group-hover:opacity-100"
48
+ onClick={() => {
49
+ remove(i);
50
+ }}
51
+ type="button"
52
+ >
53
+ <XIcon size={16} />
54
+ </Button>
55
+ </div>
56
+ </td>
57
+ </tr>
58
+ ))}
59
+ </tbody>
60
+ </table>
61
+ <div className="text-end">
62
+ <Button
63
+ className=""
64
+ onClick={() => append({ name: "", value: "" })}
65
+ type="button"
66
+ >
67
+ Add header
68
+ </Button>
69
+ </div>
85
70
  </div>
86
71
  );
87
72
  };
@@ -51,9 +51,7 @@ export const PathParams = ({
51
51
  <Input
52
52
  {...field}
53
53
  placeholder="Enter value"
54
- className={cn(
55
- "border-0 shadow-none ring-0 font-mono text-xs",
56
- )}
54
+ className="border-0 shadow-none ring-0 font-mono text-xs"
57
55
  />
58
56
  )}
59
57
  />
@@ -11,9 +11,9 @@ import {
11
11
  } from "../../../components/Select.js";
12
12
  import { Spinner } from "../../../components/Spinner.js";
13
13
  import { Button } from "../../../ui/Button.js";
14
- import { Card } from "../../../ui/Card.js";
14
+ import { Callout } from "../../../ui/Callout.js";
15
+ import { Card, CardContent, CardHeader, CardTitle } from "../../../ui/Card.js";
15
16
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../../ui/Tabs.js";
16
- import { fetchTimeout } from "../../../util/fetchTimeout.js";
17
17
  import { ColorizedParam } from "../ColorizedParam.js";
18
18
  import { createUrl } from "./createUrl.js";
19
19
  import { Headers } from "./Headers.js";
@@ -23,23 +23,6 @@ import { ResponseTab } from "./ResponseTab.js";
23
23
 
24
24
  export const NO_IDENTITY = "__none";
25
25
 
26
- function mimeTypeToLanguage(mimeType: string) {
27
- const mimeTypeMapping = {
28
- "application/json": "json",
29
- "text/json": "json",
30
- "text/html": "html",
31
- "text/css": "css",
32
- "text/javascript": "javascript",
33
- "application/xml": "xml",
34
- "application/xhtml+xml": "xhtml",
35
- "text/plain": "plain",
36
- } as const;
37
-
38
- return Object.entries(mimeTypeMapping).find(([mime]) =>
39
- mimeType.includes(mime),
40
- )?.[1];
41
- }
42
-
43
26
  const statusCodeMap: Record<number, string> = {
44
27
  200: "OK",
45
28
  201: "Created",
@@ -148,18 +131,31 @@ export const Playground = ({
148
131
  ?.find((i) => i.id === data.identity)
149
132
  ?.authorizeRequest(request);
150
133
  }
151
- const response = await fetchTimeout(request);
152
- const time = performance.now() - start;
134
+ try {
135
+ const response = await fetch(request, {
136
+ signal: AbortSignal.timeout(5000),
137
+ });
138
+
139
+ const time = performance.now() - start;
153
140
 
154
- const body = await response.text();
141
+ const body = await response.text();
155
142
 
156
- return {
157
- status: response.status,
158
- headers: response.headers,
159
- size: body.length,
160
- body,
161
- time,
162
- };
143
+ return {
144
+ status: response.status,
145
+ headers: response.headers,
146
+ size: body.length,
147
+ body,
148
+ time,
149
+ };
150
+ } catch (error) {
151
+ if (error instanceof TypeError) {
152
+ throw new Error(
153
+ "The request failed, possibly due to network issues or CORS policy.",
154
+ );
155
+ } else {
156
+ throw error;
157
+ }
158
+ }
163
159
  },
164
160
  });
165
161
 
@@ -298,11 +294,24 @@ export const Playground = ({
298
294
  </div>
299
295
  <div className="flex flex-col gap-4 p-8 bg-muted/70">
300
296
  {queryMutation.error ? (
301
- <div>
302
- Error:{" "}
303
- {queryMutation.error.message ||
304
- String(queryMutation.error) ||
305
- "Unexpected error"}
297
+ <div className="flex flex-col gap-2">
298
+ {formState.pathParams.some((p) => p.value === "") && (
299
+ <Callout type="caution">
300
+ Some path parameters are missing values. Please fill them in
301
+ to ensure the request is sent correctly.
302
+ </Callout>
303
+ )}
304
+ <Card>
305
+ <CardHeader>
306
+ <CardTitle>Request failed</CardTitle>
307
+ </CardHeader>
308
+ <CardContent>
309
+ Error:{" "}
310
+ {queryMutation.error.message ||
311
+ String(queryMutation.error) ||
312
+ "Unexpected error"}
313
+ </CardContent>
314
+ </Card>
306
315
  </div>
307
316
  ) : queryMutation.data ? (
308
317
  <div className="flex flex-col gap-2">
@@ -55,7 +55,7 @@ export const ResponseTab = ({
55
55
  }
56
56
  noBackground
57
57
  showLanguageIndicator
58
- className="overflow-x-auto p-4 text-xs"
58
+ className="overflow-x-auto p-4 text-xs max-h-[480px]"
59
59
  code={view === "raw" ? body : beautifiedBody}
60
60
  />
61
61
  </Card>
@@ -26,7 +26,7 @@ export const SchemaView = ({
26
26
  }
27
27
 
28
28
  const renderSchema = (schema: SchemaObject, level: number) => {
29
- if (schema.oneOf || schema.allOf || schema.anyOf) {
29
+ if (hasLogicalGroupings(schema)) {
30
30
  return <SchemaLogicalGroup schema={schema} level={level} />;
31
31
  }
32
32
 
@@ -55,10 +55,7 @@ export const SchemaView = ({
55
55
  )}
56
56
  </Card>
57
57
  );
58
- } else if (
59
- itemsSchema.type === "object" ||
60
- hasLogicalGroupings(itemsSchema)
61
- ) {
58
+ } else if (itemsSchema.type === "object") {
62
59
  return (
63
60
  <Card className="flex flex-col gap-2 bg-border/30 p-4">
64
61
  <span className="text-sm text-muted-foreground">object[]</span>
@@ -100,9 +97,6 @@ export const SchemaView = ({
100
97
  },
101
98
  );
102
99
 
103
- const isTopLevelSingleItem =
104
- level === 0 && Object.keys(groupedProperties).length === 1;
105
-
106
100
  const groupNames = ["required", "optional", "deprecated"] as const;
107
101
 
108
102
  return (
@@ -118,8 +112,7 @@ export const SchemaView = ({
118
112
  schema={schema}
119
113
  group={group}
120
114
  level={level}
121
- defaultOpen={isTopLevelSingleItem || defaultOpen}
122
- showCollapseButton={!isTopLevelSingleItem}
115
+ defaultOpen={defaultOpen}
123
116
  />
124
117
  ))}
125
118
  </ul>
@@ -74,7 +74,7 @@ export const Callout = ({ type, children, title, className }: CalloutProps) => {
74
74
  )}
75
75
  >
76
76
  <Icon
77
- className={cn(!title && "mt-1 translate-y-px", iconColor)}
77
+ className={cn(!title && "translate-y-px", iconColor)}
78
78
  size={20}
79
79
  aria-hidden="true"
80
80
  />
@@ -1 +0,0 @@
1
- export declare const fetchTimeout: (input: RequestInfo, init?: RequestInit, timeout?: number) => Promise<Response>;
@@ -1,14 +0,0 @@
1
- export const fetchTimeout = async (input, init, timeout = 5000) => {
2
- const controller = new AbortController();
3
- const signal = controller.signal;
4
- const fetchPromise = fetch(input, { ...init, signal });
5
- const timeoutPromise = new Promise((_, reject) => {
6
- const timer = setTimeout(() => {
7
- controller.abort("Request timed out");
8
- reject(new Error("Request timed out"));
9
- }, timeout);
10
- void fetchPromise.finally(() => clearTimeout(timer));
11
- });
12
- return Promise.race([fetchPromise, timeoutPromise]);
13
- };
14
- //# sourceMappingURL=fetchTimeout.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fetchTimeout.js","sourceRoot":"","sources":["../../../src/lib/util/fetchTimeout.tsx"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAC/B,KAAkB,EAClB,IAAkB,EAClB,OAAO,GAAG,IAAI,EACK,EAAE;IACrB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAEjC,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAEvD,MAAM,cAAc,GAAG,IAAI,OAAO,CAAW,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QACzD,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,UAAU,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACtC,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC;QACzC,CAAC,EAAE,OAAO,CAAC,CAAC;QAEZ,KAAK,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC;AACtD,CAAC,CAAC"}