zudoku 0.79.0 → 0.80.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 (158) hide show
  1. package/dist/cli/cli.js +355 -515
  2. package/dist/declarations/app/ssrCacheControl.d.ts +1 -0
  3. package/dist/declarations/config/create-plugin.d.ts +2 -1
  4. package/dist/declarations/config/validators/InputNavigationSchema.d.ts +13 -0
  5. package/dist/declarations/config/validators/NavigationSchema.d.ts +7 -1
  6. package/dist/declarations/config/validators/ZudokuConfig.d.ts +1 -0
  7. package/dist/declarations/index.d.ts +1 -0
  8. package/dist/declarations/lib/authentication/components/CallbackHandler.d.ts +1 -1
  9. package/dist/declarations/lib/authentication/cookie-sync.d.ts +1 -0
  10. package/dist/declarations/lib/authentication/utils/redirectAfterAuth.d.ts +4 -0
  11. package/dist/declarations/lib/components/Anchor.d.ts +5 -0
  12. package/dist/declarations/lib/components/Bootstrap.d.ts +5 -4
  13. package/dist/declarations/lib/components/Meta.d.ts +1 -1
  14. package/dist/declarations/lib/components/PluginHeads.d.ts +1 -1
  15. package/dist/declarations/lib/components/index.d.ts +3 -1
  16. package/dist/declarations/lib/components/navigation/Navigation.d.ts +2 -1
  17. package/dist/declarations/lib/components/navigation/NavigationFilterContext.d.ts +3 -1
  18. package/dist/declarations/lib/components/navigation/NavigationFrames.d.ts +6 -0
  19. package/dist/declarations/lib/components/navigation/StackRows.d.ts +12 -0
  20. package/dist/declarations/lib/components/navigation/motionFeatures.d.ts +1 -0
  21. package/dist/declarations/lib/components/navigation/useNavigationFrame.d.ts +15 -0
  22. package/dist/declarations/lib/components/navigation/utils.d.ts +16 -1
  23. package/dist/declarations/lib/core/plugin-config.d.ts +2 -0
  24. package/dist/declarations/lib/graphiql/GraphiQLViewer.d.ts +29 -0
  25. package/dist/declarations/lib/graphiql/index.d.ts +2 -0
  26. package/dist/declarations/lib/graphiql/loadGraphiQLFromCdn.d.ts +45 -0
  27. package/dist/declarations/lib/hooks/index.d.ts +1 -0
  28. package/dist/declarations/lib/plugins/openapi/ApiHeader.d.ts +1 -2
  29. package/dist/declarations/lib/plugins/openapi/ParameterList.d.ts +2 -1
  30. package/dist/declarations/lib/plugins/openapi/ParameterListItem.d.ts +1 -1
  31. package/dist/declarations/lib/plugins/openapi/PlaygroundDialogWrapper.d.ts +3 -2
  32. package/dist/declarations/lib/plugins/openapi/RequestBodySidecarBox.d.ts +2 -2
  33. package/dist/declarations/lib/plugins/openapi/ResponsesSidecarBox.d.ts +12 -4
  34. package/dist/declarations/lib/plugins/openapi/SchemaInfo.d.ts +4 -1
  35. package/dist/declarations/lib/plugins/openapi/Sidecar.d.ts +3 -3
  36. package/dist/declarations/lib/plugins/openapi/SidecarExamples.d.ts +2 -2
  37. package/dist/declarations/lib/plugins/openapi/components/ResponseContent.d.ts +2 -2
  38. package/dist/declarations/lib/plugins/openapi/graphql/gql.d.ts +1 -1
  39. package/dist/declarations/lib/plugins/openapi/graphql/graphql.d.ts +136 -466
  40. package/dist/declarations/lib/plugins/openapi/index.d.ts +3 -3
  41. package/dist/declarations/lib/plugins/openapi/interfaces.d.ts +2 -2
  42. package/dist/declarations/lib/plugins/openapi/playground/BodyPanel.d.ts +2 -2
  43. package/dist/declarations/lib/plugins/openapi/playground/ExamplesDropdown.d.ts +3 -3
  44. package/dist/declarations/lib/plugins/openapi/playground/GraphiQL.d.ts +9 -0
  45. package/dist/declarations/lib/plugins/openapi/playground/GraphiQLDialog.d.ts +11 -0
  46. package/dist/declarations/lib/plugins/openapi/playground/Playground.d.ts +5 -3
  47. package/dist/declarations/lib/plugins/openapi/playground/result-panel/ResponseTab.d.ts +2 -1
  48. package/dist/declarations/lib/plugins/openapi/playground/result-panel/ResultPanel.d.ts +2 -1
  49. package/dist/declarations/lib/plugins/openapi/playground/result-panel/convertToTypes.d.ts +2 -2
  50. package/dist/declarations/lib/plugins/openapi/util/extractOperationSecuritySchemes.d.ts +2 -1
  51. package/dist/declarations/lib/plugins/openapi/util/graphqlEndpoint.d.ts +6 -0
  52. package/dist/declarations/lib/plugins/openapi/util/shouldShowInfoPage.d.ts +1 -0
  53. package/dist/declarations/lib/ui/Callout.d.ts +32 -28
  54. package/dist/declarations/lib/util/MdxComponents.d.ts +8 -2
  55. package/dist/declarations/vite/index.d.ts +3 -0
  56. package/dist/flat-config.d.ts +7 -0
  57. package/docs/components/callout.mdx +126 -8
  58. package/docs/components/head.mdx +2 -12
  59. package/docs/components/sidecar-box.mdx +131 -0
  60. package/docs/configuration/api-catalog.md +62 -43
  61. package/docs/configuration/api-reference.md +5 -4
  62. package/docs/configuration/navigation.mdx +70 -7
  63. package/docs/customization/colors-theme.mdx +19 -0
  64. package/docs/markdown/admonitions.md +79 -0
  65. package/package.json +30 -24
  66. package/src/app/defaultTheme.css +22 -0
  67. package/src/app/demo.tsx +4 -1
  68. package/src/app/entry.client.tsx +4 -2
  69. package/src/app/entry.server.tsx +13 -19
  70. package/src/app/main.css +14 -1
  71. package/src/app/ssrCacheControl.ts +20 -0
  72. package/src/app/standalone.tsx +4 -1
  73. package/src/config/create-plugin.ts +47 -28
  74. package/src/config/loader.ts +92 -34
  75. package/src/config/validators/InputNavigationSchema.ts +10 -0
  76. package/src/config/validators/NavigationSchema.ts +16 -2
  77. package/src/config/validators/ZudokuConfig.ts +32 -3
  78. package/src/index.ts +1 -0
  79. package/src/lib/authentication/components/CallbackHandler.tsx +9 -2
  80. package/src/lib/authentication/cookie-sync.ts +39 -6
  81. package/src/lib/authentication/providers/supabase.tsx +7 -1
  82. package/src/lib/authentication/ui/EmailLinkCallbackUi.tsx +2 -1
  83. package/src/lib/authentication/ui/ZudokuAuthUi.tsx +5 -4
  84. package/src/lib/authentication/utils/redirectAfterAuth.ts +25 -0
  85. package/src/lib/components/Anchor.tsx +29 -0
  86. package/src/lib/components/Bootstrap.tsx +10 -7
  87. package/src/lib/components/Header.tsx +3 -3
  88. package/src/lib/components/Main.tsx +2 -1
  89. package/src/lib/components/Meta.tsx +51 -45
  90. package/src/lib/components/PluginHeads.tsx +16 -8
  91. package/src/lib/components/context/ZudokuContext.ts +3 -0
  92. package/src/lib/components/index.ts +3 -1
  93. package/src/lib/components/navigation/Navigation.tsx +33 -39
  94. package/src/lib/components/navigation/NavigationCategory.tsx +28 -16
  95. package/src/lib/components/navigation/NavigationFilterContext.tsx +15 -1
  96. package/src/lib/components/navigation/NavigationFrames.tsx +104 -0
  97. package/src/lib/components/navigation/NavigationItem.tsx +33 -21
  98. package/src/lib/components/navigation/NavigationWrapper.tsx +29 -2
  99. package/src/lib/components/navigation/StackRows.tsx +65 -0
  100. package/src/lib/components/navigation/motionFeatures.ts +2 -0
  101. package/src/lib/components/navigation/useNavigationFrame.ts +107 -0
  102. package/src/lib/components/navigation/utils.ts +60 -6
  103. package/src/lib/core/RouteGuard.tsx +3 -3
  104. package/src/lib/core/plugin-config.ts +25 -0
  105. package/src/lib/graphiql/GraphiQLViewer.tsx +247 -0
  106. package/src/lib/graphiql/graphiql-sri.json +11 -0
  107. package/src/lib/graphiql/graphiql-theme.css +83 -0
  108. package/src/lib/graphiql/graphiql.css +6 -0
  109. package/src/lib/graphiql/index.ts +7 -0
  110. package/src/lib/graphiql/loadGraphiQLFromCdn.ts +191 -0
  111. package/src/lib/hooks/index.ts +1 -0
  112. package/src/lib/plugins/api-catalog/Catalog.tsx +3 -3
  113. package/src/lib/plugins/markdown/MdxPage.tsx +3 -3
  114. package/src/lib/plugins/openapi/ApiHeader.tsx +1 -3
  115. package/src/lib/plugins/openapi/GeneratedExampleSidecarBox.tsx +1 -1
  116. package/src/lib/plugins/openapi/OperationList.tsx +4 -9
  117. package/src/lib/plugins/openapi/OperationListItem.tsx +150 -118
  118. package/src/lib/plugins/openapi/ParamInfos.tsx +1 -1
  119. package/src/lib/plugins/openapi/ParameterList.tsx +5 -1
  120. package/src/lib/plugins/openapi/ParameterListItem.tsx +1 -1
  121. package/src/lib/plugins/openapi/PlaygroundDialogWrapper.tsx +22 -5
  122. package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +3 -3
  123. package/src/lib/plugins/openapi/ResponsesSidecarBox.tsx +17 -9
  124. package/src/lib/plugins/openapi/SchemaInfo.tsx +27 -7
  125. package/src/lib/plugins/openapi/SchemaList.tsx +6 -6
  126. package/src/lib/plugins/openapi/Sidecar.tsx +118 -43
  127. package/src/lib/plugins/openapi/SidecarExamples.tsx +3 -3
  128. package/src/lib/plugins/openapi/components/ResponseContent.tsx +2 -2
  129. package/src/lib/plugins/openapi/graphql/gql.ts +3 -3
  130. package/src/lib/plugins/openapi/graphql/graphql.ts +146 -524
  131. package/src/lib/plugins/openapi/index.tsx +8 -1
  132. package/src/lib/plugins/openapi/interfaces.ts +2 -2
  133. package/src/lib/plugins/openapi/playground/BodyPanel.tsx +2 -2
  134. package/src/lib/plugins/openapi/playground/ExamplesDropdown.tsx +3 -3
  135. package/src/lib/plugins/openapi/playground/GraphiQL.tsx +24 -0
  136. package/src/lib/plugins/openapi/playground/GraphiQLDialog.tsx +79 -0
  137. package/src/lib/plugins/openapi/playground/Playground.tsx +5 -2
  138. package/src/lib/plugins/openapi/playground/result-panel/ResponseTab.tsx +7 -5
  139. package/src/lib/plugins/openapi/playground/result-panel/ResultPanel.tsx +18 -0
  140. package/src/lib/plugins/openapi/playground/result-panel/convertToTypes.ts +28 -9
  141. package/src/lib/plugins/openapi/util/extractOperationSecuritySchemes.ts +5 -4
  142. package/src/lib/plugins/openapi/util/getRoutes.tsx +27 -14
  143. package/src/lib/plugins/openapi/util/graphqlEndpoint.ts +28 -0
  144. package/src/lib/plugins/openapi/util/shouldShowInfoPage.ts +15 -0
  145. package/src/lib/shiki.ts +1 -1
  146. package/src/lib/testing/index.tsx +4 -3
  147. package/src/lib/ui/Callout.tsx +68 -68
  148. package/src/lib/ui/EmbeddedCodeBlock.tsx +2 -2
  149. package/src/lib/{plugins/openapi → ui}/SidecarBox.tsx +1 -1
  150. package/src/lib/util/MdxComponents.tsx +6 -0
  151. package/src/vite/config.ts +7 -3
  152. package/src/vite/dev-server.ts +11 -4
  153. package/src/vite/html.ts +0 -2
  154. package/src/vite/index.ts +9 -0
  155. package/src/vite/plugin-api.ts +20 -4
  156. package/src/vite/plugin-docs.ts +3 -2
  157. package/src/vite/plugin-theme.ts +6 -2
  158. /package/dist/declarations/lib/{plugins/openapi → ui}/SidecarBox.d.ts +0 -0
package/dist/cli/cli.js CHANGED
@@ -85,9 +85,9 @@ var init_transform_config = __esm({
85
85
  }
86
86
  return result;
87
87
  };
88
- runPluginTransformConfig = async (config2) => {
89
- const plugins = config2.plugins ?? [];
90
- let result = config2;
88
+ runPluginTransformConfig = async (config) => {
89
+ const plugins = config.plugins ?? [];
90
+ let result = config;
91
91
  for (const plugin of plugins.filter(isTransformConfigPlugin)) {
92
92
  const merge = (partial) => mergeConfig(result, partial);
93
93
  const transformed = await plugin.transformConfig?.({
@@ -506,8 +506,8 @@ var init_plugin_theme = __esm({
506
506
  // Handle the virtual module for dynamic theme content
507
507
  async load(id) {
508
508
  if (id !== resolvedVirtualModuleId) return;
509
- const config2 = getCurrentConfig();
510
- const themeConfig = config2.theme ?? {};
509
+ const config = getCurrentConfig();
510
+ const themeConfig = config.theme ?? {};
511
511
  const themeCss = [];
512
512
  const fonts = await processFonts(themeConfig);
513
513
  if (fonts.imports.length > 0) {
@@ -583,10 +583,18 @@ ${generateCss(themeConfig.dark)}
583
583
  if (fonts.families.serif) {
584
584
  rootVars.push(` --font-serif: ${fonts.families.serif};`);
585
585
  }
586
- const shikiThemes = config2.syntaxHighlighting?.themes ?? defaultHighlightOptions.themes;
586
+ const shikiThemes = config.syntaxHighlighting?.themes ?? defaultHighlightOptions.themes;
587
587
  const [lightTheme, darkTheme] = (await Promise.all([
588
- import(`@shikijs/themes/${shikiThemes.light}`).then((m) => m.default),
589
- import(`@shikijs/themes/${shikiThemes.dark}`).then((m) => m.default)
588
+ import(
589
+ /* @vite-ignore */
590
+ `@shikijs/themes/${shikiThemes.light}`
591
+ ).then((m) => m.default),
592
+ import(
593
+ /* @vite-ignore */
594
+ `@shikijs/themes/${shikiThemes.dark}`
595
+ ).then(
596
+ (m) => m.default
597
+ )
590
598
  ])).map(normalizeTheme);
591
599
  rootVars.push(
592
600
  ` --shiki-light: ${lightTheme?.fg ?? "#000"};`,
@@ -603,12 +611,12 @@ ${rootVars.join("\n")}
603
611
  // This goes through the normal CSS pipeline so Tailwind can process it
604
612
  async transform(src, id) {
605
613
  if (!id.endsWith("/src/app/main.css")) return;
606
- const config2 = getCurrentConfig();
614
+ const config = getCurrentConfig();
607
615
  const files = new Set(
608
616
  [
609
- config2.__meta.rootDir,
610
- ...config2.__meta.dependencies,
611
- ...config2.__pluginDirs ?? []
617
+ config.__meta.rootDir,
618
+ ...config.__meta.dependencies,
619
+ ...config.__pluginDirs ?? []
612
620
  ].map((file) => path2.relative(path2.dirname(id), file))
613
621
  );
614
622
  const code = [...files].map((file) => `@source "${file}";`);
@@ -660,11 +668,11 @@ ${rootVars.join("\n")}
660
668
  ` --font-serif: var(--font-serif);`
661
669
  );
662
670
  code.push("}");
663
- const customCss = config2.theme?.customCss;
671
+ const customCss = config.theme?.customCss;
664
672
  if (customCss) {
665
673
  code.push(processCustomCss(customCss));
666
674
  }
667
- const defaultThemeImport = config2.theme?.noDefaultTheme ? "" : '@import "./defaultTheme.css" layer(theme);';
675
+ const defaultThemeImport = config.theme?.noDefaultTheme ? "" : '@import "./defaultTheme.css" layer(theme);';
668
676
  return src.replace(DEFAULT_THEME_REPLACE, defaultThemeImport).replace(MAIN_REPLACE, code.join("\n"));
669
677
  }
670
678
  };
@@ -2695,6 +2703,11 @@ var init_InputNavigationSchema = __esm({
2695
2703
  file: z5.string(),
2696
2704
  label: z5.string().optional(),
2697
2705
  path: z5.string().optional()
2706
+ }),
2707
+ z5.object({
2708
+ type: z5.literal("link"),
2709
+ to: z5.string(),
2710
+ label: z5.string().optional()
2698
2711
  })
2699
2712
  ]);
2700
2713
  DisplaySchema = z5.union([
@@ -2710,7 +2723,10 @@ var init_InputNavigationSchema = __esm({
2710
2723
  badge: BadgeSchema.optional(),
2711
2724
  collapsed: z5.boolean().optional(),
2712
2725
  collapsible: z5.boolean().optional(),
2713
- display: DisplaySchema
2726
+ display: DisplaySchema,
2727
+ // Turn a (plugin-generated) category into a stacked sub-nav
2728
+ // E.g. make each OpenAPI tag drill into its own panel. See `stack` above.
2729
+ stack: z5.boolean().optional()
2714
2730
  })
2715
2731
  });
2716
2732
  NavigationInsertRuleSchema = z5.object({
@@ -2762,7 +2778,8 @@ var init_InputNavigationSchema = __esm({
2762
2778
  target: z5.enum(["_self", "_blank"]).optional(),
2763
2779
  icon: IconSchema2.optional(),
2764
2780
  badge: BadgeSchema.optional(),
2765
- display: DisplaySchema
2781
+ display: DisplaySchema,
2782
+ stack: z5.boolean().optional()
2766
2783
  });
2767
2784
  InputNavigationCustomPageSchema = z5.object({
2768
2785
  type: z5.literal("custom-page"),
@@ -2795,7 +2812,8 @@ var init_InputNavigationSchema = __esm({
2795
2812
  collapsible: z5.boolean().optional(),
2796
2813
  collapsed: z5.boolean().optional(),
2797
2814
  link: InputNavigationCategoryLinkDocSchema.optional(),
2798
- display: DisplaySchema
2815
+ display: DisplaySchema,
2816
+ stack: z5.boolean().optional()
2799
2817
  });
2800
2818
  InputNavigationCategorySchema = BaseInputNavigationCategorySchema.extend({
2801
2819
  items: z5.lazy(() => InputNavigationItemSchema.array())
@@ -2919,20 +2937,35 @@ __export(ZudokuConfig_exports, {
2919
2937
  import colors from "picocolors";
2920
2938
  import { isValidElement as isValidElement2 } from "react";
2921
2939
  import { z as z7 } from "zod";
2922
- function validateConfig(config2, configPath) {
2923
- const validationResult = ZudokuConfig.safeParse(config2);
2940
+ function validateConfig(config, configPath) {
2941
+ warnUnsafeConfigKeys(config);
2942
+ const validationResult = ZudokuConfig.safeParse(config);
2924
2943
  if (!validationResult.success) {
2944
+ const prettyErrors = z7.prettifyError(validationResult.error);
2945
+ const location = configPath ? ` at ${configPath}` : "";
2925
2946
  if (process.env.NODE_ENV === "production") {
2926
2947
  throw new Error(
2927
- `Whoops, looks like there's an issue with your ${configPath ?? "config"}:
2928
- ${z7.prettifyError(validationResult.error)}`
2948
+ `Invalid Zudoku configuration${location}:
2949
+ ${prettyErrors}`
2929
2950
  );
2930
2951
  }
2931
- console.log(colors.yellow("Validation errors:"));
2932
- console.log(colors.yellow(z7.prettifyError(validationResult.error)));
2952
+ console.log(colors.yellow(`Invalid Zudoku configuration${location}:`));
2953
+ console.log(colors.yellow(prettyErrors));
2933
2954
  }
2934
2955
  }
2935
- var ThemeSchema, ApiCatalogCategorySchema, LanguageOption, AiAssistantCustomSchema, AiAssistantPresets, AiAssistantsSchema, ApiOptionsSchema, ApiConfigSchema, VersionConfigSchema, ApiSchema, ApiKeysSchema, LogoSchema, FooterSocialIcons, FooterSocialSchema, FooterSchema, SiteMapSchema, DEFAULT_DOCS_FILES, LlmsConfigSchema, DocsConfigSchema, Redirect, SearchSchema, SignUpUrlValueSchema, SignUpUrlSchema, SignUpOpenIdSchema, AuthenticationSchema, MetadataSchema, FontConfigSchema, FontsConfigSchema, CssObject, ThemeConfigSchema, SiteSchema, PlacementPosition, HeaderConfigSchema, ApiCatalogSchema, CdnUrlSchema, BaseConfigSchema, ZudokuConfig;
2956
+ function warnUnsafeConfigKeys(config) {
2957
+ if (typeof config !== "object" || config === null) return;
2958
+ const usedKeys = DEPRECATED_UNSAFE_KEYS.filter(
2959
+ (key) => Object.hasOwn(config, key)
2960
+ );
2961
+ if (usedKeys.length === 0) return;
2962
+ console.log(
2963
+ colors.yellow(
2964
+ `Warning: The following config ${usedKeys.length === 1 ? "option is" : "options are"} deprecated and will be removed soon: ${usedKeys.join(", ")}`
2965
+ )
2966
+ );
2967
+ }
2968
+ var ThemeSchema, ApiCatalogCategorySchema, LanguageOption, AiAssistantCustomSchema, AiAssistantPresets, AiAssistantsSchema, ApiOptionsSchema, ApiConfigSchema, VersionConfigSchema, ApiSchema, ApiKeysSchema, LogoSchema, FooterSocialIcons, FooterSocialSchema, FooterSchema, SiteMapSchema, DEFAULT_DOCS_FILES, LlmsConfigSchema, DocsConfigSchema, Redirect, SearchSchema, SignUpUrlValueSchema, SignUpUrlSchema, SignUpOpenIdSchema, AuthenticationSchema, MetadataSchema, FontConfigSchema, FontsConfigSchema, CssObject, ThemeConfigSchema, SiteSchema, PlacementPosition, HeaderConfigSchema, ApiCatalogSchema, CdnUrlSchema, BaseConfigSchema, ZudokuConfig, DEPRECATED_UNSAFE_KEYS;
2936
2969
  var init_ZudokuConfig = __esm({
2937
2970
  "src/config/validators/ZudokuConfig.ts"() {
2938
2971
  init_plugin_theme();
@@ -3471,6 +3504,7 @@ var init_ZudokuConfig = __esm({
3471
3504
  __pluginDirs: z7.array(z7.string())
3472
3505
  });
3473
3506
  ZudokuConfig = BaseConfigSchema.partial();
3507
+ DEPRECATED_UNSAFE_KEYS = ["UNSAFE_slotlets"];
3474
3508
  }
3475
3509
  });
3476
3510
 
@@ -3493,29 +3527,48 @@ async function getConfigFilePath(rootDir) {
3493
3527
  }
3494
3528
  async function loadZudokuConfigWithMeta(rootDir) {
3495
3529
  const configPath = await getConfigFilePath(rootDir);
3496
- const { module, dependencies } = await runnerImport(configPath, {
3497
- plugins: [virtualModuleStubPlugin],
3498
- environments: {
3499
- inline: {
3500
- resolve: {
3501
- // Prevent Node.js from trying to load zudoku's raw .ts source
3502
- // directly, which fails with ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING
3503
- // when --experimental-strip-types is enabled. Uses regex to also
3504
- // catch plugins that re-export from zudoku (e.g. @zuplo/zudoku-plugin-*).
3505
- noExternal: [/zudoku/]
3530
+ let module;
3531
+ let dependencies;
3532
+ try {
3533
+ ({ module, dependencies } = await runnerImport(configPath, {
3534
+ plugins: [virtualModuleStubPlugin],
3535
+ environments: {
3536
+ inline: {
3537
+ resolve: {
3538
+ // Prevent Node.js from trying to load zudoku's raw .ts source
3539
+ // directly, which fails with ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING
3540
+ // when --experimental-strip-types is enabled. Uses regex to also
3541
+ // catch plugins that re-export from zudoku (e.g. @zuplo/zudoku-plugin-*).
3542
+ noExternal: [/zudoku/]
3543
+ }
3506
3544
  }
3545
+ },
3546
+ server: {
3547
+ // this allows us to 'load' CSS files in the config
3548
+ // see https://github.com/vitejs/vite/pull/19577
3549
+ perEnvironmentStartEndDuringDev: true
3507
3550
  }
3508
- },
3509
- server: {
3510
- // this allows us to 'load' CSS files in the config
3511
- // see https://github.com/vitejs/vite/pull/19577
3512
- perEnvironmentStartEndDuringDev: true
3513
- }
3514
- });
3515
- const config2 = module.default;
3516
- validateConfig(config2, configPath);
3551
+ }));
3552
+ } catch (error) {
3553
+ const detail = error instanceof Error ? error.message : String(error);
3554
+ throw new Error(
3555
+ `Invalid Zudoku configuration at ${colors2.dim(configPath)}:
3556
+
3557
+ ${detail}`,
3558
+ { cause: error }
3559
+ );
3560
+ }
3561
+ if (module.default === void 0) {
3562
+ throw new Error(
3563
+ `Invalid Zudoku configuration at ${colors2.dim(configPath)}:
3564
+
3565
+ Config file must have a default export.`
3566
+ );
3567
+ }
3568
+ const config = module.default;
3569
+ validateConfig(config, configPath);
3517
3570
  const configWithMetadata = {
3518
- ...config2,
3571
+ ...config,
3519
3572
  __meta: {
3520
3573
  rootDir,
3521
3574
  moduleDir: getZudokuRootDir(),
@@ -3536,8 +3589,12 @@ function loadEnv(configEnv, rootDir) {
3536
3589
  return { publicEnv: publicEnv2, envPrefix: envPrefix2 };
3537
3590
  }
3538
3591
  async function hasConfigChanged() {
3592
+ const config = getConfig();
3539
3593
  if (!config || !modifiedTimes) return true;
3540
- const files = [config.__meta.configPath, ...config.__meta.dependencies];
3594
+ const files = [
3595
+ config.__meta.configPath,
3596
+ ...config.__meta.dependencies.filter(isFileSystemPath)
3597
+ ];
3541
3598
  try {
3542
3599
  const hasChanged = await Promise.all(
3543
3600
  files.map(async (depPath) => {
@@ -3552,8 +3609,12 @@ async function hasConfigChanged() {
3552
3609
  }
3553
3610
  }
3554
3611
  async function updateModifiedTimes() {
3612
+ const config = getConfig();
3555
3613
  if (!config) return;
3556
- const files = [config.__meta.configPath, ...config.__meta.dependencies];
3614
+ const files = [
3615
+ config.__meta.configPath,
3616
+ ...config.__meta.dependencies.filter(isFileSystemPath)
3617
+ ];
3557
3618
  modifiedTimes = /* @__PURE__ */ new Map();
3558
3619
  await Promise.all(
3559
3620
  files.map(async (depPath) => {
@@ -3564,29 +3625,38 @@ async function updateModifiedTimes() {
3564
3625
  }
3565
3626
  async function loadZudokuConfig(configEnv, rootDir) {
3566
3627
  const shouldReload = await hasConfigChanged();
3567
- if (!shouldReload && config && envPrefix && publicEnv) {
3568
- return { config, envPrefix, publicEnv };
3628
+ const existing = getConfig();
3629
+ if (!shouldReload && existing && envPrefix && publicEnv) {
3630
+ return { config: existing, envPrefix, publicEnv };
3569
3631
  }
3570
3632
  ({ publicEnv, envPrefix } = loadEnv(configEnv, rootDir));
3571
3633
  try {
3572
3634
  const loadedConfig = await loadZudokuConfigWithMeta(rootDir);
3573
- config = await runPluginTransformConfig(loadedConfig);
3635
+ const config = await runPluginTransformConfig(loadedConfig);
3636
+ setConfig(config);
3574
3637
  logger.info(
3575
3638
  colors2.cyan(`loaded config file `) + colors2.dim(config.__meta.configPath),
3576
3639
  { timestamp: true }
3577
3640
  );
3578
3641
  return { config, envPrefix, publicEnv };
3579
3642
  } catch (error) {
3580
- const errorMessage = error instanceof Error ? error.message : String(error);
3581
- if (config) {
3582
- return { config, envPrefix, publicEnv };
3643
+ const lastValid = getConfig();
3644
+ if (lastValid) {
3645
+ logger.error(
3646
+ colors2.red("Failed to reload config, using last valid config."),
3647
+ {
3648
+ timestamp: true,
3649
+ error: error instanceof Error ? error : new Error(String(error))
3650
+ }
3651
+ );
3652
+ return { config: lastValid, envPrefix, publicEnv };
3583
3653
  }
3584
- throw new Error(errorMessage, { cause: error });
3654
+ throw error;
3585
3655
  } finally {
3586
3656
  await updateModifiedTimes();
3587
3657
  }
3588
3658
  }
3589
- var config, envPrefix, publicEnv, modifiedTimes, zudokuConfigFiles, virtualModuleStubPlugin, getCurrentConfig;
3659
+ var configStore, getConfig, setConfig, envPrefix, publicEnv, modifiedTimes, zudokuConfigFiles, virtualModuleStubPlugin, isFileSystemPath, getCurrentConfig;
3590
3660
  var init_loader = __esm({
3591
3661
  "src/config/loader.ts"() {
3592
3662
  init_logger();
@@ -3595,6 +3665,11 @@ var init_loader = __esm({
3595
3665
  init_invariant();
3596
3666
  init_file_exists();
3597
3667
  init_ZudokuConfig();
3668
+ configStore = globalThis;
3669
+ getConfig = () => configStore.__zudokuConfig;
3670
+ setConfig = (next) => {
3671
+ configStore.__zudokuConfig = next;
3672
+ };
3598
3673
  zudokuConfigFiles = [
3599
3674
  "zudoku.config.js",
3600
3675
  "zudoku.config.jsx",
@@ -3611,7 +3686,9 @@ var init_loader = __esm({
3611
3686
  if (id.startsWith("\0virtual:")) return "export default {}";
3612
3687
  }
3613
3688
  };
3689
+ isFileSystemPath = (p) => !p.startsWith("\0") && !p.includes("virtual:");
3614
3690
  getCurrentConfig = () => {
3691
+ const config = getConfig();
3615
3692
  invariant(config, "Config not loaded");
3616
3693
  return config;
3617
3694
  };
@@ -3808,25 +3885,25 @@ var getClerkFrontendApi = (publishableKey) => {
3808
3885
  };
3809
3886
 
3810
3887
  // src/lib/auth/issuer.ts
3811
- var getIssuer = async (config2) => {
3812
- switch (config2.authentication?.type) {
3888
+ var getIssuer = async (config) => {
3889
+ switch (config.authentication?.type) {
3813
3890
  case "clerk": {
3814
- return `https://${getClerkFrontendApi(config2.authentication.clerkPubKey)}`;
3891
+ return `https://${getClerkFrontendApi(config.authentication.clerkPubKey)}`;
3815
3892
  }
3816
3893
  case "auth0": {
3817
- return `https://${config2.authentication.domain}/`;
3894
+ return `https://${config.authentication.domain}/`;
3818
3895
  }
3819
3896
  case "openid": {
3820
- return config2.authentication.issuer;
3897
+ return config.authentication.issuer;
3821
3898
  }
3822
3899
  case "supabase": {
3823
- return config2.authentication.supabaseUrl;
3900
+ return config.authentication.supabaseUrl;
3824
3901
  }
3825
3902
  case "azureb2c": {
3826
- return config2.authentication.issuer;
3903
+ return config.authentication.issuer;
3827
3904
  }
3828
3905
  case "firebase": {
3829
- return `https://securetoken.google.com/${config2.authentication.projectId}`;
3906
+ return `https://securetoken.google.com/${config.authentication.projectId}`;
3830
3907
  }
3831
3908
  case void 0: {
3832
3909
  return void 0;
@@ -3849,269 +3926,6 @@ import {
3849
3926
  loadConfigFromFile,
3850
3927
  mergeConfig as mergeConfig2
3851
3928
  } from "vite";
3852
-
3853
- // package.json
3854
- var package_default = {
3855
- name: "zudoku",
3856
- version: "0.78.1",
3857
- type: "module",
3858
- sideEffects: [
3859
- "**/*.css",
3860
- "**/polyfills.ts"
3861
- ],
3862
- homepage: "https://zudoku.dev",
3863
- repository: {
3864
- type: "git",
3865
- url: "git+https://github.com/zuplo/zudoku.git"
3866
- },
3867
- bugs: {
3868
- url: "https://github.com/zuplo/zudoku/issues"
3869
- },
3870
- description: "Framework for building high quality, interactive API documentation.",
3871
- files: [
3872
- "dist",
3873
- "cli.js",
3874
- "src",
3875
- "client.d.ts",
3876
- "docs"
3877
- ],
3878
- bin: {
3879
- zudoku: "./cli.js"
3880
- },
3881
- exports: {
3882
- ".": "./src/index.ts",
3883
- "./package.json": "./package.json",
3884
- "./ui/*": {
3885
- types: "./src/lib/ui/*.tsx",
3886
- default: "./src/lib/ui/*.tsx"
3887
- },
3888
- "./ui/*.js": {
3889
- types: "./src/lib/ui/*.tsx",
3890
- default: "./src/lib/ui/*.tsx"
3891
- },
3892
- "./client": {
3893
- types: "./client.d.ts"
3894
- },
3895
- "./auth/clerk": "./src/lib/authentication/providers/clerk.tsx",
3896
- "./auth/auth0": "./src/lib/authentication/providers/auth0.tsx",
3897
- "./auth/openid": "./src/lib/authentication/providers/openid.tsx",
3898
- "./auth/supabase": "./src/lib/authentication/providers/supabase.tsx",
3899
- "./auth/azureb2c": "./src/lib/authentication/providers/azureb2c.tsx",
3900
- "./auth/firebase": "./src/lib/authentication/providers/firebase.tsx",
3901
- "./plugins": "./src/lib/core/plugins.ts",
3902
- "./plugins/api-keys": "./src/lib/plugins/api-keys/index.tsx",
3903
- "./plugins/markdown": "./src/lib/plugins/markdown/index.tsx",
3904
- "./plugins/openapi": "./src/lib/plugins/openapi/index.tsx",
3905
- "./plugins/custom-pages": "./src/lib/plugins/custom-pages/index.tsx",
3906
- "./plugins/search-inkeep": "./src/lib/plugins/search-inkeep/index.tsx",
3907
- "./plugins/search-pagefind": "./src/lib/plugins/search-pagefind/index.tsx",
3908
- "./plugins/api-catalog": "./src/lib/plugins/api-catalog/index.tsx",
3909
- "./components": "./src/lib/components/index.ts",
3910
- "./mermaid": "./src/lib/components/Mermaid.tsx",
3911
- "./router": "./src/lib/core/router.ts",
3912
- "./react-query": "./src/lib/core/react-query.ts",
3913
- "./icons": "./src/lib/icons.ts",
3914
- "./vite": "./src/vite/index.ts",
3915
- "./server": "./src/app/entry.server.tsx",
3916
- "./server/adapters/lambda": "./src/app/adapters/lambda.ts",
3917
- "./server/adapters/node": "./src/app/adapters/node.ts",
3918
- "./server/adapters/vercel": "./src/app/adapters/vercel.ts",
3919
- "./server/adapters/cloudflare": "./src/app/adapters/cloudflare.ts",
3920
- "./app/*": "./src/app/*",
3921
- "./hooks": "./src/lib/hooks/index.ts",
3922
- "./processors/*": "./src/lib/plugins/openapi/processors/*.ts",
3923
- "./with-zuplo": "./src/zuplo/with-zuplo.ts",
3924
- "./testing": "./src/lib/testing/index.tsx"
3925
- },
3926
- scripts: {
3927
- build: "esbuild src/cli/cli.ts src/vite/prerender/worker.ts --outdir=dist/cli --entry-names=[name] --bundle --format=esm --packages=external --target=node20 --platform=node --log-level=error",
3928
- postbuild: "tsx scripts/check-external-deps.ts",
3929
- typecheck: "tsc --project tsconfig.app.json --noEmit",
3930
- "generate:types": "tsx scripts/generate-types.js && tsx scripts/generate-flat-config.js",
3931
- "build:standalone": "vite build --mode standalone --config vite.standalone.config.ts --log-level=error",
3932
- prepublishOnly: "tsx scripts/generate-publish-exports.ts && publint .",
3933
- postpublish: "git checkout -- package.json",
3934
- clean: "rm -rf dist",
3935
- codegen: "graphql-codegen --config ./src/codegen.ts"
3936
- },
3937
- dependencies: {
3938
- "@apidevtools/json-schema-ref-parser": "15.3.5",
3939
- "@base-ui/react": "^1.4.1",
3940
- "@envelop/core": "5.5.1",
3941
- "@graphql-typed-document-node/core": "3.2.0",
3942
- "@hono/node-server": "2.0.2",
3943
- "@lekoarts/rehype-meta-as-attributes": "3.0.3",
3944
- "@mdx-js/react": "3.1.1",
3945
- "@mdx-js/rollup": "3.1.1",
3946
- "@pothos/core": "4.12.0",
3947
- "@radix-ui/react-accordion": "1.2.12",
3948
- "@radix-ui/react-alert-dialog": "1.1.15",
3949
- "@radix-ui/react-aspect-ratio": "1.1.8",
3950
- "@radix-ui/react-checkbox": "1.3.3",
3951
- "@radix-ui/react-collapsible": "1.1.12",
3952
- "@radix-ui/react-dialog": "1.1.15",
3953
- "@radix-ui/react-dropdown-menu": "2.1.16",
3954
- "@radix-ui/react-hover-card": "1.1.15",
3955
- "@radix-ui/react-label": "2.1.8",
3956
- "@radix-ui/react-navigation-menu": "1.2.14",
3957
- "@radix-ui/react-popover": "1.1.15",
3958
- "@radix-ui/react-progress": "1.1.8",
3959
- "@radix-ui/react-radio-group": "1.3.8",
3960
- "@radix-ui/react-scroll-area": "1.2.10",
3961
- "@radix-ui/react-select": "2.2.6",
3962
- "@radix-ui/react-separator": "^1.1.8",
3963
- "@radix-ui/react-slider": "1.3.6",
3964
- "@radix-ui/react-slot": "1.2.4",
3965
- "@radix-ui/react-switch": "1.2.6",
3966
- "@radix-ui/react-tabs": "1.1.13",
3967
- "@radix-ui/react-toggle": "1.1.10",
3968
- "@radix-ui/react-toggle-group": "1.1.11",
3969
- "@radix-ui/react-tooltip": "1.2.8",
3970
- "@radix-ui/react-visually-hidden": "1.2.4",
3971
- "@scalar/openapi-parser": "0.23.13",
3972
- "@scalar/snippetz": "0.9.6",
3973
- "@sentry/node": "10.52.0",
3974
- "@shikijs/langs": "4.0.2",
3975
- "@shikijs/rehype": "4.0.2",
3976
- "@shikijs/themes": "4.0.2",
3977
- "@shikijs/transformers": "4.0.2",
3978
- "@tailwindcss/typography": "0.5.19",
3979
- "@tailwindcss/vite": "4.2.2",
3980
- "@tanem/react-nprogress": "6.0.3",
3981
- "@tanstack/react-query": "5.97.0",
3982
- "@types/react": "catalog:",
3983
- "@types/react-dom": "catalog:",
3984
- "@vitejs/plugin-react": "6.0.1",
3985
- "@x0k/json-schema-merge": "1.0.2",
3986
- "@zudoku/react-helmet-async": "2.0.5",
3987
- "@zuplo/mcp": "0.0.32",
3988
- bs58: "6.0.0",
3989
- "class-variance-authority": "0.7.1",
3990
- clsx: "2.1.1",
3991
- cmdk: "1.1.1",
3992
- dotenv: "17.3.1",
3993
- "embla-carousel-react": "8.6.0",
3994
- esbuild: "^0.28.0",
3995
- "estree-util-is-identifier-name": "3.0.0",
3996
- "estree-util-value-to-estree": "3.5.0",
3997
- "fast-equals": "6.0.0",
3998
- glob: "13.0.6",
3999
- "glob-parent": "6.0.2",
4000
- graphql: "16.14.0",
4001
- "graphql-type-json": "0.3.2",
4002
- "graphql-yoga": "5.18.0",
4003
- "gray-matter": "4.0.3",
4004
- "hast-util-heading-rank": "3.0.0",
4005
- "hast-util-to-jsx-runtime": "2.3.6",
4006
- "hast-util-to-string": "3.0.1",
4007
- hono: "4.12.18",
4008
- "http-terminator": "3.2.0",
4009
- "javascript-stringify": "2.1.0",
4010
- jose: "6.2.2",
4011
- "json-schema-to-typescript-lite": "15.0.0",
4012
- loglevel: "1.9.2",
4013
- "lucide-react": "1.16.0",
4014
- "mdast-util-from-markdown": "2.0.2",
4015
- "mdast-util-mdx": "3.0.0",
4016
- "mdast-util-mdx-jsx": "3.2.0",
4017
- "micromark-extension-mdxjs": "3.0.0",
4018
- motion: "12.38.0",
4019
- nanoevents: "9.1.0",
4020
- "next-themes": "0.4.6",
4021
- oauth4webapi: "3.8.5",
4022
- "openapi-types": "12.1.3",
4023
- pagefind: "1.5.2",
4024
- picocolors: "1.1.1",
4025
- piscina: "5.1.4",
4026
- "posthog-node": "5.33.4",
4027
- "quick-lru": "7.3.0",
4028
- "react-error-boundary": "6.1.1",
4029
- "react-hook-form": "7.75.0",
4030
- "react-is": "catalog:",
4031
- "react-markdown": "10.1.0",
4032
- "react-router": "7.14.1",
4033
- "rehype-mdx-import-media": "1.4.0",
4034
- "rehype-raw": "7.0.0",
4035
- "rehype-slug": "6.0.0",
4036
- "remark-comment": "1.0.0",
4037
- "remark-directive": "3.0.1",
4038
- "remark-directive-rehype": "1.0.0",
4039
- "remark-frontmatter": "5.0.0",
4040
- "remark-gfm": "4.0.1",
4041
- "remark-mdx-frontmatter": "5.2.0",
4042
- semver: "7.8.0",
4043
- shiki: "4.0.2",
4044
- sitemap: "9.0.1",
4045
- "strip-ansi": "7.2.0",
4046
- "tailwind-merge": "3.6.0",
4047
- tailwindcss: "4.3.0",
4048
- "tw-animate-css": "1.4.0",
4049
- unified: "11.0.5",
4050
- "unist-util-visit": "5.1.0",
4051
- vaul: "1.1.2",
4052
- vfile: "6.0.3",
4053
- vite: "8.0.13",
4054
- yaml: "2.8.4",
4055
- yargs: "18.0.0",
4056
- zod: "4.3.6",
4057
- zustand: "5.0.13"
4058
- },
4059
- devDependencies: {
4060
- "@graphql-codegen/cli": "7.0.0",
4061
- "@inkeep/cxkit-types": "0.5.117",
4062
- "@testing-library/dom": "catalog:",
4063
- "@testing-library/jest-dom": "catalog:",
4064
- "@testing-library/react": "catalog:",
4065
- "@testing-library/user-event": "catalog:",
4066
- "@types/estree": "1.0.9",
4067
- "@types/glob-parent": "5.1.3",
4068
- "@types/har-format": "^1.2.16",
4069
- "@types/hast": "3.0.4",
4070
- "@types/json-schema": "7.0.15",
4071
- "@types/mdast": "4.0.4",
4072
- "@types/mdx": "2.0.13",
4073
- "@types/node": "catalog:",
4074
- "@types/react-is": "catalog:",
4075
- "@types/semver": "7.7.1",
4076
- "@types/unist": "3.0.3",
4077
- "@types/yargs": "17.0.35",
4078
- "@vitest/coverage-v8": "4.0.18",
4079
- "happy-dom": "catalog:",
4080
- "oxc-parser": "^0.126.0",
4081
- react: "catalog:",
4082
- "react-dom": "catalog:",
4083
- tsx: "4.21.0",
4084
- typescript: "catalog:"
4085
- },
4086
- peerDependencies: {
4087
- "@azure/msal-browser": "^4.13.0",
4088
- "@sentry/react": "^10.0.0",
4089
- "@supabase/supabase-js": "^2.49.4",
4090
- firebase: "^12.6.0",
4091
- mermaid: "^11.0.0",
4092
- react: ">=19.2.0",
4093
- "react-dom": ">=19.2.0"
4094
- },
4095
- peerDependenciesMeta: {
4096
- "@azure/msal-browser": {
4097
- optional: true
4098
- },
4099
- "@sentry/react": {
4100
- optional: true
4101
- },
4102
- "@supabase/supabase-js": {
4103
- optional: true
4104
- },
4105
- firebase: {
4106
- optional: true
4107
- },
4108
- mermaid: {
4109
- optional: true
4110
- }
4111
- }
4112
- };
4113
-
4114
- // src/vite/config.ts
4115
3929
  init_logger();
4116
3930
  init_package_json();
4117
3931
  init_loader();
@@ -4130,22 +3944,22 @@ init_joinUrl();
4130
3944
  var PROTECTED_CHUNK_DIR = "_protected";
4131
3945
  var MANIFEST_VERSION = 1;
4132
3946
  var MANIFEST_FILENAME = "zudoku-manifest.json";
4133
- var buildManifest = (config2) => {
4134
- const protectedRoutes = ProtectedRoutesSchema.parse(config2.protectedRoutes);
3947
+ var buildManifest = (config) => {
3948
+ const protectedRoutes = ProtectedRoutesSchema.parse(config.protectedRoutes);
4135
3949
  const routePatterns = protectedRoutes ? Object.keys(protectedRoutes) : [];
4136
3950
  return {
4137
3951
  version: MANIFEST_VERSION,
4138
- basePath: config2.basePath ?? "/",
3952
+ basePath: config.basePath ?? "/",
4139
3953
  ssrEntry: "server/entry.js",
4140
3954
  static: {
4141
- prefixes: [joinUrl(config2.basePath, "assets")]
3955
+ prefixes: [joinUrl(config.basePath, "assets")]
4142
3956
  },
4143
3957
  protected: {
4144
- chunkPrefix: joinUrl(config2.basePath, PROTECTED_CHUNK_DIR),
3958
+ chunkPrefix: joinUrl(config.basePath, PROTECTED_CHUNK_DIR),
4145
3959
  routePatterns
4146
3960
  },
4147
3961
  auth: {
4148
- sessionEndpoint: joinUrl(config2.basePath, "/__z/auth/session"),
3962
+ sessionEndpoint: joinUrl(config.basePath, "/__z/auth/session"),
4149
3963
  cookies: {
4150
3964
  access: ACCESS_TOKEN_COOKIE,
4151
3965
  refresh: REFRESH_TOKEN_COOKIE,
@@ -4210,9 +4024,9 @@ async function collectStyleUrls(server, entries) {
4210
4024
  var VIRTUAL_ENTRY = "virtual:ssr-css.css";
4211
4025
  function vitePluginSsrCss(pluginOpts) {
4212
4026
  let server;
4213
- const config2 = getCurrentConfig();
4027
+ const config = getCurrentConfig();
4214
4028
  const virtualHref = path5.join(
4215
- config2.basePath ?? "",
4029
+ config.basePath ?? "",
4216
4030
  `/@id/__x00__${VIRTUAL_ENTRY}?direct`
4217
4031
  );
4218
4032
  const cssModuleMap = /* @__PURE__ */ new Map();
@@ -4320,8 +4134,8 @@ var viteApiKeysPlugin = () => {
4320
4134
  },
4321
4135
  async load(id) {
4322
4136
  if (id === resolvedVirtualModuleId4) {
4323
- const config2 = getCurrentConfig();
4324
- if (!config2.apiKeys?.enabled || config2.__meta.mode === "standalone") {
4137
+ const config = getCurrentConfig();
4138
+ if (!config.apiKeys?.enabled || config.__meta.mode === "standalone") {
4325
4139
  return `export const configuredApiKeysPlugin = undefined;`;
4326
4140
  }
4327
4141
  const deploymentName = ZuploEnv.buildConfig?.deploymentName || getZuploSystemConfigurations(process.env.ZUPLO_SYSTEM_CONFIGURATIONS)?.__ZUPLO_DEPLOYMENT_NAME;
@@ -4397,8 +4211,8 @@ var getBuildConfig = async () => {
4397
4211
  ).then((m) => m.module.default);
4398
4212
  return validateBuildConfig(buildModule);
4399
4213
  };
4400
- function validateBuildConfig(config2) {
4401
- const validationResult = BuildConfigSchema2.safeParse(config2);
4214
+ function validateBuildConfig(config) {
4215
+ const validationResult = BuildConfigSchema2.safeParse(config);
4402
4216
  if (!validationResult.success) {
4403
4217
  if (process.env.NODE_ENV === "production") {
4404
4218
  throw new Error(z8.prettifyError(validationResult.error));
@@ -5718,11 +5532,11 @@ var SchemaManager = class {
5718
5532
  config;
5719
5533
  constructor({
5720
5534
  storeDir,
5721
- config: config2,
5535
+ config,
5722
5536
  processors
5723
5537
  }) {
5724
5538
  this.storeDir = storeDir;
5725
- this.config = config2;
5539
+ this.config = config;
5726
5540
  this.processors = [
5727
5541
  ({ schema: schema2 }) => upgrade(schema2).specification,
5728
5542
  flattenAllOfProcessor,
@@ -5800,7 +5614,7 @@ var SchemaManager = class {
5800
5614
  const existingSchema = schemas[index];
5801
5615
  const schemaVersion = processedSchema.info.version ?? FALLBACK_VERSION;
5802
5616
  const versionPath = existingSchema?.path && existingSchema.path.length > 0 ? existingSchema.path : paramsPath(params) || schemaVersion;
5803
- const config2 = ensureArray(this.config.apis ?? []).find(
5617
+ const config = ensureArray(this.config.apis ?? []).find(
5804
5618
  (c) => c.path === configuredPath
5805
5619
  );
5806
5620
  const processed = {
@@ -5816,7 +5630,7 @@ var SchemaManager = class {
5816
5630
  versionPath,
5817
5631
  configuredPath,
5818
5632
  params,
5819
- config2?.options
5633
+ config?.options
5820
5634
  ),
5821
5635
  processedJsonPath,
5822
5636
  processedTime
@@ -5902,10 +5716,10 @@ var SchemaManager = class {
5902
5716
  }
5903
5717
  return map;
5904
5718
  };
5905
- createSchemaPath = (inputPath, versionPath, apiPath, params, config2) => {
5719
+ createSchemaPath = (inputPath, versionPath, apiPath, params, config) => {
5906
5720
  const suffix = paramsSuffix(params);
5907
5721
  const extension = suffix ? ".json" : path7.extname(inputPath);
5908
- const fileName = config2?.schemaDownload?.fileName ?? this.config.defaults?.apis?.schemaDownload?.fileName ?? "schema";
5722
+ const fileName = config?.schemaDownload?.fileName ?? this.config.defaults?.apis?.schemaDownload?.fileName ?? "schema";
5909
5723
  return joinUrl(
5910
5724
  this.config.basePath,
5911
5725
  apiPath,
@@ -5996,10 +5810,10 @@ var NavigationResolver = class {
5996
5810
  globFiles = [];
5997
5811
  items = [];
5998
5812
  itemIndex = 0;
5999
- constructor(config2) {
6000
- this.rootDir = config2.__meta.rootDir;
6001
- this.globPatterns = DocsConfigSchema.parse(config2.docs ?? {}).files;
6002
- this.items = config2.navigation ?? [];
5813
+ constructor(config) {
5814
+ this.rootDir = config.__meta.rootDir;
5815
+ this.globPatterns = DocsConfigSchema.parse(config.docs ?? {}).files;
5816
+ this.items = config.navigation ?? [];
6003
5817
  }
6004
5818
  async initialize() {
6005
5819
  if (this.globFiles.length > 0) return;
@@ -6066,6 +5880,9 @@ var NavigationResolver = class {
6066
5880
  if (typeof item === "string") {
6067
5881
  return this.resolveLink(item);
6068
5882
  }
5883
+ if (item.type === "link") {
5884
+ return { type: "link", to: item.to, label: item.label };
5885
+ }
6069
5886
  const doc = await this.resolveDoc(item.file);
6070
5887
  return doc ? {
6071
5888
  ...item,
@@ -6153,11 +5970,11 @@ var viteNavigationPlugin = () => {
6153
5970
  },
6154
5971
  async load(id) {
6155
5972
  if (id !== resolvedVirtualModuleId2) return;
6156
- const config2 = getCurrentConfig();
6157
- const resolver = new NavigationResolver(config2);
5973
+ const config = getCurrentConfig();
5974
+ const resolver = new NavigationResolver(config);
6158
5975
  const resolvedNavigation = await resolver.resolve();
6159
5976
  const resolvedRules = await resolver.resolveRules(
6160
- config2.navigationRules ?? []
5977
+ config.navigationRules ?? []
6161
5978
  );
6162
5979
  const collectedIcons = /* @__PURE__ */ new Set();
6163
5980
  let hasMissingIcon = false;
@@ -6183,7 +6000,7 @@ var viteNavigationPlugin = () => {
6183
6000
  2
6184
6001
  );
6185
6002
  const headerNavigationCode = stringifyWithIcons(
6186
- config2.header?.navigation ?? []
6003
+ config.header?.navigation ?? []
6187
6004
  );
6188
6005
  const navigationCode = stringifyWithIcons(resolvedNavigation);
6189
6006
  const rulesCode = stringifyWithIcons(resolvedRules);
@@ -6191,7 +6008,7 @@ var viteNavigationPlugin = () => {
6191
6008
  invariant(navigationCode, "Failed to stringify navigation");
6192
6009
  invariant(rulesCode, "Failed to stringify navigation rules");
6193
6010
  await writePluginDebugCode(
6194
- config2.__meta.rootDir,
6011
+ config.__meta.rootDir,
6195
6012
  "navigation-plugin",
6196
6013
  `export const headerNavigation = ${headerNavigationCode};
6197
6014
  export const navigation = ${navigationCode};
@@ -6294,8 +6111,24 @@ var viteApiPlugin = async () => {
6294
6111
  const mainFiles = schemaManager.getFilesToReprocess(id);
6295
6112
  if (mainFiles.length === 0) return;
6296
6113
  console.log(`Re-processing schema ${id}`);
6297
- for (const inputConfig of mainFiles) {
6298
- await schemaManager.processSchema(inputConfig);
6114
+ try {
6115
+ for (const inputConfig of mainFiles) {
6116
+ await schemaManager.processSchema(inputConfig);
6117
+ }
6118
+ } catch (error) {
6119
+ const err = error instanceof Error ? error : new Error(String(error));
6120
+ server.config.logger.error(
6121
+ `Failed to re-process schema ${id}. Fix the error and save again.`,
6122
+ { error: err }
6123
+ );
6124
+ server.ws.send({
6125
+ type: "error",
6126
+ err: {
6127
+ message: `Failed to re-process schema ${id}: ${err.message}`,
6128
+ stack: err.stack ?? ""
6129
+ }
6130
+ });
6131
+ return;
6299
6132
  }
6300
6133
  schemaManager.getAllTrackedFiles().forEach((file) => server.watcher.add(file));
6301
6134
  invalidate(server);
@@ -6309,13 +6142,13 @@ var viteApiPlugin = async () => {
6309
6142
  },
6310
6143
  async load(id) {
6311
6144
  if (id !== resolvedVirtualModuleId4) return;
6312
- const config2 = getCurrentConfig();
6313
- if (!deepEqual2(schemaManager.config.apis, config2.apis)) {
6314
- schemaManager.config = config2;
6145
+ const config = getCurrentConfig();
6146
+ if (!deepEqual2(schemaManager.config.apis, config.apis)) {
6147
+ schemaManager.config = config;
6315
6148
  await schemaManager.processAllSchemas();
6316
6149
  schemaManager.getAllTrackedFiles().forEach((file) => this.addWatchFile(file));
6317
6150
  }
6318
- if (config2.__meta.mode === "standalone") {
6151
+ if (config.__meta.mode === "standalone") {
6319
6152
  return [
6320
6153
  "export const configuredApiPlugins = [];",
6321
6154
  "export const configuredApiCatalogPlugins = [];"
@@ -6326,12 +6159,12 @@ var viteApiPlugin = async () => {
6326
6159
  `const configuredApiPlugins = [];`,
6327
6160
  `const configuredApiCatalogPlugins = [];`
6328
6161
  ];
6329
- if (config2.apis) {
6162
+ if (config.apis) {
6330
6163
  code.push('import { openApiPlugin } from "zudoku/plugins/openapi";');
6331
6164
  code.push(
6332
6165
  `const apis = Array.isArray(config.apis) ? config.apis : [config.apis]`
6333
6166
  );
6334
- const apis = ensureArray(config2.apis);
6167
+ const apis = ensureArray(config.apis);
6335
6168
  const apiMetadata = [];
6336
6169
  const httpMethods = /* @__PURE__ */ new Set([
6337
6170
  "get",
@@ -6408,7 +6241,7 @@ var viteApiPlugin = async () => {
6408
6241
  ` disableSecurity: config.defaults?.apis?.disableSecurity ?? true,`,
6409
6242
  ` showVersionSelect: config.defaults?.apis?.showVersionSelect ?? "if-available",`,
6410
6243
  ` expandAllTags: config.defaults?.apis?.expandAllTags ?? true,`,
6411
- ` showInfoPage: config.defaults?.apis?.showInfoPage ?? true,`,
6244
+ ` showInfoPage: config.defaults?.apis?.showInfoPage,`,
6412
6245
  ` schemaDownload: config.defaults?.apis?.schemaDownload,`,
6413
6246
  ` transformExamples: config.defaults?.apis?.transformExamples,`,
6414
6247
  ` generateCodeSnippet: config.defaults?.apis?.generateCodeSnippet,`,
@@ -6433,7 +6266,7 @@ var viteApiPlugin = async () => {
6433
6266
  ` disableSecurity: config.defaults?.apis?.disableSecurity ?? true,`,
6434
6267
  ` showVersionSelect: config.defaults?.apis?.showVersionSelect ?? "if-available",`,
6435
6268
  ` expandAllTags: config.defaults?.apis?.expandAllTags ?? false,`,
6436
- ` showInfoPage: config.defaults?.apis?.showInfoPage ?? true,`,
6269
+ ` showInfoPage: config.defaults?.apis?.showInfoPage,`,
6437
6270
  ` schemaDownload: config.defaults?.apis?.schemaDownload,`,
6438
6271
  ` ...${JSON.stringify(apiConfig.options ?? {})},`,
6439
6272
  " },",
@@ -6441,11 +6274,11 @@ var viteApiPlugin = async () => {
6441
6274
  );
6442
6275
  }
6443
6276
  }
6444
- if (config2.catalogs) {
6277
+ if (config.catalogs) {
6445
6278
  code.push(
6446
6279
  'import { apiCatalogPlugin } from "zudoku/plugins/api-catalog";'
6447
6280
  );
6448
- const catalogs = ensureArray(config2.catalogs);
6281
+ const catalogs = ensureArray(config.catalogs);
6449
6282
  const categories = apis.flatMap((api) => api.categories ?? []).reduce((acc, catalog) => {
6450
6283
  if (!acc.has(catalog.label)) {
6451
6284
  acc.set(catalog.label ?? "", new Set(catalog.tags));
@@ -6491,12 +6324,12 @@ var viteApiPlugin = async () => {
6491
6324
  },
6492
6325
  async closeBundle() {
6493
6326
  if (this.environment.name === "ssr") return;
6494
- const config2 = getCurrentConfig();
6327
+ const config = getCurrentConfig();
6495
6328
  const pathMap = schemaManager.getUrlToFilePathMap();
6496
6329
  if (process.env.NODE_ENV !== "production") return;
6497
6330
  for (const [urlPath, inputPath] of pathMap) {
6498
6331
  const content = await fs2.readFile(inputPath, "utf-8");
6499
- const outputPath = path11.join(config2.__meta.rootDir, "dist", urlPath);
6332
+ const outputPath = path11.join(config.__meta.rootDir, "dist", urlPath);
6500
6333
  await fs2.mkdir(path11.dirname(outputPath), { recursive: true });
6501
6334
  await fs2.writeFile(outputPath, content, "utf-8");
6502
6335
  }
@@ -6520,16 +6353,16 @@ var viteAuthPlugin = () => {
6520
6353
  },
6521
6354
  async load(id) {
6522
6355
  if (id === resolvedVirtualModuleId4) {
6523
- const config2 = getCurrentConfig();
6524
- if (!config2.authentication || config2.__meta.mode === "standalone") {
6356
+ const config = getCurrentConfig();
6357
+ if (!config.authentication || config.__meta.mode === "standalone") {
6525
6358
  return `export const configuredAuthProvider = undefined;`;
6526
6359
  }
6527
6360
  return [
6528
6361
  `const config = {
6529
- ...${JSON.stringify(config2.authentication, null, 2)},
6530
- basePath: ${config2.basePath ? JSON.stringify(config2.basePath) : "undefined"},
6362
+ ...${JSON.stringify(config.authentication, null, 2)},
6363
+ basePath: ${config.basePath ? JSON.stringify(config.basePath) : "undefined"},
6531
6364
  };`,
6532
- `import authProvider from "zudoku/auth/${config2.authentication.type}";`,
6365
+ `import authProvider from "zudoku/auth/${config.authentication.type}";`,
6533
6366
  `export const configuredAuthProvider = authProvider(config);`
6534
6367
  ].join("\n");
6535
6368
  }
@@ -6612,8 +6445,8 @@ var viteCustomPagesPlugin = () => {
6612
6445
  },
6613
6446
  async load(id) {
6614
6447
  if (id === resolvedVirtualModuleId4) {
6615
- const config2 = getCurrentConfig();
6616
- if (config2.__meta.mode === "standalone" || !config2.navigation) {
6448
+ const config = getCurrentConfig();
6449
+ if (config.__meta.mode === "standalone" || !config.navigation) {
6617
6450
  return `export const configuredCustomPagesPlugin = undefined;`;
6618
6451
  }
6619
6452
  const code = [
@@ -6640,9 +6473,9 @@ var viteDocMetadataPlugin = () => ({
6640
6473
  enforce: "pre",
6641
6474
  name: "zudoku-doc-metadata-plugin",
6642
6475
  configureServer: async (server) => {
6643
- const config2 = getCurrentConfig();
6476
+ const config = getCurrentConfig();
6644
6477
  const files = await glob2("**/*.{md,mdx}", {
6645
- cwd: config2.__meta.rootDir,
6478
+ cwd: config.__meta.rootDir,
6646
6479
  ignore: ["node_modules", "dist"],
6647
6480
  absolute: true
6648
6481
  });
@@ -6720,12 +6553,12 @@ var navigationListItem = cva(
6720
6553
  // src/vite/plugin-docs.ts
6721
6554
  init_joinUrl();
6722
6555
  var ensureLeadingSlash = joinUrl;
6723
- var globMarkdownFiles = async (config2, options = { absolute: false }) => {
6724
- const docsConfig = DocsConfigSchema.parse(config2.docs ?? {});
6556
+ var globMarkdownFiles = async (config, options = { absolute: false }) => {
6557
+ const docsConfig = DocsConfigSchema.parse(config.docs ?? {});
6725
6558
  const fileMapping = {};
6726
6559
  for (const globPattern of docsConfig.files) {
6727
6560
  const globbedFiles = await glob3(globPattern, {
6728
- root: config2.__meta.rootDir,
6561
+ root: config.__meta.rootDir,
6729
6562
  ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"],
6730
6563
  // Always glob with relative paths to avoid issues on different OS
6731
6564
  absolute: false,
@@ -6736,7 +6569,7 @@ var globMarkdownFiles = async (config2, options = { absolute: false }) => {
6736
6569
  if (process.env.NODE_ENV !== "development") {
6737
6570
  const draftStatuses = await Promise.all(
6738
6571
  globbedFiles.map(async (file) => {
6739
- const absolutePath = path12.resolve(config2.__meta.rootDir, file);
6572
+ const absolutePath = path12.resolve(config.__meta.rootDir, file);
6740
6573
  const { data } = await readFrontmatter(absolutePath);
6741
6574
  return { file, isDraft: data.draft === true };
6742
6575
  })
@@ -6751,32 +6584,32 @@ var globMarkdownFiles = async (config2, options = { absolute: false }) => {
6751
6584
  }
6752
6585
  const relativePath = path12.posix.relative(parent, file);
6753
6586
  const routePath = ensureLeadingSlash(relativePath.replace(/\.mdx?$/, ""));
6754
- const filePath = options.absolute ? path12.resolve(config2.__meta.rootDir, file) : file;
6587
+ const filePath = options.absolute ? path12.resolve(config.__meta.rootDir, file) : file;
6755
6588
  fileMapping[routePath] = filePath;
6756
6589
  }
6757
6590
  }
6758
6591
  return fileMapping;
6759
6592
  };
6760
- var resolveCustomNavigationPaths = async (config2, fileMapping) => {
6761
- if (!config2.navigation && !config2.navigationRules) return fileMapping;
6762
- const resolver = new NavigationResolver(config2);
6593
+ var resolveCustomNavigationPaths = async (config, fileMapping) => {
6594
+ if (!config.navigation && !config.navigationRules) return fileMapping;
6595
+ const resolver = new NavigationResolver(config);
6763
6596
  const mapping = { ...fileMapping };
6764
6597
  const processItem = (item) => {
6765
- const doc = item.type === "doc" ? { file: item.file, path: item.path } : item.type === "category" && item.link ? { file: item.link.file, path: item.link.path } : void 0;
6598
+ const doc = item.type === "doc" ? { file: item.file, path: item.path } : item.type === "category" && item.link?.type === "doc" ? { file: item.link.file, path: item.link.path } : void 0;
6766
6599
  if (!doc || doc.path === doc.file) return;
6767
6600
  const fileRoutePath = ensureLeadingSlash(doc.file.replace(/\.mdx?$/, ""));
6768
6601
  const filePath = mapping[fileRoutePath];
6769
6602
  if (!filePath) return;
6770
6603
  const customPath = ensureLeadingSlash(doc.path);
6771
6604
  mapping[customPath] = filePath;
6772
- delete mapping[fileRoutePath];
6605
+ if (customPath !== fileRoutePath) delete mapping[fileRoutePath];
6773
6606
  };
6774
- if (config2.navigation) {
6607
+ if (config.navigation) {
6775
6608
  const resolvedNavigation = await resolver.resolve();
6776
6609
  traverseNavigation(resolvedNavigation, processItem);
6777
6610
  }
6778
- if (config2.navigationRules) {
6779
- const resolvedRules = await resolver.resolveRules(config2.navigationRules);
6611
+ if (config.navigationRules) {
6612
+ const resolvedRules = await resolver.resolveRules(config.navigationRules);
6780
6613
  for (const rule of resolvedRules) {
6781
6614
  if (rule.type === "insert") {
6782
6615
  traverseNavigation(rule.items, processItem);
@@ -6797,17 +6630,17 @@ var viteDocsPlugin = () => {
6797
6630
  },
6798
6631
  async load(id) {
6799
6632
  if (id !== resolvedVirtualModuleId4) return;
6800
- const config2 = getCurrentConfig();
6801
- if (config2.__meta.mode === "standalone") {
6633
+ const config = getCurrentConfig();
6634
+ if (config.__meta.mode === "standalone") {
6802
6635
  return `export const configuredDocsPlugin = undefined;`;
6803
6636
  }
6804
6637
  const code = [
6805
6638
  'import { markdownPlugin } from "zudoku/plugins/markdown";'
6806
6639
  ];
6807
- const docsConfig = DocsConfigSchema.parse(config2.docs ?? {});
6640
+ const docsConfig = DocsConfigSchema.parse(config.docs ?? {});
6808
6641
  const fileMapping = await resolveCustomNavigationPaths(
6809
- config2,
6810
- await globMarkdownFiles(config2, { absolute: false })
6642
+ config,
6643
+ await globMarkdownFiles(config, { absolute: false })
6811
6644
  );
6812
6645
  const globbedDocuments = {};
6813
6646
  for (const [routePath, file] of Object.entries(fileMapping)) {
@@ -6821,13 +6654,13 @@ var viteDocsPlugin = () => {
6821
6654
  ),
6822
6655
  `};`,
6823
6656
  `export const configuredDocsPlugin = markdownPlugin({`,
6824
- ` basePath: "${config2.basePath ?? ""}",`,
6657
+ ` basePath: "${config.basePath ?? ""}",`,
6825
6658
  ` fileImports,`,
6826
6659
  ` defaultOptions: ${JSON.stringify(docsConfig.defaultOptions)},`,
6827
6660
  ` publishMarkdown: ${JSON.stringify(docsConfig.publishMarkdown)},`,
6828
6661
  `});`
6829
6662
  );
6830
- await writePluginDebugCode(config2.__meta.rootDir, "docs-plugin", code);
6663
+ await writePluginDebugCode(config.__meta.rootDir, "docs-plugin", code);
6831
6664
  return code.join("\n");
6832
6665
  }
6833
6666
  };
@@ -6877,19 +6710,19 @@ var viteMarkdownExportPlugin = () => {
6877
6710
  return env.name === "ssr";
6878
6711
  },
6879
6712
  async buildStart() {
6880
- const config2 = getCurrentConfig();
6881
- const llmsConfig = config2.docs?.llms;
6882
- const needsMdFiles = config2.docs?.publishMarkdown || llmsConfig?.llmsTxt || llmsConfig?.llmsTxtFull;
6883
- if (config2.__meta.mode === "standalone" || !needsMdFiles) {
6713
+ const config = getCurrentConfig();
6714
+ const llmsConfig = config.docs?.llms;
6715
+ const needsMdFiles = config.docs?.publishMarkdown || llmsConfig?.llmsTxt || llmsConfig?.llmsTxtFull;
6716
+ if (config.__meta.mode === "standalone" || !needsMdFiles) {
6884
6717
  return;
6885
6718
  }
6886
6719
  markdownFiles = await resolveCustomNavigationPaths(
6887
- config2,
6888
- await globMarkdownFiles(config2, { absolute: true })
6720
+ config,
6721
+ await globMarkdownFiles(config, { absolute: true })
6889
6722
  );
6890
6723
  if (!llmsConfig?.includeProtected) {
6891
6724
  const protectedRoutes = ProtectedRoutesSchema.parse(
6892
- config2.protectedRoutes
6725
+ config.protectedRoutes
6893
6726
  );
6894
6727
  if (protectedRoutes) {
6895
6728
  const patterns = Object.keys(protectedRoutes);
@@ -6902,19 +6735,19 @@ var viteMarkdownExportPlugin = () => {
6902
6735
  }
6903
6736
  },
6904
6737
  async configureServer(server) {
6905
- const config2 = getCurrentConfig();
6906
- const llmsConfig = config2.docs?.llms;
6907
- const needsMdFiles = config2.docs?.publishMarkdown || llmsConfig?.llmsTxt || llmsConfig?.llmsTxtFull;
6738
+ const config = getCurrentConfig();
6739
+ const llmsConfig = config.docs?.llms;
6740
+ const needsMdFiles = config.docs?.publishMarkdown || llmsConfig?.llmsTxt || llmsConfig?.llmsTxtFull;
6908
6741
  if (!needsMdFiles) return;
6909
6742
  markdownFiles = await resolveCustomNavigationPaths(
6910
- config2,
6911
- await globMarkdownFiles(config2, { absolute: true })
6743
+ config,
6744
+ await globMarkdownFiles(config, { absolute: true })
6912
6745
  );
6913
6746
  server.middlewares.use(async (req, res, next) => {
6914
6747
  if (req.method !== "GET" || !req.url?.endsWith(".md")) {
6915
6748
  return next();
6916
6749
  }
6917
- const basePath = joinUrl(config2.basePath);
6750
+ const basePath = joinUrl(config.basePath);
6918
6751
  const routePath = resolveMarkdownRoutePath(req.url, basePath);
6919
6752
  const filePath = markdownFiles[routePath];
6920
6753
  if (!filePath) return next();
@@ -6929,16 +6762,16 @@ var viteMarkdownExportPlugin = () => {
6929
6762
  });
6930
6763
  },
6931
6764
  async closeBundle() {
6932
- const config2 = getCurrentConfig();
6933
- const llmsConfig = config2.docs?.llms;
6934
- const needsMdFiles = config2.docs?.publishMarkdown || llmsConfig?.llmsTxt || llmsConfig?.llmsTxtFull;
6765
+ const config = getCurrentConfig();
6766
+ const llmsConfig = config.docs?.llms;
6767
+ const needsMdFiles = config.docs?.publishMarkdown || llmsConfig?.llmsTxt || llmsConfig?.llmsTxtFull;
6935
6768
  if (process.env.NODE_ENV !== "production" || Object.keys(markdownFiles).length === 0 || !needsMdFiles) {
6936
6769
  return;
6937
6770
  }
6938
6771
  const distDir = path13.join(
6939
- config2.__meta.rootDir,
6772
+ config.__meta.rootDir,
6940
6773
  "dist",
6941
- config2.basePath ?? ""
6774
+ config.basePath ?? ""
6942
6775
  );
6943
6776
  markdownFileInfos = [];
6944
6777
  for (const [routePath, filePath] of Object.entries(markdownFiles)) {
@@ -6962,9 +6795,9 @@ var viteMarkdownExportPlugin = () => {
6962
6795
  console.warn(`Failed to export markdown for ${routePath}:`, error);
6963
6796
  }
6964
6797
  }
6965
- if (config2.docs?.llms?.llmsTxt || config2.docs?.llms?.llmsTxtFull) {
6798
+ if (config.docs?.llms?.llmsTxt || config.docs?.llms?.llmsTxtFull) {
6966
6799
  const markdownInfoPath = path13.join(
6967
- config2.__meta.rootDir,
6800
+ config.__meta.rootDir,
6968
6801
  "node_modules/.zudoku/markdown-info.json"
6969
6802
  );
6970
6803
  await writeFile2(
@@ -7382,12 +7215,12 @@ var rehypeExcerptWithMdxExport = () => (tree) => {
7382
7215
  tree.children.unshift(exportMdxjsConst("excerpt", excerpt));
7383
7216
  };
7384
7217
  var viteMdxPlugin = async () => {
7385
- const config2 = getCurrentConfig();
7218
+ const config = getCurrentConfig();
7386
7219
  const buildConfig = await getBuildConfig();
7387
7220
  const highlighter = await highlighterPromise;
7388
7221
  const defaultRemarkPlugins = [
7389
7222
  remarkStaticGeneration,
7390
- [remarkInjectFilepath, config2.__meta.rootDir],
7223
+ [remarkInjectFilepath, config.__meta.rootDir],
7391
7224
  remarkComment,
7392
7225
  remarkGfm,
7393
7226
  remarkFrontmatter,
@@ -7399,9 +7232,9 @@ var viteMdxPlugin = async () => {
7399
7232
  remarkDirective,
7400
7233
  remarkDirectiveRehype,
7401
7234
  remarkCodeTabs,
7402
- [remarkLinkRewrite, config2.basePath],
7403
- [remarkNormalizeImageUrl, config2.basePath],
7404
- ...config2.build?.remarkPlugins ?? []
7235
+ [remarkLinkRewrite, config.basePath],
7236
+ [remarkNormalizeImageUrl, config.basePath],
7237
+ ...config.build?.remarkPlugins ?? []
7405
7238
  ];
7406
7239
  const remarkPlugins = typeof buildConfig?.remarkPlugins === "function" ? buildConfig.remarkPlugins(defaultRemarkPlugins) : [...defaultRemarkPlugins, ...buildConfig?.remarkPlugins ?? []];
7407
7240
  const defaultRehypePlugins = [
@@ -7414,9 +7247,9 @@ var viteMdxPlugin = async () => {
7414
7247
  rehypeMetaAsAttributes,
7415
7248
  ...createConfiguredShikiRehypePlugins(
7416
7249
  highlighter,
7417
- config2.syntaxHighlighting?.themes
7250
+ config.syntaxHighlighting?.themes
7418
7251
  ),
7419
- ...config2.build?.rehypePlugins ?? []
7252
+ ...config.build?.rehypePlugins ?? []
7420
7253
  ];
7421
7254
  const rehypePlugins = typeof buildConfig?.rehypePlugins === "function" ? buildConfig.rehypePlugins(defaultRehypePlugins) : [...defaultRehypePlugins, ...buildConfig?.rehypePlugins ?? []];
7422
7255
  return {
@@ -7447,12 +7280,12 @@ var viteSearchPlugin = () => {
7447
7280
  },
7448
7281
  async load(id) {
7449
7282
  if (id !== resolvedVirtualModuleId4) return;
7450
- const config2 = getCurrentConfig();
7451
- if (!config2.search || config2.__meta.mode === "standalone") {
7283
+ const config = getCurrentConfig();
7284
+ if (!config.search || config.__meta.mode === "standalone") {
7452
7285
  return `export const configuredSearchPlugin = undefined;`;
7453
7286
  }
7454
7287
  const code = [];
7455
- if (config2.search.type === "inkeep") {
7288
+ if (config.search.type === "inkeep") {
7456
7289
  code.push(
7457
7290
  `import config from 'virtual:zudoku-config';`,
7458
7291
  `import { inkeepSearchPlugin } from "zudoku/plugins/search-inkeep";`,
@@ -7460,7 +7293,7 @@ var viteSearchPlugin = () => {
7460
7293
  );
7461
7294
  return code.join("\n");
7462
7295
  }
7463
- if (config2.search.type === "pagefind") {
7296
+ if (config.search.type === "pagefind") {
7464
7297
  code.push(
7465
7298
  `import config from 'virtual:zudoku-config';`,
7466
7299
  `import { pagefindSearchPlugin } from "zudoku/plugins/search-pagefind";`,
@@ -7490,10 +7323,10 @@ var viteShikiPlugin = () => {
7490
7323
  return {
7491
7324
  name: "vite-plugin-shiki-register",
7492
7325
  config() {
7493
- const config2 = getCurrentConfig();
7494
- const languages = config2.syntaxHighlighting?.languages ?? defaultLanguages;
7326
+ const config = getCurrentConfig();
7327
+ const languages = config.syntaxHighlighting?.languages ?? defaultLanguages;
7495
7328
  const themes = Object.values(
7496
- config2.syntaxHighlighting?.themes ?? defaultHighlightOptions.themes
7329
+ config.syntaxHighlighting?.themes ?? defaultHighlightOptions.themes
7497
7330
  );
7498
7331
  const shikiIds = [
7499
7332
  ...languages.map((lang) => `@shikijs/langs/${resolveLang(lang)}`),
@@ -7516,10 +7349,10 @@ var viteShikiPlugin = () => {
7516
7349
  },
7517
7350
  async load(id) {
7518
7351
  if (id !== resolvedVirtualModuleId4) return;
7519
- const config2 = getCurrentConfig();
7520
- const languages = config2.syntaxHighlighting?.languages ?? defaultLanguages;
7352
+ const config = getCurrentConfig();
7353
+ const languages = config.syntaxHighlighting?.languages ?? defaultLanguages;
7521
7354
  const themes = Object.values(
7522
- config2.syntaxHighlighting?.themes ?? defaultHighlightOptions.themes
7355
+ config.syntaxHighlighting?.themes ?? defaultHighlightOptions.themes
7523
7356
  );
7524
7357
  const highlighter = await highlighterPromise;
7525
7358
  await Promise.all([
@@ -7595,8 +7428,8 @@ var scopeMatchesPattern = (scope, pattern) => {
7595
7428
  }
7596
7429
  return matchPath2({ path: pattern, end: false }, root) != null;
7597
7430
  };
7598
- var getProtectedSourceMatcher = (config2) => {
7599
- const protectedRoutes = ProtectedRoutesSchema.parse(config2.protectedRoutes);
7431
+ var getProtectedSourceMatcher = (config) => {
7432
+ const protectedRoutes = ProtectedRoutesSchema.parse(config.protectedRoutes);
7600
7433
  const patterns = protectedRoutes ? Object.keys(protectedRoutes) : [];
7601
7434
  if (patterns.length === 0) {
7602
7435
  return { match: () => false, enabled: false, patterns };
@@ -7734,16 +7567,16 @@ var defineEnvVars = (vars) => Object.fromEntries(
7734
7567
  ])
7735
7568
  );
7736
7569
  async function getViteConfig(dir, configEnv, options = {}) {
7737
- const { config: config2, publicEnv: publicEnv2, envPrefix: envPrefix2 } = await loadZudokuConfig(
7570
+ const { config, publicEnv: publicEnv2, envPrefix: envPrefix2 } = await loadZudokuConfig(
7738
7571
  configEnv,
7739
7572
  dir
7740
7573
  );
7741
- const { match: isProtectedSource, enabled: hasProtectedSources } = getProtectedSourceMatcher(config2);
7574
+ const { match: isProtectedSource, enabled: hasProtectedSources } = getProtectedSourceMatcher(config);
7742
7575
  const shouldProtectChunks = hasProtectedSources && options.ssr === true;
7743
7576
  const isProtectedChunk = (chunk) => chunk.facadeModuleId && isProtectedSource(chunk.facadeModuleId) || chunk.moduleIds.some(isProtectedSource);
7744
7577
  const isWorker = options.adapter === "cloudflare";
7745
- const cdnUrl = CdnUrlSchema.parse(config2.cdnUrl);
7746
- const base = cdnUrl?.base ? joinUrl(cdnUrl.base, config2.basePath) : config2.basePath;
7578
+ const cdnUrl = CdnUrlSchema.parse(config.cdnUrl);
7579
+ const base = cdnUrl?.base ? joinUrl(cdnUrl.base, config.basePath) : config.basePath;
7747
7580
  if (cdnUrl && !hasLoggedCdnInfo) {
7748
7581
  logger.info(colors4.blue(`Using CDN URL:`));
7749
7582
  logger.info(colors4.blue(` base: `) + colors4.dim(cdnUrl.base));
@@ -7758,7 +7591,7 @@ async function getViteConfig(dir, configEnv, options = {}) {
7758
7591
  );
7759
7592
  if (ZuploEnv.isZuplo) {
7760
7593
  dotenv.config({
7761
- path: path16.resolve(config2.__meta.rootDir, "../.env.zuplo"),
7594
+ path: path16.resolve(config.__meta.rootDir, "../.env.zuplo"),
7762
7595
  quiet: true
7763
7596
  });
7764
7597
  }
@@ -7783,7 +7616,9 @@ async function getViteConfig(dir, configEnv, options = {}) {
7783
7616
  }
7784
7617
  },
7785
7618
  define: {
7786
- "process.env.ZUDOKU_VERSION": JSON.stringify(package_default.version),
7619
+ "process.env.ZUDOKU_VERSION": JSON.stringify(
7620
+ getZudokuPackageJson().version
7621
+ ),
7787
7622
  "process.env.IS_ZUPLO": ZuploEnv.isZuplo,
7788
7623
  "import.meta.env.IS_ZUPLO": ZuploEnv.isZuplo,
7789
7624
  "import.meta.env.ZUDOKU_HAS_SERVER": JSON.stringify(options.ssr === true),
@@ -7807,8 +7642,8 @@ async function getViteConfig(dir, configEnv, options = {}) {
7807
7642
  `${dir}/dist`,
7808
7643
  `${dir}/lib`,
7809
7644
  `${dir}/.git`,
7810
- `${config2.__meta.moduleDir}/src/vite`,
7811
- `${config2.__meta.moduleDir}/src/cli`
7645
+ `${config.__meta.moduleDir}/src/vite`,
7646
+ `${config.__meta.moduleDir}/src/cli`
7812
7647
  ]
7813
7648
  }
7814
7649
  },
@@ -7816,10 +7651,10 @@ async function getViteConfig(dir, configEnv, options = {}) {
7816
7651
  sourcemap: true,
7817
7652
  target: "es2022",
7818
7653
  chunkSizeWarningLimit: 1500,
7819
- outDir: path16.resolve(path16.join(dir, "dist", config2.basePath ?? "")),
7654
+ outDir: path16.resolve(path16.join(dir, "dist", config.basePath ?? "")),
7820
7655
  emptyOutDir: false,
7821
7656
  rolldownOptions: {
7822
- external: [joinUrl(config2.basePath, "/pagefind/pagefind.js")],
7657
+ external: [joinUrl(config.basePath, "/pagefind/pagefind.js")],
7823
7658
  logLevel: process.env.ZUDOKU_ENV === "internal" ? "info" : "warn",
7824
7659
  checks: {
7825
7660
  pluginTimings: process.env.ZUDOKU_ENV === "internal"
@@ -7847,12 +7682,12 @@ async function getViteConfig(dir, configEnv, options = {}) {
7847
7682
  },
7848
7683
  build: {
7849
7684
  outDir: path16.resolve(
7850
- path16.join(dir, "dist", config2.basePath ?? "", "server")
7685
+ path16.join(dir, "dist", config.basePath ?? "", "server")
7851
7686
  ),
7852
7687
  copyPublicDir: false,
7853
7688
  rolldownOptions: {
7854
7689
  logLevel: "warn",
7855
- input: ["zudoku/app/entry.server.tsx", config2.__meta.configPath]
7690
+ input: ["zudoku/app/entry.server.tsx", config.__meta.configPath]
7856
7691
  }
7857
7692
  }
7858
7693
  }
@@ -7860,7 +7695,7 @@ async function getViteConfig(dir, configEnv, options = {}) {
7860
7695
  experimental: {
7861
7696
  renderBuiltUrl(filename) {
7862
7697
  if (filename.startsWith(`${PROTECTED_CHUNK_DIR}/`)) {
7863
- return joinUrl(config2.basePath, `/${filename}`);
7698
+ return joinUrl(config.basePath, `/${filename}`);
7864
7699
  }
7865
7700
  if (cdnUrl?.base && [".js", ".css"].includes(path16.extname(filename))) {
7866
7701
  return joinUrl(cdnUrl.base, filename);
@@ -7899,7 +7734,7 @@ async function getViteConfig(dir, configEnv, options = {}) {
7899
7734
  }
7900
7735
  };
7901
7736
  const configRoots = await Promise.all(
7902
- (config2.__pluginDirs ?? []).map(findPackageRoot)
7737
+ (config.__pluginDirs ?? []).map(findPackageRoot)
7903
7738
  );
7904
7739
  configRoots.push(dir);
7905
7740
  let mergedViteConfig = viteConfig;
@@ -7935,7 +7770,6 @@ function getDevHtml({
7935
7770
  <head>
7936
7771
  <meta charset="UTF-8" />
7937
7772
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
7938
- <!--app-helmet-->
7939
7773
  <link rel="preconnect" href="https://cdn.zudoku.dev/">
7940
7774
  </head>
7941
7775
  <body>
@@ -7959,7 +7793,6 @@ function getBuildHtml({
7959
7793
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
7960
7794
  <script type="module" crossorigin src="${jsEntry}"></script>
7961
7795
  ${cssLinks}
7962
- <!--app-helmet-->
7963
7796
  <link rel="preconnect" href="https://cdn.zudoku.dev/">
7964
7797
  </head>
7965
7798
  <body>
@@ -7972,10 +7805,10 @@ ${cssLinks}
7972
7805
  // src/vite/manifest.ts
7973
7806
  import { writeFile as writeFile3 } from "node:fs/promises";
7974
7807
  import path17 from "node:path";
7975
- var writeManifest = async (distDir, config2) => {
7808
+ var writeManifest = async (distDir, config) => {
7976
7809
  await writeFile3(
7977
7810
  path17.join(distDir, MANIFEST_FILENAME),
7978
- `${JSON.stringify(buildManifest(config2), null, 2)}
7811
+ `${JSON.stringify(buildManifest(config), null, 2)}
7979
7812
  `,
7980
7813
  "utf-8"
7981
7814
  );
@@ -7989,7 +7822,7 @@ import { cp, mkdir as mkdir3, writeFile as writeFile4 } from "node:fs/promises";
7989
7822
  import path18 from "node:path";
7990
7823
  var pkgJson = getZudokuPackageJson();
7991
7824
  function generateOutput({
7992
- config: config2,
7825
+ config,
7993
7826
  redirects,
7994
7827
  rewrites = []
7995
7828
  }) {
@@ -8014,7 +7847,7 @@ function generateOutput({
8014
7847
  }
8015
7848
  ],
8016
7849
  headers: {
8017
- "Set-Cookie": `__vdpl=${process.env.VERCEL_DEPLOYMENT_ID}; Path=${joinUrl(config2.basePath)}; SameSite=Strict; Secure; HttpOnly`
7850
+ "Set-Cookie": `__vdpl=${process.env.VERCEL_DEPLOYMENT_ID}; Path=${joinUrl(config.basePath)}; SameSite=Strict; Secure; HttpOnly`
8018
7851
  },
8019
7852
  continue: true
8020
7853
  });
@@ -8023,8 +7856,8 @@ function generateOutput({
8023
7856
  routes.push({ handle: "filesystem" });
8024
7857
  for (const rewrite of rewrites) {
8025
7858
  routes.push({
8026
- src: joinUrl(config2.basePath, rewrite.source),
8027
- dest: joinUrl(config2.basePath, rewrite.destination)
7859
+ src: joinUrl(config.basePath, rewrite.source),
7860
+ dest: joinUrl(config.basePath, rewrite.destination)
8028
7861
  });
8029
7862
  }
8030
7863
  }
@@ -8038,11 +7871,11 @@ function generateOutput({
8038
7871
  return output;
8039
7872
  }
8040
7873
  async function writeOutput(dir, {
8041
- config: config2,
7874
+ config,
8042
7875
  redirects,
8043
7876
  rewrites
8044
7877
  }) {
8045
- const output = generateOutput({ config: config2, redirects, rewrites });
7878
+ const output = generateOutput({ config, redirects, rewrites });
8046
7879
  const outputDir = process.env.VERCEL ? path18.join(dir, ".vercel/output") : path18.join(dir, "dist/.output");
8047
7880
  await mkdir3(outputDir, { recursive: true });
8048
7881
  const outputFile = path18.join(outputDir, "config.json");
@@ -8107,14 +7940,14 @@ async function generateSitemap({
8107
7940
  outputUrls,
8108
7941
  basePath,
8109
7942
  baseOutputDir,
8110
- config: config2,
7943
+ config,
8111
7944
  redirectUrls
8112
7945
  }) {
8113
- if (!config2) {
7946
+ if (!config) {
8114
7947
  return;
8115
7948
  }
8116
- const sitemap = new SitemapStream({ hostname: config2.siteUrl });
8117
- const outputDir = path19.resolve(baseOutputDir, config2.outDir ?? "");
7949
+ const sitemap = new SitemapStream({ hostname: config.siteUrl });
7950
+ const outputDir = path19.resolve(baseOutputDir, config.outDir ?? "");
8118
7951
  if (!existsSync(outputDir)) {
8119
7952
  await mkdir4(outputDir, { recursive: true });
8120
7953
  }
@@ -8122,18 +7955,18 @@ async function generateSitemap({
8122
7955
  const writeStream = createWriteStream(sitemapOutputPath);
8123
7956
  sitemap.pipe(writeStream);
8124
7957
  let lastmod;
8125
- if (config2.autoLastmod !== false) {
7958
+ if (config.autoLastmod !== false) {
8126
7959
  lastmod = (/* @__PURE__ */ new Date()).toISOString();
8127
7960
  }
8128
- const exclude = (typeof config2.exclude === "function" ? await config2.exclude() : config2.exclude) ?? [];
7961
+ const exclude = (typeof config.exclude === "function" ? await config.exclude() : config.exclude) ?? [];
8129
7962
  for (const url of outputUrls) {
8130
7963
  const shouldExclude = exclude.includes(url) || url.includes("*") || /(400|404|500)$/.test(url) || redirectUrls.has(url);
8131
7964
  if (shouldExclude) continue;
8132
7965
  sitemap.write({
8133
- url: new URL(joinUrl(basePath, url), config2.siteUrl).toString(),
7966
+ url: new URL(joinUrl(basePath, url), config.siteUrl).toString(),
8134
7967
  lastmod,
8135
- changefreq: config2.changefreq ?? "daily",
8136
- priority: config2.priority ?? 0.7
7968
+ changefreq: config.changefreq ?? "daily",
7969
+ priority: config.priority ?? 0.7
8137
7970
  });
8138
7971
  }
8139
7972
  sitemap.end();
@@ -8214,15 +8047,15 @@ var prerender = async ({
8214
8047
  const rawConfig = await import(serverConfigPath).then(
8215
8048
  (m) => m.default
8216
8049
  );
8217
- const config2 = await runPluginTransformConfig(rawConfig);
8050
+ const config = await runPluginTransformConfig(rawConfig);
8218
8051
  const buildConfig = await getBuildConfig();
8219
8052
  const module = await import(entryServerPath);
8220
8053
  const getRoutes = module.getRoutesByConfig;
8221
- const routes = getRoutes(config2);
8054
+ const routes = getRoutes(config);
8222
8055
  const paths = routesToPaths(routes);
8223
8056
  const rewrites = routesToRewrites(routes);
8224
- if (config2.redirects) {
8225
- for (const r of config2.redirects) {
8057
+ if (config.redirects) {
8058
+ for (const r of config.redirects) {
8226
8059
  paths.push(joinUrl(r.from));
8227
8060
  }
8228
8061
  }
@@ -8246,7 +8079,7 @@ var prerender = async ({
8246
8079
  }
8247
8080
  let completedCount = 0;
8248
8081
  let pagefindIndex;
8249
- if (config2.search?.type === "pagefind") {
8082
+ if (config.search?.type === "pagefind") {
8250
8083
  const { index, errors } = await createIndex();
8251
8084
  invariant(
8252
8085
  index,
@@ -8332,18 +8165,18 @@ var prerender = async ({
8332
8165
  );
8333
8166
  }
8334
8167
  }
8335
- const redirectUrls = getRedirectUrls(workerResults, config2.basePath);
8168
+ const redirectUrls = getRedirectUrls(workerResults, config.basePath);
8336
8169
  await generateSitemap({
8337
- basePath: config2.basePath,
8170
+ basePath: config.basePath,
8338
8171
  outputUrls: paths,
8339
- config: config2.sitemap,
8172
+ config: config.sitemap,
8340
8173
  baseOutputDir: distDir,
8341
8174
  redirectUrls
8342
8175
  });
8343
- if (config2.docs) {
8176
+ if (config.docs) {
8344
8177
  const { DocsConfigSchema: DocsConfigSchema2 } = await Promise.resolve().then(() => (init_ZudokuConfig(), ZudokuConfig_exports));
8345
8178
  const { generateLlmsTxtFiles: generateLlmsTxtFiles2 } = await Promise.resolve().then(() => (init_llms(), llms_exports));
8346
- const docsConfig = DocsConfigSchema2.parse(config2.docs);
8179
+ const docsConfig = DocsConfigSchema2.parse(config.docs);
8347
8180
  const llmsConfig = docsConfig.llms ?? {};
8348
8181
  const markdownInfoPath = path21.join(
8349
8182
  dir,
@@ -8357,10 +8190,10 @@ var prerender = async ({
8357
8190
  if (llmsConfig.llmsTxt || llmsConfig.llmsTxtFull) {
8358
8191
  await generateLlmsTxtFiles2({
8359
8192
  markdownFileInfos,
8360
- basePath: config2.basePath,
8193
+ basePath: config.basePath,
8361
8194
  outputUrls: paths,
8362
8195
  baseOutputDir: distDir,
8363
- siteName: config2.site?.title,
8196
+ siteName: config.site?.title,
8364
8197
  llmsTxt: llmsConfig.llmsTxt,
8365
8198
  llmsTxtFull: llmsConfig.llmsTxtFull,
8366
8199
  redirectUrls
@@ -8432,8 +8265,8 @@ var getContainerMemoryLimitMb = () => {
8432
8265
  import { mkdir as mkdir5, readdir, readFile as readFile3, rename, rm as rm2 } from "node:fs/promises";
8433
8266
  import path22 from "node:path";
8434
8267
  init_joinUrl();
8435
- var assertProtectedPatternsCovered = (config2) => {
8436
- const { patterns } = getProtectedSourceMatcher(config2);
8268
+ var assertProtectedPatternsCovered = (config) => {
8269
+ const { patterns } = getProtectedSourceMatcher(config);
8437
8270
  const unmatched = findUnmatchedProtectedPatterns(patterns);
8438
8271
  if (unmatched.length === 0) return;
8439
8272
  throw new Error(
@@ -8509,10 +8342,10 @@ These would be served publicly. Aborting build.`
8509
8342
  }
8510
8343
  await rm2(srcDir, { recursive: true, force: true });
8511
8344
  };
8512
- var assertCloudflareWranglerGatesProtected = async (dir, config2) => {
8513
- const { enabled } = getProtectedSourceMatcher(config2);
8345
+ var assertCloudflareWranglerGatesProtected = async (dir, config) => {
8346
+ const { enabled } = getProtectedSourceMatcher(config);
8514
8347
  if (!enabled) return;
8515
- const protectedPrefix = `${joinUrl(config2.basePath, PROTECTED_CHUNK_DIR)}/`;
8348
+ const protectedPrefix = `${joinUrl(config.basePath, PROTECTED_CHUNK_DIR)}/`;
8516
8349
  const candidates = ["wrangler.toml", "wrangler.jsonc", "wrangler.json"];
8517
8350
  for (const name of candidates) {
8518
8351
  const file = await readFile3(path22.join(dir, name), "utf-8").catch(
@@ -8557,7 +8390,7 @@ async function runBuild(options) {
8557
8390
  serverResult && !Array.isArray(serverResult) && "output" in serverResult,
8558
8391
  "SSR build failed to produce valid output"
8559
8392
  );
8560
- const { config: config2 } = await loadZudokuConfig(
8393
+ const { config } = await loadZudokuConfig(
8561
8394
  { mode: "production", command: "build" },
8562
8395
  dir
8563
8396
  );
@@ -8576,7 +8409,7 @@ async function runBuild(options) {
8576
8409
  const html = getBuildHtml({
8577
8410
  jsEntry: joinUrl(base, jsEntry),
8578
8411
  cssEntries: cssEntries.map((css) => joinUrl(base, css)),
8579
- dir: config2.site?.dir
8412
+ dir: config.site?.dir
8580
8413
  });
8581
8414
  if (ssr) {
8582
8415
  await bundleSSREntry({
@@ -8585,12 +8418,12 @@ async function runBuild(options) {
8585
8418
  serverOutDir,
8586
8419
  html
8587
8420
  });
8588
- assertProtectedPatternsCovered(config2);
8421
+ assertProtectedPatternsCovered(config);
8589
8422
  assertNoProtectedLeaks(clientResult.output);
8590
8423
  if (adapter !== "cloudflare") {
8591
8424
  await moveProtectedChunks(clientOutDir, serverOutDir);
8592
8425
  } else {
8593
- await assertCloudflareWranglerGatesProtected(dir, config2);
8426
+ await assertCloudflareWranglerGatesProtected(dir, config);
8594
8427
  }
8595
8428
  await writeFile6(
8596
8429
  path23.join(distDir, "package.json"),
@@ -8598,12 +8431,12 @@ async function runBuild(options) {
8598
8431
  `,
8599
8432
  "utf-8"
8600
8433
  );
8601
- await writeManifest(distDir, config2);
8434
+ await writeManifest(distDir, config);
8602
8435
  await rm3(path23.join(clientOutDir, "index.html"), { force: true });
8603
8436
  } else {
8604
8437
  await runPrerender({
8605
8438
  dir,
8606
- config: config2,
8439
+ config,
8607
8440
  html,
8608
8441
  clientOutDir,
8609
8442
  serverOutDir,
@@ -8619,14 +8452,14 @@ var findServerConfigFilename = (result) => {
8619
8452
  return entry.fileName;
8620
8453
  };
8621
8454
  var runPrerender = async (options) => {
8622
- const { dir, config: config2, html, clientOutDir, serverOutDir, serverResult } = options;
8623
- const issuer = await getIssuer(config2);
8455
+ const { dir, config, html, clientOutDir, serverOutDir, serverResult } = options;
8456
+ const issuer = await getIssuer(config);
8624
8457
  const serverConfigFilename = findServerConfigFilename(serverResult);
8625
8458
  try {
8626
8459
  const { workerResults, rewrites } = await prerender({
8627
8460
  html,
8628
8461
  dir,
8629
- basePath: config2.basePath,
8462
+ basePath: config.basePath,
8630
8463
  serverConfigFilename,
8631
8464
  writeRedirects: process.env.VERCEL === void 0
8632
8465
  });
@@ -8652,12 +8485,12 @@ var runPrerender = async (options) => {
8652
8485
  );
8653
8486
  }
8654
8487
  await writeOutput(dir, {
8655
- config: config2,
8488
+ config,
8656
8489
  redirects: workerResults.flatMap((r) => r.redirect ?? []),
8657
8490
  rewrites
8658
8491
  });
8659
8492
  if (ZuploEnv.isZuplo && issuer) {
8660
- const provider = config2.authentication?.type;
8493
+ const provider = config.authentication?.type;
8661
8494
  await writeFile6(
8662
8495
  path23.join(dir, DIST_DIR, ".output/zuplo.json"),
8663
8496
  JSON.stringify({ issuer, provider }, null, 2),
@@ -8959,6 +8792,7 @@ import fs3 from "node:fs/promises";
8959
8792
  import http from "node:http";
8960
8793
  import https from "node:https";
8961
8794
  import path27 from "node:path";
8795
+ import { stripVTControlCharacters } from "node:util";
8962
8796
  import { createHttpTerminator } from "http-terminator";
8963
8797
  import {
8964
8798
  createServer as createViteServer,
@@ -8995,7 +8829,7 @@ init_joinUrl();
8995
8829
  import path26 from "node:path";
8996
8830
  import { createIndex as createIndex2 } from "pagefind";
8997
8831
  import { isRunnableDevEnvironment } from "vite";
8998
- async function* buildPagefindDevIndex(vite, config2) {
8832
+ async function* buildPagefindDevIndex(vite, config) {
8999
8833
  const { index, errors } = await createIndex2();
9000
8834
  invariant(index, `Failed to create pagefind index: ${errors.join(", ")}`);
9001
8835
  const pagefindIndex = index;
@@ -9006,12 +8840,12 @@ async function* buildPagefindDevIndex(vite, config2) {
9006
8840
  const serverModule = await ssrEnvironment.runner.import(
9007
8841
  getAppServerEntryPath()
9008
8842
  );
9009
- const routes = serverModule.getRoutesByConfig(config2);
8843
+ const routes = serverModule.getRoutesByConfig(config);
9010
8844
  const paths = routesToPaths(routes);
9011
- const { basePath } = config2;
8845
+ const { basePath } = config;
9012
8846
  const template = getDevHtml({
9013
8847
  jsEntry: "/__z/entry.client.tsx",
9014
- dir: config2.site?.dir
8848
+ dir: config.site?.dir
9015
8849
  });
9016
8850
  const transformedTemplate = await vite.transformIndexHtml("/", template);
9017
8851
  let indexed = 0;
@@ -9060,14 +8894,14 @@ var DevServer = class {
9060
8894
  constructor(options) {
9061
8895
  this.#options = options;
9062
8896
  }
9063
- async createNodeServer(config2) {
9064
- if (!config2.https) return http.createServer();
8897
+ async createNodeServer(config) {
8898
+ if (!config.https) return http.createServer();
9065
8899
  this.protocol = "https";
9066
8900
  const { dir } = this.#options;
9067
8901
  const [key, cert, ca] = await Promise.all([
9068
- fs3.readFile(path27.resolve(dir, config2.https.key)),
9069
- fs3.readFile(path27.resolve(dir, config2.https.cert)),
9070
- config2.https.ca ? fs3.readFile(path27.resolve(dir, config2.https.ca)) : void 0
8902
+ fs3.readFile(path27.resolve(dir, config.https.key)),
8903
+ fs3.readFile(path27.resolve(dir, config.https.cert)),
8904
+ config.https.ca ? fs3.readFile(path27.resolve(dir, config.https.ca)) : void 0
9071
8905
  ]);
9072
8906
  return https.createServer({ key, cert, ca });
9073
8907
  }
@@ -9076,12 +8910,14 @@ var DevServer = class {
9076
8910
  mode: "development",
9077
8911
  command: "serve"
9078
8912
  };
9079
- const viteConfig = await getViteConfig(this.#options.dir, configEnv);
9080
- const { config: config2 } = await loadZudokuConfig(configEnv, this.#options.dir);
8913
+ const viteConfig = await getViteConfig(this.#options.dir, configEnv, {
8914
+ ssr: this.#options.ssr
8915
+ });
8916
+ const { config } = await loadZudokuConfig(configEnv, this.#options.dir);
9081
8917
  this.resolvedPort = await findAvailablePort(
9082
- this.#options.argPort ?? config2.port ?? DEFAULT_DEV_PORT
8918
+ this.#options.argPort ?? config.port ?? DEFAULT_DEV_PORT
9083
8919
  );
9084
- const server = await this.createNodeServer(config2);
8920
+ const server = await this.createNodeServer(config);
9085
8921
  const mergedViteConfig = mergeConfig3(viteConfig, {
9086
8922
  server: {
9087
8923
  hmr: { server }
@@ -9116,15 +8952,15 @@ var DevServer = class {
9116
8952
  const vite = await createViteServer(mergedViteConfig);
9117
8953
  const graphql = createGraphQLServer({ graphqlEndpoint: "/__z/graphql" });
9118
8954
  vite.middlewares.use((req, res, next) => {
9119
- if (req.method === "GET" && req.originalUrl === "/" && config2.basePath && config2.basePath !== "/") {
9120
- res.writeHead(307, { Location: config2.basePath });
8955
+ if (req.method === "GET" && req.originalUrl === "/" && config.basePath && config.basePath !== "/") {
8956
+ res.writeHead(307, { Location: config.basePath });
9121
8957
  res.end();
9122
8958
  return;
9123
8959
  }
9124
8960
  next();
9125
8961
  });
9126
8962
  vite.middlewares.use(graphql.graphqlEndpoint, graphql);
9127
- const sessionEndpoint = joinUrl(config2.basePath, "/__z/auth/session");
8963
+ const sessionEndpoint = joinUrl(config.basePath, "/__z/auth/session");
9128
8964
  vite.middlewares.use(sessionEndpoint, async (req, res) => {
9129
8965
  if (req.method !== "POST" && req.method !== "DELETE") {
9130
8966
  res.writeHead(405, { Allow: "POST, DELETE" });
@@ -9205,7 +9041,7 @@ var DevServer = class {
9205
9041
  printDiagnosticsToConsole(
9206
9042
  `Server-side rendering ${this.#options.ssr ? "enabled" : "disabled"}`
9207
9043
  );
9208
- if (config2.search?.type === "pagefind") {
9044
+ if (config.search?.type === "pagefind") {
9209
9045
  const pagefindPath = path27.join(
9210
9046
  vite.config.publicDir,
9211
9047
  "pagefind/pagefind.js"
@@ -9278,11 +9114,15 @@ var DevServer = class {
9278
9114
  const html = `<!DOCTYPE html><html><body><script type="module">
9279
9115
  import { ErrorOverlay } from '/@vite/client';
9280
9116
  document.body.appendChild(new ErrorOverlay(${JSON.stringify({
9281
- message: e instanceof Error ? e.message : String(e),
9282
- stack: e instanceof Error ? e.stack : ""
9117
+ message: stripVTControlCharacters(
9118
+ e instanceof Error ? e.message : String(e)
9119
+ ),
9120
+ stack: stripVTControlCharacters(
9121
+ e instanceof Error ? e.stack ?? "" : ""
9122
+ )
9283
9123
  })}));
9284
9124
  </script></body></html>`;
9285
- res.writeHead(500, { "Content-Type": "text/html" });
9125
+ res.writeHead(500, { "Content-Type": "text/html; charset=utf-8" });
9286
9126
  res.end(html);
9287
9127
  }
9288
9128
  });