zudoku 0.71.10 → 0.72.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/cli/cli.js CHANGED
@@ -3810,7 +3810,7 @@ import {
3810
3810
  // package.json
3811
3811
  var package_default = {
3812
3812
  name: "zudoku",
3813
- version: "0.71.9",
3813
+ version: "0.71.10",
3814
3814
  type: "module",
3815
3815
  sideEffects: [
3816
3816
  "**/*.css",
@@ -3871,7 +3871,6 @@ var package_default = {
3871
3871
  "./vite": "./src/vite/index.ts",
3872
3872
  "./app/*": "./src/app/*",
3873
3873
  "./hooks": "./src/lib/hooks/index.ts",
3874
- "./main.css": "./src/app/main.css",
3875
3874
  "./processors/*": "./src/lib/plugins/openapi/processors/*.ts",
3876
3875
  "./with-zuplo": "./src/zuplo/with-zuplo.ts",
3877
3876
  "./testing": "./src/lib/testing/index.tsx"
@@ -3882,7 +3881,7 @@ var package_default = {
3882
3881
  typecheck: "tsc --project tsconfig.app.json --noEmit",
3883
3882
  "generate:types": "tsx scripts/generate-types.js && tsx scripts/generate-flat-config.js",
3884
3883
  "build:standalone": "vite build --mode standalone --config vite.standalone.config.ts --log-level=error",
3885
- prepublishOnly: "tsx scripts/generate-publish-exports.ts",
3884
+ prepublishOnly: "tsx scripts/generate-publish-exports.ts && publint .",
3886
3885
  postpublish: "git checkout -- package.json",
3887
3886
  clean: "rm -rf dist",
3888
3887
  codegen: "graphql-codegen --config ./src/codegen.ts"
@@ -4002,10 +4001,10 @@ var package_default = {
4002
4001
  vaul: "1.1.2",
4003
4002
  vfile: "6.0.3",
4004
4003
  vite: "7.3.1",
4005
- yaml: "2.8.2",
4004
+ yaml: "2.8.3",
4006
4005
  yargs: "18.0.0",
4007
4006
  zod: "4.3.6",
4008
- zustand: "5.0.11"
4007
+ zustand: "5.0.12"
4009
4008
  },
4010
4009
  devDependencies: {
4011
4010
  "@clerk/clerk-js": "^5.125.3",
@@ -6606,6 +6605,10 @@ ${markdownContent}`;
6606
6605
  description: frontmatter.description
6607
6606
  };
6608
6607
  };
6608
+ var getMarkdownOutputPath = (distDir, routePath) => {
6609
+ const segments = routePath === "/" ? ["index"] : routePath.split("/").filter(Boolean);
6610
+ return `${path14.join(distDir, ...segments)}.md`;
6611
+ };
6609
6612
  var viteMarkdownExportPlugin = () => {
6610
6613
  let markdownFiles = {};
6611
6614
  let markdownFileInfos = [];
@@ -6699,8 +6702,7 @@ var viteMarkdownExportPlugin = () => {
6699
6702
  description,
6700
6703
  content: finalMarkdown
6701
6704
  });
6702
- const segments = routePath === "/" ? ["index"] : routePath.split("/").filter(Boolean);
6703
- const outputPath = `${path14.join(distDir, ...segments)}.md`;
6705
+ const outputPath = getMarkdownOutputPath(distDir, routePath);
6704
6706
  await mkdir2(path14.dirname(outputPath), { recursive: true });
6705
6707
  await writeFile2(outputPath, finalMarkdown, "utf-8");
6706
6708
  } catch (error) {
@@ -7896,8 +7898,14 @@ var prerender = async ({
7896
7898
  }
7897
7899
  if (!docsConfig.publishMarkdown) {
7898
7900
  await Promise.all(
7899
- markdownFileInfos.map((info) => rm(info.filePath).catch(() => {
7900
- }))
7901
+ markdownFileInfos.map((info) => {
7902
+ const outputPath = getMarkdownOutputPath(distDir, info.routePath);
7903
+ if (!path21.resolve(outputPath).startsWith(path21.resolve(distDir))) {
7904
+ return;
7905
+ }
7906
+ return rm(outputPath).catch(() => {
7907
+ });
7908
+ })
7901
7909
  );
7902
7910
  }
7903
7911
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zudoku",
3
- "version": "0.71.10",
3
+ "version": "0.72.0",
4
4
  "type": "module",
5
5
  "sideEffects": [
6
6
  "**/*.css",
@@ -130,7 +130,6 @@
130
130
  "types": "./dist/declarations/lib/hooks/index.d.ts",
131
131
  "default": "./src/lib/hooks/index.ts"
132
132
  },
133
- "./main.css": "./src/app/main.css",
134
133
  "./processors/*": {
135
134
  "types": "./dist/declarations/lib/plugins/openapi/processors/*.d.ts",
136
135
  "default": "./src/lib/plugins/openapi/processors/*.ts"
@@ -259,10 +258,10 @@
259
258
  "vaul": "1.1.2",
260
259
  "vfile": "6.0.3",
261
260
  "vite": "7.3.1",
262
- "yaml": "2.8.2",
261
+ "yaml": "2.8.3",
263
262
  "yargs": "18.0.0",
264
263
  "zod": "4.3.6",
265
- "zustand": "5.0.11"
264
+ "zustand": "5.0.12"
266
265
  },
267
266
  "devDependencies": {
268
267
  "@clerk/clerk-js": "^5.125.3",
@@ -13,19 +13,17 @@ const errorDetailsMap: Record<string, { message: string }> = {
13
13
  "The authentication request was invalid. Please try signing in again.",
14
14
  },
15
15
  unauthorized_client: {
16
- message:
17
- "This application is not authorized to access your account. Please contact support.",
16
+ message: "This application is not authorized to access your account.",
18
17
  },
19
18
  access_denied: {
20
19
  message:
21
20
  "You denied access to this application. To continue, please sign in and grant access.",
22
21
  },
23
22
  unsupported_response_type: {
24
- message:
25
- "The authentication method is not supported. Please contact support.",
23
+ message: "The authentication method is not supported.",
26
24
  },
27
25
  invalid_scope: {
28
- message: "The requested permissions are invalid. Please contact support.",
26
+ message: "The requested permissions are invalid.",
29
27
  },
30
28
  server_error: {
31
29
  message:
@@ -37,15 +35,14 @@ const errorDetailsMap: Record<string, { message: string }> = {
37
35
  },
38
36
  // Token errors
39
37
  invalid_client: {
40
- message: "Invalid application credentials. Please contact support.",
38
+ message: "Invalid application credentials.",
41
39
  },
42
40
  invalid_grant: {
43
41
  message:
44
42
  "The authentication code has expired or is invalid. Please sign in again.",
45
43
  },
46
44
  unsupported_grant_type: {
47
- message:
48
- "The authentication method is not supported. Please contact support.",
45
+ message: "The authentication method is not supported.",
49
46
  },
50
47
  // Custom errors
51
48
  invalid_state: {
@@ -64,8 +61,7 @@ const errorDetailsMap: Record<string, { message: string }> = {
64
61
  message: "Your authentication session has expired. Please sign in again.",
65
62
  },
66
63
  configuration_error: {
67
- message:
68
- "There is an issue with the authentication configuration. Please contact support.",
64
+ message: "There is an issue with the authentication configuration.",
69
65
  },
70
66
  unknown_error: {
71
67
  message:
@@ -13,7 +13,7 @@ import type {
13
13
  import { CoreAuthenticationPlugin } from "../AuthenticationPlugin.js";
14
14
  import { CallbackHandler } from "../components/CallbackHandler.js";
15
15
  import { OAuthErrorPage } from "../components/OAuthErrorPage.js";
16
- import { AuthorizationError } from "../errors.js";
16
+ import { AuthorizationError, OAuthAuthorizationError } from "../errors.js";
17
17
  import { type UserProfile, useAuthState } from "../state.js";
18
18
 
19
19
  const CODE_VERIFIER_KEY = "code-verifier";
@@ -106,6 +106,19 @@ export class OpenIDAuthenticationProvider
106
106
  throw new AuthorizationError("No expires_in in response");
107
107
  }
108
108
 
109
+ const accessToken = response.access_token;
110
+ if (accessToken.split(".").length !== 3) {
111
+ throw new OAuthAuthorizationError(
112
+ "The access token received is not a valid JWT.",
113
+ {
114
+ error: "configuration_error",
115
+ error_description:
116
+ "The authentication provider is issuing opaque tokens instead of JWTs. " +
117
+ "Ensure you have configured the correct `audience` in your authentication settings.",
118
+ },
119
+ );
120
+ }
121
+
109
122
  const claims = response.id_token
110
123
  ? oauth.getValidatedIdTokenClaims(response)
111
124
  : undefined;
@@ -17,7 +17,7 @@ export const DeveloperHint = ({
17
17
  if (process.env.NODE_ENV !== "development") return null;
18
18
 
19
19
  return (
20
- <Alert variant="info" className={className}>
20
+ <Alert variant="info" className={className} fit="loose">
21
21
  <InfoIcon />
22
22
  <AlertTitle>Developer hint</AlertTitle>
23
23
  <AlertDescription>
@@ -12,9 +12,9 @@ import { Slot } from "./Slot.js";
12
12
  import { Spinner } from "./Spinner.js";
13
13
 
14
14
  const LoadingFallback = () => (
15
- <main className="col-span-full row-span-full grid place-items-center">
15
+ <div className="col-span-full row-span-full grid place-items-center">
16
16
  <Spinner />
17
- </main>
17
+ </div>
18
18
  );
19
19
 
20
20
  export const Layout = ({ children }: { children?: ReactNode }) => {
@@ -256,12 +256,13 @@ export const Playground = ({
256
256
  break;
257
257
  }
258
258
 
259
+ const upperMethod = method.toUpperCase();
259
260
  const request = new Request(
260
261
  createUrl(server ?? selectedServer, url, data),
261
262
  {
262
- method,
263
+ method: upperMethod,
263
264
  headers,
264
- body: ["GET", "HEAD"].includes(method.toUpperCase()) ? null : body,
265
+ body: ["GET", "HEAD"].includes(upperMethod) ? null : body,
265
266
  },
266
267
  );
267
268
 
@@ -153,7 +153,7 @@ const ObjectSchemaView = ({
153
153
  return properties ? { group, properties } : [];
154
154
  });
155
155
 
156
- const deprecatedProperties = groupedProperties["deprecated"];
156
+ const deprecatedProperties = groupedProperties.deprecated;
157
157
 
158
158
  const additionalObjectProperties = typeof schema.additionalProperties ===
159
159
  "object" && <SchemaView schema={schema.additionalProperties} embedded />;
@@ -120,7 +120,7 @@ const StaticZudoku = ({
120
120
  ],
121
121
  },
122
122
  ],
123
- { initialEntries: [path] },
123
+ { initialEntries: [path], basename: options.basePath },
124
124
  );
125
125
 
126
126
  return (
@@ -41,6 +41,26 @@ const normalizeProblemJson = (data: unknown): ProblemJson | undefined => {
41
41
  } as ProblemJson;
42
42
  };
43
43
 
44
+ /** Some gateways return RFC 7807-shaped bodies with `application/json`. */
45
+ const normalizeProblemJsonIfProblemLike = (
46
+ data: unknown,
47
+ ): ProblemJson | undefined => {
48
+ if (typeof data !== "object" || data === null || Array.isArray(data)) {
49
+ return;
50
+ }
51
+
52
+ const record = data as Record<string, unknown>;
53
+ const hasDetail = typeof record.detail === "string";
54
+ const hasTitle = typeof record.title === "string";
55
+ const hasStatus = typeof record.status === "number";
56
+
57
+ if (!hasDetail && !(hasTitle && hasStatus)) {
58
+ return;
59
+ }
60
+
61
+ return normalizeProblemJson(data);
62
+ };
63
+
44
64
  export const getProblemJson = async (
45
65
  response: Response,
46
66
  ): Promise<ProblemJson | undefined> => {
@@ -54,10 +74,25 @@ export const getProblemJson = async (
54
74
  };
55
75
 
56
76
  export const throwIfProblemJson = async (response: Response) => {
57
- if (!response.ok) {
77
+ if (response.ok) {
78
+ return;
79
+ }
80
+
81
+ const contentType = response.headers.get("content-type") ?? "";
82
+
83
+ if (isProblemJsonContentType(response)) {
58
84
  const problem = await getProblemJson(response);
59
85
  if (problem) {
60
86
  throw new Error(problem.detail ?? problem.title ?? "Unknown error");
61
87
  }
88
+ return;
89
+ }
90
+
91
+ if (contentType.includes("application/json")) {
92
+ const data = await parseJsonSafe(response.clone());
93
+ const problem = normalizeProblemJsonIfProblemLike(data);
94
+ if (problem) {
95
+ throw new Error(problem.detail ?? problem.title ?? "Unknown error");
96
+ }
62
97
  }
63
98
  };
@@ -49,6 +49,12 @@ const processMarkdownFile = async (
49
49
  *
50
50
  * It also writes metadata to markdown-info.json used by the llms.txt generator.
51
51
  */
52
+ export const getMarkdownOutputPath = (distDir: string, routePath: string) => {
53
+ const segments =
54
+ routePath === "/" ? ["index"] : routePath.split("/").filter(Boolean);
55
+ return `${path.join(distDir, ...segments)}.md`;
56
+ };
57
+
52
58
  const viteMarkdownExportPlugin = (): Plugin => {
53
59
  let markdownFiles: Record<string, string> = {};
54
60
  let markdownFileInfos: MarkdownFileInfo[] = [];
@@ -180,12 +186,7 @@ const viteMarkdownExportPlugin = (): Plugin => {
180
186
  content: finalMarkdown,
181
187
  });
182
188
 
183
- const segments =
184
- routePath === "/"
185
- ? ["index"]
186
- : routePath.split("/").filter(Boolean);
187
-
188
- const outputPath = `${path.join(distDir, ...segments)}.md`;
189
+ const outputPath = getMarkdownOutputPath(distDir, routePath);
189
190
 
190
191
  await mkdir(path.dirname(outputPath), { recursive: true });
191
192
 
@@ -13,7 +13,10 @@ import type { ZudokuConfig } from "../../config/validators/ZudokuConfig.js";
13
13
  import { runPluginTransformConfig } from "../../lib/core/transform-config.js";
14
14
  import invariant from "../../lib/util/invariant.js";
15
15
  import { joinUrl } from "../../lib/util/joinUrl.js";
16
- import type { MarkdownFileInfo } from "../plugin-markdown-export.js";
16
+ import {
17
+ getMarkdownOutputPath,
18
+ type MarkdownFileInfo,
19
+ } from "../plugin-markdown-export.js";
17
20
  import { isTTY, throttle, writeLine } from "../reporter.js";
18
21
  import { generateSitemap } from "../sitemap.js";
19
22
  import { routesToPaths, routesToRewrites } from "./utils.js";
@@ -224,7 +227,13 @@ export const prerender = async ({
224
227
 
225
228
  if (!docsConfig.publishMarkdown) {
226
229
  await Promise.all(
227
- markdownFileInfos.map((info) => rm(info.filePath).catch(() => {})),
230
+ markdownFileInfos.map((info) => {
231
+ const outputPath = getMarkdownOutputPath(distDir, info.routePath);
232
+ if (!path.resolve(outputPath).startsWith(path.resolve(distDir))) {
233
+ return;
234
+ }
235
+ return rm(outputPath).catch(() => {});
236
+ }),
228
237
  );
229
238
  }
230
239
  }