@farm.js/core 0.1.0-beta.5 → 0.1.0-beta.7

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 (149) hide show
  1. package/dist/agent-runtime.d.mts +2 -2
  2. package/dist/agent-runtime.d.ts +2 -2
  3. package/dist/api/route-manager.d.mts +3 -3
  4. package/dist/api/route-manager.d.ts +3 -3
  5. package/dist/api.d.mts +3 -3
  6. package/dist/api.d.ts +3 -3
  7. package/dist/{app-CakAr8Be.d.mts → app-BWtqQu3R.d.mts} +6 -4
  8. package/dist/app-markdown.cjs +31 -7
  9. package/dist/app-markdown.cjs.map +1 -1
  10. package/dist/app-markdown.d.mts +2 -2
  11. package/dist/app-markdown.d.ts +2 -2
  12. package/dist/app-markdown.mjs +2 -1
  13. package/dist/{app-BjN-da13.d.ts → app-xltejvLY.d.ts} +6 -4
  14. package/dist/{chunk-A2LUXHD2.mjs → chunk-5VYHFKWE.mjs} +214 -58
  15. package/dist/chunk-5VYHFKWE.mjs.map +1 -0
  16. package/dist/{chunk-EEABSBKK.mjs → chunk-6F5OI5GA.mjs} +2 -2
  17. package/dist/chunk-6F5OI5GA.mjs.map +1 -0
  18. package/dist/{chunk-LLC7BNXW.mjs → chunk-7FBJLMQH.mjs} +73 -10
  19. package/dist/chunk-7FBJLMQH.mjs.map +1 -0
  20. package/dist/{chunk-NM3CRAAL.mjs → chunk-B4W3BNTL.mjs} +24 -8
  21. package/dist/chunk-B4W3BNTL.mjs.map +1 -0
  22. package/dist/{chunk-BHG3LVHH.mjs → chunk-CGIXMLSY.mjs} +15 -7
  23. package/dist/chunk-CGIXMLSY.mjs.map +1 -0
  24. package/dist/{chunk-C3DLZMBU.mjs → chunk-DJSGLHCN.mjs} +2 -2
  25. package/dist/{chunk-2NHCNRF6.mjs → chunk-GFMBXLGP.mjs} +56 -20
  26. package/dist/chunk-GFMBXLGP.mjs.map +1 -0
  27. package/dist/chunk-I4CUBGVF.mjs +93 -0
  28. package/dist/chunk-I4CUBGVF.mjs.map +1 -0
  29. package/dist/{chunk-HNIQFZKB.mjs → chunk-ME4MO2RJ.mjs} +27 -37
  30. package/dist/chunk-ME4MO2RJ.mjs.map +1 -0
  31. package/dist/{chunk-RSKVYESE.mjs → chunk-RQ633A5I.mjs} +1 -1
  32. package/dist/chunk-RQ633A5I.mjs.map +1 -0
  33. package/dist/{chunk-2CUKEMVR.mjs → chunk-WDU6QXNK.mjs} +1 -1
  34. package/dist/chunk-WDU6QXNK.mjs.map +1 -0
  35. package/dist/{chunk-QGQX7SFC.mjs → chunk-ZVWA4ZQ3.mjs} +17 -8
  36. package/dist/chunk-ZVWA4ZQ3.mjs.map +1 -0
  37. package/dist/{client-plugins-DQQ1adXM.d.mts → client-plugins-BI2R6Eae.d.mts} +74 -3
  38. package/dist/{client-plugins-Cw4qUGsw.d.ts → client-plugins-DU9oMspX.d.ts} +74 -3
  39. package/dist/client-plugins.d.mts +2 -2
  40. package/dist/client-plugins.d.ts +2 -2
  41. package/dist/client.cjs.map +1 -1
  42. package/dist/client.d.mts +2 -2
  43. package/dist/client.d.ts +2 -2
  44. package/dist/client.mjs +1 -1
  45. package/dist/config.d.mts +2 -2
  46. package/dist/config.d.ts +2 -2
  47. package/dist/{devtools-LVC3VB5P.mjs → devtools-REQTS3I7.mjs} +6 -5
  48. package/dist/{devtools-LVC3VB5P.mjs.map → devtools-REQTS3I7.mjs.map} +1 -1
  49. package/dist/docs.cjs +51 -56
  50. package/dist/docs.cjs.map +1 -1
  51. package/dist/docs.mjs +6 -5
  52. package/dist/env-types.cjs +14 -5
  53. package/dist/env-types.cjs.map +1 -1
  54. package/dist/env-types.d.mts +2 -1
  55. package/dist/env-types.d.ts +2 -1
  56. package/dist/env-types.mjs +3 -1
  57. package/dist/env.cjs.map +1 -1
  58. package/dist/env.d.mts +1 -1
  59. package/dist/env.d.ts +1 -1
  60. package/dist/env.mjs +1 -1
  61. package/dist/i18n/client.d.mts +2 -2
  62. package/dist/i18n/client.d.ts +2 -2
  63. package/dist/i18n/index.d.mts +3 -3
  64. package/dist/i18n/index.d.ts +3 -3
  65. package/dist/i18n/server.d.mts +5 -5
  66. package/dist/i18n/server.d.ts +5 -5
  67. package/dist/index.cjs +931 -567
  68. package/dist/index.cjs.map +1 -1
  69. package/dist/index.d.mts +15 -13
  70. package/dist/index.d.ts +15 -13
  71. package/dist/index.mjs +23 -16
  72. package/dist/index.mjs.map +1 -1
  73. package/dist/integrations.d.mts +2 -2
  74. package/dist/integrations.d.ts +2 -2
  75. package/dist/internal/build-runtime.cjs +643 -322
  76. package/dist/internal/build-runtime.cjs.map +1 -1
  77. package/dist/internal/build-runtime.d.mts +4 -4
  78. package/dist/internal/build-runtime.d.ts +4 -4
  79. package/dist/internal/build-runtime.mjs +11 -10
  80. package/dist/internal/config-runtime.cjs +135 -39
  81. package/dist/internal/config-runtime.cjs.map +1 -1
  82. package/dist/internal/config-runtime.d.mts +3 -3
  83. package/dist/internal/config-runtime.d.ts +3 -3
  84. package/dist/internal/config-runtime.mjs +5 -4
  85. package/dist/internal/production-runtime.d.mts +6 -6
  86. package/dist/internal/production-runtime.d.ts +6 -6
  87. package/dist/markdown.cjs +73 -8
  88. package/dist/markdown.cjs.map +1 -1
  89. package/dist/markdown.d.mts +19 -2
  90. package/dist/markdown.d.ts +19 -2
  91. package/dist/markdown.mjs +5 -1
  92. package/dist/{metadata-BAPg_Nmo.d.ts → metadata-Cm9ujH4I.d.ts} +1 -1
  93. package/dist/{metadata-_6i9oFG3.d.mts → metadata-DacXbnLA.d.mts} +1 -1
  94. package/dist/middleware.d.mts +4 -4
  95. package/dist/middleware.d.ts +4 -4
  96. package/dist/plugin.cjs +679 -434
  97. package/dist/plugin.cjs.map +1 -1
  98. package/dist/plugin.d.mts +2 -2
  99. package/dist/plugin.d.ts +2 -2
  100. package/dist/plugin.mjs +8 -7
  101. package/dist/{production-runtime-DPfgMV9Y.d.mts → production-runtime-4KKq1AVC.d.mts} +2 -2
  102. package/dist/{production-runtime-BoJDc5mc.d.ts → production-runtime-DRsWDN2x.d.ts} +2 -2
  103. package/dist/{request-BrFBuc8G.d.mts → request-Dsq4kGW0.d.mts} +1 -1
  104. package/dist/{request-BslSZIRz.d.ts → request-udtobOLv.d.ts} +1 -1
  105. package/dist/request.d.mts +2 -2
  106. package/dist/request.d.ts +2 -2
  107. package/dist/{resolver-DlOPpjkB.d.mts → resolver-DJqjLMg_.d.mts} +1 -1
  108. package/dist/{resolver-C6iecsDV.d.ts → resolver-IH4RmPEl.d.ts} +1 -1
  109. package/dist/routes.d.mts +2 -2
  110. package/dist/routes.d.ts +2 -2
  111. package/dist/{runtime-DeAAZ6gO.d.mts → runtime-Cxpq6xZN.d.mts} +2 -2
  112. package/dist/{runtime-B6GvwDS1.d.ts → runtime-bv63eUiO.d.ts} +2 -2
  113. package/dist/server-plugins.d.mts +3 -3
  114. package/dist/server-plugins.d.ts +3 -3
  115. package/dist/server.cjs +731 -447
  116. package/dist/server.cjs.map +1 -1
  117. package/dist/server.d.mts +9 -9
  118. package/dist/server.d.ts +9 -9
  119. package/dist/server.mjs +9 -8
  120. package/dist/server.mjs.map +1 -1
  121. package/dist/testing.d.mts +2 -2
  122. package/dist/testing.d.ts +2 -2
  123. package/dist/{types-BH1lhg5G.d.mts → types-BMxWr97v.d.mts} +2 -2
  124. package/dist/{types-BH1lhg5G.d.ts → types-BMxWr97v.d.ts} +2 -2
  125. package/dist/{utils-Drsyz1Vj.d.ts → utils-B-cUHwoK.d.ts} +1 -1
  126. package/dist/{utils-CHXlMDkg.d.mts → utils-Cm41AefV.d.mts} +1 -1
  127. package/dist/version.cjs +1 -1
  128. package/dist/version.cjs.map +1 -1
  129. package/dist/version.mjs +1 -1
  130. package/dist/vite.cjs +682 -437
  131. package/dist/vite.cjs.map +1 -1
  132. package/dist/vite.d.mts +2 -2
  133. package/dist/vite.d.ts +2 -2
  134. package/dist/vite.mjs +6 -5
  135. package/package.json +3 -2
  136. package/types/client.d.ts +1 -1
  137. package/types/image.d.ts +4 -0
  138. package/types/images.d.ts +59 -0
  139. package/dist/chunk-2CUKEMVR.mjs.map +0 -1
  140. package/dist/chunk-2NHCNRF6.mjs.map +0 -1
  141. package/dist/chunk-A2LUXHD2.mjs.map +0 -1
  142. package/dist/chunk-BHG3LVHH.mjs.map +0 -1
  143. package/dist/chunk-EEABSBKK.mjs.map +0 -1
  144. package/dist/chunk-HNIQFZKB.mjs.map +0 -1
  145. package/dist/chunk-LLC7BNXW.mjs.map +0 -1
  146. package/dist/chunk-NM3CRAAL.mjs.map +0 -1
  147. package/dist/chunk-QGQX7SFC.mjs.map +0 -1
  148. package/dist/chunk-RSKVYESE.mjs.map +0 -1
  149. /package/dist/{chunk-C3DLZMBU.mjs.map → chunk-DJSGLHCN.mjs.map} +0 -0
package/dist/index.cjs CHANGED
@@ -673,13 +673,13 @@ function defineIntegrationAPI(api3) {
673
673
  }
674
674
  function operation(method, pathOrOptions, maybeOptions = {}) {
675
675
  const hasExplicitPath = typeof pathOrOptions === "string";
676
- const path28 = hasExplicitPath ? pathOrOptions : "";
676
+ const path29 = hasExplicitPath ? pathOrOptions : "";
677
677
  const options = hasExplicitPath ? maybeOptions : {
678
678
  ...maybeOptions,
679
679
  ...pathOrOptions
680
680
  };
681
681
  return defineIntegrationAPIOperation({
682
- path: path28,
682
+ path: path29,
683
683
  method,
684
684
  __pathless: !hasExplicitPath,
685
685
  ...options
@@ -691,26 +691,26 @@ function get(pathOrOptions, maybeOptions = {}) {
691
691
  function isOperation(value) {
692
692
  return !!value && typeof value === "object" && value.kind === "farm-integration-api-operation";
693
693
  }
694
- function bindRoutePath(path28, api3) {
694
+ function bindRoutePath(path29, api3) {
695
695
  const entries = Object.entries(api3).map(([key, value]) => {
696
696
  if (isOperation(value)) {
697
697
  return [
698
698
  key,
699
699
  {
700
700
  ...value,
701
- path: path28,
701
+ path: path29,
702
702
  __pathless: false
703
703
  }
704
704
  ];
705
705
  }
706
706
  if (value && typeof value === "object") {
707
- return [key, bindRoutePath(path28, value)];
707
+ return [key, bindRoutePath(path29, value)];
708
708
  }
709
709
  return [key, value];
710
710
  });
711
711
  return Object.fromEntries(entries);
712
712
  }
713
- function route(path28, definitionOrOperation, ...operations) {
713
+ function route(path29, definitionOrOperation, ...operations) {
714
714
  if (isOperation(definitionOrOperation)) {
715
715
  const allOperations = [definitionOrOperation, ...operations];
716
716
  return Object.fromEntries(
@@ -718,13 +718,13 @@ function route(path28, definitionOrOperation, ...operations) {
718
718
  operation2.method.toLowerCase(),
719
719
  {
720
720
  ...operation2,
721
- path: path28,
721
+ path: path29,
722
722
  __pathless: false
723
723
  }
724
724
  ])
725
725
  );
726
726
  }
727
- return bindRoutePath(path28, definitionOrOperation);
727
+ return bindRoutePath(path29, definitionOrOperation);
728
728
  }
729
729
  function normalizeRouteSegment(segment) {
730
730
  if (!segment) {
@@ -745,8 +745,8 @@ function normalizeRouteSegment(segment) {
745
745
  function camelCaseRouteSegment(segment) {
746
746
  return segment.replace(/-([a-zA-Z0-9])/g, (_match, value) => value.toUpperCase());
747
747
  }
748
- function getRouteClientSegments(path28) {
749
- const segments = path28.split("/").filter(Boolean);
748
+ function getRouteClientSegments(path29) {
749
+ const segments = path29.split("/").filter(Boolean);
750
750
  if (segments.length === 0) {
751
751
  return ["index"];
752
752
  }
@@ -1156,9 +1156,9 @@ function getFarmIntegrationPluginServerRuntime(plugin) {
1156
1156
  const value = plugin[FARM_INTEGRATION_PLUGIN_SERVER_RUNTIME];
1157
1157
  return typeof value === "boolean" ? value : void 0;
1158
1158
  }
1159
- function defineTypedIntegrationRoute(method, path28, input) {
1159
+ function defineTypedIntegrationRoute(method, path29, input) {
1160
1160
  return {
1161
- path: path28,
1161
+ path: path29,
1162
1162
  method,
1163
1163
  middleware: input.middleware,
1164
1164
  before: input.before,
@@ -1168,7 +1168,7 @@ function defineTypedIntegrationRoute(method, path28, input) {
1168
1168
  input: normalizeIntegrationRouteInputSchemas(input),
1169
1169
  handler: input.handler,
1170
1170
  __operation: defineIntegrationAPIOperation({
1171
- path: path28,
1171
+ path: path29,
1172
1172
  method,
1173
1173
  bodyFormat: input.bodyFormat,
1174
1174
  responseFormat: input.responseFormat,
@@ -1180,52 +1180,52 @@ function defineTypedIntegrationRoute(method, path28, input) {
1180
1180
  }
1181
1181
  function createIntegrationRouteFactory() {
1182
1182
  return {
1183
- get(path28, input) {
1183
+ get(path29, input) {
1184
1184
  return defineTypedIntegrationRoute(
1185
1185
  "GET",
1186
- path28,
1186
+ path29,
1187
1187
  input
1188
1188
  );
1189
1189
  },
1190
- post(path28, input) {
1190
+ post(path29, input) {
1191
1191
  return defineTypedIntegrationRoute(
1192
1192
  "POST",
1193
- path28,
1193
+ path29,
1194
1194
  {
1195
1195
  bodyFormat: "json",
1196
1196
  ...input
1197
1197
  }
1198
1198
  );
1199
1199
  },
1200
- put(path28, input) {
1200
+ put(path29, input) {
1201
1201
  return defineTypedIntegrationRoute(
1202
1202
  "PUT",
1203
- path28,
1203
+ path29,
1204
1204
  {
1205
1205
  bodyFormat: "json",
1206
1206
  ...input
1207
1207
  }
1208
1208
  );
1209
1209
  },
1210
- patch(path28, input) {
1211
- return defineTypedIntegrationRoute("PATCH", path28, {
1210
+ patch(path29, input) {
1211
+ return defineTypedIntegrationRoute("PATCH", path29, {
1212
1212
  bodyFormat: "json",
1213
1213
  ...input
1214
1214
  });
1215
1215
  },
1216
- delete(path28, input) {
1217
- return defineTypedIntegrationRoute("DELETE", path28, {
1216
+ delete(path29, input) {
1217
+ return defineTypedIntegrationRoute("DELETE", path29, {
1218
1218
  bodyFormat: "json",
1219
1219
  ...input
1220
1220
  });
1221
1221
  },
1222
- options(path28, input) {
1223
- return defineTypedIntegrationRoute("OPTIONS", path28, input);
1222
+ options(path29, input) {
1223
+ return defineTypedIntegrationRoute("OPTIONS", path29, input);
1224
1224
  },
1225
- head(path28, input) {
1225
+ head(path29, input) {
1226
1226
  return defineTypedIntegrationRoute(
1227
1227
  "HEAD",
1228
- path28,
1228
+ path29,
1229
1229
  input
1230
1230
  );
1231
1231
  }
@@ -1515,8 +1515,8 @@ async function parseIntegrationConfigSchema(integration, schema, value) {
1515
1515
  function createIntegrationConfigValidationError(integration, error) {
1516
1516
  const issues = Array.isArray(error.issues) && error.issues.length > 0 ? error.issues.map((issue) => {
1517
1517
  const normalizedPath = normalizeIntegrationValidationPath(issue.path);
1518
- const path28 = normalizedPath.length ? `${normalizedPath.join(".")}: ` : "";
1519
- return `${path28}${issue.message || "Invalid config"}`;
1518
+ const path29 = normalizedPath.length ? `${normalizedPath.join(".")}: ` : "";
1519
+ return `${path29}${issue.message || "Invalid config"}`;
1520
1520
  }).join("; ") : error.message || "Invalid config";
1521
1521
  return new Error(`Integration "${integration.type}" config validation failed: ${issues}`);
1522
1522
  }
@@ -2201,8 +2201,8 @@ function normalizeIntegrationValidationIssues(source, error) {
2201
2201
  }
2202
2202
  ];
2203
2203
  }
2204
- function normalizeIntegrationValidationPath(path28) {
2205
- return (path28 || []).map((segment) => {
2204
+ function normalizeIntegrationValidationPath(path29) {
2205
+ return (path29 || []).map((segment) => {
2206
2206
  const key = typeof segment === "object" && segment !== null && "key" in segment ? segment.key : segment;
2207
2207
  return typeof key === "symbol" ? key.description || key.toString() : key;
2208
2208
  });
@@ -2853,13 +2853,13 @@ function getRequestId(req) {
2853
2853
  return headerValue || String(Date.now());
2854
2854
  }
2855
2855
  async function readRequestBody(req) {
2856
- return await new Promise((resolve5, reject) => {
2856
+ return await new Promise((resolve6, reject) => {
2857
2857
  const chunks = [];
2858
2858
  req.on("data", (chunk) => {
2859
2859
  chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
2860
2860
  });
2861
2861
  req.on("end", () => {
2862
- resolve5(Buffer.concat(chunks));
2862
+ resolve6(Buffer.concat(chunks));
2863
2863
  });
2864
2864
  req.on("error", reject);
2865
2865
  });
@@ -2965,178 +2965,9 @@ var init_integrations = __esm({
2965
2965
  }
2966
2966
  });
2967
2967
 
2968
- // src/app-markdown.ts
2969
- function resolveMdxConfig(config) {
2970
- return {
2971
- components: config?.components,
2972
- markdownRoutes: config?.markdownRoutes ?? true,
2973
- className: config?.className ?? "farm-markdown"
2974
- };
2975
- }
2976
- function isFarmMarkdownPageFile(filePath) {
2977
- return /(^|[/\\])page\.mdx?$/i.test(filePath);
2978
- }
2979
- function normalizeFarmMarkdownRoutePath(pathname) {
2980
- const withoutExtension = pathname.replace(/\.md$/i, "");
2981
- const normalized = withoutExtension.startsWith("/") ? withoutExtension : `/${withoutExtension}`;
2982
- return normalized === "/index" ? "/" : normalized.replace(/\/+$/g, "") || "/";
2983
- }
2984
- function parseMarkdownFrontmatter(source) {
2985
- if (!source.startsWith("---")) {
2986
- return { frontmatter: {}, body: source };
2987
- }
2988
- const endIndex = source.indexOf("\n---", 3);
2989
- if (endIndex === -1) {
2990
- return { frontmatter: {}, body: source };
2991
- }
2992
- const frontmatterSource = source.slice(3, endIndex).trim();
2993
- const closingFenceEnd = endIndex + "\n---".length;
2994
- const bodyStart = source.slice(closingFenceEnd, closingFenceEnd + 2) === "\r\n" ? closingFenceEnd + 2 : source[closingFenceEnd] === "\n" ? closingFenceEnd + 1 : closingFenceEnd;
2995
- const body = source.slice(bodyStart);
2996
- const frontmatter = {};
2997
- for (const line of frontmatterSource.split(/\r?\n/)) {
2998
- const separator = line.indexOf(":");
2999
- if (separator === -1) continue;
3000
- const key = line.slice(0, separator).trim();
3001
- const value = line.slice(separator + 1).trim().replace(/^["']|["']$/g, "");
3002
- if (key && value) frontmatter[key] = value;
3003
- }
3004
- return { frontmatter, body };
3005
- }
3006
- function titleFromMarkdown(body, fallback) {
3007
- return body.match(/^#\s+(.+)$/m)?.[1]?.trim() || fallback;
3008
- }
3009
- function createMarkdownMetadata(source, filePath) {
3010
- const { frontmatter, body } = parseMarkdownFrontmatter(source);
3011
- const routeTitle = titleFromMarkdown(body);
3012
- const title = frontmatter.title || routeTitle;
3013
- const description = frontmatter.description;
3014
- if (!title && !description) {
3015
- return void 0;
3016
- }
3017
- return {
3018
- ...title ? { title } : {},
3019
- ...description ? { description } : {},
3020
- source: filePath
3021
- };
3022
- }
3023
- async function evaluateMdxSource(source, filePath) {
3024
- const [{ evaluate }, runtime, remarkGfmModule] = await Promise.all([
3025
- import("@mdx-js/mdx"),
3026
- import("react/jsx-runtime"),
3027
- import("remark-gfm")
3028
- ]);
3029
- const remarkGfm = remarkGfmModule.default;
3030
- return evaluate(source, {
3031
- ...runtime,
3032
- baseUrl: (0, import_url.pathToFileURL)(filePath),
3033
- remarkPlugins: [remarkGfm]
3034
- });
3035
- }
3036
- function createFarmMarkdownRouteModule(input) {
3037
- const { body } = parseMarkdownFrontmatter(input.source);
3038
- const components = input.components || {};
3039
- const className = input.config?.className || "farm-markdown";
3040
- let evaluatedPromise;
3041
- const loadContent = /* @__PURE__ */ __name(async () => {
3042
- evaluatedPromise ?? (evaluatedPromise = evaluateMdxSource(body, input.filePath));
3043
- return evaluatedPromise;
3044
- }, "loadContent");
3045
- async function FarmMarkdownPage(props) {
3046
- const evaluated = await loadContent();
3047
- const MDXContent = evaluated.default;
3048
- return import_react.default.createElement(
3049
- "article",
3050
- { className, "data-farm-markdown-page": "" },
3051
- import_react.default.createElement(MDXContent, {
3052
- ...props,
3053
- components: {
3054
- ...components,
3055
- ...props?.components
3056
- }
3057
- })
3058
- );
3059
- }
3060
- __name(FarmMarkdownPage, "FarmMarkdownPage");
3061
- return {
3062
- default: FarmMarkdownPage,
3063
- metadata: createMarkdownMetadata(input.source, input.filePath),
3064
- source: input.source
3065
- };
3066
- }
3067
- async function createFarmMarkdownRouteModuleFromFile(filePath, options = {}) {
3068
- const source = await (0, import_promises.readFile)(filePath, "utf8");
3069
- return createFarmMarkdownRouteModule({
3070
- source,
3071
- filePath,
3072
- components: options.components,
3073
- config: options.config
3074
- });
3075
- }
3076
- async function loadFarmMdxComponents(config, options) {
3077
- const configured = config?.components;
3078
- if (!configured) {
3079
- return {};
3080
- }
3081
- if (typeof configured !== "string") {
3082
- return configured;
3083
- }
3084
- const modulePath = import_path2.default.isAbsolute(configured) ? configured : import_path2.default.join(options.root, configured);
3085
- const mod = options.loadModule ? await options.loadModule(modulePath) : await import((0, import_url.pathToFileURL)(modulePath).href);
3086
- const maybeModule = mod;
3087
- return maybeModule.components || maybeModule.default || {};
3088
- }
3089
- async function createFarmMarkdownSourceResponse(options) {
3090
- if (options.request.method !== "GET" && options.request.method !== "HEAD") {
3091
- return null;
3092
- }
3093
- if (options.config?.markdownRoutes === false) {
3094
- return null;
3095
- }
3096
- const url = new URL(options.request.url);
3097
- if (!url.pathname.endsWith(".md")) {
3098
- return null;
3099
- }
3100
- const targetPathname = normalizeFarmMarkdownRoutePath(url.pathname);
3101
- const source = await options.resolveSource(targetPathname);
3102
- if (!source) {
3103
- return null;
3104
- }
3105
- return new Response(options.request.method === "HEAD" ? null : source.source, {
3106
- status: 200,
3107
- headers: {
3108
- "Content-Type": "text/markdown; charset=utf-8",
3109
- "Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
3110
- "X-Farm-Markdown-Route": targetPathname,
3111
- "X-Farm-Markdown-Source": source.filePath
3112
- }
3113
- });
3114
- }
3115
- var import_react, import_promises, import_path2, import_url;
3116
- var init_app_markdown = __esm({
3117
- "src/app-markdown.ts"() {
3118
- "use strict";
3119
- import_react = __toESM(require("react"));
3120
- import_promises = require("fs/promises");
3121
- import_path2 = __toESM(require("path"));
3122
- import_url = require("url");
3123
- __name(resolveMdxConfig, "resolveMdxConfig");
3124
- __name(isFarmMarkdownPageFile, "isFarmMarkdownPageFile");
3125
- __name(normalizeFarmMarkdownRoutePath, "normalizeFarmMarkdownRoutePath");
3126
- __name(parseMarkdownFrontmatter, "parseMarkdownFrontmatter");
3127
- __name(titleFromMarkdown, "titleFromMarkdown");
3128
- __name(createMarkdownMetadata, "createMarkdownMetadata");
3129
- __name(evaluateMdxSource, "evaluateMdxSource");
3130
- __name(createFarmMarkdownRouteModule, "createFarmMarkdownRouteModule");
3131
- __name(createFarmMarkdownRouteModuleFromFile, "createFarmMarkdownRouteModuleFromFile");
3132
- __name(loadFarmMdxComponents, "loadFarmMdxComponents");
3133
- __name(createFarmMarkdownSourceResponse, "createFarmMarkdownSourceResponse");
3134
- }
3135
- });
3136
-
3137
2968
  // src/markdown.ts
3138
2969
  function resolveMarkdownConfig(config) {
3139
- if (config === false || config === void 0) {
2970
+ if (config === false) {
3140
2971
  return {
3141
2972
  enabled: false,
3142
2973
  expose: [],
@@ -3144,7 +2975,7 @@ function resolveMarkdownConfig(config) {
3144
2975
  includeMetadata: true
3145
2976
  };
3146
2977
  }
3147
- if (config === true) {
2978
+ if (config === true || config === void 0) {
3148
2979
  return {
3149
2980
  enabled: true,
3150
2981
  expose: true,
@@ -3152,7 +2983,7 @@ function resolveMarkdownConfig(config) {
3152
2983
  includeMetadata: true
3153
2984
  };
3154
2985
  }
3155
- const exposeInput = config.expose ?? config.routes ?? [];
2986
+ const exposeInput = config.expose ?? config.routes ?? true;
3156
2987
  const expose = exposeInput === true ? true : Array.isArray(exposeInput) ? exposeInput.map(normalizeMarkdownRouteInput) : [];
3157
2988
  return {
3158
2989
  enabled: config.enabled !== false && (expose === true || expose.length > 0),
@@ -3161,11 +2992,14 @@ function resolveMarkdownConfig(config) {
3161
2992
  includeMetadata: config.includeMetadata ?? true
3162
2993
  };
3163
2994
  }
3164
- function resolveMarkdownMirrorTarget(config, pathname) {
3165
- if (!config?.enabled || !pathname.endsWith(".md")) {
2995
+ function resolveMarkdownMirrorTarget(config, pathname, options = {}) {
2996
+ const hasMarkdownExtension = pathname.toLowerCase().endsWith(".md");
2997
+ if (!config?.enabled || !hasMarkdownExtension && !requestAcceptsMarkdown(options.accept)) {
3166
2998
  return null;
3167
2999
  }
3168
- const targetPathname = normalizeMarkdownRoute(pathname.slice(0, -".md".length) || "/");
3000
+ const targetPathname = normalizeMarkdownRoute(
3001
+ hasMarkdownExtension ? pathname.slice(0, -".md".length) || "/" : pathname
3002
+ );
3169
3003
  const route2 = findExposedMarkdownRoute(config, targetPathname);
3170
3004
  if (!route2 && config.expose !== true) {
3171
3005
  return null;
@@ -3180,7 +3014,10 @@ async function createMarkdownMirrorResponse(options) {
3180
3014
  return null;
3181
3015
  }
3182
3016
  const requestUrl = new URL(options.request.url);
3183
- const target = resolveMarkdownMirrorTarget(options.config, requestUrl.pathname);
3017
+ const hasMarkdownExtension = requestUrl.pathname.toLowerCase().endsWith(".md");
3018
+ const target = resolveMarkdownMirrorTarget(options.config, requestUrl.pathname, {
3019
+ accept: options.request.headers.get("accept")
3020
+ });
3184
3021
  if (!target) {
3185
3022
  return null;
3186
3023
  }
@@ -3208,8 +3045,12 @@ async function createMarkdownMirrorResponse(options) {
3208
3045
  });
3209
3046
  const headersOut = new Headers({
3210
3047
  "Content-Type": "text/markdown; charset=utf-8",
3048
+ "Content-Location": target.pathname === "/" ? "/index.md" : `${target.pathname}.md`,
3211
3049
  "X-Farm-Markdown-Route": target.pathname
3212
3050
  });
3051
+ if (!hasMarkdownExtension) {
3052
+ headersOut.set("Vary", "Accept");
3053
+ }
3213
3054
  const cache = target.route?.cache ?? options.config?.cache ?? false;
3214
3055
  headersOut.set("Cache-Control", createMarkdownCacheHeader(cache));
3215
3056
  return new Response(options.request.method === "HEAD" ? null : markdown, {
@@ -3217,6 +3058,26 @@ async function createMarkdownMirrorResponse(options) {
3217
3058
  headers: headersOut
3218
3059
  });
3219
3060
  }
3061
+ function applyMarkdownNegotiationHeaders(response, options) {
3062
+ if (!isHtmlResponse(response)) {
3063
+ return response;
3064
+ }
3065
+ const target = resolveMarkdownMirrorTarget(options.config, options.pathname, {
3066
+ accept: "text/markdown"
3067
+ });
3068
+ if (!target) {
3069
+ return response;
3070
+ }
3071
+ const alternatePath = getMarkdownAlternatePath(target.pathname);
3072
+ const headers2 = new Headers(response.headers);
3073
+ appendHeaderToken(headers2, "Vary", "Accept");
3074
+ headers2.append("Link", `<${alternatePath}>; rel="alternate"; type="text/markdown"`);
3075
+ return new Response(response.body, {
3076
+ status: response.status,
3077
+ statusText: response.statusText,
3078
+ headers: headers2
3079
+ });
3080
+ }
3220
3081
  function htmlToMarkdown(html, options = {}) {
3221
3082
  const title = options.title ?? extractHtmlTitle(html);
3222
3083
  let source = extractHtmlBody(html).replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, "").replace(/<noscript\b[^>]*>[\s\S]*?<\/noscript>/gi, "").replace(/<!--[\s\S]*?-->/g, "");
@@ -3295,11 +3156,38 @@ function normalizeMarkdownRouteInput(input) {
3295
3156
  };
3296
3157
  }
3297
3158
  function normalizeMarkdownRoute(route2) {
3298
- const withoutMarkdownExtension = route2.endsWith(".md") ? route2.slice(0, -3) : route2;
3159
+ const withoutMarkdownExtension = route2.toLowerCase().endsWith(".md") ? route2.slice(0, -3) : route2;
3299
3160
  const withSlash = withoutMarkdownExtension.startsWith("/") ? withoutMarkdownExtension : `/${withoutMarkdownExtension}`;
3300
3161
  const normalized = withSlash.replace(/\/+/g, "/").replace(/\/$/g, "");
3301
3162
  return normalized === "" || normalized === "/index" ? "/" : normalized;
3302
3163
  }
3164
+ function requestAcceptsMarkdown(accept) {
3165
+ if (!accept) {
3166
+ return false;
3167
+ }
3168
+ return accept.split(",").some((entry) => {
3169
+ const [mediaType, ...parameters] = entry.trim().toLowerCase().split(";").map((part) => part.trim());
3170
+ if (mediaType !== "text/markdown") {
3171
+ return false;
3172
+ }
3173
+ const quality = parameters.find((parameter) => parameter.startsWith("q="));
3174
+ return quality === void 0 || Number(quality.slice(2)) > 0;
3175
+ });
3176
+ }
3177
+ function getMarkdownAlternatePath(pathname) {
3178
+ return pathname === "/" ? "/index.md" : `${pathname}.md`;
3179
+ }
3180
+ function appendHeaderToken(headers2, name, token) {
3181
+ const current = headers2.get(name);
3182
+ if (!current) {
3183
+ headers2.set(name, token);
3184
+ return;
3185
+ }
3186
+ const tokens = current.split(",").map((value) => value.trim().toLowerCase());
3187
+ if (!tokens.includes(token.toLowerCase())) {
3188
+ headers2.set(name, `${current}, ${token}`);
3189
+ }
3190
+ }
3303
3191
  function findExposedMarkdownRoute(config, pathname) {
3304
3192
  if (config.expose === true) {
3305
3193
  return null;
@@ -3387,9 +3275,13 @@ var init_markdown = __esm({
3387
3275
  __name(resolveMarkdownConfig, "resolveMarkdownConfig");
3388
3276
  __name(resolveMarkdownMirrorTarget, "resolveMarkdownMirrorTarget");
3389
3277
  __name(createMarkdownMirrorResponse, "createMarkdownMirrorResponse");
3278
+ __name(applyMarkdownNegotiationHeaders, "applyMarkdownNegotiationHeaders");
3390
3279
  __name(htmlToMarkdown, "htmlToMarkdown");
3391
3280
  __name(normalizeMarkdownRouteInput, "normalizeMarkdownRouteInput");
3392
3281
  __name(normalizeMarkdownRoute, "normalizeMarkdownRoute");
3282
+ __name(requestAcceptsMarkdown, "requestAcceptsMarkdown");
3283
+ __name(getMarkdownAlternatePath, "getMarkdownAlternatePath");
3284
+ __name(appendHeaderToken, "appendHeaderToken");
3393
3285
  __name(findExposedMarkdownRoute, "findExposedMarkdownRoute");
3394
3286
  __name(routeMatches, "routeMatches");
3395
3287
  __name(isHtmlResponse, "isHtmlResponse");
@@ -3403,6 +3295,182 @@ var init_markdown = __esm({
3403
3295
  }
3404
3296
  });
3405
3297
 
3298
+ // src/app-markdown.ts
3299
+ function resolveMdxConfig(config) {
3300
+ return {
3301
+ components: config?.components,
3302
+ markdownRoutes: config?.markdownRoutes ?? true,
3303
+ className: config?.className ?? "farm-markdown"
3304
+ };
3305
+ }
3306
+ function isFarmMarkdownPageFile(filePath) {
3307
+ return /(^|[/\\])page\.mdx?$/i.test(filePath);
3308
+ }
3309
+ function normalizeFarmMarkdownRoutePath(pathname) {
3310
+ const withoutExtension = pathname.replace(/\.md$/i, "");
3311
+ const normalized = withoutExtension.startsWith("/") ? withoutExtension : `/${withoutExtension}`;
3312
+ return normalized === "/index" ? "/" : normalized.replace(/\/+$/g, "") || "/";
3313
+ }
3314
+ function parseMarkdownFrontmatter(source) {
3315
+ if (!source.startsWith("---")) {
3316
+ return { frontmatter: {}, body: source };
3317
+ }
3318
+ const endIndex = source.indexOf("\n---", 3);
3319
+ if (endIndex === -1) {
3320
+ return { frontmatter: {}, body: source };
3321
+ }
3322
+ const frontmatterSource = source.slice(3, endIndex).trim();
3323
+ const closingFenceEnd = endIndex + "\n---".length;
3324
+ const bodyStart = source.slice(closingFenceEnd, closingFenceEnd + 2) === "\r\n" ? closingFenceEnd + 2 : source[closingFenceEnd] === "\n" ? closingFenceEnd + 1 : closingFenceEnd;
3325
+ const body = source.slice(bodyStart);
3326
+ const frontmatter = {};
3327
+ for (const line of frontmatterSource.split(/\r?\n/)) {
3328
+ const separator = line.indexOf(":");
3329
+ if (separator === -1) continue;
3330
+ const key = line.slice(0, separator).trim();
3331
+ const value = line.slice(separator + 1).trim().replace(/^["']|["']$/g, "");
3332
+ if (key && value) frontmatter[key] = value;
3333
+ }
3334
+ return { frontmatter, body };
3335
+ }
3336
+ function titleFromMarkdown(body, fallback) {
3337
+ return body.match(/^#\s+(.+)$/m)?.[1]?.trim() || fallback;
3338
+ }
3339
+ function createMarkdownMetadata(source, filePath) {
3340
+ const { frontmatter, body } = parseMarkdownFrontmatter(source);
3341
+ const routeTitle = titleFromMarkdown(body);
3342
+ const title = frontmatter.title || routeTitle;
3343
+ const description = frontmatter.description;
3344
+ if (!title && !description) {
3345
+ return void 0;
3346
+ }
3347
+ return {
3348
+ ...title ? { title } : {},
3349
+ ...description ? { description } : {},
3350
+ source: filePath
3351
+ };
3352
+ }
3353
+ async function evaluateMdxSource(source, filePath) {
3354
+ const [{ evaluate }, runtime, remarkGfmModule] = await Promise.all([
3355
+ import("@mdx-js/mdx"),
3356
+ import("react/jsx-runtime"),
3357
+ import("remark-gfm")
3358
+ ]);
3359
+ const remarkGfm = remarkGfmModule.default;
3360
+ return evaluate(source, {
3361
+ ...runtime,
3362
+ baseUrl: (0, import_url.pathToFileURL)(filePath),
3363
+ remarkPlugins: [remarkGfm]
3364
+ });
3365
+ }
3366
+ function createFarmMarkdownRouteModule(input) {
3367
+ const { body } = parseMarkdownFrontmatter(input.source);
3368
+ const components = input.components || {};
3369
+ const className = input.config?.className || "farm-markdown";
3370
+ let evaluatedPromise;
3371
+ const loadContent = /* @__PURE__ */ __name(async () => {
3372
+ evaluatedPromise ?? (evaluatedPromise = evaluateMdxSource(body, input.filePath));
3373
+ return evaluatedPromise;
3374
+ }, "loadContent");
3375
+ async function FarmMarkdownPage(props) {
3376
+ const evaluated = await loadContent();
3377
+ const MDXContent = evaluated.default;
3378
+ return import_react.default.createElement(
3379
+ "article",
3380
+ { className, "data-farm-markdown-page": "" },
3381
+ import_react.default.createElement(MDXContent, {
3382
+ ...props,
3383
+ components: {
3384
+ ...components,
3385
+ ...props?.components
3386
+ }
3387
+ })
3388
+ );
3389
+ }
3390
+ __name(FarmMarkdownPage, "FarmMarkdownPage");
3391
+ return {
3392
+ default: FarmMarkdownPage,
3393
+ metadata: createMarkdownMetadata(input.source, input.filePath),
3394
+ source: input.source
3395
+ };
3396
+ }
3397
+ async function createFarmMarkdownRouteModuleFromFile(filePath, options = {}) {
3398
+ const source = await (0, import_promises.readFile)(filePath, "utf8");
3399
+ return createFarmMarkdownRouteModule({
3400
+ source,
3401
+ filePath,
3402
+ components: options.components,
3403
+ config: options.config
3404
+ });
3405
+ }
3406
+ async function loadFarmMdxComponents(config, options) {
3407
+ const configured = config?.components;
3408
+ if (!configured) {
3409
+ return {};
3410
+ }
3411
+ if (typeof configured !== "string") {
3412
+ return configured;
3413
+ }
3414
+ const modulePath = import_path2.default.isAbsolute(configured) ? configured : import_path2.default.join(options.root, configured);
3415
+ const mod = options.loadModule ? await options.loadModule(modulePath) : await import((0, import_url.pathToFileURL)(modulePath).href);
3416
+ const maybeModule = mod;
3417
+ return maybeModule.components || maybeModule.default || {};
3418
+ }
3419
+ async function createFarmMarkdownSourceResponse(options) {
3420
+ if (options.request.method !== "GET" && options.request.method !== "HEAD") {
3421
+ return null;
3422
+ }
3423
+ if (options.config?.markdownRoutes === false) {
3424
+ return null;
3425
+ }
3426
+ const url = new URL(options.request.url);
3427
+ const hasMarkdownExtension = url.pathname.toLowerCase().endsWith(".md");
3428
+ if (!hasMarkdownExtension && !requestAcceptsMarkdown(options.request.headers.get("accept"))) {
3429
+ return null;
3430
+ }
3431
+ const targetPathname = normalizeFarmMarkdownRoutePath(url.pathname);
3432
+ const source = await options.resolveSource(targetPathname);
3433
+ if (!source) {
3434
+ return null;
3435
+ }
3436
+ const headers2 = new Headers({
3437
+ "Content-Type": "text/markdown; charset=utf-8",
3438
+ "Content-Location": targetPathname === "/" ? "/index.md" : `${targetPathname}.md`,
3439
+ "Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
3440
+ "X-Farm-Markdown-Route": targetPathname,
3441
+ "X-Farm-Markdown-Source": source.filePath
3442
+ });
3443
+ if (!hasMarkdownExtension) {
3444
+ headers2.set("Vary", "Accept");
3445
+ }
3446
+ return new Response(options.request.method === "HEAD" ? null : source.source, {
3447
+ status: 200,
3448
+ headers: headers2
3449
+ });
3450
+ }
3451
+ var import_react, import_promises, import_path2, import_url;
3452
+ var init_app_markdown = __esm({
3453
+ "src/app-markdown.ts"() {
3454
+ "use strict";
3455
+ import_react = __toESM(require("react"));
3456
+ import_promises = require("fs/promises");
3457
+ import_path2 = __toESM(require("path"));
3458
+ import_url = require("url");
3459
+ init_markdown();
3460
+ __name(resolveMdxConfig, "resolveMdxConfig");
3461
+ __name(isFarmMarkdownPageFile, "isFarmMarkdownPageFile");
3462
+ __name(normalizeFarmMarkdownRoutePath, "normalizeFarmMarkdownRoutePath");
3463
+ __name(parseMarkdownFrontmatter, "parseMarkdownFrontmatter");
3464
+ __name(titleFromMarkdown, "titleFromMarkdown");
3465
+ __name(createMarkdownMetadata, "createMarkdownMetadata");
3466
+ __name(evaluateMdxSource, "evaluateMdxSource");
3467
+ __name(createFarmMarkdownRouteModule, "createFarmMarkdownRouteModule");
3468
+ __name(createFarmMarkdownRouteModuleFromFile, "createFarmMarkdownRouteModuleFromFile");
3469
+ __name(loadFarmMdxComponents, "loadFarmMdxComponents");
3470
+ __name(createFarmMarkdownSourceResponse, "createFarmMarkdownSourceResponse");
3471
+ }
3472
+ });
3473
+
3406
3474
  // src/workflows.ts
3407
3475
  var workflows_exports = {};
3408
3476
  __export(workflows_exports, {
@@ -3555,26 +3623,26 @@ async function prepareFarmWorkflowsForNitro(config) {
3555
3623
  const root = config.root || process.cwd();
3556
3624
  const distDir = config.distDir || ".farm";
3557
3625
  const fs9 = await import("fs/promises");
3558
- const path28 = await import("path");
3559
- const generatedDir = path28.join(root, distDir, ".nitro", "farm-workflows");
3626
+ const path29 = await import("path");
3627
+ const generatedDir = path29.join(root, distDir, ".nitro", "farm-workflows");
3560
3628
  await fs9.mkdir(generatedDir, { recursive: true });
3561
3629
  const tasks = {};
3562
3630
  const scheduledTasks = createScheduledTasks(workflows);
3563
3631
  for (const workflow of workflows) {
3564
- const wrapperPath = path28.join(generatedDir, `${safeFileName(workflow.id)}.mjs`);
3632
+ const wrapperPath = path29.join(generatedDir, `${safeFileName(workflow.id)}.mjs`);
3565
3633
  await fs9.writeFile(wrapperPath, createNitroTaskWrapper(workflow), "utf8");
3566
3634
  tasks[workflow.id] = {
3567
3635
  handler: wrapperPath,
3568
3636
  description: workflow.description || `Farm workflow ${workflow.id}`
3569
3637
  };
3570
3638
  }
3571
- const handlerPath = path28.join(generatedDir, "http-handler.mjs");
3639
+ const handlerPath = path29.join(generatedDir, "http-handler.mjs");
3572
3640
  await fs9.writeFile(
3573
3641
  handlerPath,
3574
3642
  createNitroWorkflowHTTPHandler(workflowConfig, workflows),
3575
3643
  "utf8"
3576
3644
  );
3577
- const manifestPath = path28.join(generatedDir, "manifest.json");
3645
+ const manifestPath = path29.join(generatedDir, "manifest.json");
3578
3646
  await fs9.writeFile(
3579
3647
  manifestPath,
3580
3648
  JSON.stringify(
@@ -3657,10 +3725,10 @@ function resolveWorkflowDefinition(module2) {
3657
3725
  }
3658
3726
  async function findWorkflowFiles(root, dirs) {
3659
3727
  const fs9 = await import("fs/promises");
3660
- const path28 = await import("path");
3728
+ const path29 = await import("path");
3661
3729
  const files = [];
3662
3730
  for (const dir of dirs) {
3663
- const absoluteDir = path28.isAbsolute(dir) ? dir : path28.join(root, dir);
3731
+ const absoluteDir = path29.isAbsolute(dir) ? dir : path29.join(root, dir);
3664
3732
  if (!await pathExists(absoluteDir)) continue;
3665
3733
  await walkWorkflowDir(absoluteDir, files);
3666
3734
  }
@@ -3668,10 +3736,10 @@ async function findWorkflowFiles(root, dirs) {
3668
3736
  }
3669
3737
  async function walkWorkflowDir(dir, files) {
3670
3738
  const fs9 = await import("fs/promises");
3671
- const path28 = await import("path");
3739
+ const path29 = await import("path");
3672
3740
  const entries = await fs9.readdir(dir, { withFileTypes: true });
3673
3741
  for (const entry of entries) {
3674
- const filePath = path28.join(dir, entry.name);
3742
+ const filePath = path29.join(dir, entry.name);
3675
3743
  if (entry.isDirectory()) {
3676
3744
  if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
3677
3745
  await walkWorkflowDir(filePath, files);
@@ -3691,12 +3759,12 @@ function isWorkflowFile(fileName) {
3691
3759
  }
3692
3760
  async function loadWorkflowModule(filePath, root) {
3693
3761
  const fs9 = await import("fs/promises");
3694
- const path28 = await import("path");
3695
- const { pathToFileURL: pathToFileURL3 } = await import("url");
3762
+ const path29 = await import("path");
3763
+ const { pathToFileURL: pathToFileURL4 } = await import("url");
3696
3764
  const { build: build2 } = await import("esbuild");
3697
- const outDir = path28.join(root, ".farm", ".workflow-loader");
3765
+ const outDir = path29.join(root, ".farm", ".workflow-loader");
3698
3766
  await fs9.mkdir(outDir, { recursive: true });
3699
- const outfile = path28.join(
3767
+ const outfile = path29.join(
3700
3768
  outDir,
3701
3769
  `workflow-${Date.now()}-${Math.random().toString(36).slice(2)}.mjs`
3702
3770
  );
@@ -3717,7 +3785,7 @@ async function loadWorkflowModule(filePath, root) {
3717
3785
  try {
3718
3786
  return await import(
3719
3787
  /* @vite-ignore */
3720
- `${pathToFileURL3(outfile).href}?t=${Date.now()}`
3788
+ `${pathToFileURL4(outfile).href}?t=${Date.now()}`
3721
3789
  );
3722
3790
  } finally {
3723
3791
  await fs9.unlink(outfile).catch(() => void 0);
@@ -3975,9 +4043,9 @@ async function prepareFarmCronForNitro(config) {
3975
4043
  const root = config.root || process.cwd();
3976
4044
  const distDir = config.distDir || ".farm";
3977
4045
  const fs9 = await import("fs/promises");
3978
- const path28 = await import("path");
3979
- const manifestPath = path28.join(root, distDir, FARM_CRON_MANIFEST);
3980
- const generatedDir = path28.join(root, distDir, ".nitro", "farm-cron");
4046
+ const path29 = await import("path");
4047
+ const manifestPath = path29.join(root, distDir, FARM_CRON_MANIFEST);
4048
+ const generatedDir = path29.join(root, distDir, ".nitro", "farm-cron");
3981
4049
  if (!cron.enabled) {
3982
4050
  await Promise.all([
3983
4051
  fs9.rm(manifestPath, { force: true }),
@@ -3994,7 +4062,7 @@ async function prepareFarmCronForNitro(config) {
3994
4062
  const tasks = {};
3995
4063
  for (const job of cron.jobs) {
3996
4064
  const taskName = getFarmCronTaskName(job.name);
3997
- const wrapperPath = path28.join(generatedDir, `${safeFileName2(job.name)}.mjs`);
4065
+ const wrapperPath = path29.join(generatedDir, `${safeFileName2(job.name)}.mjs`);
3998
4066
  await fs9.writeFile(wrapperPath, createNitroCronTaskWrapper(job, cron.secretEnv), "utf8");
3999
4067
  tasks[taskName] = {
4000
4068
  handler: wrapperPath,
@@ -4002,7 +4070,7 @@ async function prepareFarmCronForNitro(config) {
4002
4070
  };
4003
4071
  }
4004
4072
  const manifest = createFarmCronManifest(cron);
4005
- await fs9.mkdir(path28.dirname(manifestPath), { recursive: true });
4073
+ await fs9.mkdir(path29.dirname(manifestPath), { recursive: true });
4006
4074
  await fs9.writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}
4007
4075
  `, "utf8");
4008
4076
  return {
@@ -4104,7 +4172,7 @@ function normalizeCronJob(name, job) {
4104
4172
  if (!job || typeof job !== "object" || Array.isArray(job)) {
4105
4173
  throw new TypeError(`Farm cron ${JSON.stringify(name)} must be a configuration object.`);
4106
4174
  }
4107
- const path28 = normalizeCronPath(name, job.path);
4175
+ const path29 = normalizeCronPath(name, job.path);
4108
4176
  const rawSchedule = Array.isArray(job.schedule) ? job.schedule : [job.schedule];
4109
4177
  const schedule = [...new Set(rawSchedule.map((value) => normalizeCronExpression(name, value)))];
4110
4178
  if (schedule.length === 0) {
@@ -4113,7 +4181,7 @@ function normalizeCronJob(name, job) {
4113
4181
  return {
4114
4182
  name,
4115
4183
  schedule,
4116
- path: path28,
4184
+ path: path29,
4117
4185
  description: job.description?.trim() || void 0
4118
4186
  };
4119
4187
  }
@@ -4121,13 +4189,13 @@ function normalizeCronPath(name, value) {
4121
4189
  if (typeof value !== "string" || !value.trim().startsWith("/")) {
4122
4190
  throw new TypeError(`Farm cron ${JSON.stringify(name)} path must start with "/".`);
4123
4191
  }
4124
- const path28 = value.trim();
4125
- if (path28.startsWith("//") || path28.includes("?") || path28.includes("#")) {
4192
+ const path29 = value.trim();
4193
+ if (path29.startsWith("//") || path29.includes("?") || path29.includes("#")) {
4126
4194
  throw new TypeError(
4127
4195
  `Farm cron ${JSON.stringify(name)} path must be an application pathname without a host, query, or hash.`
4128
4196
  );
4129
4197
  }
4130
- return path28.length > 1 ? path28.replace(/\/+$/, "") : path28;
4198
+ return path29.length > 1 ? path29.replace(/\/+$/, "") : path29;
4131
4199
  }
4132
4200
  function normalizeCronExpression(name, value) {
4133
4201
  if (typeof value !== "string") {
@@ -5219,7 +5287,7 @@ var init_server_action_security = __esm({
5219
5287
 
5220
5288
  // src/image-config.ts
5221
5289
  function resolveFarmImageConfig(config) {
5222
- const path28 = normalizeImagePath(config?.path ?? DEFAULT_FARM_IMAGE_PATH);
5290
+ const path29 = normalizeImagePath(config?.path ?? DEFAULT_FARM_IMAGE_PATH);
5223
5291
  const deviceSizes = normalizeIntegerList(
5224
5292
  config?.deviceSizes ?? DEFAULT_FARM_IMAGE_DEVICE_SIZES,
5225
5293
  "images.deviceSizes"
@@ -5247,7 +5315,7 @@ function resolveFarmImageConfig(config) {
5247
5315
  );
5248
5316
  return Object.freeze({
5249
5317
  provider: config?.provider ?? "auto",
5250
- path: path28,
5318
+ path: path29,
5251
5319
  domains: Object.freeze([
5252
5320
  ...new Set(
5253
5321
  (config?.domains ?? []).map((domain) => domain.trim().toLowerCase()).filter(Boolean)
@@ -5286,11 +5354,11 @@ function getPublicFarmImageConfig(config) {
5286
5354
  };
5287
5355
  }
5288
5356
  function normalizeImagePath(value) {
5289
- const path28 = value.trim().replace(/\/+$/, "") || "/";
5290
- if (!path28.startsWith("/") || path28.includes("?") || path28.includes("#")) {
5357
+ const path29 = value.trim().replace(/\/+$/, "") || "/";
5358
+ if (!path29.startsWith("/") || path29.includes("?") || path29.includes("#")) {
5291
5359
  throw new TypeError("images.path must be an absolute pathname without a query or hash");
5292
5360
  }
5293
- return path28;
5361
+ return path29;
5294
5362
  }
5295
5363
  function normalizeIntegerList(values, name, max) {
5296
5364
  if (values.length === 0) {
@@ -6447,7 +6515,7 @@ function normalizePositiveDuration(value, fallback, name) {
6447
6515
  return Math.floor(value);
6448
6516
  }
6449
6517
  function delay(ms) {
6450
- return new Promise((resolve5) => setTimeout(resolve5, ms));
6518
+ return new Promise((resolve6) => setTimeout(resolve6, ms));
6451
6519
  }
6452
6520
  function normalizeCacheOptionsTags(options) {
6453
6521
  const tags = /* @__PURE__ */ new Set();
@@ -7031,7 +7099,7 @@ function getProgrammaticRouteSearchClientOptions(search) {
7031
7099
  if (search.temporary?.length) options.temporary = [...search.temporary];
7032
7100
  return Object.keys(options).length > 0 ? options : void 0;
7033
7101
  }
7034
- function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path28, routePath) {
7102
+ function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path29, routePath) {
7035
7103
  const schema = getProgrammaticRouteSearchSchema(searchConfig);
7036
7104
  const search = parseProgrammaticSchema(schema, rawSearch, "search", routePath);
7037
7105
  const options = getProgrammaticRouteSearchOptions(searchConfig);
@@ -7040,7 +7108,7 @@ function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path28, routePa
7040
7108
  schema,
7041
7109
  rawSearch,
7042
7110
  parsedSearch: search,
7043
- path: path28
7111
+ path: path29
7044
7112
  });
7045
7113
  return { search, canonicalPath };
7046
7114
  }
@@ -7119,8 +7187,8 @@ function normalizeComparableValue(value) {
7119
7187
  }
7120
7188
  return value;
7121
7189
  }
7122
- function createRoute(path28, options) {
7123
- return routesBuilder.page(path28, options);
7190
+ function createRoute(path29, options) {
7191
+ return routesBuilder.page(path29, options);
7124
7192
  }
7125
7193
  function isProgrammaticRoutesFileName(fileName) {
7126
7194
  const normalized = fileName.replace(/\\/g, "/");
@@ -7210,7 +7278,7 @@ function createRouteModuleFromProgrammaticPage(route2) {
7210
7278
  mod.__farmRouteData = route2.data;
7211
7279
  mod.__farmRouteParsesProps = true;
7212
7280
  mod.__farmResolveRouteProps = (props) => resolveProgrammaticRouteProps(route2, props);
7213
- mod.__farmResolveRouteCanonicalPath = (rawSearch, path28) => resolveProgrammaticRouteSearch(route2.search, rawSearch, path28, route2.path).canonicalPath;
7281
+ mod.__farmResolveRouteCanonicalPath = (rawSearch, path29) => resolveProgrammaticRouteSearch(route2.search, rawSearch, path29, route2.path).canonicalPath;
7214
7282
  }
7215
7283
  if (route2.pending || route2.error || route2.notFound) {
7216
7284
  mod.__farmRouteComponents = {
@@ -7608,25 +7676,25 @@ var init_routes = __esm({
7608
7676
  ];
7609
7677
  __name(defineRoutes, "defineRoutes");
7610
7678
  routesBuilder = {
7611
- page(path28, options) {
7679
+ page(path29, options) {
7612
7680
  return normalizeProgrammaticRoute({
7613
7681
  kind: "page",
7614
- path: path28,
7682
+ path: path29,
7615
7683
  ...options
7616
7684
  });
7617
7685
  },
7618
- layout(path28, options) {
7686
+ layout(path29, options) {
7619
7687
  return normalizeProgrammaticRoute({
7620
7688
  kind: "layout",
7621
- path: path28,
7689
+ path: path29,
7622
7690
  ...options
7623
7691
  });
7624
7692
  },
7625
- api(path28, options) {
7693
+ api(path29, options) {
7626
7694
  const { render, runtime, regions, maxDuration, ...methods } = options;
7627
7695
  return normalizeProgrammaticRoute({
7628
7696
  kind: "api",
7629
- path: path28,
7697
+ path: path29,
7630
7698
  render,
7631
7699
  runtime,
7632
7700
  regions,
@@ -8588,8 +8656,56 @@ var init_route_manager = __esm({
8588
8656
  "**/{opengraph-image,twitter-image}.{ts,tsx,js,jsx,png,jpg,jpeg,gif,webp}",
8589
8657
  appDir
8590
8658
  );
8659
+ const canonicalPageGroups = /* @__PURE__ */ new Map();
8660
+ for (const file of pageFiles.filter((candidate) => parseRouteSlotFile(candidate) === null)) {
8661
+ const route2 = parseRoutePath(file);
8662
+ const pattern = this.createRoutePattern(route2);
8663
+ const group = canonicalPageGroups.get(pattern);
8664
+ if (group) {
8665
+ group.files.push(file);
8666
+ } else {
8667
+ canonicalPageGroups.set(pattern, {
8668
+ route: route2,
8669
+ files: [file]
8670
+ });
8671
+ }
8672
+ }
8673
+ for (const [pattern, group] of canonicalPageGroups) {
8674
+ const componentFiles = group.files.filter((file) => !isFarmMarkdownPageFile(file));
8675
+ const markdownFiles = group.files.filter(isFarmMarkdownPageFile);
8676
+ if (componentFiles.length > 1) {
8677
+ throw new Error(
8678
+ `Duplicate page route "${pattern}". Found ${componentFiles.map((file) => import_path5.default.join(appDir, file)).join(" and ")}.`
8679
+ );
8680
+ }
8681
+ if (markdownFiles.length > 1) {
8682
+ throw new Error(
8683
+ `Duplicate markdown representation for page route "${pattern}". Found ${markdownFiles.map((file) => import_path5.default.join(appDir, file)).join(" and ")}.`
8684
+ );
8685
+ }
8686
+ const componentFile = componentFiles[0];
8687
+ const markdownFile = markdownFiles[0];
8688
+ const primaryFile = componentFile || markdownFile;
8689
+ if (!primaryFile) continue;
8690
+ const modulePath = import_path5.default.join(appDir, primaryFile);
8691
+ const existing = this.routes.get(pattern);
8692
+ if (existing?.sourceRoot === source.root) {
8693
+ throw new Error(
8694
+ `Duplicate page route "${pattern}". Found both ${existing.modulePath} and ${modulePath}.`
8695
+ );
8696
+ }
8697
+ this.routes.set(pattern, {
8698
+ route: group.route,
8699
+ modulePath,
8700
+ ...markdownFile ? {
8701
+ markdownSourcePath: import_path5.default.join(appDir, markdownFile)
8702
+ } : {},
8703
+ pattern,
8704
+ source: "file",
8705
+ sourceRoot: source.root
8706
+ });
8707
+ }
8591
8708
  for (const [kind, files, target] of [
8592
- ["page", pageFiles.filter((file) => parseRouteSlotFile(file) === null), this.routes],
8593
8709
  ["layout", layoutFiles, this.layouts],
8594
8710
  ["loading", loadingFiles, this.loadings],
8595
8711
  ["error", errorFiles, this.errors]
@@ -9178,12 +9294,12 @@ function isFarmRouteActive(pattern, pathname, options = {}) {
9178
9294
  }
9179
9295
  function normalizeRouteInput(input, index) {
9180
9296
  const route2 = typeof input === "string" ? { path: input } : input;
9181
- const path28 = normalizePathname2(route2.path);
9182
- const segments = parseRoutePattern(path28);
9297
+ const path29 = normalizePathname2(route2.path);
9298
+ const segments = parseRoutePattern(path29);
9183
9299
  return {
9184
9300
  route: {
9185
9301
  ...route2,
9186
- path: path28
9302
+ path: path29
9187
9303
  },
9188
9304
  segments,
9189
9305
  score: scoreSegments(segments),
@@ -9614,8 +9730,8 @@ function getControlledDeferred(id, controllers) {
9614
9730
  if (existing) return existing;
9615
9731
  let nativeResolve;
9616
9732
  let nativeReject;
9617
- const promise = new Promise((resolve5, reject) => {
9618
- nativeResolve = resolve5;
9733
+ const promise = new Promise((resolve6, reject) => {
9734
+ nativeResolve = resolve6;
9619
9735
  nativeReject = reject;
9620
9736
  });
9621
9737
  promise.status = "pending";
@@ -9820,8 +9936,8 @@ function createFarmDeploymentMismatchError(response, clientDeploymentId) {
9820
9936
  getFarmResponseDeploymentId(response) || "unknown"
9821
9937
  );
9822
9938
  }
9823
- function createFarmDeploymentCookie(deploymentId, path28 = "/", secure = false) {
9824
- const normalizedPath = path28.startsWith("/") ? path28 : `/${path28}`;
9939
+ function createFarmDeploymentCookie(deploymentId, path29 = "/", secure = false) {
9940
+ const normalizedPath = path29.startsWith("/") ? path29 : `/${path29}`;
9825
9941
  return [
9826
9942
  `${FARM_DEPLOYMENT_COOKIE}=${encodeURIComponent(deploymentId)}`,
9827
9943
  `Path=${normalizedPath}`,
@@ -10001,11 +10117,11 @@ function readPageState() {
10001
10117
  if (!state || typeof state !== "object") return null;
10002
10118
  return state[FARM_PAGE_STATE_KEY] ?? null;
10003
10119
  }
10004
- function createHistoryState(path28, pageState, currentState, interceptFrom) {
10120
+ function createHistoryState(path29, pageState, currentState, interceptFrom) {
10005
10121
  const base = currentState && typeof currentState === "object" ? { ...currentState } : {};
10006
10122
  const nextState = {
10007
10123
  ...base,
10008
- path: path28,
10124
+ path: path29,
10009
10125
  [FARM_PAGE_STATE_KEY]: pageState
10010
10126
  };
10011
10127
  if (interceptFrom === null) {
@@ -10015,9 +10131,9 @@ function createHistoryState(path28, pageState, currentState, interceptFrom) {
10015
10131
  }
10016
10132
  return nextState;
10017
10133
  }
10018
- function getPageDataCacheKey(path28, interceptFrom) {
10019
- return interceptFrom ? `${path28}
10020
- intercept:${interceptFrom}` : path28;
10134
+ function getPageDataCacheKey(path29, interceptFrom) {
10135
+ return interceptFrom ? `${path29}
10136
+ intercept:${interceptFrom}` : path29;
10021
10137
  }
10022
10138
  function createNavigationLocation(url) {
10023
10139
  return {
@@ -10027,8 +10143,8 @@ function createNavigationLocation(url) {
10027
10143
  hash: url.hash
10028
10144
  };
10029
10145
  }
10030
- function getScrollElementStorageKey(path28, key) {
10031
- return `farm-scroll-${path28}:${key}`;
10146
+ function getScrollElementStorageKey(path29, key) {
10147
+ return `farm-scroll-${path29}:${key}`;
10032
10148
  }
10033
10149
  var FARM_PAGE_STATE_KEY, FARM_INTERCEPT_FROM_KEY, IDLE_NAVIGATION_STATE, routerInstance, _SPARouter, SPARouter;
10034
10150
  var init_spa_router = __esm({
@@ -10314,13 +10430,13 @@ var init_spa_router = __esm({
10314
10430
  /**
10315
10431
  * Fetch page data from cache or server
10316
10432
  */
10317
- async fetchPageData(path28, recover = true, interceptFrom) {
10318
- const cacheKey = getPageDataCacheKey(path28, interceptFrom);
10433
+ async fetchPageData(path29, recover = true, interceptFrom) {
10434
+ const cacheKey = getPageDataCacheKey(path29, interceptFrom);
10319
10435
  const cached = this.cache.get(cacheKey);
10320
10436
  if (cached && Date.now() - cached.timestamp < this.options.cacheMaxAge) {
10321
10437
  return cached.data;
10322
10438
  }
10323
- const response = await fetch(`/__farm/page-data?path=${encodeURIComponent(path28)}`, {
10439
+ const response = await fetch(`/__farm/page-data?path=${encodeURIComponent(path29)}`, {
10324
10440
  headers: createFarmDeploymentRequestHeaders(this.options.deploymentId, {
10325
10441
  Accept: "application/x-farm-deferred+json, application/json",
10326
10442
  "X-Farm-SPA": "1",
@@ -10334,7 +10450,7 @@ var init_spa_router = __esm({
10334
10450
  );
10335
10451
  dispatchDeploymentMismatch(error);
10336
10452
  if (recover) {
10337
- window.location.assign(path28);
10453
+ window.location.assign(path29);
10338
10454
  }
10339
10455
  throw error;
10340
10456
  }
@@ -10353,16 +10469,16 @@ var init_spa_router = __esm({
10353
10469
  */
10354
10470
  async handlePopState(event) {
10355
10471
  if (document.documentElement.dataset.farmDocsRuntime === "true") return;
10356
- const path28 = window.location.pathname + window.location.search;
10472
+ const path29 = window.location.pathname + window.location.search;
10357
10473
  if (await this.shouldBlockNavigation({
10358
- from: event.state?.path || path28,
10359
- to: path28,
10474
+ from: event.state?.path || path29,
10475
+ to: path29,
10360
10476
  action: "pop"
10361
10477
  })) {
10362
10478
  return;
10363
10479
  }
10364
10480
  this.startNavigation({
10365
- from: event.state?.path || path28,
10481
+ from: event.state?.path || path29,
10366
10482
  to: createNavigationLocation(new URL(window.location.href)),
10367
10483
  action: "pop"
10368
10484
  });
@@ -10374,7 +10490,7 @@ var init_spa_router = __esm({
10374
10490
  action: "pop"
10375
10491
  });
10376
10492
  const interceptFrom = typeof event.state?.[FARM_INTERCEPT_FROM_KEY] === "string" ? event.state[FARM_INTERCEPT_FROM_KEY] : void 0;
10377
- const pageData = await this.fetchPageData(path28, true, interceptFrom);
10493
+ const pageData = await this.fetchPageData(path29, true, interceptFrom);
10378
10494
  if (clientNavigation) {
10379
10495
  await this.clientPlugins?.markNavigationLoaded(clientNavigation, pageData);
10380
10496
  }
@@ -10405,8 +10521,8 @@ var init_spa_router = __esm({
10405
10521
  /**
10406
10522
  * Check if URL is cached
10407
10523
  */
10408
- isCached(path28, interceptFrom) {
10409
- const cached = this.cache.get(getPageDataCacheKey(path28, interceptFrom));
10524
+ isCached(path29, interceptFrom) {
10525
+ const cached = this.cache.get(getPageDataCacheKey(path29, interceptFrom));
10410
10526
  return cached !== void 0 && Date.now() - cached.timestamp < this.options.cacheMaxAge;
10411
10527
  }
10412
10528
  /**
@@ -10460,15 +10576,15 @@ var init_spa_router = __esm({
10460
10576
  /**
10461
10577
  * Save scroll position for a path
10462
10578
  */
10463
- saveScrollPosition(path28) {
10579
+ saveScrollPosition(path29) {
10464
10580
  try {
10465
10581
  sessionStorage.setItem(
10466
- `farm-scroll-${path28}`,
10582
+ `farm-scroll-${path29}`,
10467
10583
  JSON.stringify({ x: window.scrollX, y: window.scrollY })
10468
10584
  );
10469
10585
  for (const [key, element] of this.scrollElements) {
10470
10586
  sessionStorage.setItem(
10471
- getScrollElementStorageKey(path28, key),
10587
+ getScrollElementStorageKey(path29, key),
10472
10588
  JSON.stringify({ x: element.scrollLeft, y: element.scrollTop })
10473
10589
  );
10474
10590
  }
@@ -10478,22 +10594,22 @@ var init_spa_router = __esm({
10478
10594
  /**
10479
10595
  * Restore scroll position for a path
10480
10596
  */
10481
- restoreScrollPosition(path28) {
10597
+ restoreScrollPosition(path29) {
10482
10598
  try {
10483
- const saved = sessionStorage.getItem(`farm-scroll-${path28}`);
10599
+ const saved = sessionStorage.getItem(`farm-scroll-${path29}`);
10484
10600
  if (saved) {
10485
10601
  const { x, y } = JSON.parse(saved);
10486
10602
  setTimeout(() => window.scrollTo(x, y), 0);
10487
10603
  }
10488
10604
  for (const [key, element] of this.scrollElements) {
10489
- this.restoreScrollElement(path28, key, element);
10605
+ this.restoreScrollElement(path29, key, element);
10490
10606
  }
10491
10607
  } catch {
10492
10608
  }
10493
10609
  }
10494
- restoreScrollElement(path28, key, element) {
10610
+ restoreScrollElement(path29, key, element) {
10495
10611
  try {
10496
- const saved = sessionStorage.getItem(getScrollElementStorageKey(path28, key));
10612
+ const saved = sessionStorage.getItem(getScrollElementStorageKey(path29, key));
10497
10613
  if (!saved) return;
10498
10614
  const { x, y } = JSON.parse(saved);
10499
10615
  setTimeout(() => {
@@ -11844,6 +11960,7 @@ var init_renderer = __esm({
11844
11960
  init_server2();
11845
11961
  init_resolver();
11846
11962
  init_routing();
11963
+ init_response();
11847
11964
  cachedClerkProvider = null;
11848
11965
  importRuntimeModule = new Function("specifier", "return import(specifier);");
11849
11966
  __name(hasRequestHeader, "hasRequestHeader");
@@ -12536,6 +12653,15 @@ var init_renderer = __esm({
12536
12653
  });
12537
12654
  });
12538
12655
  } catch (error) {
12656
+ if (isWebResponse(error)) {
12657
+ if (!res.headersSent && !res.writableEnded) {
12658
+ await sendWebResponse(res, error);
12659
+ } else if (!res.writableEnded) {
12660
+ res.end();
12661
+ }
12662
+ completeRender(error.status, pathname);
12663
+ return;
12664
+ }
12539
12665
  if (isFarmRedirectError(error)) {
12540
12666
  const redirect3 = getFarmRedirectError(error);
12541
12667
  const snapshot = getFarmI18nClientSnapshot();
@@ -12836,7 +12962,7 @@ var init_renderer = __esm({
12836
12962
  }
12837
12963
  }
12838
12964
  async renderWithSSR(element, req, res, clearMiddlewareData, options = {}) {
12839
- return new Promise((resolve5, reject) => {
12965
+ return new Promise((resolve6, reject) => {
12840
12966
  const streamStartTime = Date.now();
12841
12967
  const observabilityRoute = options.observabilityRoute || req.__FARM_ROUTE__ || req.url || "/";
12842
12968
  const deploymentId = this.getDeploymentId();
@@ -13016,7 +13142,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
13016
13142
  route: observabilityRoute,
13017
13143
  durationMs: Date.now() - streamStartTime
13018
13144
  });
13019
- resolve5();
13145
+ resolve6();
13020
13146
  }
13021
13147
  });
13022
13148
  res.write(shell);
@@ -13027,7 +13153,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
13027
13153
  },
13028
13154
  onShellError(error) {
13029
13155
  didError = true;
13030
- if (!isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
13156
+ if (!isWebResponse(error) && !isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
13031
13157
  logger.error(`SSR shell error: ${error}`);
13032
13158
  emitFarmEvent({
13033
13159
  type: "render.error",
@@ -13042,7 +13168,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
13042
13168
  },
13043
13169
  onError(error) {
13044
13170
  didError = true;
13045
- if (!isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
13171
+ if (!isWebResponse(error) && !isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
13046
13172
  logger.error(`SSR streaming error: ${error}`);
13047
13173
  emitFarmEvent({
13048
13174
  type: "render.error",
@@ -13222,6 +13348,96 @@ var init_devtools_config = __esm({
13222
13348
  }
13223
13349
  });
13224
13350
 
13351
+ // src/auth-config.ts
13352
+ function resolveFarmAuthConfig(input) {
13353
+ const config = input === true ? {} : input && typeof input === "object" ? input : {};
13354
+ const passwordConfig = typeof config.emailAndPassword === "object" ? config.emailAndPassword : {};
13355
+ const resolved = {
13356
+ enabled: input !== void 0 && input !== false && config.enabled !== false,
13357
+ appName: config.appName,
13358
+ basePath: normalizeBasePath(config.basePath),
13359
+ emailAndPassword: {
13360
+ enabled: config.emailAndPassword !== false,
13361
+ requireEmailVerification: passwordConfig.requireEmailVerification ?? false,
13362
+ minPasswordLength: passwordConfig.minPasswordLength ?? 8,
13363
+ maxPasswordLength: passwordConfig.maxPasswordLength ?? 128
13364
+ },
13365
+ session: {
13366
+ expiresIn: config.session?.expiresIn ?? 60 * 60 * 24 * 7,
13367
+ updateAge: config.session?.updateAge ?? 60 * 60 * 24
13368
+ },
13369
+ database: {
13370
+ url: config.database?.url,
13371
+ path: config.database?.path || ".farm/auth.sqlite",
13372
+ migrateInDevelopment: config.database?.migrateInDevelopment ?? true
13373
+ }
13374
+ };
13375
+ validateFarmAuthConfig(resolved);
13376
+ return resolved;
13377
+ }
13378
+ async function resolveFarmAuthIntegration(config, options) {
13379
+ if (!config.enabled) return void 0;
13380
+ const root = import_node_path4.default.resolve(options.root);
13381
+ let modulePath;
13382
+ try {
13383
+ const resolveFromApp = (0, import_node_module2.createRequire)(import_node_path4.default.join(root, "package.json"));
13384
+ modulePath = resolveFromApp.resolve("@farm.js/auth/internal");
13385
+ } catch {
13386
+ throw new Error(
13387
+ "The `auth` config requires @farm.js/auth. Install it with `pnpm add @farm.js/auth` and try again."
13388
+ );
13389
+ }
13390
+ const runtime = await import(
13391
+ /* @vite-ignore */
13392
+ (0, import_node_url2.pathToFileURL)(modulePath).href
13393
+ );
13394
+ if (typeof runtime.createFarmAuthIntegration !== "function") {
13395
+ throw new Error(
13396
+ "The installed @farm.js/auth package is incompatible with this version of @farm.js/core."
13397
+ );
13398
+ }
13399
+ return runtime.createFarmAuthIntegration(config, {
13400
+ ...options,
13401
+ root
13402
+ });
13403
+ }
13404
+ function normalizeBasePath(value) {
13405
+ const route2 = (value || "/api/auth").trim();
13406
+ const withLeadingSlash = route2.startsWith("/") ? route2 : `/${route2}`;
13407
+ const normalized = withLeadingSlash.replace(/\/+/g, "/").replace(/\/+$/, "");
13408
+ return normalized || "/api/auth";
13409
+ }
13410
+ function validateFarmAuthConfig(config) {
13411
+ const { minPasswordLength, maxPasswordLength } = config.emailAndPassword;
13412
+ if (!Number.isInteger(minPasswordLength) || minPasswordLength < 1) {
13413
+ throw new Error("auth.emailAndPassword.minPasswordLength must be a positive integer.");
13414
+ }
13415
+ if (!Number.isInteger(maxPasswordLength) || maxPasswordLength < minPasswordLength) {
13416
+ throw new Error(
13417
+ "auth.emailAndPassword.maxPasswordLength must be an integer greater than or equal to minPasswordLength."
13418
+ );
13419
+ }
13420
+ if (!Number.isInteger(config.session.expiresIn) || config.session.expiresIn < 1) {
13421
+ throw new Error("auth.session.expiresIn must be a positive integer.");
13422
+ }
13423
+ if (!Number.isInteger(config.session.updateAge) || config.session.updateAge < 0) {
13424
+ throw new Error("auth.session.updateAge must be a non-negative integer.");
13425
+ }
13426
+ }
13427
+ var import_node_module2, import_node_path4, import_node_url2;
13428
+ var init_auth_config = __esm({
13429
+ "src/auth-config.ts"() {
13430
+ "use strict";
13431
+ import_node_module2 = require("module");
13432
+ import_node_path4 = __toESM(require("path"));
13433
+ import_node_url2 = require("url");
13434
+ __name(resolveFarmAuthConfig, "resolveFarmAuthConfig");
13435
+ __name(resolveFarmAuthIntegration, "resolveFarmAuthIntegration");
13436
+ __name(normalizeBasePath, "normalizeBasePath");
13437
+ __name(validateFarmAuthConfig, "validateFarmAuthConfig");
13438
+ }
13439
+ });
13440
+
13225
13441
  // src/app.ts
13226
13442
  function isResolvedDocsConfig(value) {
13227
13443
  return !!value && typeof value === "object" && "enabled" in value && "entry" in value && "config" in value;
@@ -13229,6 +13445,11 @@ function isResolvedDocsConfig(value) {
13229
13445
  function isResolvedI18nConfig(value) {
13230
13446
  return Boolean(value && typeof value === "object" && "enabled" in value);
13231
13447
  }
13448
+ function isResolvedAuthConfig(value) {
13449
+ return Boolean(
13450
+ value && typeof value === "object" && "enabled" in value && "emailAndPassword" in value && "database" in value
13451
+ );
13452
+ }
13232
13453
  function createFarmApp(config, viteServer) {
13233
13454
  return new FarmApp(config, viteServer);
13234
13455
  }
@@ -13255,6 +13476,7 @@ var init_app = __esm({
13255
13476
  init_config();
13256
13477
  init_server2();
13257
13478
  init_cache();
13479
+ init_auth_config();
13258
13480
  defaultDocsConfig = {
13259
13481
  enabled: false,
13260
13482
  entry: "/docs",
@@ -13309,6 +13531,7 @@ var init_app = __esm({
13309
13531
  deploy: config.deploy || {},
13310
13532
  storage: config.storage || {},
13311
13533
  cache: config.cache || {},
13534
+ auth: isResolvedAuthConfig(config.auth) ? config.auth : resolveFarmAuthConfig(config.auth),
13312
13535
  integrations: config.integrations || {},
13313
13536
  plugins: config.plugins || [],
13314
13537
  migrations: config.migrations || { commands: [] },
@@ -13378,6 +13601,7 @@ var init_app = __esm({
13378
13601
  __name(_FarmApp, "FarmApp");
13379
13602
  FarmApp = _FarmApp;
13380
13603
  __name(isResolvedI18nConfig, "isResolvedI18nConfig");
13604
+ __name(isResolvedAuthConfig, "isResolvedAuthConfig");
13381
13605
  __name(createFarmApp, "createFarmApp");
13382
13606
  }
13383
13607
  });
@@ -14090,15 +14314,15 @@ function isEndpointFailure(value) {
14090
14314
  return value instanceof EndpointFailure;
14091
14315
  }
14092
14316
  function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
14093
- let path28;
14317
+ let path29;
14094
14318
  let options;
14095
14319
  let handler;
14096
14320
  if (typeof pathOrOptions === "string") {
14097
- path28 = pathOrOptions;
14321
+ path29 = pathOrOptions;
14098
14322
  options = optionsOrHandler;
14099
14323
  handler = maybeHandler;
14100
14324
  } else {
14101
- path28 = "";
14325
+ path29 = "";
14102
14326
  options = pathOrOptions;
14103
14327
  handler = optionsOrHandler;
14104
14328
  }
@@ -14125,13 +14349,13 @@ function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
14125
14349
  ...betterCallOptions
14126
14350
  } = options;
14127
14351
  const endpoint2 = (0, import_better_call.createEndpoint)(
14128
- path28 || "/__farm_auto_path__",
14352
+ path29 || "/__farm_auto_path__",
14129
14353
  betterCallOptions,
14130
14354
  wrappedHandler
14131
14355
  );
14132
- endpoint2.__path = path28 || void 0;
14356
+ endpoint2.__path = path29 || void 0;
14133
14357
  endpoint2.__method = options.method || "GET";
14134
- endpoint2.__autoPath = !path28;
14358
+ endpoint2.__autoPath = !path29;
14135
14359
  endpoint2.__handler = wrappedHandler;
14136
14360
  endpoint2.__farmInvoke = (ctx) => runEndpointMiddleware(middleware2, ctx, handler, fail, options.invalidates);
14137
14361
  endpoint2.__middleware = middleware2;
@@ -14669,12 +14893,12 @@ var init_runtime2 = __esm({
14669
14893
  });
14670
14894
 
14671
14895
  // src/api/route-manager.ts
14672
- var fs3, path10, API_ROUTE_METHODS, _APIRouteManager, APIRouteManager;
14896
+ var fs3, path11, API_ROUTE_METHODS, _APIRouteManager, APIRouteManager;
14673
14897
  var init_route_manager2 = __esm({
14674
14898
  "src/api/route-manager.ts"() {
14675
14899
  "use strict";
14676
14900
  fs3 = __toESM(require("fs"));
14677
- path10 = __toESM(require("path"));
14901
+ path11 = __toESM(require("path"));
14678
14902
  init_utils();
14679
14903
  init_routes();
14680
14904
  init_routes_server();
@@ -14705,7 +14929,7 @@ var init_route_manager2 = __esm({
14705
14929
  async discoverRoutes() {
14706
14930
  this.routes.clear();
14707
14931
  for (const appDir of this.appDirs) {
14708
- const apiDir = path10.join(appDir, "api");
14932
+ const apiDir = path11.join(appDir, "api");
14709
14933
  let routeFiles = [];
14710
14934
  if (fs3.existsSync(apiDir)) {
14711
14935
  routeFiles = this.findRouteFiles(apiDir);
@@ -14733,7 +14957,7 @@ var init_route_manager2 = __esm({
14733
14957
  }
14734
14958
  const entries = fs3.readdirSync(dir, { withFileTypes: true });
14735
14959
  for (const entry of entries) {
14736
- const fullPath = path10.join(dir, entry.name);
14960
+ const fullPath = path11.join(dir, entry.name);
14737
14961
  if (entry.isDirectory()) {
14738
14962
  files.push(...this.findRouteFiles(fullPath));
14739
14963
  } else if (entry.name === "route.ts" || entry.name === "route.tsx" || entry.name === "route.js") {
@@ -14747,8 +14971,8 @@ var init_route_manager2 = __esm({
14747
14971
  */
14748
14972
  async loadRoute(filePath, appDir) {
14749
14973
  try {
14750
- const apiDir = path10.join(appDir, "api");
14751
- const relativePath2 = path10.relative(apiDir, path10.dirname(filePath));
14974
+ const apiDir = path11.join(appDir, "api");
14975
+ const relativePath2 = path11.relative(apiDir, path11.dirname(filePath));
14752
14976
  const routePath = "/api/" + (relativePath2 === "." ? "" : relativePath2.replace(/\\/g, "/"));
14753
14977
  const routeModule = await this.loadModule(filePath);
14754
14978
  const endpoints = {};
@@ -14799,7 +15023,7 @@ var init_route_manager2 = __esm({
14799
15023
  }
14800
15024
  }
14801
15025
  async loadProgrammaticApiRoutes(appDir) {
14802
- const candidateRoots = [path10.dirname(appDir), appDir];
15026
+ const candidateRoots = [path11.dirname(appDir), appDir];
14803
15027
  const routeFiles = Array.from(
14804
15028
  new Set(candidateRoots.flatMap((srcRoot) => findProgrammaticRouteFilesInDir(srcRoot)))
14805
15029
  );
@@ -14825,11 +15049,11 @@ var init_route_manager2 = __esm({
14825
15049
  }
14826
15050
  findRootRoutesFile(appDir) {
14827
15051
  const routeNames = ["routes.ts", "routes.tsx", "routes.js"];
14828
- const candidateDirs = [path10.dirname(appDir), appDir];
15052
+ const candidateDirs = [path11.dirname(appDir), appDir];
14829
15053
  const seen = /* @__PURE__ */ new Set();
14830
15054
  for (const dir of candidateDirs) {
14831
15055
  for (const routeName of routeNames) {
14832
- const routesFile = path10.join(dir, routeName);
15056
+ const routesFile = path11.join(dir, routeName);
14833
15057
  if (seen.has(routesFile)) {
14834
15058
  continue;
14835
15059
  }
@@ -15254,12 +15478,12 @@ var init_module = __esm({
15254
15478
  function isMiddlewareResponse(value) {
15255
15479
  return value instanceof Response;
15256
15480
  }
15257
- var fs4, path11, _MiddlewareManager, MiddlewareManager;
15481
+ var fs4, path12, _MiddlewareManager, MiddlewareManager;
15258
15482
  var init_manager = __esm({
15259
15483
  "src/middleware/manager.ts"() {
15260
15484
  "use strict";
15261
15485
  fs4 = __toESM(require("fs"));
15262
- path11 = __toESM(require("path"));
15486
+ path12 = __toESM(require("path"));
15263
15487
  init_context();
15264
15488
  init_module();
15265
15489
  init_utils();
@@ -15339,8 +15563,8 @@ var init_manager = __esm({
15339
15563
  const entries = fs4.readdirSync(dir, { withFileTypes: true });
15340
15564
  for (const entry of entries) {
15341
15565
  if (entry.isDirectory() && !entry.name.startsWith(".") && !entry.name.startsWith("_")) {
15342
- const subPath = path11.join(dir, entry.name);
15343
- const subRoutePath = path11.posix.join(routePath, entry.name);
15566
+ const subPath = path12.join(dir, entry.name);
15567
+ const subRoutePath = path12.posix.join(routePath, entry.name);
15344
15568
  await this.discoverInDirectory(subPath, subRoutePath, discovered);
15345
15569
  }
15346
15570
  }
@@ -15351,7 +15575,7 @@ var init_manager = __esm({
15351
15575
  findMiddlewareFile(dir) {
15352
15576
  const extensions = [".ts", ".tsx", ".js", ".jsx"];
15353
15577
  for (const ext of extensions) {
15354
- const filePath = path11.join(dir, `middleware${ext}`);
15578
+ const filePath = path12.join(dir, `middleware${ext}`);
15355
15579
  if (fs4.existsSync(filePath)) {
15356
15580
  return filePath;
15357
15581
  }
@@ -15818,11 +16042,11 @@ var init_type_generator = __esm({
15818
16042
  routeGroups.get(key).push(route2);
15819
16043
  }
15820
16044
  const nestedStructure = {};
15821
- for (const [path28, routeList] of routeGroups) {
16045
+ for (const [path29, routeList] of routeGroups) {
15822
16046
  const route2 = routeList[0];
15823
16047
  const importPath = this.getRouteImportPath(route2, options.outFile);
15824
16048
  const routeName = this.pathToRouteName(route2.path);
15825
- const cleanPath = path28 === "/api" ? "" : path28.replace(/^\/api\//, "");
16049
+ const cleanPath = path29 === "/api" ? "" : path29.replace(/^\/api\//, "");
15826
16050
  const parts = cleanPath ? cleanPath.split("/") : [];
15827
16051
  const allMethods = routeList.flatMap((r) => r.methods);
15828
16052
  for (const method of allMethods) {
@@ -15881,8 +16105,8 @@ ${typeExports}
15881
16105
  const relativeImport = (0, import_path7.relative)((0, import_path7.dirname)(outFile), route2.filePath).replace(/\\/g, "/").replace(/\.(ts|tsx|js|jsx)$/, "");
15882
16106
  return relativeImport.startsWith(".") ? relativeImport : `./${relativeImport}`;
15883
16107
  }
15884
- pathToRouteName(path28) {
15885
- return (path28 === "/api" ? "root" : path28.replace(/^\/api\//, "")).replace(/\//g, "_").replace(/[^a-zA-Z0-9_]/g, "");
16108
+ pathToRouteName(path29) {
16109
+ return (path29 === "/api" ? "root" : path29.replace(/^\/api\//, "")).replace(/\//g, "_").replace(/[^a-zA-Z0-9_]/g, "");
15886
16110
  }
15887
16111
  structureToTypeString(obj, indent) {
15888
16112
  const spaces = " ".repeat(indent);
@@ -15902,15 +16126,15 @@ ${typeExports}
15902
16126
  toTypePropertyKey(key) {
15903
16127
  return /^[$A-Z_][0-9A-Z_$]*$/i.test(key) ? key : JSON.stringify(key);
15904
16128
  }
15905
- getBaseExportName(path28) {
15906
- const cleanPath = path28.replace(/^\/api\//, "");
16129
+ getBaseExportName(path29) {
16130
+ const cleanPath = path29.replace(/^\/api\//, "");
15907
16131
  if (cleanPath === "") {
15908
16132
  return "api";
15909
16133
  }
15910
16134
  return cleanPath;
15911
16135
  }
15912
- getExportName(path28, method) {
15913
- const cleanPath = path28.replace(/^\/api\//, "");
16136
+ getExportName(path29, method) {
16137
+ const cleanPath = path29.replace(/^\/api\//, "");
15914
16138
  if (cleanPath === "") {
15915
16139
  return method.toLowerCase();
15916
16140
  }
@@ -15972,19 +16196,22 @@ function createRoutePattern(route2) {
15972
16196
  }).join("/");
15973
16197
  }
15974
16198
  async function generateRouteTypes(options) {
15975
- const {
15976
- root,
15977
- srcDir = "src",
15978
- outFile = DEFAULT_OUT_FILE,
15979
- extraRoutes = [],
15980
- suppressLintOnLink = false
15981
- } = options;
16199
+ const root = path13.resolve(options.root);
16200
+ const srcDir = options.srcDir || "src";
16201
+ const outFile = options.outFile || DEFAULT_OUT_FILE;
16202
+ const outPath = path13.isAbsolute(outFile) ? outFile : path13.join(root, srcDir, outFile);
16203
+ const content = await createRouteTypeDeclarations(options, outPath);
16204
+ fs5.mkdirSync(path13.dirname(outPath), { recursive: true });
16205
+ writeFileIfChanged(outPath, content);
16206
+ return outPath;
16207
+ }
16208
+ async function createRouteTypeDeclarations(options, outPath) {
16209
+ const { root, srcDir = "src", extraRoutes = [], suppressLintOnLink = false } = options;
15982
16210
  const sourceRoots = options.sourceRoots ?? [{ name: "project", root, srcDir, layer: false }];
15983
- const outPath = path12.join(root, srcDir, outFile);
15984
16211
  const patterns = /* @__PURE__ */ new Set();
15985
16212
  const glob = await import("fast-glob");
15986
16213
  for (const source of sourceRoots) {
15987
- const appDir = path12.join(source.root, source.srcDir, "app");
16214
+ const appDir = path13.join(source.root, source.srcDir, "app");
15988
16215
  if (fs5.existsSync(appDir)) {
15989
16216
  const pageFiles = await glob.default("**/page.{ts,tsx,js,jsx,md,mdx}", {
15990
16217
  cwd: appDir,
@@ -16013,18 +16240,19 @@ async function generateRouteTypes(options) {
16013
16240
  const patternLiterals = sortedPatterns.map(routePatternToRouteLiteral);
16014
16241
  const routePathType = suppressLintOnLink ? "string" : typeLiterals.length ? typeLiterals.join(" | ") : "never";
16015
16242
  const routePatternType = suppressLintOnLink ? "string" : patternLiterals.length ? patternLiterals.join(" | ") : "never";
16243
+ const routeTypesImportPath = `./${path13.basename(outPath).replace(/\.d\.ts$/, "")}`;
16016
16244
  const augmentationBlock = suppressLintOnLink ? "" : `
16017
16245
  declare module "@farm.js/core/client" {
16018
16246
  interface LinkDefaultRoute {
16019
- _: import("./farm-routes").RoutePath;
16020
- pattern: import("./farm-routes").RoutePattern;
16247
+ _: import(${JSON.stringify(routeTypesImportPath)}).RoutePath;
16248
+ pattern: import(${JSON.stringify(routeTypesImportPath)}).RoutePattern;
16021
16249
  }
16022
16250
  }
16023
16251
 
16024
16252
  declare module "@farm.js/core" {
16025
16253
  interface LinkDefaultRoute {
16026
- _: import("./farm-routes").RoutePath;
16027
- pattern: import("./farm-routes").RoutePattern;
16254
+ _: import(${JSON.stringify(routeTypesImportPath)}).RoutePath;
16255
+ pattern: import(${JSON.stringify(routeTypesImportPath)}).RoutePattern;
16028
16256
  }
16029
16257
  // Ensure root import ("@farm.js/core") uses the same typed Link signature as client entry.
16030
16258
  const Link: typeof import("@farm.js/core/client").Link;
@@ -16033,8 +16261,8 @@ declare module "@farm.js/core" {
16033
16261
  // Internal declaration path used by @farm.js/core root type re-exports.
16034
16262
  declare module "@farm.js/core/dist/client.js" {
16035
16263
  interface LinkDefaultRoute {
16036
- _: import("./farm-routes").RoutePath;
16037
- pattern: import("./farm-routes").RoutePattern;
16264
+ _: import(${JSON.stringify(routeTypesImportPath)}).RoutePath;
16265
+ pattern: import(${JSON.stringify(routeTypesImportPath)}).RoutePattern;
16038
16266
  }
16039
16267
  }
16040
16268
  `;
@@ -16046,15 +16274,13 @@ declare module "@farm.js/core/dist/client.js" {
16046
16274
  export type RoutePath = ${routePathType};
16047
16275
  export type RoutePattern = ${routePatternType};${augmentationBlock}
16048
16276
  `;
16049
- fs5.mkdirSync(path12.dirname(outPath), { recursive: true });
16050
- writeFileIfChanged(outPath, content);
16051
- return outPath;
16277
+ return content;
16052
16278
  }
16053
- var path12, fs5, DEFAULT_OUT_FILE;
16279
+ var path13, fs5, DEFAULT_OUT_FILE;
16054
16280
  var init_generate_route_types = __esm({
16055
16281
  "src/routing/generate-route-types.ts"() {
16056
16282
  "use strict";
16057
- path12 = __toESM(require("path"));
16283
+ path13 = __toESM(require("path"));
16058
16284
  fs5 = __toESM(require("fs"));
16059
16285
  init_utils();
16060
16286
  init_route_slots();
@@ -16066,23 +16292,30 @@ var init_generate_route_types = __esm({
16066
16292
  __name(createRoutePattern, "createRoutePattern");
16067
16293
  DEFAULT_OUT_FILE = "farm-routes.d.ts";
16068
16294
  __name(generateRouteTypes, "generateRouteTypes");
16295
+ __name(createRouteTypeDeclarations, "createRouteTypeDeclarations");
16069
16296
  }
16070
16297
  });
16071
16298
 
16072
16299
  // src/env-types.ts
16073
16300
  async function generateEnvTypes(options) {
16074
- const root = path13.resolve(options.root);
16301
+ const root = path14.resolve(options.root);
16075
16302
  const srcDir = options.srcDir || "src";
16076
- const outPath = path13.join(root, srcDir, options.outFile || DEFAULT_OUT_FILE2);
16303
+ const outFile = options.outFile || DEFAULT_OUT_FILE2;
16304
+ const outPath = path14.isAbsolute(outFile) ? outFile : path14.join(root, srcDir, outFile);
16305
+ const content = createEnvTypeDeclarations(options, outPath);
16306
+ fs6.mkdirSync(path14.dirname(outPath), { recursive: true });
16307
+ writeFileIfChanged(outPath, content);
16308
+ return outPath;
16309
+ }
16310
+ function createEnvTypeDeclarations(options, outPath) {
16311
+ const root = path14.resolve(options.root);
16077
16312
  const configPath = findConfigPath(root, options.configPath);
16078
16313
  const configPaths = [
16079
16314
  ...(options.layerConfigPaths ?? []).filter((value) => fs6.existsSync(value)),
16080
16315
  ...configPath ? [configPath] : []
16081
16316
  ];
16082
16317
  const content = configPaths.length > 1 ? createLayeredConfigBackedEnvTypes(outPath, configPaths) : configPaths.length === 1 ? createConfigBackedEnvTypes(outPath, configPaths[0]) : createEmptyEnvTypes();
16083
- fs6.mkdirSync(path13.dirname(outPath), { recursive: true });
16084
- writeFileIfChanged(outPath, content);
16085
- return outPath;
16318
+ return content;
16086
16319
  }
16087
16320
  function createLayeredConfigBackedEnvTypes(outPath, configPaths) {
16088
16321
  const imports = configPaths.map(
@@ -16138,11 +16371,11 @@ export {};
16138
16371
  }
16139
16372
  function findConfigPath(root, configPath) {
16140
16373
  if (configPath) {
16141
- const resolvedPath = path13.isAbsolute(configPath) ? configPath : path13.join(root, configPath);
16374
+ const resolvedPath = path14.isAbsolute(configPath) ? configPath : path14.join(root, configPath);
16142
16375
  return fs6.existsSync(resolvedPath) ? resolvedPath : null;
16143
16376
  }
16144
16377
  for (const filename of CONFIG_FILENAMES2) {
16145
- const resolvedPath = path13.join(root, filename);
16378
+ const resolvedPath = path14.join(root, filename);
16146
16379
  if (fs6.existsSync(resolvedPath)) {
16147
16380
  return resolvedPath;
16148
16381
  }
@@ -16203,15 +16436,15 @@ export {};
16203
16436
  `;
16204
16437
  }
16205
16438
  function toTypeImportPath(outPath, targetPath) {
16206
- const relativePath2 = path13.relative(path13.dirname(outPath), targetPath).replace(/\\/g, "/").replace(/\.(tsx?|jsx?|mjs|cjs|mts|cts)$/, "");
16439
+ const relativePath2 = path14.relative(path14.dirname(outPath), targetPath).replace(/\\/g, "/").replace(/\.(tsx?|jsx?|mjs|cjs|mts|cts)$/, "");
16207
16440
  return relativePath2.startsWith(".") ? relativePath2 : `./${relativePath2}`;
16208
16441
  }
16209
- var fs6, path13, DEFAULT_OUT_FILE2, CONFIG_FILENAMES2;
16442
+ var fs6, path14, DEFAULT_OUT_FILE2, CONFIG_FILENAMES2;
16210
16443
  var init_env_types = __esm({
16211
16444
  "src/env-types.ts"() {
16212
16445
  "use strict";
16213
16446
  fs6 = __toESM(require("fs"));
16214
- path13 = __toESM(require("path"));
16447
+ path14 = __toESM(require("path"));
16215
16448
  init_write_file_if_changed();
16216
16449
  DEFAULT_OUT_FILE2 = "farm-env.d.ts";
16217
16450
  CONFIG_FILENAMES2 = [
@@ -16233,6 +16466,7 @@ var init_env_types = __esm({
16233
16466
  "config.cjs"
16234
16467
  ];
16235
16468
  __name(generateEnvTypes, "generateEnvTypes");
16469
+ __name(createEnvTypeDeclarations, "createEnvTypeDeclarations");
16236
16470
  __name(createLayeredConfigBackedEnvTypes, "createLayeredConfigBackedEnvTypes");
16237
16471
  __name(findConfigPath, "findConfigPath");
16238
16472
  __name(createConfigBackedEnvTypes, "createConfigBackedEnvTypes");
@@ -16243,8 +16477,8 @@ var init_env_types = __esm({
16243
16477
 
16244
16478
  // src/image-types.ts
16245
16479
  function generateFarmImageTypes(options) {
16246
- const outputPath = options.outFile ? import_node_path4.default.resolve(options.root, options.outFile) : import_node_path4.default.join(options.root, options.srcDir || "src", "farm-images.d.ts");
16247
- (0, import_node_fs3.mkdirSync)(import_node_path4.default.dirname(outputPath), { recursive: true });
16480
+ const outputPath = options.outFile ? import_node_path5.default.resolve(options.root, options.outFile) : import_node_path5.default.join(options.root, options.srcDir || "src", "farm-images.d.ts");
16481
+ (0, import_node_fs3.mkdirSync)(import_node_path5.default.dirname(outputPath), { recursive: true });
16248
16482
  writeFileIfChanged(outputPath, createFarmImageTypeDeclarations());
16249
16483
  return outputPath;
16250
16484
  }
@@ -16268,12 +16502,12 @@ declare module "*?url" {
16268
16502
  }
16269
16503
  `;
16270
16504
  }
16271
- var import_node_fs3, import_node_path4, FARM_STATIC_IMAGE_EXTENSIONS;
16505
+ var import_node_fs3, import_node_path5, FARM_STATIC_IMAGE_EXTENSIONS;
16272
16506
  var init_image_types = __esm({
16273
16507
  "src/image-types.ts"() {
16274
16508
  "use strict";
16275
16509
  import_node_fs3 = require("fs");
16276
- import_node_path4 = __toESM(require("path"));
16510
+ import_node_path5 = __toESM(require("path"));
16277
16511
  init_write_file_if_changed();
16278
16512
  FARM_STATIC_IMAGE_EXTENSIONS = ["avif", "gif", "jpeg", "jpg", "png", "webp"];
16279
16513
  __name(generateFarmImageTypes, "generateFarmImageTypes");
@@ -16285,9 +16519,9 @@ var init_image_types = __esm({
16285
16519
  async function generateFarmI18nTypes(options) {
16286
16520
  if (!options.config.enabled) return void 0;
16287
16521
  const { signatures } = await readFarmI18nCatalogs(options.config);
16288
- const outFile = options.outFile ? (0, import_node_path5.resolve)(options.root, options.outFile) : (0, import_node_path5.join)((0, import_node_path5.resolve)(options.root), options.srcDir || "src", "farm-i18n.d.ts");
16522
+ const outFile = options.outFile ? (0, import_node_path6.resolve)(options.root, options.outFile) : (0, import_node_path6.join)((0, import_node_path6.resolve)(options.root), options.srcDir || "src", "farm-i18n.d.ts");
16289
16523
  const content = renderFarmI18nTypes(options.config.locales, signatures);
16290
- (0, import_node_fs4.mkdirSync)((0, import_node_path5.dirname)(outFile), { recursive: true });
16524
+ (0, import_node_fs4.mkdirSync)((0, import_node_path6.dirname)(outFile), { recursive: true });
16291
16525
  writeFileIfChanged(outFile, content);
16292
16526
  return outFile;
16293
16527
  }
@@ -16328,12 +16562,12 @@ function argumentType(kind) {
16328
16562
  return "string";
16329
16563
  }
16330
16564
  }
16331
- var import_node_fs4, import_node_path5;
16565
+ var import_node_fs4, import_node_path6;
16332
16566
  var init_type_generator2 = __esm({
16333
16567
  "src/i18n/type-generator.ts"() {
16334
16568
  "use strict";
16335
16569
  import_node_fs4 = require("fs");
16336
- import_node_path5 = require("path");
16570
+ import_node_path6 = require("path");
16337
16571
  init_catalog();
16338
16572
  init_write_file_if_changed();
16339
16573
  __name(generateFarmI18nTypes, "generateFarmI18nTypes");
@@ -16357,7 +16591,10 @@ async function generateFarmTypeArtifacts(options) {
16357
16591
  const result = {
16358
16592
  apiRoutes: []
16359
16593
  };
16360
- if (shouldGenerateRoutes) {
16594
+ const unifiedTypesPath = (0, import_path8.join)(root, srcDir, "farm.d.ts");
16595
+ const shouldRefreshUnifiedTypes = shouldGenerateRoutes && !options.routeTypesOutFile || shouldGenerateEnv && !options.envTypesOutFile || shouldGenerateI18n && !options.i18nTypesOutFile;
16596
+ const unifiedSections = [];
16597
+ if (shouldRefreshUnifiedTypes && !options.routeTypesOutFile) {
16361
16598
  const routeOptions = {
16362
16599
  root,
16363
16600
  srcDir,
@@ -16365,10 +16602,17 @@ async function generateFarmTypeArtifacts(options) {
16365
16602
  suppressLintOnLink: options.suppressLintOnLink,
16366
16603
  sourceRoots
16367
16604
  };
16368
- if (options.routeTypesOutFile) {
16369
- routeOptions.outFile = options.routeTypesOutFile;
16370
- }
16371
- result.routeTypesPath = await generateRouteTypes(routeOptions);
16605
+ unifiedSections.push(await createRouteTypeDeclarations(routeOptions, unifiedTypesPath));
16606
+ result.routeTypesPath = unifiedTypesPath;
16607
+ } else if (shouldGenerateRoutes) {
16608
+ result.routeTypesPath = await generateRouteTypes({
16609
+ root,
16610
+ srcDir,
16611
+ outFile: options.routeTypesOutFile,
16612
+ extraRoutes: options.extraRoutes || [],
16613
+ suppressLintOnLink: options.suppressLintOnLink,
16614
+ sourceRoots
16615
+ });
16372
16616
  }
16373
16617
  if (shouldGenerateApi) {
16374
16618
  const generator = new APITypeGenerator(appDirs);
@@ -16380,22 +16624,40 @@ async function generateFarmTypeArtifacts(options) {
16380
16624
  result.apiTypesPath = apiTypesPath;
16381
16625
  result.apiRoutes = apiRoutes;
16382
16626
  }
16383
- if (shouldGenerateEnv) {
16627
+ if (shouldRefreshUnifiedTypes && !options.envTypesOutFile) {
16628
+ unifiedSections.push(
16629
+ createEnvTypeDeclarations(
16630
+ {
16631
+ root,
16632
+ srcDir,
16633
+ configPath: options.configPath,
16634
+ layerConfigPaths: (options.layers ?? []).map((layer) => layer.configFile).filter((configFile) => Boolean(configFile))
16635
+ },
16636
+ unifiedTypesPath
16637
+ )
16638
+ );
16639
+ result.envTypesPath = unifiedTypesPath;
16640
+ } else if (shouldGenerateEnv) {
16384
16641
  result.envTypesPath = await generateEnvTypes({
16385
16642
  root,
16386
16643
  srcDir,
16387
16644
  outFile: options.envTypesOutFile,
16645
+ configPath: options.configPath,
16388
16646
  layerConfigPaths: (options.layers ?? []).map((layer) => layer.configFile).filter((configFile) => Boolean(configFile))
16389
16647
  });
16390
16648
  }
16391
- if (shouldGenerateImages) {
16649
+ if (shouldGenerateImages && options.imageTypesOutFile) {
16392
16650
  result.imageTypesPath = generateFarmImageTypes({
16393
16651
  root,
16394
16652
  srcDir,
16395
16653
  outFile: options.imageTypesOutFile
16396
16654
  });
16397
16655
  }
16398
- if (shouldGenerateI18n && options.i18nConfig) {
16656
+ if (shouldRefreshUnifiedTypes && options.i18nConfig?.enabled && !options.i18nTypesOutFile) {
16657
+ const { signatures } = await readFarmI18nCatalogs(options.i18nConfig);
16658
+ unifiedSections.push(renderFarmI18nTypes(options.i18nConfig.locales, signatures));
16659
+ result.i18nTypesPath = unifiedTypesPath;
16660
+ } else if (shouldGenerateI18n && options.i18nConfig) {
16399
16661
  result.i18nTypesPath = await generateFarmI18nTypes({
16400
16662
  root,
16401
16663
  srcDir,
@@ -16403,9 +16665,35 @@ async function generateFarmTypeArtifacts(options) {
16403
16665
  outFile: options.i18nTypesOutFile
16404
16666
  });
16405
16667
  }
16668
+ if (shouldRefreshUnifiedTypes) {
16669
+ (0, import_fs4.mkdirSync)((0, import_path8.dirname)(unifiedTypesPath), { recursive: true });
16670
+ writeFileIfChanged(
16671
+ unifiedTypesPath,
16672
+ `/**
16673
+ * Generated by Farm.js. Do not edit.
16674
+ * Contains project-specific route, environment, and internationalization types.
16675
+ */
16676
+
16677
+ import "@farm.js/core/image";
16678
+
16679
+ ${unifiedSections.join("\n")}`
16680
+ );
16681
+ result.typesPath = unifiedTypesPath;
16682
+ removeLegacyTypeArtifacts(root, srcDir);
16683
+ }
16406
16684
  return result;
16407
16685
  }
16408
- var import_fs4, import_path8;
16686
+ function removeLegacyTypeArtifacts(root, srcDir) {
16687
+ for (const [fileName, marker] of LEGACY_TYPE_ARTIFACTS) {
16688
+ const filePath = (0, import_path8.join)(root, srcDir, fileName);
16689
+ if (!(0, import_fs4.existsSync)(filePath)) continue;
16690
+ const source = (0, import_fs4.readFileSync)(filePath, "utf8");
16691
+ if (source.includes(marker)) {
16692
+ (0, import_fs4.unlinkSync)(filePath);
16693
+ }
16694
+ }
16695
+ }
16696
+ var import_fs4, import_path8, LEGACY_TYPE_ARTIFACTS;
16409
16697
  var init_type_artifacts = __esm({
16410
16698
  "src/type-artifacts.ts"() {
16411
16699
  "use strict";
@@ -16416,9 +16704,17 @@ var init_type_artifacts = __esm({
16416
16704
  init_env_types();
16417
16705
  init_image_types();
16418
16706
  init_type_generator2();
16707
+ init_catalog();
16419
16708
  init_layers();
16420
16709
  init_write_file_if_changed();
16421
16710
  __name(generateFarmTypeArtifacts, "generateFarmTypeArtifacts");
16711
+ LEGACY_TYPE_ARTIFACTS = [
16712
+ ["farm-routes.d.ts", "Auto-generated route types"],
16713
+ ["farm-env.d.ts", "Auto-generated env types"],
16714
+ ["farm-images.d.ts", "Generated by Farm.js"],
16715
+ ["farm-i18n.d.ts", "Generated by Farm.js"]
16716
+ ];
16717
+ __name(removeLegacyTypeArtifacts, "removeLegacyTypeArtifacts");
16422
16718
  }
16423
16719
  });
16424
16720
 
@@ -16775,7 +17071,7 @@ var init_environment_vite = __esm({
16775
17071
  var version;
16776
17072
  var init_package = __esm({
16777
17073
  "package.json"() {
16778
- version = "0.1.0-beta.5";
17074
+ version = "0.1.0-beta.7";
16779
17075
  }
16780
17076
  });
16781
17077
 
@@ -16812,8 +17108,8 @@ function reportAfterError(state, error) {
16812
17108
  function createAfterRequestState(reportError = defaultAfterErrorReporter) {
16813
17109
  let resolveResponseFinished;
16814
17110
  let responseFinished = false;
16815
- const responseFinishedPromise = new Promise((resolve5) => {
16816
- resolveResponseFinished = resolve5;
17111
+ const responseFinishedPromise = new Promise((resolve6) => {
17112
+ resolveResponseFinished = resolve6;
16817
17113
  });
16818
17114
  const state = {
16819
17115
  completion: Promise.resolve(),
@@ -16920,8 +17216,8 @@ function after(callback) {
16920
17216
  throw new Error("after() cannot schedule work after the request lifecycle has completed.");
16921
17217
  }
16922
17218
  let start;
16923
- const ready = new Promise((resolve5) => {
16924
- start = resolve5;
17219
+ const ready = new Promise((resolve6) => {
17220
+ start = resolve6;
16925
17221
  });
16926
17222
  const result = ready.then(callback);
16927
17223
  state.tasks.push({ result, start });
@@ -17046,12 +17342,12 @@ async function createBlurDataURL(bytes) {
17046
17342
  return void 0;
17047
17343
  }
17048
17344
  }
17049
- var import_promises6, import_node_path6, import_image_size2, FARM_IMAGE_ID_PREFIX, STATIC_IMAGE_RE, SCRIPT_IMPORTER_RE;
17345
+ var import_promises6, import_node_path7, import_image_size2, FARM_IMAGE_ID_PREFIX, STATIC_IMAGE_RE, SCRIPT_IMPORTER_RE;
17050
17346
  var init_image_vite = __esm({
17051
17347
  "src/image-vite.ts"() {
17052
17348
  "use strict";
17053
17349
  import_promises6 = require("fs/promises");
17054
- import_node_path6 = __toESM(require("path"));
17350
+ import_node_path7 = __toESM(require("path"));
17055
17351
  import_image_size2 = require("image-size");
17056
17352
  FARM_IMAGE_ID_PREFIX = "\0farm:image:";
17057
17353
  STATIC_IMAGE_RE = /\.(?:avif|gif|jpe?g|png|webp)$/i;
@@ -17486,11 +17782,11 @@ function resolveExistingPath(filePath) {
17486
17782
  try {
17487
17783
  return (0, import_node_fs5.realpathSync)(filePath);
17488
17784
  } catch {
17489
- return import_node_path7.default.resolve(filePath);
17785
+ return import_node_path8.default.resolve(filePath);
17490
17786
  }
17491
17787
  }
17492
17788
  function isDocsSourceFile(filePath) {
17493
- return DOCS_FILE_EXTENSIONS.has(import_node_path7.default.extname(filePath).toLowerCase());
17789
+ return DOCS_FILE_EXTENSIONS.has(import_node_path8.default.extname(filePath).toLowerCase());
17494
17790
  }
17495
17791
  function discoverDocsSourceFiles(contentDir) {
17496
17792
  const files = [];
@@ -17499,7 +17795,7 @@ function discoverDocsSourceFiles(contentDir) {
17499
17795
  (a, b) => a.name.localeCompare(b.name)
17500
17796
  )) {
17501
17797
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
17502
- const absolutePath = import_node_path7.default.join(dir, entry.name);
17798
+ const absolutePath = import_node_path8.default.join(dir, entry.name);
17503
17799
  if (entry.isDirectory()) {
17504
17800
  visit(absolutePath);
17505
17801
  } else if (entry.isFile() && isDocsSourceFile(absolutePath)) {
@@ -17517,7 +17813,7 @@ function getGitLastModifiedDates(contentDir) {
17517
17813
  stdio: ["ignore", "pipe", "ignore"]
17518
17814
  }).trim();
17519
17815
  if (!gitRoot) return {};
17520
- const contentPathspec = normalizeRelativePath(import_node_path7.default.relative(gitRoot, contentDir)) || ".";
17816
+ const contentPathspec = normalizeRelativePath(import_node_path8.default.relative(gitRoot, contentDir)) || ".";
17521
17817
  const contentPrefix = contentPathspec === "." ? "" : `${contentPathspec}/`;
17522
17818
  const history = (0, import_node_child_process.execFileSync)(
17523
17819
  "git",
@@ -17559,7 +17855,7 @@ function getGitLastModifiedDates(contentDir) {
17559
17855
  }
17560
17856
  }
17561
17857
  function readManifest(contentDir) {
17562
- const manifestPath = import_node_path7.default.join(contentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
17858
+ const manifestPath = import_node_path8.default.join(contentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
17563
17859
  if (!(0, import_node_fs5.existsSync)(manifestPath)) return null;
17564
17860
  try {
17565
17861
  const parsed = JSON.parse(
@@ -17582,14 +17878,14 @@ function createFarmDocsLastModifiedManifest(contentDir, options = {}) {
17582
17878
  const fallbackDate = (options.now ?? /* @__PURE__ */ new Date()).toISOString();
17583
17879
  const pages = {};
17584
17880
  for (const sourcePath of discoverDocsSourceFiles(resolvedContentDir)) {
17585
- const relativePath2 = normalizeRelativePath(import_node_path7.default.relative(resolvedContentDir, sourcePath));
17881
+ const relativePath2 = normalizeRelativePath(import_node_path8.default.relative(resolvedContentDir, sourcePath));
17586
17882
  pages[relativePath2] = gitDates[relativePath2] || (options.fallback === "now" ? fallbackDate : (0, import_node_fs5.statSync)(sourcePath).mtime.toISOString());
17587
17883
  }
17588
17884
  return { version: 1, pages };
17589
17885
  }
17590
17886
  function getLastModifiedManifest(contentDir) {
17591
17887
  const resolvedContentDir = resolveExistingPath(contentDir);
17592
- const manifestPath = import_node_path7.default.join(resolvedContentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
17888
+ const manifestPath = import_node_path8.default.join(resolvedContentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
17593
17889
  const manifestStat = (0, import_node_fs5.existsSync)(manifestPath) ? (0, import_node_fs5.statSync)(manifestPath) : null;
17594
17890
  const signature = manifestStat ? `file:${manifestStat.mtimeMs}:${manifestStat.size}` : "generated";
17595
17891
  const cached = manifestCache.get(resolvedContentDir);
@@ -17603,21 +17899,21 @@ function resolveFarmDocsPageLastModified(contentDir, sourcePath, frontmatter) {
17603
17899
  if (configured) return configured;
17604
17900
  const resolvedContentDir = resolveExistingPath(contentDir);
17605
17901
  const resolvedSourcePath = resolveExistingPath(sourcePath);
17606
- const relativePath2 = normalizeRelativePath(import_node_path7.default.relative(resolvedContentDir, resolvedSourcePath));
17607
- const isInsideContentDir = relativePath2 !== ".." && !relativePath2.startsWith("../") && !import_node_path7.default.isAbsolute(relativePath2);
17902
+ const relativePath2 = normalizeRelativePath(import_node_path8.default.relative(resolvedContentDir, resolvedSourcePath));
17903
+ const isInsideContentDir = relativePath2 !== ".." && !relativePath2.startsWith("../") && !import_node_path8.default.isAbsolute(relativePath2);
17608
17904
  if (isInsideContentDir) {
17609
17905
  const generated = getLastModifiedManifest(resolvedContentDir).pages[relativePath2];
17610
17906
  if (generated) return generated;
17611
17907
  }
17612
17908
  return (0, import_node_fs5.statSync)(resolvedSourcePath).mtime.toISOString();
17613
17909
  }
17614
- var import_node_child_process, import_node_fs5, import_node_path7, FARM_DOCS_LAST_MODIFIED_MANIFEST, COMMIT_MARKER, DOCS_FILE_EXTENSIONS, manifestCache;
17910
+ var import_node_child_process, import_node_fs5, import_node_path8, FARM_DOCS_LAST_MODIFIED_MANIFEST, COMMIT_MARKER, DOCS_FILE_EXTENSIONS, manifestCache;
17615
17911
  var init_last_modified = __esm({
17616
17912
  "src/docs/last-modified.ts"() {
17617
17913
  "use strict";
17618
17914
  import_node_child_process = require("child_process");
17619
17915
  import_node_fs5 = require("fs");
17620
- import_node_path7 = __toESM(require("path"));
17916
+ import_node_path8 = __toESM(require("path"));
17621
17917
  FARM_DOCS_LAST_MODIFIED_MANIFEST = ".farm-docs-last-modified.json";
17622
17918
  COMMIT_MARKER = "__FARM_DOCS_COMMIT__";
17623
17919
  DOCS_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".mdx"]);
@@ -18055,8 +18351,8 @@ code:not(pre code) {
18055
18351
  }
18056
18352
 
18057
18353
  .code-block-header {
18058
- min-height: 28px;
18059
- padding: 3px 7px 3px 9px;
18354
+ min-height: 34px;
18355
+ padding: 4px 8px 4px 10px;
18060
18356
  }
18061
18357
 
18062
18358
  .code-block-title {
@@ -18270,8 +18566,8 @@ code:not(pre code) {
18270
18566
  }
18271
18567
 
18272
18568
  .code-block-header {
18273
- min-height: 26px;
18274
- padding: 2px 6px 2px 8px;
18569
+ min-height: 32px;
18570
+ padding: 3px 7px 3px 9px;
18275
18571
  }
18276
18572
 
18277
18573
  .code-copy-floating {
@@ -18311,38 +18607,30 @@ code:not(pre code) {
18311
18607
 
18312
18608
  @media (max-width: 640px) {
18313
18609
  .code-block-header {
18314
- min-height: 22px;
18315
- padding: 1px 4px 1px 7px;
18316
- }
18317
-
18318
- .code-block-title {
18319
- font-size: 9px;
18320
- }
18321
-
18322
- .code-copy {
18323
- width: 20px;
18324
- height: 20px;
18325
- }
18326
-
18327
- .code-copy svg {
18328
- width: 12px;
18329
- height: 12px;
18610
+ min-height: 30px;
18611
+ padding: 3px 6px 3px 8px;
18330
18612
  }
18331
18613
 
18332
18614
  .code-copy-floating {
18333
- top: 5px;
18334
- right: 5px;
18615
+ top: 7px;
18616
+ right: 7px;
18335
18617
  }
18336
18618
 
18337
18619
  #nd-docs-layout figure.shiki.code-block pre,
18338
18620
  .code-block pre {
18339
- padding: 10px !important;
18340
- font-size: 11px;
18341
- line-height: 1.55;
18621
+ padding: 12px !important;
18622
+ font-size: 12px;
18623
+ line-height: 1.6;
18624
+ }
18625
+
18626
+ #nd-docs-layout figure.shiki.code-block-plain pre,
18627
+ .code-block-plain pre {
18628
+ padding: 16px 44px 16px 14px !important;
18629
+ line-height: 1.65;
18342
18630
  }
18343
18631
 
18344
18632
  .sh__line {
18345
- min-height: 1.55em;
18633
+ min-height: 1.6em;
18346
18634
  }
18347
18635
  }
18348
18636
 
@@ -18929,9 +19217,9 @@ function isFarmDocsSearchEnabled(docs) {
18929
19217
  }
18930
19218
  function resolveFarmDocsSearchClientModule(root) {
18931
19219
  try {
18932
- const requireFromApp = (0, import_node_module2.createRequire)(import_node_path8.default.join(import_node_path8.default.resolve(root), "package.json"));
19220
+ const requireFromApp = (0, import_node_module3.createRequire)(import_node_path9.default.join(import_node_path9.default.resolve(root), "package.json"));
18933
19221
  const themeEntry = requireFromApp.resolve("@farming-labs/theme");
18934
- const commandSearchModule = import_node_path8.default.join(import_node_path8.default.dirname(themeEntry), "docs-command-search.mjs");
19222
+ const commandSearchModule = import_node_path9.default.join(import_node_path9.default.dirname(themeEntry), "docs-command-search.mjs");
18935
19223
  if ((0, import_node_fs6.existsSync)(commandSearchModule)) return commandSearchModule;
18936
19224
  } catch {
18937
19225
  }
@@ -19071,13 +19359,13 @@ async function mountFarmDocsSearch() {
19071
19359
  window.__FARM_MOUNT_DOCS_SEARCH__ = mountFarmDocsSearch;
19072
19360
  `;
19073
19361
  }
19074
- var import_node_fs6, import_node_module2, import_node_path8;
19362
+ var import_node_fs6, import_node_module3, import_node_path9;
19075
19363
  var init_search_client = __esm({
19076
19364
  "src/docs/search-client.ts"() {
19077
19365
  "use strict";
19078
19366
  import_node_fs6 = require("fs");
19079
- import_node_module2 = require("module");
19080
- import_node_path8 = __toESM(require("path"));
19367
+ import_node_module3 = require("module");
19368
+ import_node_path9 = __toESM(require("path"));
19081
19369
  __name(isFarmDocsSearchEnabled, "isFarmDocsSearchEnabled");
19082
19370
  __name(resolveFarmDocsSearchClientModule, "resolveFarmDocsSearchClientModule");
19083
19371
  __name(generateFarmDocsSearchBootstrapRuntime, "generateFarmDocsSearchBootstrapRuntime");
@@ -19101,9 +19389,9 @@ function resolveFarmDocsFavicon(docs, options) {
19101
19389
  if (typeof configuredFavicon === "string" && configuredFavicon.trim()) {
19102
19390
  return configuredFavicon.trim();
19103
19391
  }
19104
- const publicDir = import_node_path9.default.join(import_node_path9.default.resolve(options.root), "public");
19392
+ const publicDir = import_node_path10.default.join(import_node_path10.default.resolve(options.root), "public");
19105
19393
  for (const fileName of FARM_DOCS_FAVICON_FILES) {
19106
- const faviconPath = import_node_path9.default.join(publicDir, fileName);
19394
+ const faviconPath = import_node_path10.default.join(publicDir, fileName);
19107
19395
  if ((0, import_node_fs7.existsSync)(faviconPath) && (0, import_node_fs7.statSync)(faviconPath).isFile()) {
19108
19396
  return `/${fileName}`;
19109
19397
  }
@@ -19138,10 +19426,10 @@ function isSafeSegment(segment) {
19138
19426
  return segment !== ".." && !segment.includes("/") && !segment.includes("\\");
19139
19427
  }
19140
19428
  function resolveInside(root, target) {
19141
- const resolvedRoot = import_node_path9.default.resolve(root);
19142
- const resolvedTarget = import_node_path9.default.resolve(target);
19143
- const relative4 = import_node_path9.default.relative(resolvedRoot, resolvedTarget);
19144
- if (relative4 === "" || !relative4.startsWith("..") && !import_node_path9.default.isAbsolute(relative4)) {
19429
+ const resolvedRoot = import_node_path10.default.resolve(root);
19430
+ const resolvedTarget = import_node_path10.default.resolve(target);
19431
+ const relative4 = import_node_path10.default.relative(resolvedRoot, resolvedTarget);
19432
+ if (relative4 === "" || !relative4.startsWith("..") && !import_node_path10.default.isAbsolute(relative4)) {
19145
19433
  return resolvedTarget;
19146
19434
  }
19147
19435
  return null;
@@ -19155,16 +19443,16 @@ function isFarmDocsRequest(docs, request) {
19155
19443
  return pathname === entry || pathname === `${entry}.md` || pathname.startsWith(`${entry}/`);
19156
19444
  }
19157
19445
  function resolveFarmDocsContentDir(docs, options) {
19158
- const root = import_node_path9.default.resolve(options.root);
19446
+ const root = import_node_path10.default.resolve(options.root);
19159
19447
  const srcDir = options.srcDir || "src";
19160
19448
  const configuredContentDir = docs.contentDir || docs.config.contentDir;
19161
19449
  if (configuredContentDir) {
19162
- return import_node_path9.default.isAbsolute(configuredContentDir) ? configuredContentDir : import_node_path9.default.join(root, configuredContentDir);
19450
+ return import_node_path10.default.isAbsolute(configuredContentDir) ? configuredContentDir : import_node_path10.default.join(root, configuredContentDir);
19163
19451
  }
19164
19452
  const entryDir = docs.config.entry || trimSlashes2(docs.entry) || "docs";
19165
- const appDocsDir = import_node_path9.default.join(root, srcDir, "app", entryDir);
19453
+ const appDocsDir = import_node_path10.default.join(root, srcDir, "app", entryDir);
19166
19454
  if ((0, import_node_fs7.existsSync)(appDocsDir)) return appDocsDir;
19167
- return import_node_path9.default.join(root, entryDir);
19455
+ return import_node_path10.default.join(root, entryDir);
19168
19456
  }
19169
19457
  function getFarmDocsRouteTypeEntries(docs) {
19170
19458
  if (!docs?.enabled) return [];
@@ -19187,10 +19475,10 @@ function getRequestSlug(docs, request) {
19187
19475
  function findDocsPageFile(contentDir, slug) {
19188
19476
  const segments = slug ? slug.split("/").filter(Boolean) : [];
19189
19477
  if (!segments.every(isSafeSegment)) return null;
19190
- const slugDir = import_node_path9.default.join(contentDir, ...segments);
19191
- const candidates = segments.length === 0 ? DOCS_FILE_NAMES.map((filename) => import_node_path9.default.join(contentDir, filename)) : [
19192
- ...DOCS_FILE_NAMES.map((filename) => import_node_path9.default.join(slugDir, filename)),
19193
- ...DOCS_FILE_EXTENSIONS2.map((extension) => import_node_path9.default.join(contentDir, `${slug}${extension}`))
19478
+ const slugDir = import_node_path10.default.join(contentDir, ...segments);
19479
+ const candidates = segments.length === 0 ? DOCS_FILE_NAMES.map((filename) => import_node_path10.default.join(contentDir, filename)) : [
19480
+ ...DOCS_FILE_NAMES.map((filename) => import_node_path10.default.join(slugDir, filename)),
19481
+ ...DOCS_FILE_EXTENSIONS2.map((extension) => import_node_path10.default.join(contentDir, `${slug}${extension}`))
19194
19482
  ];
19195
19483
  for (const candidate of candidates) {
19196
19484
  const safePath = resolveInside(contentDir, candidate);
@@ -19251,9 +19539,9 @@ function createDocsHref(entry, slug) {
19251
19539
  return normalizedSlug ? `${normalizedEntry}/${normalizedSlug}` : normalizedEntry;
19252
19540
  }
19253
19541
  function pathToSlug(contentDir, filePath) {
19254
- const relative4 = import_node_path9.default.relative(contentDir, filePath).replace(/\\/g, "/");
19542
+ const relative4 = import_node_path10.default.relative(contentDir, filePath).replace(/\\/g, "/");
19255
19543
  if (relative4.startsWith("..")) return null;
19256
- const extension = import_node_path9.default.extname(relative4);
19544
+ const extension = import_node_path10.default.extname(relative4);
19257
19545
  if (!DOCS_FILE_EXTENSIONS2.includes(extension)) return null;
19258
19546
  const withoutExtension = relative4.slice(0, -extension.length);
19259
19547
  if (withoutExtension === "page" || withoutExtension === "index") return "";
@@ -19271,7 +19559,7 @@ function discoverFarmDocsPages(contentDir, docs) {
19271
19559
  const visit = /* @__PURE__ */ __name((dir) => {
19272
19560
  for (const entry of (0, import_node_fs7.readdirSync)(dir, { withFileTypes: true })) {
19273
19561
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
19274
- const absolutePath = import_node_path9.default.join(dir, entry.name);
19562
+ const absolutePath = import_node_path10.default.join(dir, entry.name);
19275
19563
  if (entry.isDirectory()) {
19276
19564
  visit(absolutePath);
19277
19565
  continue;
@@ -20110,13 +20398,13 @@ ${renderDocsHashRuntimeScript()}
20110
20398
  ${renderDocsPageActionsRuntimeScript()}`;
20111
20399
  }
20112
20400
  function readCssWithImports(filePath, seen = /* @__PURE__ */ new Set()) {
20113
- const resolved = import_node_path9.default.resolve(filePath);
20401
+ const resolved = import_node_path10.default.resolve(filePath);
20114
20402
  if (seen.has(resolved)) return "";
20115
20403
  seen.add(resolved);
20116
20404
  const source = (0, import_node_fs7.readFileSync)(resolved, "utf8");
20117
20405
  return source.replace(/@import\s+["']([^"']+)["'];?/g, (_match, importPath) => {
20118
20406
  try {
20119
- const importedPath = importPath.startsWith(".") ? import_node_path9.default.resolve(import_node_path9.default.dirname(resolved), importPath) : (0, import_node_module3.createRequire)(resolved).resolve(importPath);
20407
+ const importedPath = importPath.startsWith(".") ? import_node_path10.default.resolve(import_node_path10.default.dirname(resolved), importPath) : (0, import_node_module4.createRequire)(resolved).resolve(importPath);
20120
20408
  return readCssWithImports(importedPath, seen);
20121
20409
  } catch {
20122
20410
  return "";
@@ -20124,13 +20412,13 @@ function readCssWithImports(filePath, seen = /* @__PURE__ */ new Set()) {
20124
20412
  });
20125
20413
  }
20126
20414
  function resolvePixelBorderThemeCss(options) {
20127
- const cacheKey = import_node_path9.default.resolve(options.root);
20415
+ const cacheKey = import_node_path10.default.resolve(options.root);
20128
20416
  const cached = themeCssCache.get(cacheKey);
20129
20417
  if (cached !== void 0) return cached;
20130
20418
  try {
20131
- const requireFromApp = (0, import_node_module3.createRequire)(import_node_path9.default.join(cacheKey, "package.json"));
20419
+ const requireFromApp = (0, import_node_module4.createRequire)(import_node_path10.default.join(cacheKey, "package.json"));
20132
20420
  const themeCssPath = requireFromApp.resolve("@farming-labs/theme/pixel-border/css");
20133
- const requireFromTheme = (0, import_node_module3.createRequire)(themeCssPath);
20421
+ const requireFromTheme = (0, import_node_module4.createRequire)(themeCssPath);
20134
20422
  const fumadocsCssPath = requireFromTheme.resolve("fumadocs-ui/style.css");
20135
20423
  const css = `${readCssWithImports(fumadocsCssPath)}
20136
20424
  ${readCssWithImports(themeCssPath)}`;
@@ -20246,7 +20534,7 @@ function renderFarmDocsBridgeCss(docs) {
20246
20534
  .sh-code { --sh-class: #e5c07b; --sh-identifier: #c8ccd4; --sh-string: #98c379; --sh-keyword: #c678dd; --sh-comment: #5c6370; --sh-property: #e06c75; --sh-sign: #c8ccd4; --sh-space: inherit; }
20247
20535
  .code-block { --fd-code-header-bg: color-mix(in srgb, var(--color-fd-foreground, #fff) 5%, var(--color-fd-background, #000)); --fd-code-body-bg: color-mix(in srgb, var(--color-fd-foreground, #fff) 8%, var(--color-fd-background, #000)); position: relative; width: 100%; min-width: 0; max-width: 100%; margin: 20px 0; overflow: hidden; border: 1px solid var(--color-fd-border, hsl(0 0% 15%)); background: var(--color-fd-background, hsl(0 0% 2%)); box-shadow: 3px 3px 0 0 var(--color-fd-border, hsl(0 0% 15%)); font-family: var(--fd-docs-font-mono); }
20248
20536
  #nd-docs-layout figure.shiki.code-block { box-shadow: 3px 3px 0 0 var(--color-fd-border, hsl(0 0% 15%)) !important; }
20249
- .code-block-header { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-width: 0; min-height: 30px; border-bottom: 1px solid var(--color-fd-border, hsl(0 0% 15%)); background-color: var(--fd-code-header-bg); background-image: repeating-linear-gradient(-45deg, color-mix(in srgb, var(--color-fd-foreground, #fff) 7%, transparent), color-mix(in srgb, var(--color-fd-foreground, #fff) 7%, transparent) 1px, transparent 1px, transparent 6px); padding: 4px 8px 4px 10px; }
20537
+ .code-block-header { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-width: 0; min-height: 34px; border-bottom: 1px solid var(--color-fd-border, hsl(0 0% 15%)); background-color: var(--fd-code-header-bg); background-image: repeating-linear-gradient(-45deg, color-mix(in srgb, var(--color-fd-foreground, #fff) 4%, transparent), color-mix(in srgb, var(--color-fd-foreground, #fff) 4%, transparent) 1px, transparent 1px, transparent 6px); padding: 4px 8px 4px 10px; }
20250
20538
  .code-block-title { overflow: hidden; color: color-mix(in srgb, var(--color-fd-foreground, #fff) 50%, transparent); font-size: 10px; line-height: 1.2; text-overflow: ellipsis; text-transform: lowercase; white-space: nowrap; }
20251
20539
  .code-copy { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; flex: 0 0 auto; border: 1px solid var(--color-fd-border, hsl(0 0% 15%)); background: color-mix(in srgb, var(--color-fd-background, #000) 80%, transparent); color: var(--color-fd-muted-foreground, hsl(0 0% 55%)); cursor: pointer; padding: 0; }
20252
20540
  .code-copy-floating { position: absolute; top: 8px; right: 8px; z-index: 2; opacity: 0.72; transition: opacity 150ms ease; }
@@ -20314,7 +20602,7 @@ function renderFarmDocsBridgeCss(docs) {
20314
20602
  .prose h2 { margin-top: 34px; padding-top: 22px; font-size: 23px; }
20315
20603
  .code-block { margin: 16px 0; box-shadow: 2px 2px 0 0 var(--color-fd-border, hsl(0 0% 15%)); }
20316
20604
  #nd-docs-layout figure.shiki.code-block { box-shadow: 2px 2px 0 0 var(--color-fd-border, hsl(0 0% 15%)) !important; }
20317
- .code-block-header { min-height: 26px; padding: 2px 6px 2px 8px; }
20605
+ .code-block-header { min-height: 32px; padding: 3px 7px 3px 9px; }
20318
20606
  .code-copy-floating { top: 6px; right: 6px; }
20319
20607
  #nd-docs-layout figure.shiki.code-block pre, .code-block pre { padding: 12px 11px !important; font-size: 12px; line-height: 1.5; }
20320
20608
  .sh__line { min-height: 1.5em; }
@@ -20324,13 +20612,11 @@ function renderFarmDocsBridgeCss(docs) {
20324
20612
  .fd-page-footer .fd-last-updated-footer { margin-left: 0; }
20325
20613
  }
20326
20614
  @media (max-width: 640px) {
20327
- .code-block-header { min-height: 22px; padding: 1px 4px 1px 7px; }
20328
- .code-block-title { font-size: 9px; }
20329
- .code-copy { width: 20px; height: 20px; }
20330
- .code-copy svg { width: 12px; height: 12px; }
20331
- .code-copy-floating { top: 5px; right: 5px; }
20332
- #nd-docs-layout figure.shiki.code-block pre, .code-block pre { padding: 10px !important; font-size: 11px; line-height: 1.55; }
20333
- .sh__line { min-height: 1.55em; }
20615
+ .code-block-header { min-height: 30px; padding: 3px 6px 3px 8px; }
20616
+ .code-copy-floating { top: 7px; right: 7px; }
20617
+ #nd-docs-layout figure.shiki.code-block pre, .code-block pre { padding: 12px !important; font-size: 12px; line-height: 1.6; }
20618
+ #nd-docs-layout figure.shiki.code-block-plain pre, .code-block-plain pre { padding: 16px 44px 16px 14px !important; line-height: 1.65; }
20619
+ .sh__line { min-height: 1.6em; }
20334
20620
  }
20335
20621
  ${farmDocsPixelBorderCss}
20336
20622
  `;
@@ -20449,13 +20735,13 @@ function createFarmDocsHandler(docs, options) {
20449
20735
  );
20450
20736
  }, "handleFarmDocsRequest");
20451
20737
  }
20452
- var import_node_fs7, import_node_module3, import_node_path9, import_docs, import_marked, import_sugar_high, DOCS_FILE_NAMES, DOCS_FILE_EXTENSIONS2, FARM_DOCS_FALLBACK_FAVICON, FARM_DOCS_FAVICON_FILES, GEIST_SANS_FONT_URL, GEIST_MONO_FONT_URL, CODE_LANGUAGE_LABELS, EXTENSIONLESS_CODE_FILENAMES, SIDEBAR_SECTION_ORDER, SIDEBAR_PAGE_ORDER, themeCssCache;
20738
+ var import_node_fs7, import_node_module4, import_node_path10, import_docs, import_marked, import_sugar_high, DOCS_FILE_NAMES, DOCS_FILE_EXTENSIONS2, FARM_DOCS_FALLBACK_FAVICON, FARM_DOCS_FAVICON_FILES, GEIST_SANS_FONT_URL, GEIST_MONO_FONT_URL, CODE_LANGUAGE_LABELS, EXTENSIONLESS_CODE_FILENAMES, SIDEBAR_SECTION_ORDER, SIDEBAR_PAGE_ORDER, themeCssCache;
20453
20739
  var init_handler = __esm({
20454
20740
  "src/docs/handler.ts"() {
20455
20741
  "use strict";
20456
20742
  import_node_fs7 = require("fs");
20457
- import_node_module3 = require("module");
20458
- import_node_path9 = __toESM(require("path"));
20743
+ import_node_module4 = require("module");
20744
+ import_node_path10 = __toESM(require("path"));
20459
20745
  import_docs = require("@farming-labs/docs");
20460
20746
  import_marked = require("marked");
20461
20747
  import_sugar_high = require("sugar-high");
@@ -20790,18 +21076,18 @@ function sanitizeDocsConfig(config) {
20790
21076
  return cloneSerializable(config) || {};
20791
21077
  }
20792
21078
  async function findDocsConfigPath(rootDir, configPath) {
20793
- const { existsSync: existsSync14 } = await import("fs");
21079
+ const { existsSync: existsSync15 } = await import("fs");
20794
21080
  const root = import_path9.default.resolve(rootDir || process.cwd());
20795
21081
  if (configPath) {
20796
21082
  const resolvedPath = import_path9.default.isAbsolute(configPath) ? configPath : import_path9.default.join(root, configPath);
20797
- if (!existsSync14(resolvedPath)) {
21083
+ if (!existsSync15(resolvedPath)) {
20798
21084
  throw new Error(`Could not find docs config at ${configPath}.`);
20799
21085
  }
20800
21086
  return import_path9.default.resolve(resolvedPath);
20801
21087
  }
20802
21088
  for (const filename of DOCS_CONFIG_FILENAMES) {
20803
21089
  const resolvedPath = import_path9.default.join(root, filename);
20804
- if (existsSync14(resolvedPath)) {
21090
+ if (existsSync15(resolvedPath)) {
20805
21091
  return resolvedPath;
20806
21092
  }
20807
21093
  }
@@ -20809,7 +21095,7 @@ async function findDocsConfigPath(rootDir, configPath) {
20809
21095
  }
20810
21096
  async function loadDocsConfig(rootDir, configPath) {
20811
21097
  const fs9 = await import("fs/promises");
20812
- const { pathToFileURL: pathToFileURL3 } = await import("url");
21098
+ const { pathToFileURL: pathToFileURL4 } = await import("url");
20813
21099
  const root = import_path9.default.resolve(rootDir || process.cwd());
20814
21100
  const resolvedPath = await findDocsConfigPath(root, configPath);
20815
21101
  if (!resolvedPath) return void 0;
@@ -20838,7 +21124,7 @@ async function loadDocsConfig(rootDir, configPath) {
20838
21124
  logLevel: "silent",
20839
21125
  sourcemap: "inline"
20840
21126
  });
20841
- const moduleUrl = pathToFileURL3(modulePath).href + `?t=${Date.now()}`;
21127
+ const moduleUrl = pathToFileURL4(modulePath).href + `?t=${Date.now()}`;
20842
21128
  let importedConfig;
20843
21129
  try {
20844
21130
  importedConfig = await import(
@@ -20939,6 +21225,17 @@ async function resolveConfig(userConfig, mode) {
20939
21225
  const mdx = resolveMdxConfig(userConfig.mdx);
20940
21226
  const env2 = resolveEnv(userConfig.env, process.env);
20941
21227
  setEnv(env2);
21228
+ const auth = resolveFarmAuthConfig(userConfig.auth);
21229
+ if (auth.enabled && userConfig.integrations?.auth) {
21230
+ throw new Error(
21231
+ "Choose either the top-level `auth` config or `integrations.auth`; they cannot both own the auth route."
21232
+ );
21233
+ }
21234
+ const nativeAuthIntegration = await resolveFarmAuthIntegration(auth, {
21235
+ root,
21236
+ mode
21237
+ });
21238
+ const integrations = nativeAuthIntegration ? { ...userConfig.integrations, auth: nativeAuthIntegration } : userConfig.integrations || {};
20942
21239
  const generateBuildId = userConfig.generateBuildId || (() => `build-${Date.now()}`);
20943
21240
  const deploymentId = normalizeFarmDeploymentId(
20944
21241
  userConfig.deploymentId || process.env.FARM_DEPLOYMENT_ID || process.env.VERCEL_GIT_COMMIT_SHA || process.env.CF_PAGES_COMMIT_SHA || (mode === "production" ? await generateBuildId() : "development")
@@ -20963,14 +21260,15 @@ async function resolveConfig(userConfig, mode) {
20963
21260
  devtools: resolveFarmDevtoolsConfig(userConfig.devtools, mode),
20964
21261
  storage: userConfig.storage || {},
20965
21262
  cache: userConfig.cache || {},
21263
+ auth,
20966
21264
  suppressLintOnLink: userConfig.suppressLintOnLink ?? false,
20967
21265
  experimental: {
20968
21266
  serverComponents: false,
20969
21267
  serverActions: false,
20970
21268
  ...userConfig.experimental
20971
21269
  },
20972
- plugins: [...resolveIntegrationPlugins(userConfig.integrations), ...userConfig.plugins || []],
20973
- integrations: userConfig.integrations || {},
21270
+ plugins: [...resolveIntegrationPlugins(integrations), ...userConfig.plugins || []],
21271
+ integrations,
20974
21272
  trailingSlash: userConfig.trailingSlash ?? false,
20975
21273
  redirects: /* @__PURE__ */ __name(() => [...redirects, ...routeRuleRedirects], "redirects"),
20976
21274
  rewrites: /* @__PURE__ */ __name(() => rewrites, "rewrites"),
@@ -21015,7 +21313,7 @@ async function resolveConfig(userConfig, mode) {
21015
21313
  return resolved;
21016
21314
  }
21017
21315
  async function loadConfig(rootDir, configPath, mode = process.env.NODE_ENV === "production" ? "production" : "development", loadEnvironment) {
21018
- const { existsSync: existsSync14 } = await import("fs");
21316
+ const { existsSync: existsSync15 } = await import("fs");
21019
21317
  const loadEnv = loadEnvironment || (await import("vite")).loadEnv;
21020
21318
  const root = rootDir || process.cwd();
21021
21319
  const loadedEnv = loadEnv(mode, root, "");
@@ -21039,7 +21337,7 @@ async function loadConfig(rootDir, configPath, mode = process.env.NODE_ENV === "
21039
21337
  try {
21040
21338
  const absolutePath = relativePath2.startsWith("/") ? relativePath2 : import_path9.default.join(root, relativePath2);
21041
21339
  const normalizedPath = import_path9.default.resolve(absolutePath);
21042
- if (!existsSync14(normalizedPath)) {
21340
+ if (!existsSync15(normalizedPath)) {
21043
21341
  continue;
21044
21342
  }
21045
21343
  const loadedConfig = await loadFarmConfigFile(normalizedPath, { root });
@@ -21069,6 +21367,7 @@ var init_config2 = __esm({
21069
21367
  init_devtools_config();
21070
21368
  init_image_config();
21071
21369
  init_config();
21370
+ init_auth_config();
21072
21371
  init_config_entry();
21073
21372
  FARM_RESOLVED_CUSTOM_CONTEXT = /* @__PURE__ */ Symbol.for("farm.resolvedCustomContext");
21074
21373
  __name(hasCustomFarmRouteContext, "hasCustomFarmRouteContext");
@@ -21867,8 +22166,8 @@ var init_generator = __esm({
21867
22166
  }
21868
22167
  routeGroups.get(key).push(route2);
21869
22168
  }
21870
- for (const [path28, routeList] of routeGroups) {
21871
- const openAPIPath = this.convertToOpenAPIPath(path28);
22169
+ for (const [path29, routeList] of routeGroups) {
22170
+ const openAPIPath = this.convertToOpenAPIPath(path29);
21872
22171
  spec.paths[openAPIPath] = {};
21873
22172
  for (const route2 of routeList) {
21874
22173
  for (const method of route2.methods) {
@@ -21882,8 +22181,8 @@ var init_generator = __esm({
21882
22181
  /**
21883
22182
  * Convert Farm.js API path to OpenAPI path format
21884
22183
  */
21885
- convertToOpenAPIPath(path28) {
21886
- return path28.replace(/^\/api/, "");
22184
+ convertToOpenAPIPath(path29) {
22185
+ return path29.replace(/^\/api/, "");
21887
22186
  }
21888
22187
  /**
21889
22188
  * Extract request body schema from endpoint
@@ -22045,8 +22344,8 @@ var init_generator = __esm({
22045
22344
  /**
22046
22345
  * Generate operation summary
22047
22346
  */
22048
- generateSummary(path28, method) {
22049
- const cleanPath = path28.replace(/^\/api\//, "");
22347
+ generateSummary(path29, method) {
22348
+ const cleanPath = path29.replace(/^\/api\//, "");
22050
22349
  const pathParts = cleanPath.split("/");
22051
22350
  const lastPart = pathParts[pathParts.length - 1];
22052
22351
  const action = method === "GET" ? "Get" : method === "POST" ? "Create" : method === "PUT" ? "Update" : method === "DELETE" ? "Delete" : method === "PATCH" ? "Update" : method;
@@ -22055,22 +22354,22 @@ var init_generator = __esm({
22055
22354
  /**
22056
22355
  * Generate operation description
22057
22356
  */
22058
- generateDescription(path28, method) {
22059
- const cleanPath = path28.replace(/^\/api\//, "");
22357
+ generateDescription(path29, method) {
22358
+ const cleanPath = path29.replace(/^\/api\//, "");
22060
22359
  return `${method} ${cleanPath} endpoint`;
22061
22360
  }
22062
22361
  /**
22063
22362
  * Generate operation ID
22064
22363
  */
22065
- generateOperationId(path28, method) {
22066
- const cleanPath = path28.replace(/^\/api\//, "").replace(/\//g, "_");
22364
+ generateOperationId(path29, method) {
22365
+ const cleanPath = path29.replace(/^\/api\//, "").replace(/\//g, "_");
22067
22366
  return `${method.toLowerCase()}_${cleanPath}`;
22068
22367
  }
22069
22368
  /**
22070
22369
  * Generate tags for grouping operations
22071
22370
  */
22072
- generateTags(path28) {
22073
- const cleanPath = path28.replace(/^\/api\//, "");
22371
+ generateTags(path29) {
22372
+ const cleanPath = path29.replace(/^\/api\//, "");
22074
22373
  const pathParts = cleanPath.split("/");
22075
22374
  if (pathParts.length > 1) {
22076
22375
  return [pathParts[0]];
@@ -22083,8 +22382,8 @@ var init_generator = __esm({
22083
22382
  async generateSpecFile(routes, outputPath) {
22084
22383
  const spec = await this.generateSpec(routes);
22085
22384
  const fs9 = require("fs");
22086
- const path28 = require("path");
22087
- const dir = path28.dirname(outputPath);
22385
+ const path29 = require("path");
22386
+ const dir = path29.dirname(outputPath);
22088
22387
  if (!fs9.existsSync(dir)) {
22089
22388
  fs9.mkdirSync(dir, { recursive: true });
22090
22389
  }
@@ -22504,7 +22803,7 @@ async function createFarmDevtoolsSnapshot(input) {
22504
22803
  generatedAt: (input.now?.() || /* @__PURE__ */ new Date()).toISOString(),
22505
22804
  health: resolveHealth(diagnostics),
22506
22805
  project: {
22507
- name: import_node_path10.default.basename(import_node_path10.default.resolve(input.root)),
22806
+ name: import_node_path11.default.basename(import_node_path11.default.resolve(input.root)),
22508
22807
  root: input.root,
22509
22808
  srcDir: input.srcDir,
22510
22809
  basePath: config.basePath || "/",
@@ -22553,11 +22852,11 @@ async function createFarmDevtoolsSnapshot(input) {
22553
22852
  diagnostics
22554
22853
  };
22555
22854
  }
22556
- var import_node_path10;
22855
+ var import_node_path11;
22557
22856
  var init_devtools = __esm({
22558
22857
  "src/devtools.ts"() {
22559
22858
  "use strict";
22560
- import_node_path10 = __toESM(require("path"));
22859
+ import_node_path11 = __toESM(require("path"));
22561
22860
  init_config2();
22562
22861
  init_cron();
22563
22862
  init_route_runtime();
@@ -24381,7 +24680,7 @@ function fileContainsProgrammaticPageRoute(file) {
24381
24680
  }
24382
24681
  function rewriteEarlySsrRelativeImports(options) {
24383
24682
  const cleanId = options.id.split("?", 1)[0];
24384
- if (!path21.isAbsolute(cleanId) || cleanId.replace(/\\/g, "/").includes("/node_modules/")) {
24683
+ if (!path22.isAbsolute(cleanId) || cleanId.replace(/\\/g, "/").includes("/node_modules/")) {
24385
24684
  return null;
24386
24685
  }
24387
24686
  const replacements = [];
@@ -24401,7 +24700,7 @@ function rewriteEarlySsrRelativeImports(options) {
24401
24700
  const suffixIndex = source.value.search(/[?#]/);
24402
24701
  const sourcePath = suffixIndex === -1 ? source.value : source.value.slice(0, suffixIndex);
24403
24702
  const suffix = suffixIndex === -1 ? "" : source.value.slice(suffixIndex);
24404
- const resolvedPath = path21.resolve(path21.dirname(cleanId), sourcePath);
24703
+ const resolvedPath = path22.resolve(path22.dirname(cleanId), sourcePath);
24405
24704
  replacements.push({
24406
24705
  start: source.start,
24407
24706
  end: source.end,
@@ -24477,7 +24776,7 @@ function farmPlugin(options = {}, initialPluginManager) {
24477
24776
  ...layerRoots.length ? {
24478
24777
  server: {
24479
24778
  fs: {
24480
- allow: [path21.resolve(options.root || process.cwd()), ...layerRoots]
24779
+ allow: [path22.resolve(options.root || process.cwd()), ...layerRoots]
24481
24780
  }
24482
24781
  }
24483
24782
  } : {}
@@ -24502,9 +24801,9 @@ function farmPlugin(options = {}, initialPluginManager) {
24502
24801
  },
24503
24802
  server
24504
24803
  );
24505
- const globalsCSSPath = path21.join(server.config.root, "src/app/globals.css");
24804
+ const globalsCSSPath = path22.join(server.config.root, "src/app/globals.css");
24506
24805
  if (!fs7.existsSync(globalsCSSPath)) {
24507
- const appDir = path21.join(server.config.root, "src/app");
24806
+ const appDir = path22.join(server.config.root, "src/app");
24508
24807
  if (!fs7.existsSync(appDir)) {
24509
24808
  fs7.mkdirSync(appDir, { recursive: true });
24510
24809
  }
@@ -24526,10 +24825,10 @@ function farmPlugin(options = {}, initialPluginManager) {
24526
24825
  });
24527
24826
  }
24528
24827
  const sourceRoots = getFarmSourceRoots(farmConfig);
24529
- server.watcher.add(sourceRoots.map((source) => path21.join(source.root, source.srcDir)));
24828
+ server.watcher.add(sourceRoots.map((source) => path22.join(source.root, source.srcDir)));
24530
24829
  if (farmConfig.i18n.enabled) {
24531
24830
  server.watcher.add(
24532
- farmConfig.i18n.messages.includes("{locale}") ? path21.dirname(farmConfig.i18n.messages) : farmConfig.i18n.messages
24831
+ farmConfig.i18n.messages.includes("{locale}") ? path22.dirname(farmConfig.i18n.messages) : farmConfig.i18n.messages
24533
24832
  );
24534
24833
  }
24535
24834
  const workflowConfig = farmConfig.workflows;
@@ -24539,7 +24838,7 @@ function farmPlugin(options = {}, initialPluginManager) {
24539
24838
  ...farmDocsDevRuntime?.getFarmDocsRouteTypeEntries(farmConfig.docs) ?? []
24540
24839
  ], "getExtraRouteTypes");
24541
24840
  const appDirSlugs = sourceRoots.map(
24542
- (source) => path21.join(source.root, source.srcDir, "app").replace(/\\/g, "/")
24841
+ (source) => path22.join(source.root, source.srcDir, "app").replace(/\\/g, "/")
24543
24842
  );
24544
24843
  const generateTypeArtifacts = /* @__PURE__ */ __name(async (reason, selection = ALL_TYPE_ARTIFACTS, log = false) => {
24545
24844
  try {
@@ -24579,7 +24878,7 @@ function farmPlugin(options = {}, initialPluginManager) {
24579
24878
  }, "generateTypeArtifacts");
24580
24879
  await generateTypeArtifacts("startup");
24581
24880
  const srcDirSlugs = sourceRoots.map(
24582
- (source) => path21.join(source.root, source.srcDir).replace(/\\/g, "/")
24881
+ (source) => path22.join(source.root, source.srcDir).replace(/\\/g, "/")
24583
24882
  );
24584
24883
  const layerConfigFiles = new Set(
24585
24884
  farmConfig.layers.map((layer) => layer.configFile?.replace(/\\/g, "/")).filter((file) => Boolean(file))
@@ -24697,7 +24996,7 @@ function farmPlugin(options = {}, initialPluginManager) {
24697
24996
  await apiRouteManager.discoverRoutes();
24698
24997
  let discoveredWorkflows = [];
24699
24998
  const hasWorkflowDirectory = workflowConfig.enabled && workflowConfig.dirs.some(
24700
- (dir) => fs7.existsSync(path21.isAbsolute(dir) ? dir : path21.join(farmConfig.root, dir))
24999
+ (dir) => fs7.existsSync(path22.isAbsolute(dir) ? dir : path22.join(farmConfig.root, dir))
24701
25000
  );
24702
25001
  if (hasWorkflowDirectory) {
24703
25002
  const { createFarmWorkflowRequestHandler: createFarmWorkflowRequestHandler2, discoverFarmWorkflows: discoverFarmWorkflows2 } = await loadFarmWorkflowsDevRuntime();
@@ -24775,14 +25074,14 @@ function farmPlugin(options = {}, initialPluginManager) {
24775
25074
  farmDocsDevRuntime ? [
24776
25075
  [
24777
25076
  "/assets/Geist-Variable-CrgPqtmy.woff2",
24778
- path21.join(
25077
+ path22.join(
24779
25078
  farmConfig.root,
24780
25079
  "node_modules/geist/dist/fonts/geist-sans/Geist-Variable.woff2"
24781
25080
  )
24782
25081
  ],
24783
25082
  [
24784
25083
  "/assets/GeistMono-Variable-BNLlm6Cd.woff2",
24785
- path21.join(
25084
+ path22.join(
24786
25085
  farmConfig.root,
24787
25086
  "node_modules/geist/dist/fonts/geist-mono/GeistMono-Variable.woff2"
24788
25087
  )
@@ -24946,12 +25245,13 @@ function farmPlugin(options = {}, initialPluginManager) {
24946
25245
  config: farmApp.getConfig().mdx,
24947
25246
  resolveSource: /* @__PURE__ */ __name(async (pathname2) => {
24948
25247
  const match = farmApp.getRouteManager().matchRoute(pathname2);
24949
- if (!match.route || !isFarmMarkdownPageFile(match.route.modulePath)) {
25248
+ const sourcePath = match.route?.markdownSourcePath || (match.route && isFarmMarkdownPageFile(match.route.modulePath) ? match.route.modulePath : null);
25249
+ if (!sourcePath) {
24950
25250
  return null;
24951
25251
  }
24952
25252
  return {
24953
- source: await fs7.promises.readFile(match.route.modulePath, "utf8"),
24954
- filePath: match.route.modulePath
25253
+ source: await fs7.promises.readFile(sourcePath, "utf8"),
25254
+ filePath: sourcePath
24955
25255
  };
24956
25256
  }, "resolveSource")
24957
25257
  });
@@ -24972,16 +25272,37 @@ function farmPlugin(options = {}, initialPluginManager) {
24972
25272
  await sendWebResponse(res, markdownResponse);
24973
25273
  return;
24974
25274
  }
25275
+ const markdownPageTarget = resolveMarkdownMirrorTarget(
25276
+ farmApp.getConfig().md,
25277
+ requestPathname,
25278
+ {
25279
+ accept: "text/markdown"
25280
+ }
25281
+ );
25282
+ if (markdownPageTarget && farmApp.getRouteManager().matchRoute(markdownPageTarget.pathname).route) {
25283
+ const vary = res.getHeader("Vary");
25284
+ const varyValues = String(vary || "").split(",").map((value) => value.trim()).filter(Boolean);
25285
+ if (!varyValues.some((value) => value.toLowerCase() === "accept")) {
25286
+ res.setHeader("Vary", [...varyValues, "Accept"].join(", "));
25287
+ }
25288
+ const alternatePath = markdownPageTarget.pathname === "/" ? "/index.md" : `${markdownPageTarget.pathname}.md`;
25289
+ const alternateLink = `<${alternatePath}>; rel="alternate"; type="text/markdown"`;
25290
+ const currentLink = res.getHeader("Link");
25291
+ res.setHeader(
25292
+ "Link",
25293
+ currentLink ? `${String(currentLink)}, ${alternateLink}` : alternateLink
25294
+ );
25295
+ }
24975
25296
  if (workflowHandler && (requestPathname === workflowConfig.route || requestPathname.startsWith(`${workflowConfig.route}/`))) {
24976
25297
  let workflowBody;
24977
25298
  if (requestMethod !== "GET" && requestMethod !== "HEAD") {
24978
- workflowBody = await new Promise((resolve5) => {
25299
+ workflowBody = await new Promise((resolve6) => {
24979
25300
  let data = "";
24980
25301
  req.on("data", (chunk) => {
24981
25302
  data += chunk;
24982
25303
  });
24983
25304
  req.on("end", () => {
24984
- resolve5(data);
25305
+ resolve6(data);
24985
25306
  });
24986
25307
  });
24987
25308
  }
@@ -25024,13 +25345,13 @@ function farmPlugin(options = {}, initialPluginManager) {
25024
25345
  }
25025
25346
  let body;
25026
25347
  if (req.method !== "GET" && req.method !== "HEAD") {
25027
- body = await new Promise((resolve5) => {
25348
+ body = await new Promise((resolve6) => {
25028
25349
  let data = "";
25029
25350
  req.on("data", (chunk) => {
25030
25351
  data += chunk;
25031
25352
  });
25032
25353
  req.on("end", () => {
25033
- resolve5(data);
25354
+ resolve6(data);
25034
25355
  });
25035
25356
  });
25036
25357
  }
@@ -25136,13 +25457,13 @@ function farmPlugin(options = {}, initialPluginManager) {
25136
25457
  }
25137
25458
  let body;
25138
25459
  if (req.method !== "GET" && req.method !== "HEAD") {
25139
- body = await new Promise((resolve5) => {
25460
+ body = await new Promise((resolve6) => {
25140
25461
  let data = "";
25141
25462
  req.on("data", (chunk) => {
25142
25463
  data += chunk;
25143
25464
  });
25144
25465
  req.on("end", () => {
25145
- resolve5(data);
25466
+ resolve6(data);
25146
25467
  });
25147
25468
  });
25148
25469
  }
@@ -25199,13 +25520,13 @@ function farmPlugin(options = {}, initialPluginManager) {
25199
25520
  }
25200
25521
  let body;
25201
25522
  if (req.method !== "GET" && req.method !== "HEAD") {
25202
- body = await new Promise((resolve5) => {
25523
+ body = await new Promise((resolve6) => {
25203
25524
  let data = "";
25204
25525
  req.on("data", (chunk) => {
25205
25526
  data += chunk;
25206
25527
  });
25207
25528
  req.on("end", () => {
25208
- resolve5(data);
25529
+ resolve6(data);
25209
25530
  });
25210
25531
  });
25211
25532
  }
@@ -25925,8 +26246,8 @@ if (import.meta.hot) {
25925
26246
  }
25926
26247
  logger.info(`Found ${ssgPages.length} SSG pages, ${ssrRoutes.length} SSR routes`);
25927
26248
  logger.info("Pre-rendering SSG pages...");
25928
- const outDir = path21.join(server?.config.root || process.cwd(), options.outDir || "dist");
25929
- const clientDir = path21.join(outDir, "client");
26249
+ const outDir = path22.join(server?.config.root || process.cwd(), options.outDir || "dist");
26250
+ const clientDir = path22.join(outDir, "client");
25930
26251
  for (const page2 of ssgPages) {
25931
26252
  try {
25932
26253
  const staticRequest = new Request(new URL(page2.urlPath, "http://farm.static"));
@@ -25978,8 +26299,8 @@ if (import.meta.hot) {
25978
26299
  <script type="module" src="/assets/client.js"></script>
25979
26300
  </body>
25980
26301
  </html>`;
25981
- const outputPath = page2.urlPath === "/" ? path21.join(clientDir, "index.html") : path21.join(clientDir, page2.urlPath + ".html");
25982
- fs7.mkdirSync(path21.dirname(outputPath), { recursive: true });
26302
+ const outputPath = page2.urlPath === "/" ? path22.join(clientDir, "index.html") : path22.join(clientDir, page2.urlPath + ".html");
26303
+ fs7.mkdirSync(path22.dirname(outputPath), { recursive: true });
25983
26304
  fs7.writeFileSync(outputPath, fullHtml);
25984
26305
  const revalidateInfo = page2.revalidate ? ` (revalidate: ${page2.revalidate}s)` : "";
25985
26306
  logger.success(` \u2713 ${page2.urlPath}${revalidateInfo}`);
@@ -25988,7 +26309,7 @@ if (import.meta.hot) {
25988
26309
  logger.error(` \u2717 ${page2.urlPath}: ${error}`);
25989
26310
  }
25990
26311
  }
25991
- const manifestPath = path21.join(outDir, "__ssg_manifest.json");
26312
+ const manifestPath = path22.join(outDir, "__ssg_manifest.json");
25992
26313
  fs7.writeFileSync(
25993
26314
  manifestPath,
25994
26315
  JSON.stringify(
@@ -26024,9 +26345,9 @@ if (import.meta.hot) {
26024
26345
  }
26025
26346
  const currentFarmConfig = farmApp?.getConfig();
26026
26347
  const normalizedFile = file.replace(/\\/g, "/");
26027
- const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) => path21.join(source.root, source.srcDir).replace(/\\/g, "/")).find((sourceRoot) => normalizedFile.startsWith(`${sourceRoot}/`)) || null : null;
26348
+ const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) => path22.join(source.root, source.srcDir).replace(/\\/g, "/")).find((sourceRoot) => normalizedFile.startsWith(`${sourceRoot}/`)) || null : null;
26028
26349
  if (currentSrcRoot && normalizedFile.startsWith(`${currentSrcRoot}/`) && isProgrammaticRoutesFileName(normalizedFile)) {
26029
- logUpdate("PAGE", `updated ${path21.basename(file)}`);
26350
+ logUpdate("PAGE", `updated ${path22.basename(file)}`);
26030
26351
  for (const mod of modules) {
26031
26352
  server2.moduleGraph.invalidateModule(mod);
26032
26353
  }
@@ -27063,6 +27384,7 @@ async function buildRouteComponentProps(pageModule, params, searchParams, path,
27063
27384
  const parsedSearch = parseClientRouteSchema(schemas?.search, searchParams, 'search');
27064
27385
 
27065
27386
  return {
27387
+ ...(existingProps || {}),
27066
27388
  params: parsedParams,
27067
27389
  search: parsedSearch,
27068
27390
  searchParams: schemas ? Promise.resolve(parsedSearch) : parsedSearch,
@@ -27576,7 +27898,7 @@ function generateClientManifest(bundle) {
27576
27898
  }
27577
27899
  async function defineConfig2(config = {}) {
27578
27900
  const tailwindcss = (await import("@tailwindcss/vite")).default;
27579
- const appRoot = path21.resolve(config.root || process.cwd());
27901
+ const appRoot = path22.resolve(config.root || process.cwd());
27580
27902
  if (config.extends?.length) {
27581
27903
  const { config: layeredConfig } = await Promise.resolve().then(() => (init_layers(), layers_exports)).then(
27582
27904
  ({ resolveFarmLayers: resolveFarmLayers2 }) => resolveFarmLayers2(config, {
@@ -27762,7 +28084,7 @@ async function defineConfig2(config = {}) {
27762
28084
  // Stub out problematic server-only modules during dev mode
27763
28085
  alias: {
27764
28086
  ...getFarmLayerAliases(config.layers),
27765
- "@": path21.resolve(appRoot, "src"),
28087
+ "@": path22.resolve(appRoot, "src"),
27766
28088
  // Nitro internals that should not be resolved in browser
27767
28089
  "supports-color": "data:text/javascript,export default false; export const supportsColor = false; export const stdout = false; export const stderr = false;",
27768
28090
  "@poppinss/dumper": "data:text/javascript,export default {};",
@@ -27779,7 +28101,7 @@ async function defineConfig2(config = {}) {
27779
28101
  }
27780
28102
  };
27781
28103
  }
27782
- var fs7, path21, ALL_TYPE_ARTIFACTS, createEmptyTypeArtifactSelection, FARM_I18N_CLIENT_BRIDGE_ID, EMPTY_FARM_DOCS_SEARCH_CLIENT_RUNTIME, FARM_CONFIG_FILENAMES;
28104
+ var fs7, path22, ALL_TYPE_ARTIFACTS, createEmptyTypeArtifactSelection, FARM_I18N_CLIENT_BRIDGE_ID, EMPTY_FARM_DOCS_SEARCH_CLIENT_RUNTIME, FARM_CONFIG_FILENAMES;
27783
28105
  var init_vite = __esm({
27784
28106
  "src/vite.ts"() {
27785
28107
  "use strict";
@@ -27800,7 +28122,7 @@ var init_vite = __esm({
27800
28122
  init_route_context();
27801
28123
  init_devtools_config();
27802
28124
  fs7 = __toESM(require("fs"));
27803
- path21 = __toESM(require("path"));
28125
+ path22 = __toESM(require("path"));
27804
28126
  init_layers();
27805
28127
  init_environment_vite();
27806
28128
  init_version();
@@ -27816,7 +28138,7 @@ var init_vite = __esm({
27816
28138
  routes: true,
27817
28139
  api: true,
27818
28140
  env: true,
27819
- images: true,
28141
+ images: false,
27820
28142
  i18n: true
27821
28143
  };
27822
28144
  createEmptyTypeArtifactSelection = /* @__PURE__ */ __name(() => ({
@@ -29233,6 +29555,7 @@ __export(src_exports, {
29233
29555
  applyFarmCacheInvalidations: () => applyFarmCacheInvalidations,
29234
29556
  applyFarmCronVercelCrons: () => applyFarmCronVercelCrons,
29235
29557
  applyFarmWorkflowVercelCrons: () => applyFarmWorkflowVercelCrons,
29558
+ applyMarkdownNegotiationHeaders: () => applyMarkdownNegotiationHeaders,
29236
29559
  applyProductionMiddlewareHeaders: () => applyProductionMiddlewareHeaders,
29237
29560
  asArrayOf: () => asArrayOf,
29238
29561
  asBoolean: () => asBoolean,
@@ -29259,6 +29582,7 @@ __export(src_exports, {
29259
29582
  createDocsAPI: () => createDocsAPI,
29260
29583
  createEndpoint: () => createEndpoint,
29261
29584
  createEnvPlugin: () => createEnvPlugin,
29585
+ createEnvTypeDeclarations: () => createEnvTypeDeclarations,
29262
29586
  createFarmApp: () => createFarmApp,
29263
29587
  createFarmCacheKey: () => createFarmCacheKey,
29264
29588
  createFarmCronCloudflareConfig: () => createFarmCronCloudflareConfig,
@@ -29484,6 +29808,7 @@ __export(src_exports, {
29484
29808
  redirect: () => redirect2,
29485
29809
  redisStorage: () => redisStorage,
29486
29810
  replaceState: () => replaceState,
29811
+ requestAcceptsMarkdown: () => requestAcceptsMarkdown,
29487
29812
  resetFarmObservability: () => resetFarmObservability,
29488
29813
  resolveAppPath: () => resolveAppPath,
29489
29814
  resolveConfig: () => resolveConfig,
@@ -30745,8 +31070,8 @@ function createAPIClient(options = {}) {
30745
31070
  const inflightState = /* @__PURE__ */ new Map();
30746
31071
  const routeMeta = /* @__PURE__ */ new WeakMap();
30747
31072
  let requestCounter = 0;
30748
- const fetchClient = /* @__PURE__ */ __name(async (path28, requestOptions = {}) => {
30749
- const url = new URL(path28, baseURL);
31073
+ const fetchClient = /* @__PURE__ */ __name(async (path29, requestOptions = {}) => {
31074
+ const url = new URL(path29, baseURL);
30750
31075
  if (requestOptions.query) {
30751
31076
  Object.entries(requestOptions.query).forEach(([key, value]) => {
30752
31077
  if (value !== void 0 && value !== null) {
@@ -30781,7 +31106,7 @@ function createAPIClient(options = {}) {
30781
31106
  }
30782
31107
  return { response, data };
30783
31108
  }, "fetchClient");
30784
- const request = /* @__PURE__ */ __name(async (path28, method, input = {}, clientOptions) => {
31109
+ const request = /* @__PURE__ */ __name(async (path29, method, input = {}, clientOptions) => {
30785
31110
  const methodUpper = method.toUpperCase();
30786
31111
  const requestId = `${Date.now()}-${++requestCounter}`;
30787
31112
  const cacheOptions = clientOptions?.cache ? {
@@ -30790,7 +31115,7 @@ function createAPIClient(options = {}) {
30790
31115
  } : void 0;
30791
31116
  const configuredCacheKey = clientOptions?.key ?? cacheOptions?.key;
30792
31117
  const cacheKey = normalizeFarmClientCacheKey(
30793
- configuredCacheKey ?? buildCacheKey(methodUpper, path28, input, baseURL)
31118
+ configuredCacheKey ?? buildCacheKey(methodUpper, path29, input, baseURL)
30794
31119
  );
30795
31120
  const now2 = Date.now();
30796
31121
  const emitStatus = /* @__PURE__ */ __name((phase, payload) => {
@@ -30872,13 +31197,13 @@ function createAPIClient(options = {}) {
30872
31197
  requestId,
30873
31198
  method: methodUpper,
30874
31199
  key: cacheKey,
30875
- path: path28,
31200
+ path: path29,
30876
31201
  input,
30877
31202
  attempt,
30878
31203
  timestamp: Date.now()
30879
31204
  });
30880
31205
  try {
30881
- const { response, data } = await fetchClient(path28, {
31206
+ const { response, data } = await fetchClient(path29, {
30882
31207
  ...input,
30883
31208
  method: methodUpper
30884
31209
  });
@@ -30887,7 +31212,7 @@ function createAPIClient(options = {}) {
30887
31212
  requestId,
30888
31213
  method: methodUpper,
30889
31214
  key: cacheKey,
30890
- path: path28,
31215
+ path: path29,
30891
31216
  input,
30892
31217
  attempt,
30893
31218
  timestamp: Date.now(),
@@ -30910,7 +31235,7 @@ function createAPIClient(options = {}) {
30910
31235
  requestId,
30911
31236
  method: methodUpper,
30912
31237
  key: cacheKey,
30913
- path: path28,
31238
+ path: path29,
30914
31239
  input,
30915
31240
  attempt,
30916
31241
  timestamp: Date.now(),
@@ -30925,7 +31250,7 @@ function createAPIClient(options = {}) {
30925
31250
  attempt += 1;
30926
31251
  const delay2 = typeof clientOptions?.retry?.delay === "function" ? clientOptions.retry.delay(attempt) : clientOptions?.retry?.delay ?? 0;
30927
31252
  if (delay2 > 0) {
30928
- await new Promise((resolve5) => setTimeout(resolve5, delay2));
31253
+ await new Promise((resolve6) => setTimeout(resolve6, delay2));
30929
31254
  }
30930
31255
  }
30931
31256
  })();
@@ -31015,17 +31340,17 @@ function createAPIClient(options = {}) {
31015
31340
  );
31016
31341
  }
31017
31342
  __name(createAPIClient, "createAPIClient");
31018
- function createNestedProxy(path28, client, routeMeta, baseURL, sameOrigin, rootAliases) {
31343
+ function createNestedProxy(path29, client, routeMeta, baseURL, sameOrigin, rootAliases) {
31019
31344
  const target = /* @__PURE__ */ __name(() => {
31020
31345
  }, "target");
31021
31346
  const proxy = new Proxy(target, {
31022
31347
  // When accessing a property (api.hello)
31023
31348
  get(_target, prop) {
31024
31349
  if (prop === FARM_API_ROUTE_REF_SYMBOL) {
31025
- return path28.length > 0;
31350
+ return path29.length > 0;
31026
31351
  }
31027
31352
  if (prop === FARM_API_ROUTE_META_SYMBOL) {
31028
- const metadata = resolveRouteMeta({ path: path28, baseURL });
31353
+ const metadata = resolveRouteMeta({ path: path29, baseURL });
31029
31354
  return Object.freeze({
31030
31355
  path: metadata.routePath,
31031
31356
  method: metadata.method,
@@ -31033,14 +31358,14 @@ function createNestedProxy(path28, client, routeMeta, baseURL, sameOrigin, rootA
31033
31358
  sameOrigin
31034
31359
  });
31035
31360
  }
31036
- if (path28.length === 0 && typeof prop === "string" && rootAliases && prop in rootAliases) {
31361
+ if (path29.length === 0 && typeof prop === "string" && rootAliases && prop in rootAliases) {
31037
31362
  return rootAliases[prop];
31038
31363
  }
31039
31364
  if (typeof prop !== "string") {
31040
31365
  return Reflect.get(_target, prop);
31041
31366
  }
31042
31367
  return createNestedProxy(
31043
- [...path28, prop],
31368
+ [...path29, prop],
31044
31369
  client,
31045
31370
  routeMeta,
31046
31371
  baseURL,
@@ -31050,21 +31375,21 @@ function createNestedProxy(path28, client, routeMeta, baseURL, sameOrigin, rootA
31050
31375
  },
31051
31376
  // When calling as a function
31052
31377
  apply(_target, _thisArg, args) {
31053
- const lastPart = path28[path28.length - 1];
31378
+ const lastPart = path29[path29.length - 1];
31054
31379
  const httpMethods = ["get", "post", "put", "delete", "patch", "options", "head"];
31055
31380
  if (httpMethods.includes(lastPart)) {
31056
- const routePath = "/api/" + path28.slice(0, -1).join("/");
31381
+ const routePath = "/api/" + path29.slice(0, -1).join("/");
31057
31382
  const method = lastPart.toUpperCase();
31058
31383
  const [options, clientOptions] = args;
31059
31384
  return client(routePath, method, options, clientOptions);
31060
31385
  } else {
31061
- const routePath = "/api/" + path28.join("/");
31386
+ const routePath = "/api/" + path29.join("/");
31062
31387
  const [options, clientOptions] = args;
31063
31388
  return client(routePath, options?.method || "GET", options, clientOptions);
31064
31389
  }
31065
31390
  }
31066
31391
  });
31067
- routeMeta.set(proxy, { path: [...path28], baseURL });
31392
+ routeMeta.set(proxy, { path: [...path29], baseURL });
31068
31393
  return proxy;
31069
31394
  }
31070
31395
  __name(createNestedProxy, "createNestedProxy");
@@ -31104,9 +31429,9 @@ function createServerAPIClient(endpoints, options = {}) {
31104
31429
  return endpoints;
31105
31430
  }
31106
31431
  __name(createServerAPIClient, "createServerAPIClient");
31107
- function buildCacheKey(method, path28, input, baseURL) {
31432
+ function buildCacheKey(method, path29, input, baseURL) {
31108
31433
  const keyInput = input && typeof input === "object" ? { query: input.query, body: input.body } : input;
31109
- const url = new URL(path28, baseURL);
31434
+ const url = new URL(path29, baseURL);
31110
31435
  return `${method}:${url.origin}${url.pathname}:${stableStringify(keyInput ?? {})}`;
31111
31436
  }
31112
31437
  __name(buildCacheKey, "buildCacheKey");
@@ -31335,7 +31660,7 @@ function farmApiPlugin(options = {}) {
31335
31660
  configureServer(server) {
31336
31661
  const discoverFileRoutes = /* @__PURE__ */ __name(async (apiDir) => {
31337
31662
  const fs9 = await import("fs");
31338
- const path28 = await import("path");
31663
+ const path29 = await import("path");
31339
31664
  if (!fs9.existsSync(apiDir)) {
31340
31665
  log("No api directory found");
31341
31666
  return;
@@ -31345,7 +31670,7 @@ function farmApiPlugin(options = {}) {
31345
31670
  if (!fs9.existsSync(dir)) return files;
31346
31671
  const entries = fs9.readdirSync(dir, { withFileTypes: true });
31347
31672
  for (const entry of entries) {
31348
- const fullPath = path28.join(dir, entry.name);
31673
+ const fullPath = path29.join(dir, entry.name);
31349
31674
  if (entry.isDirectory()) {
31350
31675
  files.push(...findRouteFiles(fullPath));
31351
31676
  } else if (entry.name === "route.ts" || entry.name === "route.tsx" || entry.name === "route.js") {
@@ -31358,7 +31683,7 @@ function farmApiPlugin(options = {}) {
31358
31683
  apiRoutesCache.clear();
31359
31684
  for (const filePath of routeFiles) {
31360
31685
  try {
31361
- const relativePath2 = path28.relative(apiDir, path28.dirname(filePath));
31686
+ const relativePath2 = path29.relative(apiDir, path29.dirname(filePath));
31362
31687
  const routePath = "/api/" + (relativePath2 === "." ? "" : relativePath2.replace(/\\/g, "/"));
31363
31688
  const routeModule = await server.ssrLoadModule(filePath);
31364
31689
  const endpoints = {};
@@ -31385,11 +31710,11 @@ function farmApiPlugin(options = {}) {
31385
31710
  }, "discoverFileRoutes");
31386
31711
  const discoverRootRoutes = /* @__PURE__ */ __name(async () => {
31387
31712
  const fs9 = await import("fs");
31388
- const path28 = await import("path");
31713
+ const path29 = await import("path");
31389
31714
  const routesFiles = [
31390
- path28.join(server.config.root, srcDir, "routes.ts"),
31391
- path28.join(server.config.root, srcDir, "routes.tsx"),
31392
- path28.join(server.config.root, srcDir, "routes.js")
31715
+ path29.join(server.config.root, srcDir, "routes.ts"),
31716
+ path29.join(server.config.root, srcDir, "routes.tsx"),
31717
+ path29.join(server.config.root, srcDir, "routes.js")
31393
31718
  ];
31394
31719
  for (const routesFile of routesFiles) {
31395
31720
  if (fs9.existsSync(routesFile)) {
@@ -31412,8 +31737,8 @@ function farmApiPlugin(options = {}) {
31412
31737
  }
31413
31738
  }, "discoverRootRoutes");
31414
31739
  const discoverProgrammaticRoutes = /* @__PURE__ */ __name(async () => {
31415
- const path28 = await import("path");
31416
- const srcRoot = path28.join(server.config.root, srcDir);
31740
+ const path29 = await import("path");
31741
+ const srcRoot = path29.join(server.config.root, srcDir);
31417
31742
  const routeFiles = findProgrammaticRouteFilesInDir(srcRoot);
31418
31743
  for (const routeFile of routeFiles) {
31419
31744
  try {
@@ -31437,8 +31762,8 @@ function farmApiPlugin(options = {}) {
31437
31762
  }
31438
31763
  }, "discoverProgrammaticRoutes");
31439
31764
  const initializeDiscovery = /* @__PURE__ */ __name(async () => {
31440
- const path28 = await import("path");
31441
- const apiDir = path28.join(server.config.root, srcDir, "api");
31765
+ const path29 = await import("path");
31766
+ const apiDir = path29.join(server.config.root, srcDir, "api");
31442
31767
  log(`Discovering API routes in: ${apiDir}`);
31443
31768
  await discoverFileRoutes(apiDir);
31444
31769
  await discoverRootRoutes();
@@ -31493,13 +31818,13 @@ function farmApiPlugin(options = {}) {
31493
31818
  }
31494
31819
  let body;
31495
31820
  if (method !== "GET" && method !== "HEAD") {
31496
- body = await new Promise((resolve5) => {
31821
+ body = await new Promise((resolve6) => {
31497
31822
  let data = "";
31498
31823
  req.on("data", (chunk) => {
31499
31824
  data += chunk;
31500
31825
  });
31501
31826
  req.on("end", () => {
31502
- resolve5(data);
31827
+ resolve6(data);
31503
31828
  });
31504
31829
  });
31505
31830
  }
@@ -31606,9 +31931,9 @@ function farmApiPlugin(options = {}) {
31606
31931
  }
31607
31932
  } else {
31608
31933
  try {
31609
- const path28 = await import("path");
31610
- const apiDir = path28.join(server.config.root, srcDir, "api");
31611
- const relativePath2 = path28.relative(apiDir, path28.dirname(file));
31934
+ const path29 = await import("path");
31935
+ const apiDir = path29.join(server.config.root, srcDir, "api");
31936
+ const relativePath2 = path29.relative(apiDir, path29.dirname(file));
31612
31937
  const routePath = "/api/" + (relativePath2 === "." ? "" : relativePath2.replace(/\\/g, "/"));
31613
31938
  const routeModule = await server.ssrLoadModule(file);
31614
31939
  const endpoints = {};
@@ -31994,8 +32319,8 @@ var _MiddlewareChainImpl = class _MiddlewareChainImpl {
31994
32319
  /**
31995
32320
  * Set the base path for this middleware chain (called by manager when loading)
31996
32321
  */
31997
- setBasePath(path28) {
31998
- this.basePath = path28 === "/" ? "/" : path28.endsWith("/") ? path28.slice(0, -1) : path28;
32322
+ setBasePath(path29) {
32323
+ this.basePath = path29 === "/" ? "/" : path29.endsWith("/") ? path29.slice(0, -1) : path29;
31999
32324
  }
32000
32325
  use(fn) {
32001
32326
  this.handlers.push(fn);
@@ -32816,11 +33141,11 @@ __name(applyProductionMiddlewareHeaders, "applyProductionMiddlewareHeaders");
32816
33141
 
32817
33142
  // src/middleware/vite-plugin.ts
32818
33143
  var import_node_fs8 = __toESM(require("fs"));
32819
- var import_node_path11 = __toESM(require("path"));
33144
+ var import_node_path12 = __toESM(require("path"));
32820
33145
  init_manager();
32821
33146
  function getMiddlewareAppDirectory(root, srcDir) {
32822
- const sourceDirectory = import_node_path11.default.join(root, srcDir);
32823
- const appDirectory = import_node_path11.default.join(sourceDirectory, "app");
33147
+ const sourceDirectory = import_node_path12.default.join(root, srcDir);
33148
+ const appDirectory = import_node_path12.default.join(sourceDirectory, "app");
32824
33149
  return import_node_fs8.default.existsSync(appDirectory) ? appDirectory : sourceDirectory;
32825
33150
  }
32826
33151
  __name(getMiddlewareAppDirectory, "getMiddlewareAppDirectory");
@@ -32866,7 +33191,7 @@ function farmMiddlewarePlugin(options = {}) {
32866
33191
  };
32867
33192
  },
32868
33193
  async handleHotUpdate({ file, server, modules }) {
32869
- if (!/^middleware\.[tj]sx?$/.test(import_node_path11.default.basename(file))) {
33194
+ if (!/^middleware\.[tj]sx?$/.test(import_node_path12.default.basename(file))) {
32870
33195
  return;
32871
33196
  }
32872
33197
  for (const module2 of modules) {
@@ -34398,10 +34723,14 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
34398
34723
  const routeRuntimeManifestResultPromise = Promise.allSettled([routeRuntimeManifestPromise]);
34399
34724
  const pageRoutes = [];
34400
34725
  for (const [pattern, entry] of routeManager.getRoutes()) {
34726
+ const markdownSourcePath = entry.markdownSourcePath || (isFarmMarkdownPageFile(entry.modulePath) ? entry.modulePath : void 0);
34401
34727
  pageRoutes.push({
34402
34728
  pattern,
34403
34729
  modulePath: entry.modulePath,
34404
- ...isFarmMarkdownPageFile(entry.modulePath) ? { source: (0, import_fs5.readFileSync)(entry.modulePath, "utf8") } : {}
34730
+ ...markdownSourcePath ? {
34731
+ source: (0, import_fs5.readFileSync)(markdownSourcePath, "utf8"),
34732
+ markdownSourcePath
34733
+ } : {}
34405
34734
  });
34406
34735
  }
34407
34736
  const routeSlots = Array.from(
@@ -36312,15 +36641,13 @@ function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, routeSlot
36312
36641
  });
36313
36642
  const pageImports = [];
36314
36643
  const pageRegistrations = [];
36315
- const hasMarkdownPages = pageRoutes.some(
36316
- (route2) => route2.source !== void 0 || isFarmMarkdownPageFile(route2.modulePath)
36317
- );
36644
+ const hasMarkdownPages = pageRoutes.some((route2) => route2.source !== void 0);
36318
36645
  const orderedPageRoutes = pageRoutes.map((route2, index) => ({ route: route2, index })).sort(
36319
36646
  (left, right) => routePatternSpecificity(right.route.pattern) - routePatternSpecificity(left.route.pattern) || left.index - right.index
36320
36647
  ).map(({ route: route2 }) => route2);
36321
36648
  orderedPageRoutes.forEach((route2, index) => {
36322
36649
  const varName = `pageRoute${index}`;
36323
- if (route2.source !== void 0 || isFarmMarkdownPageFile(route2.modulePath)) {
36650
+ if (isFarmMarkdownPageFile(route2.modulePath)) {
36324
36651
  pageRegistrations.push(`
36325
36652
  {
36326
36653
  pattern: ${JSON.stringify(route2.pattern)},
@@ -36332,7 +36659,7 @@ function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, routeSlot
36332
36659
  }),
36333
36660
  markdownSource: {
36334
36661
  source: ${JSON.stringify(route2.source ?? "")},
36335
- filePath: ${JSON.stringify(route2.modulePath)},
36662
+ filePath: ${JSON.stringify(route2.markdownSourcePath ?? route2.modulePath)},
36336
36663
  },
36337
36664
  }`);
36338
36665
  return;
@@ -36344,6 +36671,10 @@ function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, routeSlot
36344
36671
  pattern: ${JSON.stringify(route2.pattern)},
36345
36672
  module: ${varName},
36346
36673
  shouldHydrate: ${JSON.stringify(shouldHydrate)},
36674
+ ${route2.source !== void 0 ? `markdownSource: {
36675
+ source: ${JSON.stringify(route2.source)},
36676
+ filePath: ${JSON.stringify(route2.markdownSourcePath)},
36677
+ },` : ""}
36347
36678
  }`);
36348
36679
  });
36349
36680
  const layoutImports = [];
@@ -36449,7 +36780,7 @@ function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, routeSlot
36449
36780
  const docsRuntimeImport = config.docs?.enabled ? `import { existsSync as farmDocsExistsSync } from "node:fs";
36450
36781
  import { dirname as farmDocsDirname, join as farmDocsJoin } from "node:path";
36451
36782
  import { fileURLToPath as farmDocsFileURLToPath } from "node:url";` : "";
36452
- const markdownHandlerImport = config.md?.enabled ? `import { createMarkdownMirrorResponse } from "@farm.js/core/markdown";` : "";
36783
+ const markdownHandlerImport = config.md?.enabled ? `import { applyMarkdownNegotiationHeaders, createMarkdownMirrorResponse } from "@farm.js/core/markdown";` : "";
36453
36784
  const appMarkdownImport = hasMarkdownPages ? `import { createFarmMarkdownRouteModule, createFarmMarkdownSourceResponse } from "@farm.js/core/app-markdown";` : "const createFarmMarkdownSourceResponse = null;";
36454
36785
  const mdxComponentsPath = typeof config.mdx?.components === "string" ? import_path12.default.isAbsolute(config.mdx.components) ? config.mdx.components : import_path12.default.join(config.root, config.mdx.components) : null;
36455
36786
  const mdxComponentsImport = mdxComponentsPath ? `import * as FarmMdxComponentsModule from "${mdxComponentsPath.replace(/\\/g, "/")}";` : "";
@@ -36699,10 +37030,12 @@ function serializeFarmInlineValue(value) {
36699
37030
  .replace(/\\u2029/g, "\\\\u2029");
36700
37031
  }
36701
37032
 
36702
- function renderFarmClientBootstrapScript(canonicalPath, selectedRouteSlots) {
37033
+ function renderFarmClientBootstrapScript(canonicalPath, selectedRouteSlots, pageProps) {
36703
37034
  const integrationManifest = ${hasRuntimeIntegrationConfig ? "getRegisteredIntegrationAPIManifest()" : "{}"};
36704
37035
  const serializedRouteSlots = serializeFarmInlineValue(selectedRouteSlots || []);
36705
- let source = 'window.__FARM_INTEGRATION_API_MANIFEST__=' +
37036
+ const serializedPageProps = serializeFarmInlineValue(pageProps || {});
37037
+ let source = 'window.__FARM_PROPS__=' + serializedPageProps +
37038
+ ';window.__FARM_INTEGRATION_API_MANIFEST__=' +
36706
37039
  serializeFarmInlineValue(integrationManifest) +
36707
37040
  ';window.__FARM_ROUTE_SLOTS__=' + serializedRouteSlots + ';';
36708
37041
  if (typeof canonicalPath === "string" && canonicalPath.startsWith("/")) {
@@ -37753,7 +38086,7 @@ async function getCachedPPRShell(cacheKey) {
37753
38086
  * Main request handler - created at runtime with bundled routes
37754
38087
  */
37755
38088
  async function handleFarmRequest(request) {
37756
- ${config.i18n.enabled ? `return _runWithFarmI18nRequest(
38089
+ const response = await ${config.i18n.enabled ? `_runWithFarmI18nRequest(
37757
38090
  farmI18nRuntime,
37758
38091
  request,
37759
38092
  async function(farmLocaleResolution) {
@@ -37772,7 +38105,15 @@ async function handleFarmRequest(request) {
37772
38105
  const response = await handleFarmRequestInContext(request, farmLocaleResolution);
37773
38106
  return applyFarmI18nResponse(response, farmLocaleResolution);
37774
38107
  }
37775
- );` : "return handleFarmRequestInContext(request, null);"}
38108
+ )` : "handleFarmRequestInContext(request, null)"};
38109
+ ${config.md?.enabled ? `const pathname = getFarmRoutePathname(new URL(request.url).pathname);
38110
+ if (matchPageRoute(pathname)) {
38111
+ return applyMarkdownNegotiationHeaders(response, {
38112
+ config: farmMarkdownConfig,
38113
+ pathname,
38114
+ });
38115
+ }` : ""}
38116
+ return response;
37776
38117
  }
37777
38118
 
37778
38119
  async function handleFarmRequestInContext(
@@ -38134,6 +38475,23 @@ async function handleFarmRequestInContext(
38134
38475
  return { ...slot, props: slotProps };
38135
38476
  }),
38136
38477
  );
38478
+ const clientMiddleware = middlewareData?.size
38479
+ ? { data: Object.fromEntries(middlewareData) }
38480
+ : undefined;
38481
+ const clientPageProps = {
38482
+ params: pageProps.params,
38483
+ search: pageProps.search ?? searchParamsObj,
38484
+ searchParams: pageProps.search ?? searchParamsObj,
38485
+ ...("data" in pageProps ? { data: pageProps.data } : {}),
38486
+ ...(pageProps.__farmCanonicalPath
38487
+ ? { __farmCanonicalPath: pageProps.__farmCanonicalPath }
38488
+ : {}),
38489
+ ...(pageProps.__farmRoutePropsResolved
38490
+ ? { __farmRoutePropsResolved: true }
38491
+ : {}),
38492
+ path: pathname,
38493
+ ...(clientMiddleware ? { middleware: clientMiddleware } : {}),
38494
+ };
38137
38495
  const routeSlotPayload = renderedRouteSlots.map(function(slot) {
38138
38496
  return {
38139
38497
  name: slot.name,
@@ -38148,6 +38506,7 @@ async function handleFarmRequestInContext(
38148
38506
  searchParams: slot.props.search || searchParamsObj,
38149
38507
  ...("data" in slot.props ? { data: slot.props.data } : {}),
38150
38508
  path: pathname,
38509
+ ...(clientMiddleware ? { middleware: clientMiddleware } : {}),
38151
38510
  },
38152
38511
  };
38153
38512
  });
@@ -38303,7 +38662,8 @@ async function handleFarmRequestInContext(
38303
38662
  const streamSuffix = '</div>\\n' +
38304
38663
  ' ' + renderFarmClientBootstrapScript(
38305
38664
  pageProps.__farmCanonicalPath,
38306
- routeSlotPayload
38665
+ routeSlotPayload,
38666
+ clientPageProps
38307
38667
  ) + '\\n' +
38308
38668
  ' <script type="module" src="/farm-client.js"></script>\\n' +
38309
38669
  '</body>\\n</html>';
@@ -38363,7 +38723,8 @@ async function handleFarmRequestInContext(
38363
38723
  /<\\/body>/i,
38364
38724
  ' ' + renderFarmClientBootstrapScript(
38365
38725
  pageProps.__farmCanonicalPath,
38366
- routeSlotPayload
38726
+ routeSlotPayload,
38727
+ clientPageProps
38367
38728
  ) + '\\n' +
38368
38729
  ' <script type="module" src="/farm-client.js"></script>\\n</body>',
38369
38730
  );
@@ -38385,7 +38746,7 @@ async function handleFarmRequestInContext(
38385
38746
  </head>
38386
38747
  <body>
38387
38748
  <div id="root">\${html}</div>
38388
- \${renderFarmClientBootstrapScript(pageProps.__farmCanonicalPath, routeSlotPayload)}
38749
+ \${renderFarmClientBootstrapScript(pageProps.__farmCanonicalPath, routeSlotPayload, clientPageProps)}
38389
38750
  <script type="module" src="/farm-client.js"></script>
38390
38751
  </body>
38391
38752
  </html>\`;
@@ -41117,10 +41478,10 @@ var _FarmClientPluginManager = class _FarmClientPluginManager {
41117
41478
  if (session.signal.aborted) return Promise.resolve();
41118
41479
  const clientWindow = this.options.window;
41119
41480
  const schedule = clientWindow?.requestAnimationFrame ? (callback) => clientWindow.requestAnimationFrame(() => clientWindow.requestAnimationFrame(callback)) : (callback) => setTimeout(callback, 0);
41120
- return new Promise((resolve5) => {
41481
+ return new Promise((resolve6) => {
41121
41482
  schedule(() => {
41122
41483
  if (session.signal.aborted || this.closed) {
41123
- resolve5();
41484
+ resolve6();
41124
41485
  return;
41125
41486
  }
41126
41487
  void this.runHook(
@@ -41134,7 +41495,7 @@ var _FarmClientPluginManager = class _FarmClientPluginManager {
41134
41495
  if (this.currentNavigation?.session === session) {
41135
41496
  this.currentNavigation = void 0;
41136
41497
  }
41137
- resolve5();
41498
+ resolve6();
41138
41499
  });
41139
41500
  });
41140
41501
  });
@@ -41504,6 +41865,7 @@ __name(decodeCookiePart, "decodeCookiePart");
41504
41865
  applyFarmCacheInvalidations,
41505
41866
  applyFarmCronVercelCrons,
41506
41867
  applyFarmWorkflowVercelCrons,
41868
+ applyMarkdownNegotiationHeaders,
41507
41869
  applyProductionMiddlewareHeaders,
41508
41870
  asArrayOf,
41509
41871
  asBoolean,
@@ -41530,6 +41892,7 @@ __name(decodeCookiePart, "decodeCookiePart");
41530
41892
  createDocsAPI,
41531
41893
  createEndpoint,
41532
41894
  createEnvPlugin,
41895
+ createEnvTypeDeclarations,
41533
41896
  createFarmApp,
41534
41897
  createFarmCacheKey,
41535
41898
  createFarmCronCloudflareConfig,
@@ -41755,6 +42118,7 @@ __name(decodeCookiePart, "decodeCookiePart");
41755
42118
  redirect,
41756
42119
  redisStorage,
41757
42120
  replaceState,
42121
+ requestAcceptsMarkdown,
41758
42122
  resetFarmObservability,
41759
42123
  resolveAppPath,
41760
42124
  resolveConfig,