@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/plugin.cjs CHANGED
@@ -222,178 +222,9 @@ var init_request_context = __esm({
222
222
  }
223
223
  });
224
224
 
225
- // src/app-markdown.ts
226
- function resolveMdxConfig(config) {
227
- return {
228
- components: config?.components,
229
- markdownRoutes: config?.markdownRoutes ?? true,
230
- className: config?.className ?? "farm-markdown"
231
- };
232
- }
233
- function isFarmMarkdownPageFile(filePath) {
234
- return /(^|[/\\])page\.mdx?$/i.test(filePath);
235
- }
236
- function normalizeFarmMarkdownRoutePath(pathname) {
237
- const withoutExtension = pathname.replace(/\.md$/i, "");
238
- const normalized = withoutExtension.startsWith("/") ? withoutExtension : `/${withoutExtension}`;
239
- return normalized === "/index" ? "/" : normalized.replace(/\/+$/g, "") || "/";
240
- }
241
- function parseMarkdownFrontmatter(source) {
242
- if (!source.startsWith("---")) {
243
- return { frontmatter: {}, body: source };
244
- }
245
- const endIndex = source.indexOf("\n---", 3);
246
- if (endIndex === -1) {
247
- return { frontmatter: {}, body: source };
248
- }
249
- const frontmatterSource = source.slice(3, endIndex).trim();
250
- const closingFenceEnd = endIndex + "\n---".length;
251
- const bodyStart = source.slice(closingFenceEnd, closingFenceEnd + 2) === "\r\n" ? closingFenceEnd + 2 : source[closingFenceEnd] === "\n" ? closingFenceEnd + 1 : closingFenceEnd;
252
- const body = source.slice(bodyStart);
253
- const frontmatter = {};
254
- for (const line of frontmatterSource.split(/\r?\n/)) {
255
- const separator = line.indexOf(":");
256
- if (separator === -1) continue;
257
- const key = line.slice(0, separator).trim();
258
- const value = line.slice(separator + 1).trim().replace(/^["']|["']$/g, "");
259
- if (key && value) frontmatter[key] = value;
260
- }
261
- return { frontmatter, body };
262
- }
263
- function titleFromMarkdown(body, fallback) {
264
- return body.match(/^#\s+(.+)$/m)?.[1]?.trim() || fallback;
265
- }
266
- function createMarkdownMetadata(source, filePath) {
267
- const { frontmatter, body } = parseMarkdownFrontmatter(source);
268
- const routeTitle = titleFromMarkdown(body);
269
- const title = frontmatter.title || routeTitle;
270
- const description = frontmatter.description;
271
- if (!title && !description) {
272
- return void 0;
273
- }
274
- return {
275
- ...title ? { title } : {},
276
- ...description ? { description } : {},
277
- source: filePath
278
- };
279
- }
280
- async function evaluateMdxSource(source, filePath) {
281
- const [{ evaluate }, runtime, remarkGfmModule] = await Promise.all([
282
- import("@mdx-js/mdx"),
283
- import("react/jsx-runtime"),
284
- import("remark-gfm")
285
- ]);
286
- const remarkGfm = remarkGfmModule.default;
287
- return evaluate(source, {
288
- ...runtime,
289
- baseUrl: (0, import_url.pathToFileURL)(filePath),
290
- remarkPlugins: [remarkGfm]
291
- });
292
- }
293
- function createFarmMarkdownRouteModule(input) {
294
- const { body } = parseMarkdownFrontmatter(input.source);
295
- const components = input.components || {};
296
- const className = input.config?.className || "farm-markdown";
297
- let evaluatedPromise;
298
- const loadContent = /* @__PURE__ */ __name(async () => {
299
- evaluatedPromise ?? (evaluatedPromise = evaluateMdxSource(body, input.filePath));
300
- return evaluatedPromise;
301
- }, "loadContent");
302
- async function FarmMarkdownPage(props) {
303
- const evaluated = await loadContent();
304
- const MDXContent = evaluated.default;
305
- return import_react.default.createElement(
306
- "article",
307
- { className, "data-farm-markdown-page": "" },
308
- import_react.default.createElement(MDXContent, {
309
- ...props,
310
- components: {
311
- ...components,
312
- ...props?.components
313
- }
314
- })
315
- );
316
- }
317
- __name(FarmMarkdownPage, "FarmMarkdownPage");
318
- return {
319
- default: FarmMarkdownPage,
320
- metadata: createMarkdownMetadata(input.source, input.filePath),
321
- source: input.source
322
- };
323
- }
324
- async function createFarmMarkdownRouteModuleFromFile(filePath, options = {}) {
325
- const source = await (0, import_promises.readFile)(filePath, "utf8");
326
- return createFarmMarkdownRouteModule({
327
- source,
328
- filePath,
329
- components: options.components,
330
- config: options.config
331
- });
332
- }
333
- async function loadFarmMdxComponents(config, options) {
334
- const configured = config?.components;
335
- if (!configured) {
336
- return {};
337
- }
338
- if (typeof configured !== "string") {
339
- return configured;
340
- }
341
- const modulePath = import_path.default.isAbsolute(configured) ? configured : import_path.default.join(options.root, configured);
342
- const mod = options.loadModule ? await options.loadModule(modulePath) : await import((0, import_url.pathToFileURL)(modulePath).href);
343
- const maybeModule = mod;
344
- return maybeModule.components || maybeModule.default || {};
345
- }
346
- async function createFarmMarkdownSourceResponse(options) {
347
- if (options.request.method !== "GET" && options.request.method !== "HEAD") {
348
- return null;
349
- }
350
- if (options.config?.markdownRoutes === false) {
351
- return null;
352
- }
353
- const url = new URL(options.request.url);
354
- if (!url.pathname.endsWith(".md")) {
355
- return null;
356
- }
357
- const targetPathname = normalizeFarmMarkdownRoutePath(url.pathname);
358
- const source = await options.resolveSource(targetPathname);
359
- if (!source) {
360
- return null;
361
- }
362
- return new Response(options.request.method === "HEAD" ? null : source.source, {
363
- status: 200,
364
- headers: {
365
- "Content-Type": "text/markdown; charset=utf-8",
366
- "Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
367
- "X-Farm-Markdown-Route": targetPathname,
368
- "X-Farm-Markdown-Source": source.filePath
369
- }
370
- });
371
- }
372
- var import_react, import_promises, import_path, import_url;
373
- var init_app_markdown = __esm({
374
- "src/app-markdown.ts"() {
375
- "use strict";
376
- import_react = __toESM(require("react"));
377
- import_promises = require("fs/promises");
378
- import_path = __toESM(require("path"));
379
- import_url = require("url");
380
- __name(resolveMdxConfig, "resolveMdxConfig");
381
- __name(isFarmMarkdownPageFile, "isFarmMarkdownPageFile");
382
- __name(normalizeFarmMarkdownRoutePath, "normalizeFarmMarkdownRoutePath");
383
- __name(parseMarkdownFrontmatter, "parseMarkdownFrontmatter");
384
- __name(titleFromMarkdown, "titleFromMarkdown");
385
- __name(createMarkdownMetadata, "createMarkdownMetadata");
386
- __name(evaluateMdxSource, "evaluateMdxSource");
387
- __name(createFarmMarkdownRouteModule, "createFarmMarkdownRouteModule");
388
- __name(createFarmMarkdownRouteModuleFromFile, "createFarmMarkdownRouteModuleFromFile");
389
- __name(loadFarmMdxComponents, "loadFarmMdxComponents");
390
- __name(createFarmMarkdownSourceResponse, "createFarmMarkdownSourceResponse");
391
- }
392
- });
393
-
394
225
  // src/markdown.ts
395
226
  function resolveMarkdownConfig(config) {
396
- if (config === false || config === void 0) {
227
+ if (config === false) {
397
228
  return {
398
229
  enabled: false,
399
230
  expose: [],
@@ -401,7 +232,7 @@ function resolveMarkdownConfig(config) {
401
232
  includeMetadata: true
402
233
  };
403
234
  }
404
- if (config === true) {
235
+ if (config === true || config === void 0) {
405
236
  return {
406
237
  enabled: true,
407
238
  expose: true,
@@ -409,7 +240,7 @@ function resolveMarkdownConfig(config) {
409
240
  includeMetadata: true
410
241
  };
411
242
  }
412
- const exposeInput = config.expose ?? config.routes ?? [];
243
+ const exposeInput = config.expose ?? config.routes ?? true;
413
244
  const expose = exposeInput === true ? true : Array.isArray(exposeInput) ? exposeInput.map(normalizeMarkdownRouteInput) : [];
414
245
  return {
415
246
  enabled: config.enabled !== false && (expose === true || expose.length > 0),
@@ -418,11 +249,14 @@ function resolveMarkdownConfig(config) {
418
249
  includeMetadata: config.includeMetadata ?? true
419
250
  };
420
251
  }
421
- function resolveMarkdownMirrorTarget(config, pathname) {
422
- if (!config?.enabled || !pathname.endsWith(".md")) {
252
+ function resolveMarkdownMirrorTarget(config, pathname, options = {}) {
253
+ const hasMarkdownExtension = pathname.toLowerCase().endsWith(".md");
254
+ if (!config?.enabled || !hasMarkdownExtension && !requestAcceptsMarkdown(options.accept)) {
423
255
  return null;
424
256
  }
425
- const targetPathname = normalizeMarkdownRoute(pathname.slice(0, -".md".length) || "/");
257
+ const targetPathname = normalizeMarkdownRoute(
258
+ hasMarkdownExtension ? pathname.slice(0, -".md".length) || "/" : pathname
259
+ );
426
260
  const route = findExposedMarkdownRoute(config, targetPathname);
427
261
  if (!route && config.expose !== true) {
428
262
  return null;
@@ -437,7 +271,10 @@ async function createMarkdownMirrorResponse(options) {
437
271
  return null;
438
272
  }
439
273
  const requestUrl = new URL(options.request.url);
440
- const target = resolveMarkdownMirrorTarget(options.config, requestUrl.pathname);
274
+ const hasMarkdownExtension = requestUrl.pathname.toLowerCase().endsWith(".md");
275
+ const target = resolveMarkdownMirrorTarget(options.config, requestUrl.pathname, {
276
+ accept: options.request.headers.get("accept")
277
+ });
441
278
  if (!target) {
442
279
  return null;
443
280
  }
@@ -465,8 +302,12 @@ async function createMarkdownMirrorResponse(options) {
465
302
  });
466
303
  const headersOut = new Headers({
467
304
  "Content-Type": "text/markdown; charset=utf-8",
305
+ "Content-Location": target.pathname === "/" ? "/index.md" : `${target.pathname}.md`,
468
306
  "X-Farm-Markdown-Route": target.pathname
469
307
  });
308
+ if (!hasMarkdownExtension) {
309
+ headersOut.set("Vary", "Accept");
310
+ }
470
311
  const cache = target.route?.cache ?? options.config?.cache ?? false;
471
312
  headersOut.set("Cache-Control", createMarkdownCacheHeader(cache));
472
313
  return new Response(options.request.method === "HEAD" ? null : markdown, {
@@ -552,11 +393,24 @@ function normalizeMarkdownRouteInput(input) {
552
393
  };
553
394
  }
554
395
  function normalizeMarkdownRoute(route) {
555
- const withoutMarkdownExtension = route.endsWith(".md") ? route.slice(0, -3) : route;
396
+ const withoutMarkdownExtension = route.toLowerCase().endsWith(".md") ? route.slice(0, -3) : route;
556
397
  const withSlash = withoutMarkdownExtension.startsWith("/") ? withoutMarkdownExtension : `/${withoutMarkdownExtension}`;
557
398
  const normalized = withSlash.replace(/\/+/g, "/").replace(/\/$/g, "");
558
399
  return normalized === "" || normalized === "/index" ? "/" : normalized;
559
400
  }
401
+ function requestAcceptsMarkdown(accept) {
402
+ if (!accept) {
403
+ return false;
404
+ }
405
+ return accept.split(",").some((entry) => {
406
+ const [mediaType, ...parameters] = entry.trim().toLowerCase().split(";").map((part) => part.trim());
407
+ if (mediaType !== "text/markdown") {
408
+ return false;
409
+ }
410
+ const quality = parameters.find((parameter) => parameter.startsWith("q="));
411
+ return quality === void 0 || Number(quality.slice(2)) > 0;
412
+ });
413
+ }
560
414
  function findExposedMarkdownRoute(config, pathname) {
561
415
  if (config.expose === true) {
562
416
  return null;
@@ -647,6 +501,7 @@ var init_markdown = __esm({
647
501
  __name(htmlToMarkdown, "htmlToMarkdown");
648
502
  __name(normalizeMarkdownRouteInput, "normalizeMarkdownRouteInput");
649
503
  __name(normalizeMarkdownRoute, "normalizeMarkdownRoute");
504
+ __name(requestAcceptsMarkdown, "requestAcceptsMarkdown");
650
505
  __name(findExposedMarkdownRoute, "findExposedMarkdownRoute");
651
506
  __name(routeMatches, "routeMatches");
652
507
  __name(isHtmlResponse, "isHtmlResponse");
@@ -660,6 +515,182 @@ var init_markdown = __esm({
660
515
  }
661
516
  });
662
517
 
518
+ // src/app-markdown.ts
519
+ function resolveMdxConfig(config) {
520
+ return {
521
+ components: config?.components,
522
+ markdownRoutes: config?.markdownRoutes ?? true,
523
+ className: config?.className ?? "farm-markdown"
524
+ };
525
+ }
526
+ function isFarmMarkdownPageFile(filePath) {
527
+ return /(^|[/\\])page\.mdx?$/i.test(filePath);
528
+ }
529
+ function normalizeFarmMarkdownRoutePath(pathname) {
530
+ const withoutExtension = pathname.replace(/\.md$/i, "");
531
+ const normalized = withoutExtension.startsWith("/") ? withoutExtension : `/${withoutExtension}`;
532
+ return normalized === "/index" ? "/" : normalized.replace(/\/+$/g, "") || "/";
533
+ }
534
+ function parseMarkdownFrontmatter(source) {
535
+ if (!source.startsWith("---")) {
536
+ return { frontmatter: {}, body: source };
537
+ }
538
+ const endIndex = source.indexOf("\n---", 3);
539
+ if (endIndex === -1) {
540
+ return { frontmatter: {}, body: source };
541
+ }
542
+ const frontmatterSource = source.slice(3, endIndex).trim();
543
+ const closingFenceEnd = endIndex + "\n---".length;
544
+ const bodyStart = source.slice(closingFenceEnd, closingFenceEnd + 2) === "\r\n" ? closingFenceEnd + 2 : source[closingFenceEnd] === "\n" ? closingFenceEnd + 1 : closingFenceEnd;
545
+ const body = source.slice(bodyStart);
546
+ const frontmatter = {};
547
+ for (const line of frontmatterSource.split(/\r?\n/)) {
548
+ const separator = line.indexOf(":");
549
+ if (separator === -1) continue;
550
+ const key = line.slice(0, separator).trim();
551
+ const value = line.slice(separator + 1).trim().replace(/^["']|["']$/g, "");
552
+ if (key && value) frontmatter[key] = value;
553
+ }
554
+ return { frontmatter, body };
555
+ }
556
+ function titleFromMarkdown(body, fallback) {
557
+ return body.match(/^#\s+(.+)$/m)?.[1]?.trim() || fallback;
558
+ }
559
+ function createMarkdownMetadata(source, filePath) {
560
+ const { frontmatter, body } = parseMarkdownFrontmatter(source);
561
+ const routeTitle = titleFromMarkdown(body);
562
+ const title = frontmatter.title || routeTitle;
563
+ const description = frontmatter.description;
564
+ if (!title && !description) {
565
+ return void 0;
566
+ }
567
+ return {
568
+ ...title ? { title } : {},
569
+ ...description ? { description } : {},
570
+ source: filePath
571
+ };
572
+ }
573
+ async function evaluateMdxSource(source, filePath) {
574
+ const [{ evaluate }, runtime, remarkGfmModule] = await Promise.all([
575
+ import("@mdx-js/mdx"),
576
+ import("react/jsx-runtime"),
577
+ import("remark-gfm")
578
+ ]);
579
+ const remarkGfm = remarkGfmModule.default;
580
+ return evaluate(source, {
581
+ ...runtime,
582
+ baseUrl: (0, import_url.pathToFileURL)(filePath),
583
+ remarkPlugins: [remarkGfm]
584
+ });
585
+ }
586
+ function createFarmMarkdownRouteModule(input) {
587
+ const { body } = parseMarkdownFrontmatter(input.source);
588
+ const components = input.components || {};
589
+ const className = input.config?.className || "farm-markdown";
590
+ let evaluatedPromise;
591
+ const loadContent = /* @__PURE__ */ __name(async () => {
592
+ evaluatedPromise ?? (evaluatedPromise = evaluateMdxSource(body, input.filePath));
593
+ return evaluatedPromise;
594
+ }, "loadContent");
595
+ async function FarmMarkdownPage(props) {
596
+ const evaluated = await loadContent();
597
+ const MDXContent = evaluated.default;
598
+ return import_react.default.createElement(
599
+ "article",
600
+ { className, "data-farm-markdown-page": "" },
601
+ import_react.default.createElement(MDXContent, {
602
+ ...props,
603
+ components: {
604
+ ...components,
605
+ ...props?.components
606
+ }
607
+ })
608
+ );
609
+ }
610
+ __name(FarmMarkdownPage, "FarmMarkdownPage");
611
+ return {
612
+ default: FarmMarkdownPage,
613
+ metadata: createMarkdownMetadata(input.source, input.filePath),
614
+ source: input.source
615
+ };
616
+ }
617
+ async function createFarmMarkdownRouteModuleFromFile(filePath, options = {}) {
618
+ const source = await (0, import_promises.readFile)(filePath, "utf8");
619
+ return createFarmMarkdownRouteModule({
620
+ source,
621
+ filePath,
622
+ components: options.components,
623
+ config: options.config
624
+ });
625
+ }
626
+ async function loadFarmMdxComponents(config, options) {
627
+ const configured = config?.components;
628
+ if (!configured) {
629
+ return {};
630
+ }
631
+ if (typeof configured !== "string") {
632
+ return configured;
633
+ }
634
+ const modulePath = import_path.default.isAbsolute(configured) ? configured : import_path.default.join(options.root, configured);
635
+ const mod = options.loadModule ? await options.loadModule(modulePath) : await import((0, import_url.pathToFileURL)(modulePath).href);
636
+ const maybeModule = mod;
637
+ return maybeModule.components || maybeModule.default || {};
638
+ }
639
+ async function createFarmMarkdownSourceResponse(options) {
640
+ if (options.request.method !== "GET" && options.request.method !== "HEAD") {
641
+ return null;
642
+ }
643
+ if (options.config?.markdownRoutes === false) {
644
+ return null;
645
+ }
646
+ const url = new URL(options.request.url);
647
+ const hasMarkdownExtension = url.pathname.toLowerCase().endsWith(".md");
648
+ if (!hasMarkdownExtension && !requestAcceptsMarkdown(options.request.headers.get("accept"))) {
649
+ return null;
650
+ }
651
+ const targetPathname = normalizeFarmMarkdownRoutePath(url.pathname);
652
+ const source = await options.resolveSource(targetPathname);
653
+ if (!source) {
654
+ return null;
655
+ }
656
+ const headers = new Headers({
657
+ "Content-Type": "text/markdown; charset=utf-8",
658
+ "Content-Location": targetPathname === "/" ? "/index.md" : `${targetPathname}.md`,
659
+ "Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
660
+ "X-Farm-Markdown-Route": targetPathname,
661
+ "X-Farm-Markdown-Source": source.filePath
662
+ });
663
+ if (!hasMarkdownExtension) {
664
+ headers.set("Vary", "Accept");
665
+ }
666
+ return new Response(options.request.method === "HEAD" ? null : source.source, {
667
+ status: 200,
668
+ headers
669
+ });
670
+ }
671
+ var import_react, import_promises, import_path, import_url;
672
+ var init_app_markdown = __esm({
673
+ "src/app-markdown.ts"() {
674
+ "use strict";
675
+ import_react = __toESM(require("react"));
676
+ import_promises = require("fs/promises");
677
+ import_path = __toESM(require("path"));
678
+ import_url = require("url");
679
+ init_markdown();
680
+ __name(resolveMdxConfig, "resolveMdxConfig");
681
+ __name(isFarmMarkdownPageFile, "isFarmMarkdownPageFile");
682
+ __name(normalizeFarmMarkdownRoutePath, "normalizeFarmMarkdownRoutePath");
683
+ __name(parseMarkdownFrontmatter, "parseMarkdownFrontmatter");
684
+ __name(titleFromMarkdown, "titleFromMarkdown");
685
+ __name(createMarkdownMetadata, "createMarkdownMetadata");
686
+ __name(evaluateMdxSource, "evaluateMdxSource");
687
+ __name(createFarmMarkdownRouteModule, "createFarmMarkdownRouteModule");
688
+ __name(createFarmMarkdownRouteModuleFromFile, "createFarmMarkdownRouteModuleFromFile");
689
+ __name(loadFarmMdxComponents, "loadFarmMdxComponents");
690
+ __name(createFarmMarkdownSourceResponse, "createFarmMarkdownSourceResponse");
691
+ }
692
+ });
693
+
663
694
  // src/workflows.ts
664
695
  var workflows_exports = {};
665
696
  __export(workflows_exports, {
@@ -812,26 +843,26 @@ async function prepareFarmWorkflowsForNitro(config) {
812
843
  const root = config.root || process.cwd();
813
844
  const distDir = config.distDir || ".farm";
814
845
  const fs8 = await import("fs/promises");
815
- const path22 = await import("path");
816
- const generatedDir = path22.join(root, distDir, ".nitro", "farm-workflows");
846
+ const path23 = await import("path");
847
+ const generatedDir = path23.join(root, distDir, ".nitro", "farm-workflows");
817
848
  await fs8.mkdir(generatedDir, { recursive: true });
818
849
  const tasks = {};
819
850
  const scheduledTasks = createScheduledTasks(workflows);
820
851
  for (const workflow of workflows) {
821
- const wrapperPath = path22.join(generatedDir, `${safeFileName(workflow.id)}.mjs`);
852
+ const wrapperPath = path23.join(generatedDir, `${safeFileName(workflow.id)}.mjs`);
822
853
  await fs8.writeFile(wrapperPath, createNitroTaskWrapper(workflow), "utf8");
823
854
  tasks[workflow.id] = {
824
855
  handler: wrapperPath,
825
856
  description: workflow.description || `Farm workflow ${workflow.id}`
826
857
  };
827
858
  }
828
- const handlerPath = path22.join(generatedDir, "http-handler.mjs");
859
+ const handlerPath = path23.join(generatedDir, "http-handler.mjs");
829
860
  await fs8.writeFile(
830
861
  handlerPath,
831
862
  createNitroWorkflowHTTPHandler(workflowConfig, workflows),
832
863
  "utf8"
833
864
  );
834
- const manifestPath = path22.join(generatedDir, "manifest.json");
865
+ const manifestPath = path23.join(generatedDir, "manifest.json");
835
866
  await fs8.writeFile(
836
867
  manifestPath,
837
868
  JSON.stringify(
@@ -914,10 +945,10 @@ function resolveWorkflowDefinition(module2) {
914
945
  }
915
946
  async function findWorkflowFiles(root, dirs) {
916
947
  const fs8 = await import("fs/promises");
917
- const path22 = await import("path");
948
+ const path23 = await import("path");
918
949
  const files = [];
919
950
  for (const dir of dirs) {
920
- const absoluteDir = path22.isAbsolute(dir) ? dir : path22.join(root, dir);
951
+ const absoluteDir = path23.isAbsolute(dir) ? dir : path23.join(root, dir);
921
952
  if (!await pathExists(absoluteDir)) continue;
922
953
  await walkWorkflowDir(absoluteDir, files);
923
954
  }
@@ -925,10 +956,10 @@ async function findWorkflowFiles(root, dirs) {
925
956
  }
926
957
  async function walkWorkflowDir(dir, files) {
927
958
  const fs8 = await import("fs/promises");
928
- const path22 = await import("path");
959
+ const path23 = await import("path");
929
960
  const entries = await fs8.readdir(dir, { withFileTypes: true });
930
961
  for (const entry of entries) {
931
- const filePath = path22.join(dir, entry.name);
962
+ const filePath = path23.join(dir, entry.name);
932
963
  if (entry.isDirectory()) {
933
964
  if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
934
965
  await walkWorkflowDir(filePath, files);
@@ -948,12 +979,12 @@ function isWorkflowFile(fileName) {
948
979
  }
949
980
  async function loadWorkflowModule(filePath, root) {
950
981
  const fs8 = await import("fs/promises");
951
- const path22 = await import("path");
952
- const { pathToFileURL: pathToFileURL3 } = await import("url");
982
+ const path23 = await import("path");
983
+ const { pathToFileURL: pathToFileURL4 } = await import("url");
953
984
  const { build } = await import("esbuild");
954
- const outDir = path22.join(root, ".farm", ".workflow-loader");
985
+ const outDir = path23.join(root, ".farm", ".workflow-loader");
955
986
  await fs8.mkdir(outDir, { recursive: true });
956
- const outfile = path22.join(
987
+ const outfile = path23.join(
957
988
  outDir,
958
989
  `workflow-${Date.now()}-${Math.random().toString(36).slice(2)}.mjs`
959
990
  );
@@ -974,7 +1005,7 @@ async function loadWorkflowModule(filePath, root) {
974
1005
  try {
975
1006
  return await import(
976
1007
  /* @vite-ignore */
977
- `${pathToFileURL3(outfile).href}?t=${Date.now()}`
1008
+ `${pathToFileURL4(outfile).href}?t=${Date.now()}`
978
1009
  );
979
1010
  } finally {
980
1011
  await fs8.unlink(outfile).catch(() => void 0);
@@ -1236,7 +1267,7 @@ function normalizeCronJob(name, job) {
1236
1267
  if (!job || typeof job !== "object" || Array.isArray(job)) {
1237
1268
  throw new TypeError(`Farm cron ${JSON.stringify(name)} must be a configuration object.`);
1238
1269
  }
1239
- const path22 = normalizeCronPath(name, job.path);
1270
+ const path23 = normalizeCronPath(name, job.path);
1240
1271
  const rawSchedule = Array.isArray(job.schedule) ? job.schedule : [job.schedule];
1241
1272
  const schedule = [...new Set(rawSchedule.map((value) => normalizeCronExpression(name, value)))];
1242
1273
  if (schedule.length === 0) {
@@ -1245,7 +1276,7 @@ function normalizeCronJob(name, job) {
1245
1276
  return {
1246
1277
  name,
1247
1278
  schedule,
1248
- path: path22,
1279
+ path: path23,
1249
1280
  description: job.description?.trim() || void 0
1250
1281
  };
1251
1282
  }
@@ -1253,13 +1284,13 @@ function normalizeCronPath(name, value) {
1253
1284
  if (typeof value !== "string" || !value.trim().startsWith("/")) {
1254
1285
  throw new TypeError(`Farm cron ${JSON.stringify(name)} path must start with "/".`);
1255
1286
  }
1256
- const path22 = value.trim();
1257
- if (path22.startsWith("//") || path22.includes("?") || path22.includes("#")) {
1287
+ const path23 = value.trim();
1288
+ if (path23.startsWith("//") || path23.includes("?") || path23.includes("#")) {
1258
1289
  throw new TypeError(
1259
1290
  `Farm cron ${JSON.stringify(name)} path must be an application pathname without a host, query, or hash.`
1260
1291
  );
1261
1292
  }
1262
- return path22.length > 1 ? path22.replace(/\/+$/, "") : path22;
1293
+ return path23.length > 1 ? path23.replace(/\/+$/, "") : path23;
1263
1294
  }
1264
1295
  function normalizeCronExpression(name, value) {
1265
1296
  if (typeof value !== "string") {
@@ -2116,7 +2147,7 @@ var init_server_action_security = __esm({
2116
2147
 
2117
2148
  // src/image-config.ts
2118
2149
  function resolveFarmImageConfig(config) {
2119
- const path22 = normalizeImagePath(config?.path ?? DEFAULT_FARM_IMAGE_PATH);
2150
+ const path23 = normalizeImagePath(config?.path ?? DEFAULT_FARM_IMAGE_PATH);
2120
2151
  const deviceSizes = normalizeIntegerList(
2121
2152
  config?.deviceSizes ?? DEFAULT_FARM_IMAGE_DEVICE_SIZES,
2122
2153
  "images.deviceSizes"
@@ -2144,7 +2175,7 @@ function resolveFarmImageConfig(config) {
2144
2175
  );
2145
2176
  return Object.freeze({
2146
2177
  provider: config?.provider ?? "auto",
2147
- path: path22,
2178
+ path: path23,
2148
2179
  domains: Object.freeze([
2149
2180
  ...new Set(
2150
2181
  (config?.domains ?? []).map((domain) => domain.trim().toLowerCase()).filter(Boolean)
@@ -2183,11 +2214,11 @@ function getPublicFarmImageConfig(config) {
2183
2214
  };
2184
2215
  }
2185
2216
  function normalizeImagePath(value) {
2186
- const path22 = value.trim().replace(/\/+$/, "") || "/";
2187
- if (!path22.startsWith("/") || path22.includes("?") || path22.includes("#")) {
2217
+ const path23 = value.trim().replace(/\/+$/, "") || "/";
2218
+ if (!path23.startsWith("/") || path23.includes("?") || path23.includes("#")) {
2188
2219
  throw new TypeError("images.path must be an absolute pathname without a query or hash");
2189
2220
  }
2190
- return path22;
2221
+ return path23;
2191
2222
  }
2192
2223
  function normalizeIntegerList(values, name, max) {
2193
2224
  if (values.length === 0) {
@@ -2536,9 +2567,9 @@ var init_integration_orm = __esm({
2536
2567
  });
2537
2568
 
2538
2569
  // src/integrations.ts
2539
- function defineTypedIntegrationRoute(method, path22, input) {
2570
+ function defineTypedIntegrationRoute(method, path23, input) {
2540
2571
  return {
2541
- path: path22,
2572
+ path: path23,
2542
2573
  method,
2543
2574
  middleware: input.middleware,
2544
2575
  before: input.before,
@@ -2548,7 +2579,7 @@ function defineTypedIntegrationRoute(method, path22, input) {
2548
2579
  input: normalizeIntegrationRouteInputSchemas(input),
2549
2580
  handler: input.handler,
2550
2581
  __operation: defineIntegrationAPIOperation({
2551
- path: path22,
2582
+ path: path23,
2552
2583
  method,
2553
2584
  bodyFormat: input.bodyFormat,
2554
2585
  responseFormat: input.responseFormat,
@@ -2560,52 +2591,52 @@ function defineTypedIntegrationRoute(method, path22, input) {
2560
2591
  }
2561
2592
  function createIntegrationRouteFactory() {
2562
2593
  return {
2563
- get(path22, input) {
2594
+ get(path23, input) {
2564
2595
  return defineTypedIntegrationRoute(
2565
2596
  "GET",
2566
- path22,
2597
+ path23,
2567
2598
  input
2568
2599
  );
2569
2600
  },
2570
- post(path22, input) {
2601
+ post(path23, input) {
2571
2602
  return defineTypedIntegrationRoute(
2572
2603
  "POST",
2573
- path22,
2604
+ path23,
2574
2605
  {
2575
2606
  bodyFormat: "json",
2576
2607
  ...input
2577
2608
  }
2578
2609
  );
2579
2610
  },
2580
- put(path22, input) {
2611
+ put(path23, input) {
2581
2612
  return defineTypedIntegrationRoute(
2582
2613
  "PUT",
2583
- path22,
2614
+ path23,
2584
2615
  {
2585
2616
  bodyFormat: "json",
2586
2617
  ...input
2587
2618
  }
2588
2619
  );
2589
2620
  },
2590
- patch(path22, input) {
2591
- return defineTypedIntegrationRoute("PATCH", path22, {
2621
+ patch(path23, input) {
2622
+ return defineTypedIntegrationRoute("PATCH", path23, {
2592
2623
  bodyFormat: "json",
2593
2624
  ...input
2594
2625
  });
2595
2626
  },
2596
- delete(path22, input) {
2597
- return defineTypedIntegrationRoute("DELETE", path22, {
2627
+ delete(path23, input) {
2628
+ return defineTypedIntegrationRoute("DELETE", path23, {
2598
2629
  bodyFormat: "json",
2599
2630
  ...input
2600
2631
  });
2601
2632
  },
2602
- options(path22, input) {
2603
- return defineTypedIntegrationRoute("OPTIONS", path22, input);
2633
+ options(path23, input) {
2634
+ return defineTypedIntegrationRoute("OPTIONS", path23, input);
2604
2635
  },
2605
- head(path22, input) {
2636
+ head(path23, input) {
2606
2637
  return defineTypedIntegrationRoute(
2607
2638
  "HEAD",
2608
- path22,
2639
+ path23,
2609
2640
  input
2610
2641
  );
2611
2642
  }
@@ -2942,8 +2973,8 @@ function normalizeIntegrationValidationIssues(source, error) {
2942
2973
  }
2943
2974
  ];
2944
2975
  }
2945
- function normalizeIntegrationValidationPath(path22) {
2946
- return (path22 || []).map((segment) => {
2976
+ function normalizeIntegrationValidationPath(path23) {
2977
+ return (path23 || []).map((segment) => {
2947
2978
  const key = typeof segment === "object" && segment !== null && "key" in segment ? segment.key : segment;
2948
2979
  return typeof key === "symbol" ? key.description || key.toString() : key;
2949
2980
  });
@@ -3632,8 +3663,8 @@ function createFarmDeploymentMismatchResponse(mismatch) {
3632
3663
  }
3633
3664
  );
3634
3665
  }
3635
- function createFarmDeploymentCookie(deploymentId, path22 = "/", secure = false) {
3636
- const normalizedPath = path22.startsWith("/") ? path22 : `/${path22}`;
3666
+ function createFarmDeploymentCookie(deploymentId, path23 = "/", secure = false) {
3667
+ const normalizedPath = path23.startsWith("/") ? path23 : `/${path23}`;
3637
3668
  return [
3638
3669
  `${FARM_DEPLOYMENT_COOKIE}=${encodeURIComponent(deploymentId)}`,
3639
3670
  `Path=${normalizedPath}`,
@@ -3826,6 +3857,69 @@ var init_devtools_config = __esm({
3826
3857
  }
3827
3858
  });
3828
3859
 
3860
+ // src/auth-config.ts
3861
+ function resolveFarmAuthConfig(input) {
3862
+ const config = input === true ? {} : input && typeof input === "object" ? input : {};
3863
+ const passwordConfig = typeof config.emailAndPassword === "object" ? config.emailAndPassword : {};
3864
+ const resolved = {
3865
+ enabled: input !== void 0 && input !== false && config.enabled !== false,
3866
+ appName: config.appName,
3867
+ basePath: normalizeBasePath(config.basePath),
3868
+ emailAndPassword: {
3869
+ enabled: config.emailAndPassword !== false,
3870
+ requireEmailVerification: passwordConfig.requireEmailVerification ?? false,
3871
+ minPasswordLength: passwordConfig.minPasswordLength ?? 8,
3872
+ maxPasswordLength: passwordConfig.maxPasswordLength ?? 128
3873
+ },
3874
+ session: {
3875
+ expiresIn: config.session?.expiresIn ?? 60 * 60 * 24 * 7,
3876
+ updateAge: config.session?.updateAge ?? 60 * 60 * 24
3877
+ },
3878
+ database: {
3879
+ url: config.database?.url,
3880
+ path: config.database?.path || ".farm/auth.sqlite",
3881
+ migrateInDevelopment: config.database?.migrateInDevelopment ?? true
3882
+ }
3883
+ };
3884
+ validateFarmAuthConfig(resolved);
3885
+ return resolved;
3886
+ }
3887
+ function normalizeBasePath(value) {
3888
+ const route = (value || "/api/auth").trim();
3889
+ const withLeadingSlash = route.startsWith("/") ? route : `/${route}`;
3890
+ const normalized = withLeadingSlash.replace(/\/+/g, "/").replace(/\/+$/, "");
3891
+ return normalized || "/api/auth";
3892
+ }
3893
+ function validateFarmAuthConfig(config) {
3894
+ const { minPasswordLength, maxPasswordLength } = config.emailAndPassword;
3895
+ if (!Number.isInteger(minPasswordLength) || minPasswordLength < 1) {
3896
+ throw new Error("auth.emailAndPassword.minPasswordLength must be a positive integer.");
3897
+ }
3898
+ if (!Number.isInteger(maxPasswordLength) || maxPasswordLength < minPasswordLength) {
3899
+ throw new Error(
3900
+ "auth.emailAndPassword.maxPasswordLength must be an integer greater than or equal to minPasswordLength."
3901
+ );
3902
+ }
3903
+ if (!Number.isInteger(config.session.expiresIn) || config.session.expiresIn < 1) {
3904
+ throw new Error("auth.session.expiresIn must be a positive integer.");
3905
+ }
3906
+ if (!Number.isInteger(config.session.updateAge) || config.session.updateAge < 0) {
3907
+ throw new Error("auth.session.updateAge must be a non-negative integer.");
3908
+ }
3909
+ }
3910
+ var import_node_module2, import_node_path4, import_node_url2;
3911
+ var init_auth_config = __esm({
3912
+ "src/auth-config.ts"() {
3913
+ "use strict";
3914
+ import_node_module2 = require("module");
3915
+ import_node_path4 = __toESM(require("path"));
3916
+ import_node_url2 = require("url");
3917
+ __name(resolveFarmAuthConfig, "resolveFarmAuthConfig");
3918
+ __name(normalizeBasePath, "normalizeBasePath");
3919
+ __name(validateFarmAuthConfig, "validateFarmAuthConfig");
3920
+ }
3921
+ });
3922
+
3829
3923
  // src/write-file-if-changed.ts
3830
3924
  function writeFileIfChanged(filePath, content) {
3831
3925
  try {
@@ -3945,11 +4039,11 @@ var init_type_generator = __esm({
3945
4039
  routeGroups.get(key).push(route);
3946
4040
  }
3947
4041
  const nestedStructure = {};
3948
- for (const [path22, routeList] of routeGroups) {
4042
+ for (const [path23, routeList] of routeGroups) {
3949
4043
  const route = routeList[0];
3950
4044
  const importPath = this.getRouteImportPath(route, options.outFile);
3951
4045
  const routeName = this.pathToRouteName(route.path);
3952
- const cleanPath = path22 === "/api" ? "" : path22.replace(/^\/api\//, "");
4046
+ const cleanPath = path23 === "/api" ? "" : path23.replace(/^\/api\//, "");
3953
4047
  const parts = cleanPath ? cleanPath.split("/") : [];
3954
4048
  const allMethods = routeList.flatMap((r) => r.methods);
3955
4049
  for (const method of allMethods) {
@@ -4008,8 +4102,8 @@ ${typeExports}
4008
4102
  const relativeImport = (0, import_path7.relative)((0, import_path7.dirname)(outFile), route.filePath).replace(/\\/g, "/").replace(/\.(ts|tsx|js|jsx)$/, "");
4009
4103
  return relativeImport.startsWith(".") ? relativeImport : `./${relativeImport}`;
4010
4104
  }
4011
- pathToRouteName(path22) {
4012
- return (path22 === "/api" ? "root" : path22.replace(/^\/api\//, "")).replace(/\//g, "_").replace(/[^a-zA-Z0-9_]/g, "");
4105
+ pathToRouteName(path23) {
4106
+ return (path23 === "/api" ? "root" : path23.replace(/^\/api\//, "")).replace(/\//g, "_").replace(/[^a-zA-Z0-9_]/g, "");
4013
4107
  }
4014
4108
  structureToTypeString(obj, indent) {
4015
4109
  const spaces = " ".repeat(indent);
@@ -4029,15 +4123,15 @@ ${typeExports}
4029
4123
  toTypePropertyKey(key) {
4030
4124
  return /^[$A-Z_][0-9A-Z_$]*$/i.test(key) ? key : JSON.stringify(key);
4031
4125
  }
4032
- getBaseExportName(path22) {
4033
- const cleanPath = path22.replace(/^\/api\//, "");
4126
+ getBaseExportName(path23) {
4127
+ const cleanPath = path23.replace(/^\/api\//, "");
4034
4128
  if (cleanPath === "") {
4035
4129
  return "api";
4036
4130
  }
4037
4131
  return cleanPath;
4038
4132
  }
4039
- getExportName(path22, method) {
4040
- const cleanPath = path22.replace(/^\/api\//, "");
4133
+ getExportName(path23, method) {
4134
+ const cleanPath = path23.replace(/^\/api\//, "");
4041
4135
  if (cleanPath === "") {
4042
4136
  return method.toLowerCase();
4043
4137
  }
@@ -4487,11 +4581,11 @@ function resolveExistingPath(filePath) {
4487
4581
  try {
4488
4582
  return (0, import_node_fs5.realpathSync)(filePath);
4489
4583
  } catch {
4490
- return import_node_path7.default.resolve(filePath);
4584
+ return import_node_path8.default.resolve(filePath);
4491
4585
  }
4492
4586
  }
4493
4587
  function isDocsSourceFile(filePath) {
4494
- return DOCS_FILE_EXTENSIONS.has(import_node_path7.default.extname(filePath).toLowerCase());
4588
+ return DOCS_FILE_EXTENSIONS.has(import_node_path8.default.extname(filePath).toLowerCase());
4495
4589
  }
4496
4590
  function discoverDocsSourceFiles(contentDir) {
4497
4591
  const files = [];
@@ -4500,7 +4594,7 @@ function discoverDocsSourceFiles(contentDir) {
4500
4594
  (a, b) => a.name.localeCompare(b.name)
4501
4595
  )) {
4502
4596
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
4503
- const absolutePath = import_node_path7.default.join(dir, entry.name);
4597
+ const absolutePath = import_node_path8.default.join(dir, entry.name);
4504
4598
  if (entry.isDirectory()) {
4505
4599
  visit(absolutePath);
4506
4600
  } else if (entry.isFile() && isDocsSourceFile(absolutePath)) {
@@ -4518,7 +4612,7 @@ function getGitLastModifiedDates(contentDir) {
4518
4612
  stdio: ["ignore", "pipe", "ignore"]
4519
4613
  }).trim();
4520
4614
  if (!gitRoot) return {};
4521
- const contentPathspec = normalizeRelativePath(import_node_path7.default.relative(gitRoot, contentDir)) || ".";
4615
+ const contentPathspec = normalizeRelativePath(import_node_path8.default.relative(gitRoot, contentDir)) || ".";
4522
4616
  const contentPrefix = contentPathspec === "." ? "" : `${contentPathspec}/`;
4523
4617
  const history = (0, import_node_child_process.execFileSync)(
4524
4618
  "git",
@@ -4560,7 +4654,7 @@ function getGitLastModifiedDates(contentDir) {
4560
4654
  }
4561
4655
  }
4562
4656
  function readManifest(contentDir) {
4563
- const manifestPath = import_node_path7.default.join(contentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
4657
+ const manifestPath = import_node_path8.default.join(contentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
4564
4658
  if (!(0, import_node_fs5.existsSync)(manifestPath)) return null;
4565
4659
  try {
4566
4660
  const parsed = JSON.parse(
@@ -4583,14 +4677,14 @@ function createFarmDocsLastModifiedManifest(contentDir, options = {}) {
4583
4677
  const fallbackDate = (options.now ?? /* @__PURE__ */ new Date()).toISOString();
4584
4678
  const pages = {};
4585
4679
  for (const sourcePath of discoverDocsSourceFiles(resolvedContentDir)) {
4586
- const relativePath2 = normalizeRelativePath(import_node_path7.default.relative(resolvedContentDir, sourcePath));
4680
+ const relativePath2 = normalizeRelativePath(import_node_path8.default.relative(resolvedContentDir, sourcePath));
4587
4681
  pages[relativePath2] = gitDates[relativePath2] || (options.fallback === "now" ? fallbackDate : (0, import_node_fs5.statSync)(sourcePath).mtime.toISOString());
4588
4682
  }
4589
4683
  return { version: 1, pages };
4590
4684
  }
4591
4685
  function getLastModifiedManifest(contentDir) {
4592
4686
  const resolvedContentDir = resolveExistingPath(contentDir);
4593
- const manifestPath = import_node_path7.default.join(resolvedContentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
4687
+ const manifestPath = import_node_path8.default.join(resolvedContentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
4594
4688
  const manifestStat = (0, import_node_fs5.existsSync)(manifestPath) ? (0, import_node_fs5.statSync)(manifestPath) : null;
4595
4689
  const signature = manifestStat ? `file:${manifestStat.mtimeMs}:${manifestStat.size}` : "generated";
4596
4690
  const cached = manifestCache.get(resolvedContentDir);
@@ -4604,21 +4698,21 @@ function resolveFarmDocsPageLastModified(contentDir, sourcePath, frontmatter) {
4604
4698
  if (configured) return configured;
4605
4699
  const resolvedContentDir = resolveExistingPath(contentDir);
4606
4700
  const resolvedSourcePath = resolveExistingPath(sourcePath);
4607
- const relativePath2 = normalizeRelativePath(import_node_path7.default.relative(resolvedContentDir, resolvedSourcePath));
4608
- const isInsideContentDir = relativePath2 !== ".." && !relativePath2.startsWith("../") && !import_node_path7.default.isAbsolute(relativePath2);
4701
+ const relativePath2 = normalizeRelativePath(import_node_path8.default.relative(resolvedContentDir, resolvedSourcePath));
4702
+ const isInsideContentDir = relativePath2 !== ".." && !relativePath2.startsWith("../") && !import_node_path8.default.isAbsolute(relativePath2);
4609
4703
  if (isInsideContentDir) {
4610
4704
  const generated = getLastModifiedManifest(resolvedContentDir).pages[relativePath2];
4611
4705
  if (generated) return generated;
4612
4706
  }
4613
4707
  return (0, import_node_fs5.statSync)(resolvedSourcePath).mtime.toISOString();
4614
4708
  }
4615
- var import_node_child_process, import_node_fs5, import_node_path7, FARM_DOCS_LAST_MODIFIED_MANIFEST, COMMIT_MARKER, DOCS_FILE_EXTENSIONS, manifestCache;
4709
+ var import_node_child_process, import_node_fs5, import_node_path8, FARM_DOCS_LAST_MODIFIED_MANIFEST, COMMIT_MARKER, DOCS_FILE_EXTENSIONS, manifestCache;
4616
4710
  var init_last_modified = __esm({
4617
4711
  "src/docs/last-modified.ts"() {
4618
4712
  "use strict";
4619
4713
  import_node_child_process = require("child_process");
4620
4714
  import_node_fs5 = require("fs");
4621
- import_node_path7 = __toESM(require("path"));
4715
+ import_node_path8 = __toESM(require("path"));
4622
4716
  FARM_DOCS_LAST_MODIFIED_MANIFEST = ".farm-docs-last-modified.json";
4623
4717
  COMMIT_MARKER = "__FARM_DOCS_COMMIT__";
4624
4718
  DOCS_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".mdx"]);
@@ -5056,8 +5150,8 @@ code:not(pre code) {
5056
5150
  }
5057
5151
 
5058
5152
  .code-block-header {
5059
- min-height: 28px;
5060
- padding: 3px 7px 3px 9px;
5153
+ min-height: 34px;
5154
+ padding: 4px 8px 4px 10px;
5061
5155
  }
5062
5156
 
5063
5157
  .code-block-title {
@@ -5271,8 +5365,8 @@ code:not(pre code) {
5271
5365
  }
5272
5366
 
5273
5367
  .code-block-header {
5274
- min-height: 26px;
5275
- padding: 2px 6px 2px 8px;
5368
+ min-height: 32px;
5369
+ padding: 3px 7px 3px 9px;
5276
5370
  }
5277
5371
 
5278
5372
  .code-copy-floating {
@@ -5312,38 +5406,30 @@ code:not(pre code) {
5312
5406
 
5313
5407
  @media (max-width: 640px) {
5314
5408
  .code-block-header {
5315
- min-height: 22px;
5316
- padding: 1px 4px 1px 7px;
5317
- }
5318
-
5319
- .code-block-title {
5320
- font-size: 9px;
5321
- }
5322
-
5323
- .code-copy {
5324
- width: 20px;
5325
- height: 20px;
5326
- }
5327
-
5328
- .code-copy svg {
5329
- width: 12px;
5330
- height: 12px;
5409
+ min-height: 30px;
5410
+ padding: 3px 6px 3px 8px;
5331
5411
  }
5332
5412
 
5333
5413
  .code-copy-floating {
5334
- top: 5px;
5335
- right: 5px;
5414
+ top: 7px;
5415
+ right: 7px;
5336
5416
  }
5337
5417
 
5338
5418
  #nd-docs-layout figure.shiki.code-block pre,
5339
5419
  .code-block pre {
5340
- padding: 10px !important;
5341
- font-size: 11px;
5342
- line-height: 1.55;
5420
+ padding: 12px !important;
5421
+ font-size: 12px;
5422
+ line-height: 1.6;
5423
+ }
5424
+
5425
+ #nd-docs-layout figure.shiki.code-block-plain pre,
5426
+ .code-block-plain pre {
5427
+ padding: 16px 44px 16px 14px !important;
5428
+ line-height: 1.65;
5343
5429
  }
5344
5430
 
5345
5431
  .sh__line {
5346
- min-height: 1.55em;
5432
+ min-height: 1.6em;
5347
5433
  }
5348
5434
  }
5349
5435
 
@@ -5930,9 +6016,9 @@ function isFarmDocsSearchEnabled(docs) {
5930
6016
  }
5931
6017
  function resolveFarmDocsSearchClientModule(root) {
5932
6018
  try {
5933
- const requireFromApp = (0, import_node_module2.createRequire)(import_node_path8.default.join(import_node_path8.default.resolve(root), "package.json"));
6019
+ const requireFromApp = (0, import_node_module3.createRequire)(import_node_path9.default.join(import_node_path9.default.resolve(root), "package.json"));
5934
6020
  const themeEntry = requireFromApp.resolve("@farming-labs/theme");
5935
- const commandSearchModule = import_node_path8.default.join(import_node_path8.default.dirname(themeEntry), "docs-command-search.mjs");
6021
+ const commandSearchModule = import_node_path9.default.join(import_node_path9.default.dirname(themeEntry), "docs-command-search.mjs");
5936
6022
  if ((0, import_node_fs6.existsSync)(commandSearchModule)) return commandSearchModule;
5937
6023
  } catch {
5938
6024
  }
@@ -6072,13 +6158,13 @@ async function mountFarmDocsSearch() {
6072
6158
  window.__FARM_MOUNT_DOCS_SEARCH__ = mountFarmDocsSearch;
6073
6159
  `;
6074
6160
  }
6075
- var import_node_fs6, import_node_module2, import_node_path8;
6161
+ var import_node_fs6, import_node_module3, import_node_path9;
6076
6162
  var init_search_client = __esm({
6077
6163
  "src/docs/search-client.ts"() {
6078
6164
  "use strict";
6079
6165
  import_node_fs6 = require("fs");
6080
- import_node_module2 = require("module");
6081
- import_node_path8 = __toESM(require("path"));
6166
+ import_node_module3 = require("module");
6167
+ import_node_path9 = __toESM(require("path"));
6082
6168
  __name(isFarmDocsSearchEnabled, "isFarmDocsSearchEnabled");
6083
6169
  __name(resolveFarmDocsSearchClientModule, "resolveFarmDocsSearchClientModule");
6084
6170
  __name(generateFarmDocsSearchBootstrapRuntime, "generateFarmDocsSearchBootstrapRuntime");
@@ -6102,9 +6188,9 @@ function resolveFarmDocsFavicon(docs, options) {
6102
6188
  if (typeof configuredFavicon === "string" && configuredFavicon.trim()) {
6103
6189
  return configuredFavicon.trim();
6104
6190
  }
6105
- const publicDir = import_node_path9.default.join(import_node_path9.default.resolve(options.root), "public");
6191
+ const publicDir = import_node_path10.default.join(import_node_path10.default.resolve(options.root), "public");
6106
6192
  for (const fileName of FARM_DOCS_FAVICON_FILES) {
6107
- const faviconPath = import_node_path9.default.join(publicDir, fileName);
6193
+ const faviconPath = import_node_path10.default.join(publicDir, fileName);
6108
6194
  if ((0, import_node_fs7.existsSync)(faviconPath) && (0, import_node_fs7.statSync)(faviconPath).isFile()) {
6109
6195
  return `/${fileName}`;
6110
6196
  }
@@ -6139,10 +6225,10 @@ function isSafeSegment(segment) {
6139
6225
  return segment !== ".." && !segment.includes("/") && !segment.includes("\\");
6140
6226
  }
6141
6227
  function resolveInside(root, target) {
6142
- const resolvedRoot = import_node_path9.default.resolve(root);
6143
- const resolvedTarget = import_node_path9.default.resolve(target);
6144
- const relative4 = import_node_path9.default.relative(resolvedRoot, resolvedTarget);
6145
- if (relative4 === "" || !relative4.startsWith("..") && !import_node_path9.default.isAbsolute(relative4)) {
6228
+ const resolvedRoot = import_node_path10.default.resolve(root);
6229
+ const resolvedTarget = import_node_path10.default.resolve(target);
6230
+ const relative4 = import_node_path10.default.relative(resolvedRoot, resolvedTarget);
6231
+ if (relative4 === "" || !relative4.startsWith("..") && !import_node_path10.default.isAbsolute(relative4)) {
6146
6232
  return resolvedTarget;
6147
6233
  }
6148
6234
  return null;
@@ -6156,16 +6242,16 @@ function isFarmDocsRequest(docs, request) {
6156
6242
  return pathname === entry || pathname === `${entry}.md` || pathname.startsWith(`${entry}/`);
6157
6243
  }
6158
6244
  function resolveFarmDocsContentDir(docs, options) {
6159
- const root = import_node_path9.default.resolve(options.root);
6245
+ const root = import_node_path10.default.resolve(options.root);
6160
6246
  const srcDir = options.srcDir || "src";
6161
6247
  const configuredContentDir = docs.contentDir || docs.config.contentDir;
6162
6248
  if (configuredContentDir) {
6163
- return import_node_path9.default.isAbsolute(configuredContentDir) ? configuredContentDir : import_node_path9.default.join(root, configuredContentDir);
6249
+ return import_node_path10.default.isAbsolute(configuredContentDir) ? configuredContentDir : import_node_path10.default.join(root, configuredContentDir);
6164
6250
  }
6165
6251
  const entryDir = docs.config.entry || trimSlashes2(docs.entry) || "docs";
6166
- const appDocsDir = import_node_path9.default.join(root, srcDir, "app", entryDir);
6252
+ const appDocsDir = import_node_path10.default.join(root, srcDir, "app", entryDir);
6167
6253
  if ((0, import_node_fs7.existsSync)(appDocsDir)) return appDocsDir;
6168
- return import_node_path9.default.join(root, entryDir);
6254
+ return import_node_path10.default.join(root, entryDir);
6169
6255
  }
6170
6256
  function getFarmDocsRouteTypeEntries(docs) {
6171
6257
  if (!docs?.enabled) return [];
@@ -6188,10 +6274,10 @@ function getRequestSlug(docs, request) {
6188
6274
  function findDocsPageFile(contentDir, slug) {
6189
6275
  const segments = slug ? slug.split("/").filter(Boolean) : [];
6190
6276
  if (!segments.every(isSafeSegment)) return null;
6191
- const slugDir = import_node_path9.default.join(contentDir, ...segments);
6192
- const candidates = segments.length === 0 ? DOCS_FILE_NAMES.map((filename) => import_node_path9.default.join(contentDir, filename)) : [
6193
- ...DOCS_FILE_NAMES.map((filename) => import_node_path9.default.join(slugDir, filename)),
6194
- ...DOCS_FILE_EXTENSIONS2.map((extension) => import_node_path9.default.join(contentDir, `${slug}${extension}`))
6277
+ const slugDir = import_node_path10.default.join(contentDir, ...segments);
6278
+ const candidates = segments.length === 0 ? DOCS_FILE_NAMES.map((filename) => import_node_path10.default.join(contentDir, filename)) : [
6279
+ ...DOCS_FILE_NAMES.map((filename) => import_node_path10.default.join(slugDir, filename)),
6280
+ ...DOCS_FILE_EXTENSIONS2.map((extension) => import_node_path10.default.join(contentDir, `${slug}${extension}`))
6195
6281
  ];
6196
6282
  for (const candidate of candidates) {
6197
6283
  const safePath = resolveInside(contentDir, candidate);
@@ -6252,9 +6338,9 @@ function createDocsHref(entry, slug) {
6252
6338
  return normalizedSlug ? `${normalizedEntry}/${normalizedSlug}` : normalizedEntry;
6253
6339
  }
6254
6340
  function pathToSlug(contentDir, filePath) {
6255
- const relative4 = import_node_path9.default.relative(contentDir, filePath).replace(/\\/g, "/");
6341
+ const relative4 = import_node_path10.default.relative(contentDir, filePath).replace(/\\/g, "/");
6256
6342
  if (relative4.startsWith("..")) return null;
6257
- const extension = import_node_path9.default.extname(relative4);
6343
+ const extension = import_node_path10.default.extname(relative4);
6258
6344
  if (!DOCS_FILE_EXTENSIONS2.includes(extension)) return null;
6259
6345
  const withoutExtension = relative4.slice(0, -extension.length);
6260
6346
  if (withoutExtension === "page" || withoutExtension === "index") return "";
@@ -6272,7 +6358,7 @@ function discoverFarmDocsPages(contentDir, docs) {
6272
6358
  const visit = /* @__PURE__ */ __name((dir) => {
6273
6359
  for (const entry of (0, import_node_fs7.readdirSync)(dir, { withFileTypes: true })) {
6274
6360
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
6275
- const absolutePath = import_node_path9.default.join(dir, entry.name);
6361
+ const absolutePath = import_node_path10.default.join(dir, entry.name);
6276
6362
  if (entry.isDirectory()) {
6277
6363
  visit(absolutePath);
6278
6364
  continue;
@@ -7111,13 +7197,13 @@ ${renderDocsHashRuntimeScript()}
7111
7197
  ${renderDocsPageActionsRuntimeScript()}`;
7112
7198
  }
7113
7199
  function readCssWithImports(filePath, seen = /* @__PURE__ */ new Set()) {
7114
- const resolved = import_node_path9.default.resolve(filePath);
7200
+ const resolved = import_node_path10.default.resolve(filePath);
7115
7201
  if (seen.has(resolved)) return "";
7116
7202
  seen.add(resolved);
7117
7203
  const source = (0, import_node_fs7.readFileSync)(resolved, "utf8");
7118
7204
  return source.replace(/@import\s+["']([^"']+)["'];?/g, (_match, importPath) => {
7119
7205
  try {
7120
- const importedPath = importPath.startsWith(".") ? import_node_path9.default.resolve(import_node_path9.default.dirname(resolved), importPath) : (0, import_node_module3.createRequire)(resolved).resolve(importPath);
7206
+ const importedPath = importPath.startsWith(".") ? import_node_path10.default.resolve(import_node_path10.default.dirname(resolved), importPath) : (0, import_node_module4.createRequire)(resolved).resolve(importPath);
7121
7207
  return readCssWithImports(importedPath, seen);
7122
7208
  } catch {
7123
7209
  return "";
@@ -7125,13 +7211,13 @@ function readCssWithImports(filePath, seen = /* @__PURE__ */ new Set()) {
7125
7211
  });
7126
7212
  }
7127
7213
  function resolvePixelBorderThemeCss(options) {
7128
- const cacheKey = import_node_path9.default.resolve(options.root);
7214
+ const cacheKey = import_node_path10.default.resolve(options.root);
7129
7215
  const cached = themeCssCache.get(cacheKey);
7130
7216
  if (cached !== void 0) return cached;
7131
7217
  try {
7132
- const requireFromApp = (0, import_node_module3.createRequire)(import_node_path9.default.join(cacheKey, "package.json"));
7218
+ const requireFromApp = (0, import_node_module4.createRequire)(import_node_path10.default.join(cacheKey, "package.json"));
7133
7219
  const themeCssPath = requireFromApp.resolve("@farming-labs/theme/pixel-border/css");
7134
- const requireFromTheme = (0, import_node_module3.createRequire)(themeCssPath);
7220
+ const requireFromTheme = (0, import_node_module4.createRequire)(themeCssPath);
7135
7221
  const fumadocsCssPath = requireFromTheme.resolve("fumadocs-ui/style.css");
7136
7222
  const css = `${readCssWithImports(fumadocsCssPath)}
7137
7223
  ${readCssWithImports(themeCssPath)}`;
@@ -7247,7 +7333,7 @@ function renderFarmDocsBridgeCss(docs) {
7247
7333
  .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; }
7248
7334
  .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); }
7249
7335
  #nd-docs-layout figure.shiki.code-block { box-shadow: 3px 3px 0 0 var(--color-fd-border, hsl(0 0% 15%)) !important; }
7250
- .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; }
7336
+ .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; }
7251
7337
  .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; }
7252
7338
  .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; }
7253
7339
  .code-copy-floating { position: absolute; top: 8px; right: 8px; z-index: 2; opacity: 0.72; transition: opacity 150ms ease; }
@@ -7315,7 +7401,7 @@ function renderFarmDocsBridgeCss(docs) {
7315
7401
  .prose h2 { margin-top: 34px; padding-top: 22px; font-size: 23px; }
7316
7402
  .code-block { margin: 16px 0; box-shadow: 2px 2px 0 0 var(--color-fd-border, hsl(0 0% 15%)); }
7317
7403
  #nd-docs-layout figure.shiki.code-block { box-shadow: 2px 2px 0 0 var(--color-fd-border, hsl(0 0% 15%)) !important; }
7318
- .code-block-header { min-height: 26px; padding: 2px 6px 2px 8px; }
7404
+ .code-block-header { min-height: 32px; padding: 3px 7px 3px 9px; }
7319
7405
  .code-copy-floating { top: 6px; right: 6px; }
7320
7406
  #nd-docs-layout figure.shiki.code-block pre, .code-block pre { padding: 12px 11px !important; font-size: 12px; line-height: 1.5; }
7321
7407
  .sh__line { min-height: 1.5em; }
@@ -7325,13 +7411,11 @@ function renderFarmDocsBridgeCss(docs) {
7325
7411
  .fd-page-footer .fd-last-updated-footer { margin-left: 0; }
7326
7412
  }
7327
7413
  @media (max-width: 640px) {
7328
- .code-block-header { min-height: 22px; padding: 1px 4px 1px 7px; }
7329
- .code-block-title { font-size: 9px; }
7330
- .code-copy { width: 20px; height: 20px; }
7331
- .code-copy svg { width: 12px; height: 12px; }
7332
- .code-copy-floating { top: 5px; right: 5px; }
7333
- #nd-docs-layout figure.shiki.code-block pre, .code-block pre { padding: 10px !important; font-size: 11px; line-height: 1.55; }
7334
- .sh__line { min-height: 1.55em; }
7414
+ .code-block-header { min-height: 30px; padding: 3px 6px 3px 8px; }
7415
+ .code-copy-floating { top: 7px; right: 7px; }
7416
+ #nd-docs-layout figure.shiki.code-block pre, .code-block pre { padding: 12px !important; font-size: 12px; line-height: 1.6; }
7417
+ #nd-docs-layout figure.shiki.code-block-plain pre, .code-block-plain pre { padding: 16px 44px 16px 14px !important; line-height: 1.65; }
7418
+ .sh__line { min-height: 1.6em; }
7335
7419
  }
7336
7420
  ${farmDocsPixelBorderCss}
7337
7421
  `;
@@ -7450,13 +7534,13 @@ function createFarmDocsHandler(docs, options) {
7450
7534
  );
7451
7535
  }, "handleFarmDocsRequest");
7452
7536
  }
7453
- 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;
7537
+ 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;
7454
7538
  var init_handler = __esm({
7455
7539
  "src/docs/handler.ts"() {
7456
7540
  "use strict";
7457
7541
  import_node_fs7 = require("fs");
7458
- import_node_module3 = require("module");
7459
- import_node_path9 = __toESM(require("path"));
7542
+ import_node_module4 = require("module");
7543
+ import_node_path10 = __toESM(require("path"));
7460
7544
  import_docs = require("@farming-labs/docs");
7461
7545
  import_marked = require("marked");
7462
7546
  import_sugar_high = require("sugar-high");
@@ -7734,18 +7818,18 @@ function sanitizeDocsConfig(config) {
7734
7818
  return cloneSerializable(config) || {};
7735
7819
  }
7736
7820
  async function findDocsConfigPath(rootDir, configPath) {
7737
- const { existsSync: existsSync13 } = await import("fs");
7821
+ const { existsSync: existsSync14 } = await import("fs");
7738
7822
  const root = import_path9.default.resolve(rootDir || process.cwd());
7739
7823
  if (configPath) {
7740
7824
  const resolvedPath = import_path9.default.isAbsolute(configPath) ? configPath : import_path9.default.join(root, configPath);
7741
- if (!existsSync13(resolvedPath)) {
7825
+ if (!existsSync14(resolvedPath)) {
7742
7826
  throw new Error(`Could not find docs config at ${configPath}.`);
7743
7827
  }
7744
7828
  return import_path9.default.resolve(resolvedPath);
7745
7829
  }
7746
7830
  for (const filename of DOCS_CONFIG_FILENAMES) {
7747
7831
  const resolvedPath = import_path9.default.join(root, filename);
7748
- if (existsSync13(resolvedPath)) {
7832
+ if (existsSync14(resolvedPath)) {
7749
7833
  return resolvedPath;
7750
7834
  }
7751
7835
  }
@@ -7753,7 +7837,7 @@ async function findDocsConfigPath(rootDir, configPath) {
7753
7837
  }
7754
7838
  async function loadDocsConfig(rootDir, configPath) {
7755
7839
  const fs8 = await import("fs/promises");
7756
- const { pathToFileURL: pathToFileURL3 } = await import("url");
7840
+ const { pathToFileURL: pathToFileURL4 } = await import("url");
7757
7841
  const root = import_path9.default.resolve(rootDir || process.cwd());
7758
7842
  const resolvedPath = await findDocsConfigPath(root, configPath);
7759
7843
  if (!resolvedPath) return void 0;
@@ -7782,7 +7866,7 @@ async function loadDocsConfig(rootDir, configPath) {
7782
7866
  logLevel: "silent",
7783
7867
  sourcemap: "inline"
7784
7868
  });
7785
- const moduleUrl = pathToFileURL3(modulePath).href + `?t=${Date.now()}`;
7869
+ const moduleUrl = pathToFileURL4(modulePath).href + `?t=${Date.now()}`;
7786
7870
  let importedConfig;
7787
7871
  try {
7788
7872
  importedConfig = await import(
@@ -7880,6 +7964,7 @@ var init_config2 = __esm({
7880
7964
  init_devtools_config();
7881
7965
  init_image_config();
7882
7966
  init_config();
7967
+ init_auth_config();
7883
7968
  init_config_entry();
7884
7969
  __name(getDeployTargetForPreset, "getDeployTargetForPreset");
7885
7970
  DOCS_CONFIG_FILENAMES = [
@@ -8668,8 +8753,8 @@ var init_generator = __esm({
8668
8753
  }
8669
8754
  routeGroups.get(key).push(route);
8670
8755
  }
8671
- for (const [path22, routeList] of routeGroups) {
8672
- const openAPIPath = this.convertToOpenAPIPath(path22);
8756
+ for (const [path23, routeList] of routeGroups) {
8757
+ const openAPIPath = this.convertToOpenAPIPath(path23);
8673
8758
  spec.paths[openAPIPath] = {};
8674
8759
  for (const route of routeList) {
8675
8760
  for (const method of route.methods) {
@@ -8683,8 +8768,8 @@ var init_generator = __esm({
8683
8768
  /**
8684
8769
  * Convert Farm.js API path to OpenAPI path format
8685
8770
  */
8686
- convertToOpenAPIPath(path22) {
8687
- return path22.replace(/^\/api/, "");
8771
+ convertToOpenAPIPath(path23) {
8772
+ return path23.replace(/^\/api/, "");
8688
8773
  }
8689
8774
  /**
8690
8775
  * Extract request body schema from endpoint
@@ -8846,8 +8931,8 @@ var init_generator = __esm({
8846
8931
  /**
8847
8932
  * Generate operation summary
8848
8933
  */
8849
- generateSummary(path22, method) {
8850
- const cleanPath = path22.replace(/^\/api\//, "");
8934
+ generateSummary(path23, method) {
8935
+ const cleanPath = path23.replace(/^\/api\//, "");
8851
8936
  const pathParts = cleanPath.split("/");
8852
8937
  const lastPart = pathParts[pathParts.length - 1];
8853
8938
  const action = method === "GET" ? "Get" : method === "POST" ? "Create" : method === "PUT" ? "Update" : method === "DELETE" ? "Delete" : method === "PATCH" ? "Update" : method;
@@ -8856,22 +8941,22 @@ var init_generator = __esm({
8856
8941
  /**
8857
8942
  * Generate operation description
8858
8943
  */
8859
- generateDescription(path22, method) {
8860
- const cleanPath = path22.replace(/^\/api\//, "");
8944
+ generateDescription(path23, method) {
8945
+ const cleanPath = path23.replace(/^\/api\//, "");
8861
8946
  return `${method} ${cleanPath} endpoint`;
8862
8947
  }
8863
8948
  /**
8864
8949
  * Generate operation ID
8865
8950
  */
8866
- generateOperationId(path22, method) {
8867
- const cleanPath = path22.replace(/^\/api\//, "").replace(/\//g, "_");
8951
+ generateOperationId(path23, method) {
8952
+ const cleanPath = path23.replace(/^\/api\//, "").replace(/\//g, "_");
8868
8953
  return `${method.toLowerCase()}_${cleanPath}`;
8869
8954
  }
8870
8955
  /**
8871
8956
  * Generate tags for grouping operations
8872
8957
  */
8873
- generateTags(path22) {
8874
- const cleanPath = path22.replace(/^\/api\//, "");
8958
+ generateTags(path23) {
8959
+ const cleanPath = path23.replace(/^\/api\//, "");
8875
8960
  const pathParts = cleanPath.split("/");
8876
8961
  if (pathParts.length > 1) {
8877
8962
  return [pathParts[0]];
@@ -8884,8 +8969,8 @@ var init_generator = __esm({
8884
8969
  async generateSpecFile(routes, outputPath) {
8885
8970
  const spec = await this.generateSpec(routes);
8886
8971
  const fs8 = require("fs");
8887
- const path22 = require("path");
8888
- const dir = path22.dirname(outputPath);
8972
+ const path23 = require("path");
8973
+ const dir = path23.dirname(outputPath);
8889
8974
  if (!fs8.existsSync(dir)) {
8890
8975
  fs8.mkdirSync(dir, { recursive: true });
8891
8976
  }
@@ -9305,7 +9390,7 @@ async function createFarmDevtoolsSnapshot(input) {
9305
9390
  generatedAt: (input.now?.() || /* @__PURE__ */ new Date()).toISOString(),
9306
9391
  health: resolveHealth(diagnostics),
9307
9392
  project: {
9308
- name: import_node_path10.default.basename(import_node_path10.default.resolve(input.root)),
9393
+ name: import_node_path11.default.basename(import_node_path11.default.resolve(input.root)),
9309
9394
  root: input.root,
9310
9395
  srcDir: input.srcDir,
9311
9396
  basePath: config.basePath || "/",
@@ -9354,11 +9439,11 @@ async function createFarmDevtoolsSnapshot(input) {
9354
9439
  diagnostics
9355
9440
  };
9356
9441
  }
9357
- var import_node_path10;
9442
+ var import_node_path11;
9358
9443
  var init_devtools = __esm({
9359
9444
  "src/devtools.ts"() {
9360
9445
  "use strict";
9361
- import_node_path10 = __toESM(require("path"));
9446
+ import_node_path11 = __toESM(require("path"));
9362
9447
  init_config2();
9363
9448
  init_cron();
9364
9449
  init_route_runtime();
@@ -12169,7 +12254,7 @@ function normalizePositiveDuration(value, fallback, name) {
12169
12254
  }
12170
12255
  __name(normalizePositiveDuration, "normalizePositiveDuration");
12171
12256
  function delay(ms) {
12172
- return new Promise((resolve5) => setTimeout(resolve5, ms));
12257
+ return new Promise((resolve6) => setTimeout(resolve6, ms));
12173
12258
  }
12174
12259
  __name(delay, "delay");
12175
12260
  function normalizeCacheOptionsTags(options) {
@@ -12305,25 +12390,25 @@ function defineRoutes(input) {
12305
12390
  }
12306
12391
  __name(defineRoutes, "defineRoutes");
12307
12392
  var routesBuilder = {
12308
- page(path22, options) {
12393
+ page(path23, options) {
12309
12394
  return normalizeProgrammaticRoute({
12310
12395
  kind: "page",
12311
- path: path22,
12396
+ path: path23,
12312
12397
  ...options
12313
12398
  });
12314
12399
  },
12315
- layout(path22, options) {
12400
+ layout(path23, options) {
12316
12401
  return normalizeProgrammaticRoute({
12317
12402
  kind: "layout",
12318
- path: path22,
12403
+ path: path23,
12319
12404
  ...options
12320
12405
  });
12321
12406
  },
12322
- api(path22, options) {
12407
+ api(path23, options) {
12323
12408
  const { render, runtime, regions, maxDuration, ...methods } = options;
12324
12409
  return normalizeProgrammaticRoute({
12325
12410
  kind: "api",
12326
- path: path22,
12411
+ path: path23,
12327
12412
  render,
12328
12413
  runtime,
12329
12414
  regions,
@@ -12359,7 +12444,7 @@ function getProgrammaticRouteSearchClientOptions(search) {
12359
12444
  return Object.keys(options).length > 0 ? options : void 0;
12360
12445
  }
12361
12446
  __name(getProgrammaticRouteSearchClientOptions, "getProgrammaticRouteSearchClientOptions");
12362
- function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path22, routePath) {
12447
+ function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path23, routePath) {
12363
12448
  const schema = getProgrammaticRouteSearchSchema(searchConfig);
12364
12449
  const search = parseProgrammaticSchema(schema, rawSearch, "search", routePath);
12365
12450
  const options = getProgrammaticRouteSearchOptions(searchConfig);
@@ -12368,7 +12453,7 @@ function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path22, routePa
12368
12453
  schema,
12369
12454
  rawSearch,
12370
12455
  parsedSearch: search,
12371
- path: path22
12456
+ path: path23
12372
12457
  });
12373
12458
  return { search, canonicalPath };
12374
12459
  }
@@ -12551,7 +12636,7 @@ function createRouteModuleFromProgrammaticPage(route) {
12551
12636
  mod.__farmRouteData = route.data;
12552
12637
  mod.__farmRouteParsesProps = true;
12553
12638
  mod.__farmResolveRouteProps = (props) => resolveProgrammaticRouteProps(route, props);
12554
- mod.__farmResolveRouteCanonicalPath = (rawSearch, path22) => resolveProgrammaticRouteSearch(route.search, rawSearch, path22, route.path).canonicalPath;
12639
+ mod.__farmResolveRouteCanonicalPath = (rawSearch, path23) => resolveProgrammaticRouteSearch(route.search, rawSearch, path23, route.path).canonicalPath;
12555
12640
  }
12556
12641
  if (route.pending || route.error || route.notFound) {
12557
12642
  mod.__farmRouteComponents = {
@@ -13758,8 +13843,56 @@ var _RouteManager = class _RouteManager {
13758
13843
  "**/{opengraph-image,twitter-image}.{ts,tsx,js,jsx,png,jpg,jpeg,gif,webp}",
13759
13844
  appDir
13760
13845
  );
13846
+ const canonicalPageGroups = /* @__PURE__ */ new Map();
13847
+ for (const file of pageFiles.filter((candidate) => parseRouteSlotFile(candidate) === null)) {
13848
+ const route = parseRoutePath(file);
13849
+ const pattern = this.createRoutePattern(route);
13850
+ const group = canonicalPageGroups.get(pattern);
13851
+ if (group) {
13852
+ group.files.push(file);
13853
+ } else {
13854
+ canonicalPageGroups.set(pattern, {
13855
+ route,
13856
+ files: [file]
13857
+ });
13858
+ }
13859
+ }
13860
+ for (const [pattern, group] of canonicalPageGroups) {
13861
+ const componentFiles = group.files.filter((file) => !isFarmMarkdownPageFile(file));
13862
+ const markdownFiles = group.files.filter(isFarmMarkdownPageFile);
13863
+ if (componentFiles.length > 1) {
13864
+ throw new Error(
13865
+ `Duplicate page route "${pattern}". Found ${componentFiles.map((file) => import_path5.default.join(appDir, file)).join(" and ")}.`
13866
+ );
13867
+ }
13868
+ if (markdownFiles.length > 1) {
13869
+ throw new Error(
13870
+ `Duplicate markdown representation for page route "${pattern}". Found ${markdownFiles.map((file) => import_path5.default.join(appDir, file)).join(" and ")}.`
13871
+ );
13872
+ }
13873
+ const componentFile = componentFiles[0];
13874
+ const markdownFile = markdownFiles[0];
13875
+ const primaryFile = componentFile || markdownFile;
13876
+ if (!primaryFile) continue;
13877
+ const modulePath = import_path5.default.join(appDir, primaryFile);
13878
+ const existing = this.routes.get(pattern);
13879
+ if (existing?.sourceRoot === source.root) {
13880
+ throw new Error(
13881
+ `Duplicate page route "${pattern}". Found both ${existing.modulePath} and ${modulePath}.`
13882
+ );
13883
+ }
13884
+ this.routes.set(pattern, {
13885
+ route: group.route,
13886
+ modulePath,
13887
+ ...markdownFile ? {
13888
+ markdownSourcePath: import_path5.default.join(appDir, markdownFile)
13889
+ } : {},
13890
+ pattern,
13891
+ source: "file",
13892
+ sourceRoot: source.root
13893
+ });
13894
+ }
13761
13895
  for (const [kind, files, target] of [
13762
- ["page", pageFiles.filter((file) => parseRouteSlotFile(file) === null), this.routes],
13763
13896
  ["layout", layoutFiles, this.layouts],
13764
13897
  ["loading", loadingFiles, this.loadings],
13765
13898
  ["error", errorFiles, this.errors]
@@ -15320,6 +15453,7 @@ __name(createTranslatorFromState, "createTranslatorFromState");
15320
15453
  _setFarmI18nSnapshotResolver(() => getFarmI18nClientSnapshot());
15321
15454
 
15322
15455
  // src/server/renderer.ts
15456
+ init_response();
15323
15457
  var cachedClerkProvider = null;
15324
15458
  var importRuntimeModule = new Function("specifier", "return import(specifier);");
15325
15459
  function hasRequestHeader(req, name) {
@@ -16166,6 +16300,15 @@ var _ServerRenderer = class _ServerRenderer {
16166
16300
  });
16167
16301
  });
16168
16302
  } catch (error) {
16303
+ if (isWebResponse(error)) {
16304
+ if (!res.headersSent && !res.writableEnded) {
16305
+ await sendWebResponse(res, error);
16306
+ } else if (!res.writableEnded) {
16307
+ res.end();
16308
+ }
16309
+ completeRender(error.status, pathname);
16310
+ return;
16311
+ }
16169
16312
  if (isFarmRedirectError(error)) {
16170
16313
  const redirect3 = getFarmRedirectError(error);
16171
16314
  const snapshot = getFarmI18nClientSnapshot();
@@ -16466,7 +16609,7 @@ var _ServerRenderer = class _ServerRenderer {
16466
16609
  }
16467
16610
  }
16468
16611
  async renderWithSSR(element, req, res, clearMiddlewareData, options = {}) {
16469
- return new Promise((resolve5, reject) => {
16612
+ return new Promise((resolve6, reject) => {
16470
16613
  const streamStartTime = Date.now();
16471
16614
  const observabilityRoute = options.observabilityRoute || req.__FARM_ROUTE__ || req.url || "/";
16472
16615
  const deploymentId = this.getDeploymentId();
@@ -16646,7 +16789,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
16646
16789
  route: observabilityRoute,
16647
16790
  durationMs: Date.now() - streamStartTime
16648
16791
  });
16649
- resolve5();
16792
+ resolve6();
16650
16793
  }
16651
16794
  });
16652
16795
  res.write(shell);
@@ -16657,7 +16800,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
16657
16800
  },
16658
16801
  onShellError(error) {
16659
16802
  didError = true;
16660
- if (!isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
16803
+ if (!isWebResponse(error) && !isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
16661
16804
  logger.error(`SSR shell error: ${error}`);
16662
16805
  emitFarmEvent({
16663
16806
  type: "render.error",
@@ -16672,7 +16815,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
16672
16815
  },
16673
16816
  onError(error) {
16674
16817
  didError = true;
16675
- if (!isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
16818
+ if (!isWebResponse(error) && !isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
16676
16819
  logger.error(`SSR streaming error: ${error}`);
16677
16820
  emitFarmEvent({
16678
16821
  type: "render.error",
@@ -16830,6 +16973,7 @@ var ServerRenderer = _ServerRenderer;
16830
16973
  var import_path6 = __toESM(require("path"));
16831
16974
  init_devtools_config();
16832
16975
  init_config();
16976
+ init_auth_config();
16833
16977
  var defaultDocsConfig = {
16834
16978
  enabled: false,
16835
16979
  entry: "/docs",
@@ -16887,6 +17031,7 @@ var _FarmApp = class _FarmApp {
16887
17031
  deploy: config.deploy || {},
16888
17032
  storage: config.storage || {},
16889
17033
  cache: config.cache || {},
17034
+ auth: isResolvedAuthConfig(config.auth) ? config.auth : resolveFarmAuthConfig(config.auth),
16890
17035
  integrations: config.integrations || {},
16891
17036
  plugins: config.plugins || [],
16892
17037
  migrations: config.migrations || { commands: [] },
@@ -16959,6 +17104,12 @@ function isResolvedI18nConfig(value) {
16959
17104
  return Boolean(value && typeof value === "object" && "enabled" in value);
16960
17105
  }
16961
17106
  __name(isResolvedI18nConfig, "isResolvedI18nConfig");
17107
+ function isResolvedAuthConfig(value) {
17108
+ return Boolean(
17109
+ value && typeof value === "object" && "enabled" in value && "emailAndPassword" in value && "database" in value
17110
+ );
17111
+ }
17112
+ __name(isResolvedAuthConfig, "isResolvedAuthConfig");
16962
17113
 
16963
17114
  // src/default-styles.ts
16964
17115
  var defaultGlobalCSS = `@import "tailwindcss";
@@ -17291,7 +17442,7 @@ var HMRManager = _HMRManager;
17291
17442
 
17292
17443
  // src/api/route-manager.ts
17293
17444
  var fs3 = __toESM(require("fs"));
17294
- var path10 = __toESM(require("path"));
17445
+ var path11 = __toESM(require("path"));
17295
17446
  init_route_runtime();
17296
17447
 
17297
17448
  // src/api/runtime.ts
@@ -17624,7 +17775,7 @@ var _APIRouteManager = class _APIRouteManager {
17624
17775
  async discoverRoutes() {
17625
17776
  this.routes.clear();
17626
17777
  for (const appDir of this.appDirs) {
17627
- const apiDir = path10.join(appDir, "api");
17778
+ const apiDir = path11.join(appDir, "api");
17628
17779
  let routeFiles = [];
17629
17780
  if (fs3.existsSync(apiDir)) {
17630
17781
  routeFiles = this.findRouteFiles(apiDir);
@@ -17652,7 +17803,7 @@ var _APIRouteManager = class _APIRouteManager {
17652
17803
  }
17653
17804
  const entries = fs3.readdirSync(dir, { withFileTypes: true });
17654
17805
  for (const entry of entries) {
17655
- const fullPath = path10.join(dir, entry.name);
17806
+ const fullPath = path11.join(dir, entry.name);
17656
17807
  if (entry.isDirectory()) {
17657
17808
  files.push(...this.findRouteFiles(fullPath));
17658
17809
  } else if (entry.name === "route.ts" || entry.name === "route.tsx" || entry.name === "route.js") {
@@ -17666,8 +17817,8 @@ var _APIRouteManager = class _APIRouteManager {
17666
17817
  */
17667
17818
  async loadRoute(filePath, appDir) {
17668
17819
  try {
17669
- const apiDir = path10.join(appDir, "api");
17670
- const relativePath2 = path10.relative(apiDir, path10.dirname(filePath));
17820
+ const apiDir = path11.join(appDir, "api");
17821
+ const relativePath2 = path11.relative(apiDir, path11.dirname(filePath));
17671
17822
  const routePath = "/api/" + (relativePath2 === "." ? "" : relativePath2.replace(/\\/g, "/"));
17672
17823
  const routeModule = await this.loadModule(filePath);
17673
17824
  const endpoints = {};
@@ -17718,7 +17869,7 @@ var _APIRouteManager = class _APIRouteManager {
17718
17869
  }
17719
17870
  }
17720
17871
  async loadProgrammaticApiRoutes(appDir) {
17721
- const candidateRoots = [path10.dirname(appDir), appDir];
17872
+ const candidateRoots = [path11.dirname(appDir), appDir];
17722
17873
  const routeFiles = Array.from(
17723
17874
  new Set(candidateRoots.flatMap((srcRoot) => findProgrammaticRouteFilesInDir(srcRoot)))
17724
17875
  );
@@ -17744,11 +17895,11 @@ var _APIRouteManager = class _APIRouteManager {
17744
17895
  }
17745
17896
  findRootRoutesFile(appDir) {
17746
17897
  const routeNames = ["routes.ts", "routes.tsx", "routes.js"];
17747
- const candidateDirs = [path10.dirname(appDir), appDir];
17898
+ const candidateDirs = [path11.dirname(appDir), appDir];
17748
17899
  const seen = /* @__PURE__ */ new Set();
17749
17900
  for (const dir of candidateDirs) {
17750
17901
  for (const routeName of routeNames) {
17751
- const routesFile = path10.join(dir, routeName);
17902
+ const routesFile = path11.join(dir, routeName);
17752
17903
  if (seen.has(routesFile)) {
17753
17904
  continue;
17754
17905
  }
@@ -17861,7 +18012,7 @@ var APIRouteManager = _APIRouteManager;
17861
18012
 
17862
18013
  // src/middleware/manager.ts
17863
18014
  var fs4 = __toESM(require("fs"));
17864
- var path11 = __toESM(require("path"));
18015
+ var path12 = __toESM(require("path"));
17865
18016
 
17866
18017
  // src/middleware/context.ts
17867
18018
  function parseCookies(cookieHeader) {
@@ -18237,8 +18388,8 @@ var _MiddlewareManager = class _MiddlewareManager {
18237
18388
  const entries = fs4.readdirSync(dir, { withFileTypes: true });
18238
18389
  for (const entry of entries) {
18239
18390
  if (entry.isDirectory() && !entry.name.startsWith(".") && !entry.name.startsWith("_")) {
18240
- const subPath = path11.join(dir, entry.name);
18241
- const subRoutePath = path11.posix.join(routePath, entry.name);
18391
+ const subPath = path12.join(dir, entry.name);
18392
+ const subRoutePath = path12.posix.join(routePath, entry.name);
18242
18393
  await this.discoverInDirectory(subPath, subRoutePath, discovered);
18243
18394
  }
18244
18395
  }
@@ -18249,7 +18400,7 @@ var _MiddlewareManager = class _MiddlewareManager {
18249
18400
  findMiddlewareFile(dir) {
18250
18401
  const extensions = [".ts", ".tsx", ".js", ".jsx"];
18251
18402
  for (const ext of extensions) {
18252
- const filePath = path11.join(dir, `middleware${ext}`);
18403
+ const filePath = path12.join(dir, `middleware${ext}`);
18253
18404
  if (fs4.existsSync(filePath)) {
18254
18405
  return filePath;
18255
18406
  }
@@ -18601,7 +18752,7 @@ var import_path8 = require("path");
18601
18752
  init_type_generator();
18602
18753
 
18603
18754
  // src/routing/generate-route-types.ts
18604
- var path12 = __toESM(require("path"));
18755
+ var path13 = __toESM(require("path"));
18605
18756
  var fs5 = __toESM(require("fs"));
18606
18757
  init_write_file_if_changed();
18607
18758
  function routeSegmentsToTsTypeLiteral(segments) {
@@ -18644,19 +18795,23 @@ function createRoutePattern(route) {
18644
18795
  __name(createRoutePattern, "createRoutePattern");
18645
18796
  var DEFAULT_OUT_FILE = "farm-routes.d.ts";
18646
18797
  async function generateRouteTypes(options) {
18647
- const {
18648
- root,
18649
- srcDir = "src",
18650
- outFile = DEFAULT_OUT_FILE,
18651
- extraRoutes = [],
18652
- suppressLintOnLink = false
18653
- } = options;
18798
+ const root = path13.resolve(options.root);
18799
+ const srcDir = options.srcDir || "src";
18800
+ const outFile = options.outFile || DEFAULT_OUT_FILE;
18801
+ const outPath = path13.isAbsolute(outFile) ? outFile : path13.join(root, srcDir, outFile);
18802
+ const content = await createRouteTypeDeclarations(options, outPath);
18803
+ fs5.mkdirSync(path13.dirname(outPath), { recursive: true });
18804
+ writeFileIfChanged(outPath, content);
18805
+ return outPath;
18806
+ }
18807
+ __name(generateRouteTypes, "generateRouteTypes");
18808
+ async function createRouteTypeDeclarations(options, outPath) {
18809
+ const { root, srcDir = "src", extraRoutes = [], suppressLintOnLink = false } = options;
18654
18810
  const sourceRoots = options.sourceRoots ?? [{ name: "project", root, srcDir, layer: false }];
18655
- const outPath = path12.join(root, srcDir, outFile);
18656
18811
  const patterns = /* @__PURE__ */ new Set();
18657
18812
  const glob = await import("fast-glob");
18658
18813
  for (const source of sourceRoots) {
18659
- const appDir = path12.join(source.root, source.srcDir, "app");
18814
+ const appDir = path13.join(source.root, source.srcDir, "app");
18660
18815
  if (fs5.existsSync(appDir)) {
18661
18816
  const pageFiles = await glob.default("**/page.{ts,tsx,js,jsx,md,mdx}", {
18662
18817
  cwd: appDir,
@@ -18685,18 +18840,19 @@ async function generateRouteTypes(options) {
18685
18840
  const patternLiterals = sortedPatterns.map(routePatternToRouteLiteral);
18686
18841
  const routePathType = suppressLintOnLink ? "string" : typeLiterals.length ? typeLiterals.join(" | ") : "never";
18687
18842
  const routePatternType = suppressLintOnLink ? "string" : patternLiterals.length ? patternLiterals.join(" | ") : "never";
18843
+ const routeTypesImportPath = `./${path13.basename(outPath).replace(/\.d\.ts$/, "")}`;
18688
18844
  const augmentationBlock = suppressLintOnLink ? "" : `
18689
18845
  declare module "@farm.js/core/client" {
18690
18846
  interface LinkDefaultRoute {
18691
- _: import("./farm-routes").RoutePath;
18692
- pattern: import("./farm-routes").RoutePattern;
18847
+ _: import(${JSON.stringify(routeTypesImportPath)}).RoutePath;
18848
+ pattern: import(${JSON.stringify(routeTypesImportPath)}).RoutePattern;
18693
18849
  }
18694
18850
  }
18695
18851
 
18696
18852
  declare module "@farm.js/core" {
18697
18853
  interface LinkDefaultRoute {
18698
- _: import("./farm-routes").RoutePath;
18699
- pattern: import("./farm-routes").RoutePattern;
18854
+ _: import(${JSON.stringify(routeTypesImportPath)}).RoutePath;
18855
+ pattern: import(${JSON.stringify(routeTypesImportPath)}).RoutePattern;
18700
18856
  }
18701
18857
  // Ensure root import ("@farm.js/core") uses the same typed Link signature as client entry.
18702
18858
  const Link: typeof import("@farm.js/core/client").Link;
@@ -18705,8 +18861,8 @@ declare module "@farm.js/core" {
18705
18861
  // Internal declaration path used by @farm.js/core root type re-exports.
18706
18862
  declare module "@farm.js/core/dist/client.js" {
18707
18863
  interface LinkDefaultRoute {
18708
- _: import("./farm-routes").RoutePath;
18709
- pattern: import("./farm-routes").RoutePattern;
18864
+ _: import(${JSON.stringify(routeTypesImportPath)}).RoutePath;
18865
+ pattern: import(${JSON.stringify(routeTypesImportPath)}).RoutePattern;
18710
18866
  }
18711
18867
  }
18712
18868
  `;
@@ -18718,15 +18874,13 @@ declare module "@farm.js/core/dist/client.js" {
18718
18874
  export type RoutePath = ${routePathType};
18719
18875
  export type RoutePattern = ${routePatternType};${augmentationBlock}
18720
18876
  `;
18721
- fs5.mkdirSync(path12.dirname(outPath), { recursive: true });
18722
- writeFileIfChanged(outPath, content);
18723
- return outPath;
18877
+ return content;
18724
18878
  }
18725
- __name(generateRouteTypes, "generateRouteTypes");
18879
+ __name(createRouteTypeDeclarations, "createRouteTypeDeclarations");
18726
18880
 
18727
18881
  // src/env-types.ts
18728
18882
  var fs6 = __toESM(require("fs"));
18729
- var path13 = __toESM(require("path"));
18883
+ var path14 = __toESM(require("path"));
18730
18884
  init_write_file_if_changed();
18731
18885
  var DEFAULT_OUT_FILE2 = "farm-env.d.ts";
18732
18886
  var CONFIG_FILENAMES = [
@@ -18748,20 +18902,27 @@ var CONFIG_FILENAMES = [
18748
18902
  "config.cjs"
18749
18903
  ];
18750
18904
  async function generateEnvTypes(options) {
18751
- const root = path13.resolve(options.root);
18905
+ const root = path14.resolve(options.root);
18752
18906
  const srcDir = options.srcDir || "src";
18753
- const outPath = path13.join(root, srcDir, options.outFile || DEFAULT_OUT_FILE2);
18907
+ const outFile = options.outFile || DEFAULT_OUT_FILE2;
18908
+ const outPath = path14.isAbsolute(outFile) ? outFile : path14.join(root, srcDir, outFile);
18909
+ const content = createEnvTypeDeclarations(options, outPath);
18910
+ fs6.mkdirSync(path14.dirname(outPath), { recursive: true });
18911
+ writeFileIfChanged(outPath, content);
18912
+ return outPath;
18913
+ }
18914
+ __name(generateEnvTypes, "generateEnvTypes");
18915
+ function createEnvTypeDeclarations(options, outPath) {
18916
+ const root = path14.resolve(options.root);
18754
18917
  const configPath = findConfigPath(root, options.configPath);
18755
18918
  const configPaths = [
18756
18919
  ...(options.layerConfigPaths ?? []).filter((value) => fs6.existsSync(value)),
18757
18920
  ...configPath ? [configPath] : []
18758
18921
  ];
18759
18922
  const content = configPaths.length > 1 ? createLayeredConfigBackedEnvTypes(outPath, configPaths) : configPaths.length === 1 ? createConfigBackedEnvTypes(outPath, configPaths[0]) : createEmptyEnvTypes();
18760
- fs6.mkdirSync(path13.dirname(outPath), { recursive: true });
18761
- writeFileIfChanged(outPath, content);
18762
- return outPath;
18923
+ return content;
18763
18924
  }
18764
- __name(generateEnvTypes, "generateEnvTypes");
18925
+ __name(createEnvTypeDeclarations, "createEnvTypeDeclarations");
18765
18926
  function createLayeredConfigBackedEnvTypes(outPath, configPaths) {
18766
18927
  const imports = configPaths.map(
18767
18928
  (configPath, index) => `import type FarmConfig${index} from ${JSON.stringify(toTypeImportPath(outPath, configPath))};`
@@ -18817,11 +18978,11 @@ export {};
18817
18978
  __name(createLayeredConfigBackedEnvTypes, "createLayeredConfigBackedEnvTypes");
18818
18979
  function findConfigPath(root, configPath) {
18819
18980
  if (configPath) {
18820
- const resolvedPath = path13.isAbsolute(configPath) ? configPath : path13.join(root, configPath);
18981
+ const resolvedPath = path14.isAbsolute(configPath) ? configPath : path14.join(root, configPath);
18821
18982
  return fs6.existsSync(resolvedPath) ? resolvedPath : null;
18822
18983
  }
18823
18984
  for (const filename of CONFIG_FILENAMES) {
18824
- const resolvedPath = path13.join(root, filename);
18985
+ const resolvedPath = path14.join(root, filename);
18825
18986
  if (fs6.existsSync(resolvedPath)) {
18826
18987
  return resolvedPath;
18827
18988
  }
@@ -18885,19 +19046,19 @@ export {};
18885
19046
  }
18886
19047
  __name(createEmptyEnvTypes, "createEmptyEnvTypes");
18887
19048
  function toTypeImportPath(outPath, targetPath) {
18888
- const relativePath2 = path13.relative(path13.dirname(outPath), targetPath).replace(/\\/g, "/").replace(/\.(tsx?|jsx?|mjs|cjs|mts|cts)$/, "");
19049
+ const relativePath2 = path14.relative(path14.dirname(outPath), targetPath).replace(/\\/g, "/").replace(/\.(tsx?|jsx?|mjs|cjs|mts|cts)$/, "");
18889
19050
  return relativePath2.startsWith(".") ? relativePath2 : `./${relativePath2}`;
18890
19051
  }
18891
19052
  __name(toTypeImportPath, "toTypeImportPath");
18892
19053
 
18893
19054
  // src/image-types.ts
18894
19055
  var import_node_fs3 = require("fs");
18895
- var import_node_path4 = __toESM(require("path"));
19056
+ var import_node_path5 = __toESM(require("path"));
18896
19057
  init_write_file_if_changed();
18897
19058
  var FARM_STATIC_IMAGE_EXTENSIONS = ["avif", "gif", "jpeg", "jpg", "png", "webp"];
18898
19059
  function generateFarmImageTypes(options) {
18899
- 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");
18900
- (0, import_node_fs3.mkdirSync)(import_node_path4.default.dirname(outputPath), { recursive: true });
19060
+ 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");
19061
+ (0, import_node_fs3.mkdirSync)(import_node_path5.default.dirname(outputPath), { recursive: true });
18901
19062
  writeFileIfChanged(outputPath, createFarmImageTypeDeclarations());
18902
19063
  return outputPath;
18903
19064
  }
@@ -18926,14 +19087,14 @@ __name(createFarmImageTypeDeclarations, "createFarmImageTypeDeclarations");
18926
19087
 
18927
19088
  // src/i18n/type-generator.ts
18928
19089
  var import_node_fs4 = require("fs");
18929
- var import_node_path5 = require("path");
19090
+ var import_node_path6 = require("path");
18930
19091
  init_write_file_if_changed();
18931
19092
  async function generateFarmI18nTypes(options) {
18932
19093
  if (!options.config.enabled) return void 0;
18933
19094
  const { signatures } = await readFarmI18nCatalogs(options.config);
18934
- 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");
19095
+ 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");
18935
19096
  const content = renderFarmI18nTypes(options.config.locales, signatures);
18936
- (0, import_node_fs4.mkdirSync)((0, import_node_path5.dirname)(outFile), { recursive: true });
19097
+ (0, import_node_fs4.mkdirSync)((0, import_node_path6.dirname)(outFile), { recursive: true });
18937
19098
  writeFileIfChanged(outFile, content);
18938
19099
  return outFile;
18939
19100
  }
@@ -18995,7 +19156,10 @@ async function generateFarmTypeArtifacts(options) {
18995
19156
  const result = {
18996
19157
  apiRoutes: []
18997
19158
  };
18998
- if (shouldGenerateRoutes) {
19159
+ const unifiedTypesPath = (0, import_path8.join)(root, srcDir, "farm.d.ts");
19160
+ const shouldRefreshUnifiedTypes = shouldGenerateRoutes && !options.routeTypesOutFile || shouldGenerateEnv && !options.envTypesOutFile || shouldGenerateI18n && !options.i18nTypesOutFile;
19161
+ const unifiedSections = [];
19162
+ if (shouldRefreshUnifiedTypes && !options.routeTypesOutFile) {
18999
19163
  const routeOptions = {
19000
19164
  root,
19001
19165
  srcDir,
@@ -19003,10 +19167,17 @@ async function generateFarmTypeArtifacts(options) {
19003
19167
  suppressLintOnLink: options.suppressLintOnLink,
19004
19168
  sourceRoots
19005
19169
  };
19006
- if (options.routeTypesOutFile) {
19007
- routeOptions.outFile = options.routeTypesOutFile;
19008
- }
19009
- result.routeTypesPath = await generateRouteTypes(routeOptions);
19170
+ unifiedSections.push(await createRouteTypeDeclarations(routeOptions, unifiedTypesPath));
19171
+ result.routeTypesPath = unifiedTypesPath;
19172
+ } else if (shouldGenerateRoutes) {
19173
+ result.routeTypesPath = await generateRouteTypes({
19174
+ root,
19175
+ srcDir,
19176
+ outFile: options.routeTypesOutFile,
19177
+ extraRoutes: options.extraRoutes || [],
19178
+ suppressLintOnLink: options.suppressLintOnLink,
19179
+ sourceRoots
19180
+ });
19010
19181
  }
19011
19182
  if (shouldGenerateApi) {
19012
19183
  const generator = new APITypeGenerator(appDirs);
@@ -19018,22 +19189,40 @@ async function generateFarmTypeArtifacts(options) {
19018
19189
  result.apiTypesPath = apiTypesPath;
19019
19190
  result.apiRoutes = apiRoutes;
19020
19191
  }
19021
- if (shouldGenerateEnv) {
19192
+ if (shouldRefreshUnifiedTypes && !options.envTypesOutFile) {
19193
+ unifiedSections.push(
19194
+ createEnvTypeDeclarations(
19195
+ {
19196
+ root,
19197
+ srcDir,
19198
+ configPath: options.configPath,
19199
+ layerConfigPaths: (options.layers ?? []).map((layer) => layer.configFile).filter((configFile) => Boolean(configFile))
19200
+ },
19201
+ unifiedTypesPath
19202
+ )
19203
+ );
19204
+ result.envTypesPath = unifiedTypesPath;
19205
+ } else if (shouldGenerateEnv) {
19022
19206
  result.envTypesPath = await generateEnvTypes({
19023
19207
  root,
19024
19208
  srcDir,
19025
19209
  outFile: options.envTypesOutFile,
19210
+ configPath: options.configPath,
19026
19211
  layerConfigPaths: (options.layers ?? []).map((layer) => layer.configFile).filter((configFile) => Boolean(configFile))
19027
19212
  });
19028
19213
  }
19029
- if (shouldGenerateImages) {
19214
+ if (shouldGenerateImages && options.imageTypesOutFile) {
19030
19215
  result.imageTypesPath = generateFarmImageTypes({
19031
19216
  root,
19032
19217
  srcDir,
19033
19218
  outFile: options.imageTypesOutFile
19034
19219
  });
19035
19220
  }
19036
- if (shouldGenerateI18n && options.i18nConfig) {
19221
+ if (shouldRefreshUnifiedTypes && options.i18nConfig?.enabled && !options.i18nTypesOutFile) {
19222
+ const { signatures } = await readFarmI18nCatalogs(options.i18nConfig);
19223
+ unifiedSections.push(renderFarmI18nTypes(options.i18nConfig.locales, signatures));
19224
+ result.i18nTypesPath = unifiedTypesPath;
19225
+ } else if (shouldGenerateI18n && options.i18nConfig) {
19037
19226
  result.i18nTypesPath = await generateFarmI18nTypes({
19038
19227
  root,
19039
19228
  srcDir,
@@ -19041,9 +19230,42 @@ async function generateFarmTypeArtifacts(options) {
19041
19230
  outFile: options.i18nTypesOutFile
19042
19231
  });
19043
19232
  }
19233
+ if (shouldRefreshUnifiedTypes) {
19234
+ (0, import_fs4.mkdirSync)((0, import_path8.dirname)(unifiedTypesPath), { recursive: true });
19235
+ writeFileIfChanged(
19236
+ unifiedTypesPath,
19237
+ `/**
19238
+ * Generated by Farm.js. Do not edit.
19239
+ * Contains project-specific route, environment, and internationalization types.
19240
+ */
19241
+
19242
+ import "@farm.js/core/image";
19243
+
19244
+ ${unifiedSections.join("\n")}`
19245
+ );
19246
+ result.typesPath = unifiedTypesPath;
19247
+ removeLegacyTypeArtifacts(root, srcDir);
19248
+ }
19044
19249
  return result;
19045
19250
  }
19046
19251
  __name(generateFarmTypeArtifacts, "generateFarmTypeArtifacts");
19252
+ var LEGACY_TYPE_ARTIFACTS = [
19253
+ ["farm-routes.d.ts", "Auto-generated route types"],
19254
+ ["farm-env.d.ts", "Auto-generated env types"],
19255
+ ["farm-images.d.ts", "Generated by Farm.js"],
19256
+ ["farm-i18n.d.ts", "Generated by Farm.js"]
19257
+ ];
19258
+ function removeLegacyTypeArtifacts(root, srcDir) {
19259
+ for (const [fileName, marker] of LEGACY_TYPE_ARTIFACTS) {
19260
+ const filePath = (0, import_path8.join)(root, srcDir, fileName);
19261
+ if (!(0, import_fs4.existsSync)(filePath)) continue;
19262
+ const source = (0, import_fs4.readFileSync)(filePath, "utf8");
19263
+ if (source.includes(marker)) {
19264
+ (0, import_fs4.unlinkSync)(filePath);
19265
+ }
19266
+ }
19267
+ }
19268
+ __name(removeLegacyTypeArtifacts, "removeLegacyTypeArtifacts");
19047
19269
 
19048
19270
  // src/vite.ts
19049
19271
  init_markdown();
@@ -19052,7 +19274,7 @@ init_response();
19052
19274
  init_integrations();
19053
19275
  init_devtools_config();
19054
19276
  var fs7 = __toESM(require("fs"));
19055
- var path21 = __toESM(require("path"));
19277
+ var path22 = __toESM(require("path"));
19056
19278
  init_layers();
19057
19279
 
19058
19280
  // src/after.ts
@@ -19084,8 +19306,8 @@ __name(reportAfterError, "reportAfterError");
19084
19306
  function createAfterRequestState(reportError = defaultAfterErrorReporter) {
19085
19307
  let resolveResponseFinished;
19086
19308
  let responseFinished = false;
19087
- const responseFinishedPromise = new Promise((resolve5) => {
19088
- resolveResponseFinished = resolve5;
19309
+ const responseFinishedPromise = new Promise((resolve6) => {
19310
+ resolveResponseFinished = resolve6;
19089
19311
  });
19090
19312
  const state = {
19091
19313
  completion: Promise.resolve(),
@@ -19162,7 +19384,7 @@ init_image_config();
19162
19384
 
19163
19385
  // src/image-vite.ts
19164
19386
  var import_promises6 = require("fs/promises");
19165
- var import_node_path6 = __toESM(require("path"));
19387
+ var import_node_path7 = __toESM(require("path"));
19166
19388
  var import_image_size2 = require("image-size");
19167
19389
  var FARM_IMAGE_ID_PREFIX = "\0farm:image:";
19168
19390
  var STATIC_IMAGE_RE = /\.(?:avif|gif|jpe?g|png|webp)$/i;
@@ -19235,7 +19457,7 @@ var ALL_TYPE_ARTIFACTS = {
19235
19457
  routes: true,
19236
19458
  api: true,
19237
19459
  env: true,
19238
- images: true,
19460
+ images: false,
19239
19461
  i18n: true
19240
19462
  };
19241
19463
  var createEmptyTypeArtifactSelection = /* @__PURE__ */ __name(() => ({
@@ -19433,7 +19655,7 @@ function fileContainsProgrammaticPageRoute(file) {
19433
19655
  __name(fileContainsProgrammaticPageRoute, "fileContainsProgrammaticPageRoute");
19434
19656
  function rewriteEarlySsrRelativeImports(options) {
19435
19657
  const cleanId = options.id.split("?", 1)[0];
19436
- if (!path21.isAbsolute(cleanId) || cleanId.replace(/\\/g, "/").includes("/node_modules/")) {
19658
+ if (!path22.isAbsolute(cleanId) || cleanId.replace(/\\/g, "/").includes("/node_modules/")) {
19437
19659
  return null;
19438
19660
  }
19439
19661
  const replacements = [];
@@ -19453,7 +19675,7 @@ function rewriteEarlySsrRelativeImports(options) {
19453
19675
  const suffixIndex = source.value.search(/[?#]/);
19454
19676
  const sourcePath = suffixIndex === -1 ? source.value : source.value.slice(0, suffixIndex);
19455
19677
  const suffix = suffixIndex === -1 ? "" : source.value.slice(suffixIndex);
19456
- const resolvedPath = path21.resolve(path21.dirname(cleanId), sourcePath);
19678
+ const resolvedPath = path22.resolve(path22.dirname(cleanId), sourcePath);
19457
19679
  replacements.push({
19458
19680
  start: source.start,
19459
19681
  end: source.end,
@@ -19533,7 +19755,7 @@ function farmPlugin(options = {}, initialPluginManager) {
19533
19755
  ...layerRoots.length ? {
19534
19756
  server: {
19535
19757
  fs: {
19536
- allow: [path21.resolve(options.root || process.cwd()), ...layerRoots]
19758
+ allow: [path22.resolve(options.root || process.cwd()), ...layerRoots]
19537
19759
  }
19538
19760
  }
19539
19761
  } : {}
@@ -19558,9 +19780,9 @@ function farmPlugin(options = {}, initialPluginManager) {
19558
19780
  },
19559
19781
  server
19560
19782
  );
19561
- const globalsCSSPath = path21.join(server.config.root, "src/app/globals.css");
19783
+ const globalsCSSPath = path22.join(server.config.root, "src/app/globals.css");
19562
19784
  if (!fs7.existsSync(globalsCSSPath)) {
19563
- const appDir = path21.join(server.config.root, "src/app");
19785
+ const appDir = path22.join(server.config.root, "src/app");
19564
19786
  if (!fs7.existsSync(appDir)) {
19565
19787
  fs7.mkdirSync(appDir, { recursive: true });
19566
19788
  }
@@ -19582,10 +19804,10 @@ function farmPlugin(options = {}, initialPluginManager) {
19582
19804
  });
19583
19805
  }
19584
19806
  const sourceRoots = getFarmSourceRoots(farmConfig);
19585
- server.watcher.add(sourceRoots.map((source) => path21.join(source.root, source.srcDir)));
19807
+ server.watcher.add(sourceRoots.map((source) => path22.join(source.root, source.srcDir)));
19586
19808
  if (farmConfig.i18n.enabled) {
19587
19809
  server.watcher.add(
19588
- farmConfig.i18n.messages.includes("{locale}") ? path21.dirname(farmConfig.i18n.messages) : farmConfig.i18n.messages
19810
+ farmConfig.i18n.messages.includes("{locale}") ? path22.dirname(farmConfig.i18n.messages) : farmConfig.i18n.messages
19589
19811
  );
19590
19812
  }
19591
19813
  const workflowConfig = farmConfig.workflows;
@@ -19595,7 +19817,7 @@ function farmPlugin(options = {}, initialPluginManager) {
19595
19817
  ...farmDocsDevRuntime?.getFarmDocsRouteTypeEntries(farmConfig.docs) ?? []
19596
19818
  ], "getExtraRouteTypes");
19597
19819
  const appDirSlugs = sourceRoots.map(
19598
- (source) => path21.join(source.root, source.srcDir, "app").replace(/\\/g, "/")
19820
+ (source) => path22.join(source.root, source.srcDir, "app").replace(/\\/g, "/")
19599
19821
  );
19600
19822
  const generateTypeArtifacts = /* @__PURE__ */ __name(async (reason, selection = ALL_TYPE_ARTIFACTS, log = false) => {
19601
19823
  try {
@@ -19635,7 +19857,7 @@ function farmPlugin(options = {}, initialPluginManager) {
19635
19857
  }, "generateTypeArtifacts");
19636
19858
  await generateTypeArtifacts("startup");
19637
19859
  const srcDirSlugs = sourceRoots.map(
19638
- (source) => path21.join(source.root, source.srcDir).replace(/\\/g, "/")
19860
+ (source) => path22.join(source.root, source.srcDir).replace(/\\/g, "/")
19639
19861
  );
19640
19862
  const layerConfigFiles = new Set(
19641
19863
  farmConfig.layers.map((layer) => layer.configFile?.replace(/\\/g, "/")).filter((file) => Boolean(file))
@@ -19753,7 +19975,7 @@ function farmPlugin(options = {}, initialPluginManager) {
19753
19975
  await apiRouteManager.discoverRoutes();
19754
19976
  let discoveredWorkflows = [];
19755
19977
  const hasWorkflowDirectory = workflowConfig.enabled && workflowConfig.dirs.some(
19756
- (dir) => fs7.existsSync(path21.isAbsolute(dir) ? dir : path21.join(farmConfig.root, dir))
19978
+ (dir) => fs7.existsSync(path22.isAbsolute(dir) ? dir : path22.join(farmConfig.root, dir))
19757
19979
  );
19758
19980
  if (hasWorkflowDirectory) {
19759
19981
  const { createFarmWorkflowRequestHandler: createFarmWorkflowRequestHandler2, discoverFarmWorkflows: discoverFarmWorkflows2 } = await loadFarmWorkflowsDevRuntime();
@@ -19831,14 +20053,14 @@ function farmPlugin(options = {}, initialPluginManager) {
19831
20053
  farmDocsDevRuntime ? [
19832
20054
  [
19833
20055
  "/assets/Geist-Variable-CrgPqtmy.woff2",
19834
- path21.join(
20056
+ path22.join(
19835
20057
  farmConfig.root,
19836
20058
  "node_modules/geist/dist/fonts/geist-sans/Geist-Variable.woff2"
19837
20059
  )
19838
20060
  ],
19839
20061
  [
19840
20062
  "/assets/GeistMono-Variable-BNLlm6Cd.woff2",
19841
- path21.join(
20063
+ path22.join(
19842
20064
  farmConfig.root,
19843
20065
  "node_modules/geist/dist/fonts/geist-mono/GeistMono-Variable.woff2"
19844
20066
  )
@@ -20002,12 +20224,13 @@ function farmPlugin(options = {}, initialPluginManager) {
20002
20224
  config: farmApp.getConfig().mdx,
20003
20225
  resolveSource: /* @__PURE__ */ __name(async (pathname2) => {
20004
20226
  const match = farmApp.getRouteManager().matchRoute(pathname2);
20005
- if (!match.route || !isFarmMarkdownPageFile(match.route.modulePath)) {
20227
+ const sourcePath = match.route?.markdownSourcePath || (match.route && isFarmMarkdownPageFile(match.route.modulePath) ? match.route.modulePath : null);
20228
+ if (!sourcePath) {
20006
20229
  return null;
20007
20230
  }
20008
20231
  return {
20009
- source: await fs7.promises.readFile(match.route.modulePath, "utf8"),
20010
- filePath: match.route.modulePath
20232
+ source: await fs7.promises.readFile(sourcePath, "utf8"),
20233
+ filePath: sourcePath
20011
20234
  };
20012
20235
  }, "resolveSource")
20013
20236
  });
@@ -20028,16 +20251,37 @@ function farmPlugin(options = {}, initialPluginManager) {
20028
20251
  await sendWebResponse(res, markdownResponse);
20029
20252
  return;
20030
20253
  }
20254
+ const markdownPageTarget = resolveMarkdownMirrorTarget(
20255
+ farmApp.getConfig().md,
20256
+ requestPathname,
20257
+ {
20258
+ accept: "text/markdown"
20259
+ }
20260
+ );
20261
+ if (markdownPageTarget && farmApp.getRouteManager().matchRoute(markdownPageTarget.pathname).route) {
20262
+ const vary = res.getHeader("Vary");
20263
+ const varyValues = String(vary || "").split(",").map((value) => value.trim()).filter(Boolean);
20264
+ if (!varyValues.some((value) => value.toLowerCase() === "accept")) {
20265
+ res.setHeader("Vary", [...varyValues, "Accept"].join(", "));
20266
+ }
20267
+ const alternatePath = markdownPageTarget.pathname === "/" ? "/index.md" : `${markdownPageTarget.pathname}.md`;
20268
+ const alternateLink = `<${alternatePath}>; rel="alternate"; type="text/markdown"`;
20269
+ const currentLink = res.getHeader("Link");
20270
+ res.setHeader(
20271
+ "Link",
20272
+ currentLink ? `${String(currentLink)}, ${alternateLink}` : alternateLink
20273
+ );
20274
+ }
20031
20275
  if (workflowHandler && (requestPathname === workflowConfig.route || requestPathname.startsWith(`${workflowConfig.route}/`))) {
20032
20276
  let workflowBody;
20033
20277
  if (requestMethod !== "GET" && requestMethod !== "HEAD") {
20034
- workflowBody = await new Promise((resolve5) => {
20278
+ workflowBody = await new Promise((resolve6) => {
20035
20279
  let data = "";
20036
20280
  req.on("data", (chunk) => {
20037
20281
  data += chunk;
20038
20282
  });
20039
20283
  req.on("end", () => {
20040
- resolve5(data);
20284
+ resolve6(data);
20041
20285
  });
20042
20286
  });
20043
20287
  }
@@ -20080,13 +20324,13 @@ function farmPlugin(options = {}, initialPluginManager) {
20080
20324
  }
20081
20325
  let body;
20082
20326
  if (req.method !== "GET" && req.method !== "HEAD") {
20083
- body = await new Promise((resolve5) => {
20327
+ body = await new Promise((resolve6) => {
20084
20328
  let data = "";
20085
20329
  req.on("data", (chunk) => {
20086
20330
  data += chunk;
20087
20331
  });
20088
20332
  req.on("end", () => {
20089
- resolve5(data);
20333
+ resolve6(data);
20090
20334
  });
20091
20335
  });
20092
20336
  }
@@ -20192,13 +20436,13 @@ function farmPlugin(options = {}, initialPluginManager) {
20192
20436
  }
20193
20437
  let body;
20194
20438
  if (req.method !== "GET" && req.method !== "HEAD") {
20195
- body = await new Promise((resolve5) => {
20439
+ body = await new Promise((resolve6) => {
20196
20440
  let data = "";
20197
20441
  req.on("data", (chunk) => {
20198
20442
  data += chunk;
20199
20443
  });
20200
20444
  req.on("end", () => {
20201
- resolve5(data);
20445
+ resolve6(data);
20202
20446
  });
20203
20447
  });
20204
20448
  }
@@ -20255,13 +20499,13 @@ function farmPlugin(options = {}, initialPluginManager) {
20255
20499
  }
20256
20500
  let body;
20257
20501
  if (req.method !== "GET" && req.method !== "HEAD") {
20258
- body = await new Promise((resolve5) => {
20502
+ body = await new Promise((resolve6) => {
20259
20503
  let data = "";
20260
20504
  req.on("data", (chunk) => {
20261
20505
  data += chunk;
20262
20506
  });
20263
20507
  req.on("end", () => {
20264
- resolve5(data);
20508
+ resolve6(data);
20265
20509
  });
20266
20510
  });
20267
20511
  }
@@ -20981,8 +21225,8 @@ if (import.meta.hot) {
20981
21225
  }
20982
21226
  logger.info(`Found ${ssgPages.length} SSG pages, ${ssrRoutes.length} SSR routes`);
20983
21227
  logger.info("Pre-rendering SSG pages...");
20984
- const outDir = path21.join(server?.config.root || process.cwd(), options.outDir || "dist");
20985
- const clientDir = path21.join(outDir, "client");
21228
+ const outDir = path22.join(server?.config.root || process.cwd(), options.outDir || "dist");
21229
+ const clientDir = path22.join(outDir, "client");
20986
21230
  for (const page2 of ssgPages) {
20987
21231
  try {
20988
21232
  const staticRequest = new Request(new URL(page2.urlPath, "http://farm.static"));
@@ -21034,8 +21278,8 @@ if (import.meta.hot) {
21034
21278
  <script type="module" src="/assets/client.js"></script>
21035
21279
  </body>
21036
21280
  </html>`;
21037
- const outputPath = page2.urlPath === "/" ? path21.join(clientDir, "index.html") : path21.join(clientDir, page2.urlPath + ".html");
21038
- fs7.mkdirSync(path21.dirname(outputPath), { recursive: true });
21281
+ const outputPath = page2.urlPath === "/" ? path22.join(clientDir, "index.html") : path22.join(clientDir, page2.urlPath + ".html");
21282
+ fs7.mkdirSync(path22.dirname(outputPath), { recursive: true });
21039
21283
  fs7.writeFileSync(outputPath, fullHtml);
21040
21284
  const revalidateInfo = page2.revalidate ? ` (revalidate: ${page2.revalidate}s)` : "";
21041
21285
  logger.success(` \u2713 ${page2.urlPath}${revalidateInfo}`);
@@ -21044,7 +21288,7 @@ if (import.meta.hot) {
21044
21288
  logger.error(` \u2717 ${page2.urlPath}: ${error}`);
21045
21289
  }
21046
21290
  }
21047
- const manifestPath = path21.join(outDir, "__ssg_manifest.json");
21291
+ const manifestPath = path22.join(outDir, "__ssg_manifest.json");
21048
21292
  fs7.writeFileSync(
21049
21293
  manifestPath,
21050
21294
  JSON.stringify(
@@ -21080,9 +21324,9 @@ if (import.meta.hot) {
21080
21324
  }
21081
21325
  const currentFarmConfig = farmApp?.getConfig();
21082
21326
  const normalizedFile = file.replace(/\\/g, "/");
21083
- const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) => path21.join(source.root, source.srcDir).replace(/\\/g, "/")).find((sourceRoot) => normalizedFile.startsWith(`${sourceRoot}/`)) || null : null;
21327
+ const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) => path22.join(source.root, source.srcDir).replace(/\\/g, "/")).find((sourceRoot) => normalizedFile.startsWith(`${sourceRoot}/`)) || null : null;
21084
21328
  if (currentSrcRoot && normalizedFile.startsWith(`${currentSrcRoot}/`) && isProgrammaticRoutesFileName(normalizedFile)) {
21085
- logUpdate("PAGE", `updated ${path21.basename(file)}`);
21329
+ logUpdate("PAGE", `updated ${path22.basename(file)}`);
21086
21330
  for (const mod of modules) {
21087
21331
  server2.moduleGraph.invalidateModule(mod);
21088
21332
  }
@@ -22125,6 +22369,7 @@ async function buildRouteComponentProps(pageModule, params, searchParams, path,
22125
22369
  const parsedSearch = parseClientRouteSchema(schemas?.search, searchParams, 'search');
22126
22370
 
22127
22371
  return {
22372
+ ...(existingProps || {}),
22128
22373
  params: parsedParams,
22129
22374
  search: parsedSearch,
22130
22375
  searchParams: schemas ? Promise.resolve(parsedSearch) : parsedSearch,