zudoku 0.87.0 → 0.89.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 (83) hide show
  1. package/dist/cli/cli.js +355 -66
  2. package/dist/cli/worker.js +10 -0
  3. package/dist/declarations/app/main.d.ts +1 -1
  4. package/dist/declarations/config/validators/HeaderNavigationSchema.d.ts +72 -0
  5. package/dist/declarations/config/validators/ZudokuConfig.d.ts +30 -0
  6. package/dist/declarations/config/validators/icon-types.d.ts +1 -1
  7. package/dist/declarations/lib/components/MobileTopNavigationDrawer.d.ts +7 -0
  8. package/dist/declarations/lib/components/navigation/MobileNavigationDrawer.d.ts +11 -0
  9. package/dist/declarations/lib/components/navigation/Navigation.d.ts +1 -2
  10. package/dist/declarations/lib/components/navigation/NavigationFrames.d.ts +2 -1
  11. package/dist/declarations/lib/core/ZudokuContext.d.ts +1 -0
  12. package/dist/declarations/lib/core/plugins.d.ts +1 -0
  13. package/dist/declarations/lib/oas/parser/index.d.ts +3 -1
  14. package/dist/declarations/lib/plugins/openapi/PlaygroundDialogWrapper.d.ts +1 -1
  15. package/dist/declarations/lib/plugins/openapi/graphql/gql.d.ts +5 -5
  16. package/dist/declarations/lib/plugins/openapi/graphql/graphql.d.ts +36 -0
  17. package/dist/declarations/lib/plugins/openapi/playground/Playground.d.ts +2 -1
  18. package/dist/declarations/lib/plugins/openapi/processors/removeInternal.d.ts +2 -0
  19. package/dist/declarations/lib/plugins/openapi/state.d.ts +13 -2
  20. package/dist/declarations/lib/plugins/openapi/util/resolveServerUrl.d.ts +14 -0
  21. package/dist/declarations/lib/util/getIntrinsicImageDimensions.d.ts +7 -0
  22. package/dist/declarations/lib/util/isHeaderNavGroup.d.ts +2 -0
  23. package/dist/declarations/lib/util/requestIdle.d.ts +1 -0
  24. package/dist/flat-config.d.ts +2 -1
  25. package/docs/concepts/auth-provider-api-identities.md +1 -1
  26. package/docs/configuration/api-reference.md +2 -0
  27. package/docs/configuration/authentication-openid.md +27 -5
  28. package/docs/configuration/authentication.md +25 -0
  29. package/docs/configuration/footer.mdx +4 -2
  30. package/docs/configuration/protected-routes.md +9 -1
  31. package/docs/configuration/site.md +2 -1
  32. package/docs/guides/processors.mdx +8 -0
  33. package/docs/openapi-extensions/x-internal.md +88 -0
  34. package/package.json +8 -6
  35. package/src/app/entry.client.tsx +19 -2
  36. package/src/app/entry.server.tsx +6 -0
  37. package/src/app/main.css +3 -0
  38. package/src/app/main.tsx +20 -8
  39. package/src/config/validators/HeaderNavigationSchema.ts +3 -0
  40. package/src/config/validators/ZudokuConfig.ts +1 -0
  41. package/src/config/validators/icon-types.ts +9 -0
  42. package/src/lib/authentication/providers/firebase.tsx +12 -7
  43. package/src/lib/authentication/providers/openid.tsx +1 -0
  44. package/src/lib/authentication/providers/supabase.tsx +33 -13
  45. package/src/lib/components/Footer.tsx +19 -2
  46. package/src/lib/components/Header.tsx +17 -2
  47. package/src/lib/components/HeaderNavigation.tsx +5 -5
  48. package/src/lib/components/Main.tsx +65 -15
  49. package/src/lib/components/Markdown.tsx +1 -1
  50. package/src/lib/components/MobileTopNavigation.tsx +51 -260
  51. package/src/lib/components/MobileTopNavigationDrawer.tsx +276 -0
  52. package/src/lib/components/Search.tsx +20 -5
  53. package/src/lib/components/navigation/MobileNavigationDrawer.tsx +60 -0
  54. package/src/lib/components/navigation/Navigation.tsx +5 -19
  55. package/src/lib/components/navigation/NavigationFrames.tsx +17 -8
  56. package/src/lib/core/ZudokuContext.ts +1 -0
  57. package/src/lib/core/plugins.ts +6 -0
  58. package/src/lib/oas/graphql/index.ts +38 -0
  59. package/src/lib/oas/parser/index.ts +5 -1
  60. package/src/lib/plugins/openapi/Endpoint.tsx +186 -21
  61. package/src/lib/plugins/openapi/McpCatalog.tsx +28 -2
  62. package/src/lib/plugins/openapi/OperationList.tsx +16 -1
  63. package/src/lib/plugins/openapi/OperationListItem.tsx +3 -1
  64. package/src/lib/plugins/openapi/PlaygroundDialogWrapper.tsx +1 -1
  65. package/src/lib/plugins/openapi/Sidecar.tsx +14 -4
  66. package/src/lib/plugins/openapi/graphql/gql.ts +15 -15
  67. package/src/lib/plugins/openapi/graphql/graphql.ts +101 -5
  68. package/src/lib/plugins/openapi/playground/Playground.tsx +20 -10
  69. package/src/lib/plugins/openapi/processors/removeInternal.ts +15 -0
  70. package/src/lib/plugins/openapi/state.ts +87 -5
  71. package/src/lib/plugins/openapi/util/resolveServerUrl.ts +77 -0
  72. package/src/lib/plugins/search-pagefind/index.tsx +43 -2
  73. package/src/lib/shiki.ts +1 -0
  74. package/src/lib/util/getIntrinsicImageDimensions.ts +15 -0
  75. package/src/lib/util/isHeaderNavGroup.ts +9 -0
  76. package/src/lib/util/requestIdle.ts +19 -0
  77. package/src/lib/util/useScrollToAnchor.ts +7 -0
  78. package/src/vite/build.ts +66 -7
  79. package/src/vite/config.ts +30 -1
  80. package/src/vite/plugin-api.ts +55 -27
  81. package/src/vite/plugin-theme.ts +6 -15
  82. package/src/vite/protected/annotator.ts +182 -23
  83. package/src/zuplo/with-zuplo-processors.ts +0 -6
package/dist/cli/cli.js CHANGED
@@ -742,9 +742,9 @@ var processFontConfig = (fontConfig) => {
742
742
  var processFonts = async (themeConfig) => {
743
743
  const imports = [];
744
744
  const families = {
745
- sans: "Geist, sans-serif",
745
+ sans: '"Geist Variable", sans-serif',
746
746
  serif: void 0,
747
- mono: '"Geist Mono", monospace'
747
+ mono: '"Geist Mono Variable", monospace'
748
748
  };
749
749
  const userFonts = {
750
750
  sans: processFontConfig(themeConfig?.fonts?.sans),
@@ -781,18 +781,9 @@ var processFonts = async (themeConfig) => {
781
781
  } catch {
782
782
  }
783
783
  }
784
- families.sans = userFonts.sans.fontFamily || registryFonts.sans || "Geist, sans-serif";
784
+ families.sans = userFonts.sans.fontFamily || registryFonts.sans || '"Geist Variable", sans-serif';
785
785
  families.serif = userFonts.serif.fontFamily || registryFonts.serif;
786
- families.mono = userFonts.mono.fontFamily || registryFonts.mono || '"Geist Mono", monospace';
787
- if (!userFonts.sans.fontFamily && !registryFonts.sans) {
788
- imports.push(getGoogleFontUrl("Geist"));
789
- }
790
- if (!userFonts.serif.fontFamily && !registryFonts.serif) {
791
- imports.push(getGoogleFontUrl("Playfair Display"));
792
- }
793
- if (!userFonts.mono.fontFamily && !registryFonts.mono) {
794
- imports.push(getGoogleFontUrl("Geist Mono"));
795
- }
786
+ families.mono = userFonts.mono.fontFamily || registryFonts.mono || '"Geist Mono Variable", monospace';
796
787
  return { imports, families };
797
788
  };
798
789
  var virtualModuleId = "virtual:zudoku-theme.css";
@@ -2020,6 +2011,7 @@ var IconNames = [
2020
2011
  "layers-plus",
2021
2012
  "layout",
2022
2013
  "layout-dashboard",
2014
+ "layout-freeform",
2023
2015
  "layout-grid",
2024
2016
  "layout-list",
2025
2017
  "layout-panel-left",
@@ -2163,7 +2155,9 @@ var IconNames = [
2163
2155
  "metronome",
2164
2156
  "mic",
2165
2157
  "mic-2",
2158
+ "mic-audio-lines",
2166
2159
  "mic-off",
2160
+ "mic-signal",
2167
2161
  "mic-vocal",
2168
2162
  "microchip",
2169
2163
  "microscope",
@@ -2196,6 +2190,7 @@ var IconNames = [
2196
2190
  "moon-star",
2197
2191
  "more-horizontal",
2198
2192
  "more-vertical",
2193
+ "mosque",
2199
2194
  "motorbike",
2200
2195
  "mountain",
2201
2196
  "mountain-snow",
@@ -2448,9 +2443,11 @@ var IconNames = [
2448
2443
  "rotate-3-d",
2449
2444
  "rotate-3d",
2450
2445
  "rotate-ccw",
2446
+ "rotate-ccw-clock",
2451
2447
  "rotate-ccw-key",
2452
2448
  "rotate-ccw-square",
2453
2449
  "rotate-cw",
2450
+ "rotate-cw-fading-clock",
2454
2451
  "rotate-cw-square",
2455
2452
  "route",
2456
2453
  "route-off",
@@ -2488,6 +2485,7 @@ var IconNames = [
2488
2485
  "scan-line",
2489
2486
  "scan-qr-code",
2490
2487
  "scan-search",
2488
+ "scan-square",
2491
2489
  "scan-text",
2492
2490
  "scatter-chart",
2493
2491
  "school",
@@ -2657,6 +2655,7 @@ var IconNames = [
2657
2655
  "square-menu",
2658
2656
  "square-minus",
2659
2657
  "square-mouse-pointer",
2658
+ "square-off",
2660
2659
  "square-parking",
2661
2660
  "square-parking-off",
2662
2661
  "square-pause",
@@ -2885,6 +2884,7 @@ var IconNames = [
2885
2884
  "user-round-search",
2886
2885
  "user-round-x",
2887
2886
  "user-search",
2887
+ "user-shield",
2888
2888
  "user-square",
2889
2889
  "user-square-2",
2890
2890
  "user-star",
@@ -3322,6 +3322,7 @@ var LogoSchema = z7.object({
3322
3322
  src: z7.object({ light: z7.string(), dark: z7.string() }),
3323
3323
  alt: z7.string().optional(),
3324
3324
  width: z7.string().or(z7.number()).optional(),
3325
+ height: z7.string().or(z7.number()).optional(),
3325
3326
  href: z7.string().optional(),
3326
3327
  reloadDocument: z7.boolean().optional()
3327
3328
  });
@@ -4957,10 +4958,36 @@ SchemaTag.implement({
4957
4958
  })
4958
4959
  })
4959
4960
  });
4961
+ var ServerVariableItem = builder.objectRef("ServerVariable").implement({
4962
+ fields: (t) => ({
4963
+ name: t.exposeString("name"),
4964
+ default: t.exposeString("default"),
4965
+ enum: t.exposeStringList("enum", { nullable: true }),
4966
+ description: t.exposeString("description", { nullable: true })
4967
+ })
4968
+ });
4960
4969
  var ServerItem = builder.objectRef("Server").implement({
4961
4970
  fields: (t) => ({
4962
4971
  url: t.exposeString("url"),
4963
- description: t.exposeString("description", { nullable: true })
4972
+ // OAS 3.2+ `name`, intended for identifying a server independent of its
4973
+ // (possibly templated/rich-text-described) `url`/`description`.
4974
+ name: t.exposeString("name", { nullable: true }),
4975
+ description: t.exposeString("description", { nullable: true }),
4976
+ variables: t.field({
4977
+ type: [ServerVariableItem],
4978
+ resolve: (parent) => Object.entries(parent.variables ?? {}).map(([name, variable]) => {
4979
+ const enumValues = variable.enum?.map(String);
4980
+ return {
4981
+ name,
4982
+ // `default` is required by the spec but often missing in real-world
4983
+ // schemas, fall back to the first enum value (or an empty string)
4984
+ // instead of failing the whole query on a non-null field.
4985
+ default: String(variable.default ?? enumValues?.[0] ?? ""),
4986
+ enum: enumValues,
4987
+ description: variable.description
4988
+ };
4989
+ })
4990
+ })
4964
4991
  })
4965
4992
  });
4966
4993
  var WebhookItem = builder.objectRef("WebhookItem").implement({
@@ -5495,6 +5522,105 @@ var createGraphQLServer = (options) => createYoga({ schema, batching: true, ...o
5495
5522
  var DOCUMENT_TYPE_EXTENSION = "x-zudoku-type";
5496
5523
  var MCP_CATALOG = "mcp-catalog";
5497
5524
 
5525
+ // src/lib/plugins/openapi/processors/removeParameters.ts
5526
+ var removeParameters = ({ names, in: locations, shouldRemove } = {}) => ({ schema: schema2 }) => traverse(schema2, (spec) => {
5527
+ const filterParameters = (parameters) => parameters.filter((p) => {
5528
+ if (names?.includes(p.name)) return false;
5529
+ if (locations?.includes(p.in)) return false;
5530
+ if (shouldRemove?.({ parameter: p })) return false;
5531
+ return true;
5532
+ });
5533
+ if (spec.components?.parameters) {
5534
+ spec = {
5535
+ ...spec,
5536
+ components: {
5537
+ ...spec.components,
5538
+ parameters: Object.fromEntries(
5539
+ Object.entries(spec.components.parameters).filter(
5540
+ ([_, param]) => {
5541
+ const p = param;
5542
+ if (p.$ref) return true;
5543
+ return !names?.includes(p.name) && !locations?.includes(p.in) && !shouldRemove?.({ parameter: p });
5544
+ }
5545
+ )
5546
+ )
5547
+ }
5548
+ };
5549
+ }
5550
+ if (spec.paths) {
5551
+ const updatedPaths = {};
5552
+ for (const [path32, pathItem] of Object.entries(spec.paths)) {
5553
+ if (typeof pathItem !== "object" || pathItem === null) {
5554
+ updatedPaths[path32] = pathItem;
5555
+ continue;
5556
+ }
5557
+ let updatedPathItem = { ...pathItem };
5558
+ if ("parameters" in updatedPathItem && Array.isArray(updatedPathItem.parameters)) {
5559
+ updatedPathItem.parameters = filterParameters(
5560
+ updatedPathItem.parameters
5561
+ );
5562
+ }
5563
+ for (const method of Object.keys(updatedPathItem)) {
5564
+ const pathItemWithMethods = updatedPathItem;
5565
+ if (method === "parameters" || typeof pathItemWithMethods[method] !== "object") {
5566
+ continue;
5567
+ }
5568
+ const operation = pathItemWithMethods[method];
5569
+ if (Array.isArray(operation.parameters)) {
5570
+ pathItemWithMethods[method] = {
5571
+ ...operation,
5572
+ parameters: filterParameters(operation.parameters)
5573
+ };
5574
+ updatedPathItem = pathItemWithMethods;
5575
+ }
5576
+ }
5577
+ updatedPaths[path32] = updatedPathItem;
5578
+ }
5579
+ spec = { ...spec, paths: updatedPaths };
5580
+ }
5581
+ return spec;
5582
+ });
5583
+
5584
+ // src/lib/plugins/openapi/processors/removePaths.ts
5585
+ var removePaths = ({ paths = {}, shouldRemove }) => ({ schema: schema2 }) => traverse(schema2, (spec) => {
5586
+ if (!spec.paths) return spec;
5587
+ const updatedPaths = {};
5588
+ for (const [path32, methods] of Object.entries(spec.paths)) {
5589
+ const operations = spec.paths[path32];
5590
+ if (paths[path32] === true) continue;
5591
+ if (shouldRemove?.({ path: path32, method: true, operation: operations }))
5592
+ continue;
5593
+ if (typeof methods === "object" && methods !== null) {
5594
+ const filteredPath = Object.fromEntries(
5595
+ Object.entries(methods).filter(([method]) => {
5596
+ const operations2 = spec.paths[path32][method];
5597
+ const isMethodToRemove = Array.isArray(paths[path32]) && paths[path32].includes(method);
5598
+ const isMethodFiltered = shouldRemove?.({
5599
+ path: path32,
5600
+ method,
5601
+ operation: operations2
5602
+ });
5603
+ return !isMethodToRemove && !isMethodFiltered;
5604
+ })
5605
+ );
5606
+ updatedPaths[path32] = filteredPath;
5607
+ } else {
5608
+ updatedPaths[path32] = methods;
5609
+ }
5610
+ }
5611
+ return { ...spec, paths: updatedPaths };
5612
+ });
5613
+
5614
+ // src/lib/plugins/openapi/processors/removeInternal.ts
5615
+ var removeInternal = () => (arg) => removeParameters({
5616
+ shouldRemove: ({ parameter }) => parameter["x-internal"]
5617
+ })({
5618
+ ...arg,
5619
+ schema: removePaths({
5620
+ shouldRemove: ({ operation }) => operation["x-internal"]
5621
+ })(arg)
5622
+ });
5623
+
5498
5624
  // src/lib/plugins/openapi/util/documentType.ts
5499
5625
  var MCP_SERVER_EXTENSION = "x-mcp-server";
5500
5626
  var HTTP_METHODS = [
@@ -6520,6 +6646,36 @@ var viteConfigReloadPlugin = () => ({
6520
6646
  // src/vite/plugin-api.ts
6521
6647
  var PROCESSED_STORE_SUBPATH = "node_modules/.zudoku/processed";
6522
6648
  var schemaConfigurationChanged = (current, next) => current.basePath !== next.basePath || !deepEqual2(current.apis, next.apis);
6649
+ var generateDefaultApiOptionsCode = () => [
6650
+ `const defaultApiOptions = {`,
6651
+ ` examplesLanguage: config.defaults?.apis?.examplesLanguage ?? config.defaults?.examplesLanguage,`,
6652
+ ` supportedLanguages: config.defaults?.apis?.supportedLanguages,`,
6653
+ ` disablePlayground: config.defaults?.apis?.disablePlayground,`,
6654
+ ` disableSidecar: config.defaults?.apis?.disableSidecar,`,
6655
+ ` disableSecurity: config.defaults?.apis?.disableSecurity ?? true,`,
6656
+ ` disableMcpAuthInstructions: config.defaults?.apis?.disableMcpAuthInstructions,`,
6657
+ ` showVersionSelect: config.defaults?.apis?.showVersionSelect ?? "if-available",`,
6658
+ ` showInfoPage: config.defaults?.apis?.showInfoPage,`,
6659
+ ` schemaDownload: config.defaults?.apis?.schemaDownload,`,
6660
+ `};`
6661
+ ];
6662
+ var UNSAFE_CODE_CHARS = {
6663
+ "<": "\\u003C",
6664
+ ">": "\\u003E",
6665
+ "\u2028": "\\u2028",
6666
+ "\u2029": "\\u2029"
6667
+ };
6668
+ var toCodeString = (value) => JSON.stringify(value).replace(
6669
+ /[<>\u2028\u2029]/g,
6670
+ (char) => UNSAFE_CODE_CHARS[char] ?? char
6671
+ );
6672
+ var generateSchemaImportsCode = (schemaImports) => [
6673
+ "const schemaImports = {",
6674
+ ...schemaImports.map(
6675
+ (schema2) => ` ${toCodeString(schema2.importKey)}: () => import(${toCodeString(`${schema2.importKey.replaceAll("\\", "/")}?d=${schema2.processedTime}`)}),`
6676
+ ),
6677
+ "};"
6678
+ ];
6523
6679
  var warn = (message) => {
6524
6680
  console.warn(`[zudoku] ${message}`);
6525
6681
  };
@@ -6552,7 +6708,7 @@ var viteApiPlugin = async () => {
6552
6708
  initialConfig.__meta.rootDir,
6553
6709
  PROCESSED_STORE_SUBPATH
6554
6710
  );
6555
- const processors = [...buildProcessors, ...zuploProcessors];
6711
+ const processors = [...buildProcessors, removeInternal(), ...zuploProcessors];
6556
6712
  const schemaManager = new SchemaManager({
6557
6713
  storeDir: tmpStoreDir,
6558
6714
  config: initialConfig,
@@ -6630,8 +6786,11 @@ var viteApiPlugin = async () => {
6630
6786
  code.push(
6631
6787
  `const apis = Array.isArray(config.apis) ? config.apis : [config.apis]`
6632
6788
  );
6789
+ code.push(...generateDefaultApiOptionsCode());
6633
6790
  const apis = ensureArray(config.apis);
6634
6791
  const apiMetadata = [];
6792
+ const schemaImports = schemaManager.getSchemaImports();
6793
+ code.push(...generateSchemaImportsCode(schemaImports));
6635
6794
  for (const apiConfig of apis) {
6636
6795
  if (apiConfig.type === "file" && apiConfig.path) {
6637
6796
  const latestSchema = schemaManager.getLatestSchema(apiConfig.path);
@@ -6677,7 +6836,6 @@ var viteApiPlugin = async () => {
6677
6836
  };
6678
6837
  });
6679
6838
  const tags = Array.from(allSlugs);
6680
- const schemaImports = schemaManager.getSchemaImports();
6681
6839
  const latest = schemas.at(0);
6682
6840
  const documentType = latest ? resolveDocumentType(latest.schema, apiConfig.path) : void 0;
6683
6841
  if (documentType === MCP_CATALOG) {
@@ -6700,25 +6858,13 @@ var viteApiPlugin = async () => {
6700
6858
  ` tagPages: ${JSON.stringify(tags)},`,
6701
6859
  ...documentType ? [` documentType: ${JSON.stringify(documentType)},`] : [],
6702
6860
  ` options: {`,
6703
- ` examplesLanguage: config.defaults?.apis?.examplesLanguage ?? config.defaults?.examplesLanguage,`,
6704
- ` supportedLanguages: config.defaults?.apis?.supportedLanguages,`,
6705
- ` disablePlayground: config.defaults?.apis?.disablePlayground,`,
6706
- ` disableSidecar: config.defaults?.apis?.disableSidecar,`,
6707
- ` disableSecurity: config.defaults?.apis?.disableSecurity ?? true,`,
6708
- ` disableMcpAuthInstructions: config.defaults?.apis?.disableMcpAuthInstructions,`,
6709
- ` showVersionSelect: config.defaults?.apis?.showVersionSelect ?? "if-available",`,
6861
+ ` ...defaultApiOptions,`,
6710
6862
  ` expandAllTags: config.defaults?.apis?.expandAllTags ?? true,`,
6711
- ` showInfoPage: config.defaults?.apis?.showInfoPage,`,
6712
- ` schemaDownload: config.defaults?.apis?.schemaDownload,`,
6713
6863
  ` transformExamples: config.defaults?.apis?.transformExamples,`,
6714
6864
  ` generateCodeSnippet: config.defaults?.apis?.generateCodeSnippet,`,
6715
6865
  ` ...(apis[${apiIndex}].options ?? {}),`,
6716
6866
  ` },`,
6717
- ` schemaImports: {`,
6718
- ...schemaImports.map(
6719
- (s) => ` "${s.importKey.replaceAll("\\", "\\\\")}": () => import("${s.importKey.replaceAll("\\", "/")}?d=${s.processedTime}"),`
6720
- ),
6721
- ` },`,
6867
+ ` schemaImports,`,
6722
6868
  "}));"
6723
6869
  );
6724
6870
  } else {
@@ -6728,16 +6874,8 @@ var viteApiPlugin = async () => {
6728
6874
  ` ...${JSON.stringify(apiConfig)},`,
6729
6875
  ...documentType ? [` documentType: ${JSON.stringify(documentType)},`] : [],
6730
6876
  " options: {",
6731
- ` examplesLanguage: config.defaults?.apis?.examplesLanguage ?? config.defaults?.examplesLanguage,`,
6732
- ` supportedLanguages: config.defaults?.apis?.supportedLanguages,`,
6733
- ` disablePlayground: config.defaults?.apis?.disablePlayground,`,
6734
- ` disableSidecar: config.defaults?.apis?.disableSidecar,`,
6735
- ` disableSecurity: config.defaults?.apis?.disableSecurity ?? true,`,
6736
- ` disableMcpAuthInstructions: config.defaults?.apis?.disableMcpAuthInstructions,`,
6737
- ` showVersionSelect: config.defaults?.apis?.showVersionSelect ?? "if-available",`,
6877
+ ` ...defaultApiOptions,`,
6738
6878
  ` expandAllTags: config.defaults?.apis?.expandAllTags ?? false,`,
6739
- ` showInfoPage: config.defaults?.apis?.showInfoPage,`,
6740
- ` schemaDownload: config.defaults?.apis?.schemaDownload,`,
6741
6879
  ` ...${JSON.stringify(apiConfig.options ?? {})},`,
6742
6880
  " },",
6743
6881
  "}));"
@@ -8298,34 +8436,132 @@ var findUnmatchedProtectedPatterns = (patterns) => patterns.filter(
8298
8436
  );
8299
8437
 
8300
8438
  // src/vite/protected/annotator.ts
8301
- var walk = (node, visit9) => {
8439
+ var FUNCTION_TYPES = /* @__PURE__ */ new Set([
8440
+ "FunctionDeclaration",
8441
+ "FunctionExpression",
8442
+ "ArrowFunctionExpression"
8443
+ ]);
8444
+ var patternNames = (pattern) => {
8445
+ switch (pattern?.type) {
8446
+ case "Identifier":
8447
+ return [pattern.name];
8448
+ case "AssignmentPattern":
8449
+ return patternNames(pattern.left);
8450
+ case "RestElement":
8451
+ return patternNames(pattern.argument);
8452
+ case "ArrayPattern":
8453
+ return (pattern.elements ?? []).flatMap(patternNames);
8454
+ case "ObjectPattern":
8455
+ return (pattern.properties ?? []).flatMap(
8456
+ (prop) => patternNames(prop.type === "RestElement" ? prop : prop.value)
8457
+ );
8458
+ default:
8459
+ return [];
8460
+ }
8461
+ };
8462
+ var declaredNames = (statement) => {
8463
+ if (statement?.type === "VariableDeclaration") {
8464
+ return (statement.declarations ?? []).flatMap(
8465
+ (declaration) => patternNames(declaration.id)
8466
+ );
8467
+ }
8468
+ if ((statement?.type === "FunctionDeclaration" || statement?.type === "ClassDeclaration") && statement.id) {
8469
+ return [statement.id.name];
8470
+ }
8471
+ return [];
8472
+ };
8473
+ var scopeNames = (node) => {
8474
+ if (FUNCTION_TYPES.has(node.type)) {
8475
+ return [
8476
+ ...(node.params ?? []).flatMap(patternNames),
8477
+ ...node.type === "FunctionExpression" && node.id ? [node.id.name] : []
8478
+ ];
8479
+ }
8480
+ switch (node.type) {
8481
+ case "BlockStatement":
8482
+ case "StaticBlock":
8483
+ return (node.body ?? []).flatMap(declaredNames);
8484
+ case "CatchClause":
8485
+ return patternNames(node.param);
8486
+ case "ForStatement":
8487
+ return declaredNames(node.init);
8488
+ case "ForInStatement":
8489
+ case "ForOfStatement":
8490
+ return declaredNames(node.left);
8491
+ case "ClassExpression":
8492
+ return node.id ? [node.id.name] : [];
8493
+ default:
8494
+ return [];
8495
+ }
8496
+ };
8497
+ var walk = (node, visit9, shadowed = /* @__PURE__ */ new Set()) => {
8302
8498
  if (!node || typeof node !== "object") return;
8303
- if (typeof node.type === "string") visit9(node);
8499
+ let inner = shadowed;
8500
+ if (typeof node.type === "string") {
8501
+ visit9(node, shadowed);
8502
+ const names = scopeNames(node);
8503
+ if (names.length > 0) inner = /* @__PURE__ */ new Set([...shadowed, ...names]);
8504
+ }
8304
8505
  for (const key of Object.keys(node)) {
8305
8506
  if (key === "loc" || key === "start" || key === "end" || key === "range") {
8306
8507
  continue;
8307
8508
  }
8308
8509
  const val = node[key];
8309
8510
  if (Array.isArray(val)) {
8310
- for (const v of val) walk(v, visit9);
8511
+ for (const v of val) walk(v, visit9, inner);
8311
8512
  } else if (val && typeof val === "object") {
8312
- walk(val, visit9);
8513
+ walk(val, visit9, inner);
8313
8514
  }
8314
8515
  }
8315
8516
  };
8316
8517
  var literalString = (node) => node?.type === "Literal" && typeof node.value === "string" ? node.value : void 0;
8317
8518
  var propKey = (prop) => prop.key?.type === "Identifier" ? prop.key.name : literalString(prop.key);
8318
- var collectImportSpecs = (node) => {
8519
+ var collectTopLevelObjectBindings = (ast) => new Map(
8520
+ (ast.body ?? []).flatMap((statement) => {
8521
+ if (statement.type !== "VariableDeclaration") return [];
8522
+ return (statement.declarations ?? []).flatMap(
8523
+ (declaration) => declaration.id?.type === "Identifier" && declaration.init?.type === "ObjectExpression" ? [[declaration.id.name, declaration.init]] : []
8524
+ );
8525
+ })
8526
+ );
8527
+ var collectImportSpecs = (node, objectBindings, shadowed, visitedBindings = /* @__PURE__ */ new Set()) => {
8319
8528
  const out = [];
8320
- walk(node, (n) => {
8321
- if (n.type === "ImportExpression") {
8322
- const spec = literalString(n.source);
8323
- if (spec) out.push(spec);
8324
- }
8325
- });
8529
+ const referenced = [];
8530
+ const considerReference = (candidate, scope) => {
8531
+ if (candidate?.type !== "Identifier") return;
8532
+ if (scope.has(candidate.name)) return;
8533
+ if (visitedBindings.has(candidate.name)) return;
8534
+ const binding = objectBindings.get(candidate.name);
8535
+ if (!binding) return;
8536
+ visitedBindings.add(candidate.name);
8537
+ referenced.push(binding);
8538
+ };
8539
+ considerReference(node, shadowed);
8540
+ walk(
8541
+ node,
8542
+ (n, scope) => {
8543
+ if (n.type === "ImportExpression") {
8544
+ const spec = literalString(n.source);
8545
+ if (spec) out.push(spec);
8546
+ return;
8547
+ }
8548
+ if (n.type === "Property") considerReference(n.value, scope);
8549
+ },
8550
+ shadowed
8551
+ );
8552
+ for (const binding of referenced) {
8553
+ out.push(
8554
+ ...collectImportSpecs(
8555
+ binding,
8556
+ objectBindings,
8557
+ /* @__PURE__ */ new Set(),
8558
+ visitedBindings
8559
+ )
8560
+ );
8561
+ }
8326
8562
  return out;
8327
8563
  };
8328
- var matchPathObject = (node) => {
8564
+ var matchPathObject = (node, objectBindings = /* @__PURE__ */ new Map(), shadowed = /* @__PURE__ */ new Set()) => {
8329
8565
  if (node.type !== "ObjectExpression") return;
8330
8566
  let root;
8331
8567
  const siblingValues = [];
@@ -8337,7 +8573,9 @@ var matchPathObject = (node) => {
8337
8573
  else siblingValues.push(prop.value);
8338
8574
  }
8339
8575
  if (!root) return;
8340
- const specs = siblingValues.flatMap(collectImportSpecs);
8576
+ const specs = siblingValues.flatMap(
8577
+ (value) => collectImportSpecs(value, objectBindings, shadowed)
8578
+ );
8341
8579
  if (specs.length === 0) return;
8342
8580
  return { root, specs };
8343
8581
  };
@@ -8359,6 +8597,17 @@ var matchRouteDict = (node) => {
8359
8597
  }
8360
8598
  return pairs;
8361
8599
  };
8600
+ var findRouteImports = (ast) => {
8601
+ const tasks = [];
8602
+ const objectBindings = collectTopLevelObjectBindings(ast);
8603
+ walk(ast, (node, shadowed) => {
8604
+ const a = matchPathObject(node, objectBindings, shadowed);
8605
+ if (a) for (const spec of a.specs) tasks.push({ spec, root: a.root });
8606
+ const b = matchRouteDict(node);
8607
+ if (b) for (const { spec, root } of b) tasks.push({ spec, root });
8608
+ });
8609
+ return tasks;
8610
+ };
8362
8611
  var protectedAnnotatorPlugin = () => ({
8363
8612
  name: "zudoku:protected-annotator",
8364
8613
  buildStart() {
@@ -8376,14 +8625,7 @@ var protectedAnnotatorPlugin = () => ({
8376
8625
  );
8377
8626
  return;
8378
8627
  }
8379
- const tasks = [];
8380
- walk(ast, (node) => {
8381
- const a = matchPathObject(node);
8382
- if (a) for (const spec of a.specs) tasks.push({ spec, root: a.root });
8383
- const b = matchRouteDict(node);
8384
- if (b) for (const { spec, root } of b) tasks.push({ spec, root });
8385
- });
8386
- for (const { spec, root } of tasks) {
8628
+ for (const { spec, root } of findRouteImports(ast)) {
8387
8629
  const resolved = await this.resolve(spec, id);
8388
8630
  if (!resolved || resolved.external) {
8389
8631
  this.warn(
@@ -8404,6 +8646,19 @@ var getAppClientEntryPath = () => path18.posix.join(getZudokuRootDir(), "src/app
8404
8646
  var getAppServerEntryPath = () => path18.posix.join(getZudokuRootDir(), "src/app/entry.server.tsx");
8405
8647
  var hasLoggedCdnInfo = false;
8406
8648
  var MEDIA_REGEX = /\.(a?png|jpe?g|gif|bmp|svg|webp|tiff|ico|webm|ogg|mp3|wav|m4a|avif|mp4)/i;
8649
+ var getDepScanEntries = () => {
8650
+ const src = path18.posix.join(getZudokuRootDir(), "src");
8651
+ return [
8652
+ `${src}/{app,lib}/**/*.{ts,tsx}`,
8653
+ // Client-environment scan: `entry.server.tsx` imports
8654
+ // `virtual:zudoku-markdown-files`, which only the `ssr` environment
8655
+ // provides. Including it fails the scan and disables pre-bundling entirely.
8656
+ `!${getAppServerEntryPath()}`,
8657
+ // Not published, but present in the monorepo — keeps local dev scanning the
8658
+ // same file set an installed site does (and out of vitest's dependencies).
8659
+ `!${src}/**/*.test.*`
8660
+ ];
8661
+ };
8407
8662
  var defineEnvVars = (vars) => Object.fromEntries(
8408
8663
  vars.flatMap((v) => [
8409
8664
  [`process.env.${v}`, JSON.stringify(process.env[v])],
@@ -8551,7 +8806,7 @@ async function getViteConfig(dir, configEnv, options = {}) {
8551
8806
  }
8552
8807
  },
8553
8808
  optimizeDeps: {
8554
- entries: [path18.posix.join(getZudokuRootDir(), "src/{app,lib}/**")],
8809
+ entries: getDepScanEntries(),
8555
8810
  exclude: ["zudoku"],
8556
8811
  include: [
8557
8812
  "@mdx-js/react",
@@ -9715,6 +9970,34 @@ var assertCloudflareWranglerGatesProtected = async (dir, config) => {
9715
9970
 
9716
9971
  // src/vite/build.ts
9717
9972
  var DIST_DIR = "dist";
9973
+ var getEagerCssEntries = (output) => {
9974
+ const cssAssets = output.filter((item) => item.fileName.endsWith(".css")).map((item) => item.fileName);
9975
+ const chunksByFileName = new Map(
9976
+ output.filter((item) => item.type === "chunk").map((item) => [item.fileName, item])
9977
+ );
9978
+ const entryChunk = output.find(
9979
+ (item) => item.type === "chunk" && item.isEntry
9980
+ );
9981
+ if (!entryChunk) return cssAssets;
9982
+ const referencedCss = new Set(
9983
+ output.flatMap((item) => [...item.viteMetadata?.importedCss ?? []])
9984
+ );
9985
+ if (referencedCss.size === 0) return cssAssets;
9986
+ const eagerCss = /* @__PURE__ */ new Set();
9987
+ const visitedChunks = /* @__PURE__ */ new Set();
9988
+ const visitChunk = (fileName) => {
9989
+ if (visitedChunks.has(fileName)) return;
9990
+ visitedChunks.add(fileName);
9991
+ const chunk = chunksByFileName.get(fileName);
9992
+ if (!chunk) return;
9993
+ chunk.viteMetadata?.importedCss.forEach((css) => eagerCss.add(css));
9994
+ chunk.imports?.forEach(visitChunk);
9995
+ };
9996
+ visitChunk(entryChunk.fileName);
9997
+ return cssAssets.filter(
9998
+ (css) => eagerCss.has(css) || !referencedCss.has(css)
9999
+ );
10000
+ };
9718
10001
  async function runBuild(options) {
9719
10002
  const { dir, ssr, adapter = "node" } = options;
9720
10003
  const viteConfig = await getViteConfig(
@@ -9751,12 +10034,18 @@ async function runBuild(options) {
9751
10034
  const serverOutDir = viteConfig.environments?.ssr?.build?.outDir;
9752
10035
  invariant(clientOutDir, "Client build outDir is missing");
9753
10036
  invariant(serverOutDir, "Server build outDir is missing");
9754
- const jsEntry = clientResult.output.find(
10037
+ const jsEntryChunk = clientResult.output.find(
9755
10038
  (o) => "isEntry" in o && o.isEntry
9756
- )?.fileName;
9757
- const cssEntries = clientResult.output.filter((o) => o.fileName.endsWith(".css")).map((o) => o.fileName);
9758
- if (!jsEntry || cssEntries.length === 0) {
9759
- throw new Error("Build failed. No js or css assets found");
10039
+ );
10040
+ const jsEntry = jsEntryChunk?.fileName;
10041
+ const cssEntries = getEagerCssEntries(clientResult.output);
10042
+ if (!jsEntry) {
10043
+ throw new Error("Build failed. No js entry chunk found");
10044
+ }
10045
+ if (cssEntries.length === 0) {
10046
+ throw new Error(
10047
+ "Build failed. No stylesheet reachable from the eager entry chunk was found"
10048
+ );
9760
10049
  }
9761
10050
  const html = getBuildHtml({
9762
10051
  jsEntry: joinUrl(base, jsEntry),
@@ -1119,6 +1119,7 @@ var IconNames = [
1119
1119
  "layers-plus",
1120
1120
  "layout",
1121
1121
  "layout-dashboard",
1122
+ "layout-freeform",
1122
1123
  "layout-grid",
1123
1124
  "layout-list",
1124
1125
  "layout-panel-left",
@@ -1262,7 +1263,9 @@ var IconNames = [
1262
1263
  "metronome",
1263
1264
  "mic",
1264
1265
  "mic-2",
1266
+ "mic-audio-lines",
1265
1267
  "mic-off",
1268
+ "mic-signal",
1266
1269
  "mic-vocal",
1267
1270
  "microchip",
1268
1271
  "microscope",
@@ -1295,6 +1298,7 @@ var IconNames = [
1295
1298
  "moon-star",
1296
1299
  "more-horizontal",
1297
1300
  "more-vertical",
1301
+ "mosque",
1298
1302
  "motorbike",
1299
1303
  "mountain",
1300
1304
  "mountain-snow",
@@ -1547,9 +1551,11 @@ var IconNames = [
1547
1551
  "rotate-3-d",
1548
1552
  "rotate-3d",
1549
1553
  "rotate-ccw",
1554
+ "rotate-ccw-clock",
1550
1555
  "rotate-ccw-key",
1551
1556
  "rotate-ccw-square",
1552
1557
  "rotate-cw",
1558
+ "rotate-cw-fading-clock",
1553
1559
  "rotate-cw-square",
1554
1560
  "route",
1555
1561
  "route-off",
@@ -1587,6 +1593,7 @@ var IconNames = [
1587
1593
  "scan-line",
1588
1594
  "scan-qr-code",
1589
1595
  "scan-search",
1596
+ "scan-square",
1590
1597
  "scan-text",
1591
1598
  "scatter-chart",
1592
1599
  "school",
@@ -1756,6 +1763,7 @@ var IconNames = [
1756
1763
  "square-menu",
1757
1764
  "square-minus",
1758
1765
  "square-mouse-pointer",
1766
+ "square-off",
1759
1767
  "square-parking",
1760
1768
  "square-parking-off",
1761
1769
  "square-pause",
@@ -1984,6 +1992,7 @@ var IconNames = [
1984
1992
  "user-round-search",
1985
1993
  "user-round-x",
1986
1994
  "user-search",
1995
+ "user-shield",
1987
1996
  "user-square",
1988
1997
  "user-square-2",
1989
1998
  "user-star",
@@ -2456,6 +2465,7 @@ var LogoSchema = z4.object({
2456
2465
  src: z4.object({ light: z4.string(), dark: z4.string() }),
2457
2466
  alt: z4.string().optional(),
2458
2467
  width: z4.string().or(z4.number()).optional(),
2468
+ height: z4.string().or(z4.number()).optional(),
2459
2469
  href: z4.string().optional(),
2460
2470
  reloadDocument: z4.boolean().optional()
2461
2471
  });