@farm.js/core 0.1.0-beta.22 → 0.1.0-beta.24

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 (132) hide show
  1. package/dist/agent-runtime.d.mts +2 -1
  2. package/dist/agent-runtime.d.ts +2 -1
  3. package/dist/{app-DwsTpyNZ.d.mts → app-DrFCUMHY.d.mts} +6 -3
  4. package/dist/app-markdown.d.mts +2 -1
  5. package/dist/app-markdown.d.ts +2 -1
  6. package/dist/{app-BB8GCH1g.d.ts → app-pwvKG2B1.d.ts} +6 -3
  7. package/dist/chunk-4IVNW5QD.mjs +82 -0
  8. package/dist/chunk-4IVNW5QD.mjs.map +1 -0
  9. package/dist/chunk-D42BNPZH.mjs +79 -0
  10. package/dist/chunk-D42BNPZH.mjs.map +1 -0
  11. package/dist/{chunk-LLPN5SEZ.mjs → chunk-DVPRBMU2.mjs} +2 -2
  12. package/dist/chunk-GQVQESLY.mjs +25 -0
  13. package/dist/chunk-GQVQESLY.mjs.map +1 -0
  14. package/dist/chunk-H53KVQUU.mjs +48 -0
  15. package/dist/chunk-H53KVQUU.mjs.map +1 -0
  16. package/dist/chunk-HCGQYYHI.mjs +1 -0
  17. package/dist/chunk-HCGQYYHI.mjs.map +1 -0
  18. package/dist/{chunk-XBKXKJX5.mjs → chunk-HVJHNKSP.mjs} +220 -63
  19. package/dist/chunk-HVJHNKSP.mjs.map +1 -0
  20. package/dist/{chunk-ZP73P4VR.mjs → chunk-HXE4VGH2.mjs} +79 -20
  21. package/dist/chunk-HXE4VGH2.mjs.map +1 -0
  22. package/dist/{chunk-UCYWGN2P.mjs → chunk-OHNSROHS.mjs} +1 -1
  23. package/dist/{chunk-FRPWCMMG.mjs → chunk-SBWOTAX4.mjs} +63 -2
  24. package/dist/chunk-SBWOTAX4.mjs.map +1 -0
  25. package/dist/{chunk-DAUR3WUZ.mjs → chunk-WO466YX5.mjs} +2 -2
  26. package/dist/chunk-WO466YX5.mjs.map +1 -0
  27. package/dist/{chunk-CEVMYGDL.mjs → chunk-YD5IRKVS.mjs} +13 -9
  28. package/dist/chunk-YD5IRKVS.mjs.map +1 -0
  29. package/dist/{client-plugins-QQntVkrv.d.mts → client-plugins-CCilIb_G.d.mts} +6 -2
  30. package/dist/{client-plugins-CbRum1fj.d.ts → client-plugins-DuuleQKk.d.ts} +6 -2
  31. package/dist/client-plugins.d.mts +2 -1
  32. package/dist/client-plugins.d.ts +2 -1
  33. package/dist/client.cjs +122 -35
  34. package/dist/client.cjs.map +1 -1
  35. package/dist/client.d.mts +2 -0
  36. package/dist/client.d.ts +2 -0
  37. package/dist/client.mjs +13 -2
  38. package/dist/config.d.mts +2 -1
  39. package/dist/config.d.ts +2 -1
  40. package/dist/{devtools-52FYXIEK.mjs → devtools-326RBQCN.mjs} +7 -6
  41. package/dist/{devtools-52FYXIEK.mjs.map → devtools-326RBQCN.mjs.map} +1 -1
  42. package/dist/docs.cjs.map +1 -1
  43. package/dist/docs.mjs +6 -5
  44. package/dist/index.cjs +910 -414
  45. package/dist/index.cjs.map +1 -1
  46. package/dist/index.d.mts +10 -7
  47. package/dist/index.d.ts +10 -7
  48. package/dist/index.mjs +66 -49
  49. package/dist/index.mjs.map +1 -1
  50. package/dist/integrations.d.mts +2 -1
  51. package/dist/integrations.d.ts +2 -1
  52. package/dist/internal/build-runtime.cjs +720 -297
  53. package/dist/internal/build-runtime.cjs.map +1 -1
  54. package/dist/internal/build-runtime.d.mts +4 -3
  55. package/dist/internal/build-runtime.d.ts +4 -3
  56. package/dist/internal/build-runtime.mjs +15 -12
  57. package/dist/internal/config-runtime.cjs +41 -0
  58. package/dist/internal/config-runtime.cjs.map +1 -1
  59. package/dist/internal/config-runtime.d.mts +3 -2
  60. package/dist/internal/config-runtime.d.ts +3 -2
  61. package/dist/internal/config-runtime.mjs +5 -4
  62. package/dist/internal/production-runtime.cjs +178 -0
  63. package/dist/internal/production-runtime.cjs.map +1 -1
  64. package/dist/internal/production-runtime.d.mts +20 -6
  65. package/dist/internal/production-runtime.d.ts +20 -6
  66. package/dist/internal/production-runtime.mjs +13 -1
  67. package/dist/internal/production-runtime.mjs.map +1 -1
  68. package/dist/{metadata-B5jBJHq1.d.ts → metadata-DyPRG0wX.d.ts} +1 -1
  69. package/dist/{metadata-BxOJ4FJl.d.mts → metadata-_GHcAySx.d.mts} +1 -1
  70. package/dist/middleware.d.mts +4 -3
  71. package/dist/middleware.d.ts +4 -3
  72. package/dist/plugin.cjs +461 -155
  73. package/dist/plugin.cjs.map +1 -1
  74. package/dist/plugin.d.mts +2 -1
  75. package/dist/plugin.d.ts +2 -1
  76. package/dist/plugin.mjs +11 -8
  77. package/dist/{production-runtime-Bxua86uR.d.mts → production-runtime-C4cO3esK.d.mts} +1 -1
  78. package/dist/{production-runtime-CZqXjRVi.d.ts → production-runtime-DrEy8kBO.d.ts} +1 -1
  79. package/dist/{request-7V0GaZK_.d.mts → request-B2PpOxYK.d.mts} +1 -1
  80. package/dist/{request-B5XYBv5a.d.ts → request-D40lt6aN.d.ts} +1 -1
  81. package/dist/request.d.mts +3 -2
  82. package/dist/request.d.ts +3 -2
  83. package/dist/routes.d.mts +2 -1
  84. package/dist/routes.d.ts +2 -1
  85. package/dist/server-plugins.d.mts +3 -2
  86. package/dist/server-plugins.d.ts +3 -2
  87. package/dist/server.cjs +490 -167
  88. package/dist/server.cjs.map +1 -1
  89. package/dist/server.d.mts +8 -6
  90. package/dist/server.d.ts +8 -6
  91. package/dist/server.mjs +20 -11
  92. package/dist/server.mjs.map +1 -1
  93. package/dist/testing.d.mts +2 -1
  94. package/dist/testing.d.ts +2 -1
  95. package/dist/theme/client.cjs +115 -0
  96. package/dist/theme/client.cjs.map +1 -0
  97. package/dist/theme/client.d.mts +17 -0
  98. package/dist/theme/client.d.ts +17 -0
  99. package/dist/theme/client.mjs +16 -0
  100. package/dist/theme/client.mjs.map +1 -0
  101. package/dist/theme/index.cjs +71 -0
  102. package/dist/theme/index.cjs.map +1 -0
  103. package/dist/theme/index.d.mts +6 -0
  104. package/dist/theme/index.d.ts +6 -0
  105. package/dist/theme/index.mjs +9 -0
  106. package/dist/theme/index.mjs.map +1 -0
  107. package/dist/theme/server.cjs +191 -0
  108. package/dist/theme/server.cjs.map +1 -0
  109. package/dist/theme/server.d.mts +8 -0
  110. package/dist/theme/server.d.ts +8 -0
  111. package/dist/theme/server.mjs +18 -0
  112. package/dist/theme/server.mjs.map +1 -0
  113. package/dist/types-CsR8fpgF.d.mts +30 -0
  114. package/dist/types-CsR8fpgF.d.ts +30 -0
  115. package/dist/{utils-xTFxzu47.d.ts → utils-3sQgfkya.d.ts} +1 -1
  116. package/dist/{utils-s9pN0Yep.d.mts → utils-Bop7bly-.d.mts} +1 -1
  117. package/dist/version.cjs +1 -1
  118. package/dist/version.cjs.map +1 -1
  119. package/dist/version.mjs +1 -1
  120. package/dist/vite.cjs +485 -157
  121. package/dist/vite.cjs.map +1 -1
  122. package/dist/vite.d.mts +2 -1
  123. package/dist/vite.d.ts +2 -1
  124. package/dist/vite.mjs +11 -8
  125. package/package.json +25 -1
  126. package/dist/chunk-CEVMYGDL.mjs.map +0 -1
  127. package/dist/chunk-DAUR3WUZ.mjs.map +0 -1
  128. package/dist/chunk-FRPWCMMG.mjs.map +0 -1
  129. package/dist/chunk-XBKXKJX5.mjs.map +0 -1
  130. package/dist/chunk-ZP73P4VR.mjs.map +0 -1
  131. /package/dist/{chunk-LLPN5SEZ.mjs.map → chunk-DVPRBMU2.mjs.map} +0 -0
  132. /package/dist/{chunk-UCYWGN2P.mjs.map → chunk-OHNSROHS.mjs.map} +0 -0
package/dist/vite.cjs CHANGED
@@ -580,11 +580,11 @@ function resolveFarmServerHealthConfig(config) {
580
580
  return Object.freeze({ enabled: true, livenessPath, readinessPath });
581
581
  }
582
582
  function normalizeHealthPath(value, optionName) {
583
- const path26 = value.trim();
584
- if (!path26.startsWith("/") || path26.includes("?") || path26.includes("#") || path26.includes("*")) {
583
+ const path27 = value.trim();
584
+ if (!path27.startsWith("/") || path27.includes("?") || path27.includes("#") || path27.includes("*")) {
585
585
  throw new TypeError(`${optionName} must be an absolute pathname without a query or wildcard`);
586
586
  }
587
- return path26.length > 1 ? path26.replace(/\/+$/, "") || "/" : path26;
587
+ return path27.length > 1 ? path27.replace(/\/+$/, "") || "/" : path27;
588
588
  }
589
589
  function parseBodySizeLimit(value, optionName = "bodySizeLimit") {
590
590
  if (typeof value === "number") {
@@ -681,7 +681,7 @@ async function readNodeRequestBody(request, limit) {
681
681
  request.resume?.();
682
682
  throw error;
683
683
  }
684
- return await new Promise((resolve6, reject) => {
684
+ return await new Promise((resolve7, reject) => {
685
685
  const chunks = [];
686
686
  let total = 0;
687
687
  let settled = false;
@@ -710,7 +710,7 @@ async function readNodeRequestBody(request, limit) {
710
710
  if (settled) return;
711
711
  settled = true;
712
712
  cleanup();
713
- resolve6(Buffer.concat(chunks, total));
713
+ resolve7(Buffer.concat(chunks, total));
714
714
  }, "onEnd");
715
715
  const onError = /* @__PURE__ */ __name((error) => rejectOnce(error), "onError");
716
716
  request.on("data", onData);
@@ -939,22 +939,22 @@ async function prepareFarmWorkflowsForNitro(config) {
939
939
  }
940
940
  const root = config.root || process.cwd();
941
941
  const distDir = config.distDir || ".farm";
942
- const fs8 = await import("fs/promises");
943
- const path26 = await import("path");
944
- const generatedDir = path26.join(root, distDir, ".nitro", "farm-workflows");
945
- await fs8.mkdir(generatedDir, { recursive: true });
942
+ const fs9 = await import("fs/promises");
943
+ const path27 = await import("path");
944
+ const generatedDir = path27.join(root, distDir, ".nitro", "farm-workflows");
945
+ await fs9.mkdir(generatedDir, { recursive: true });
946
946
  const tasks = {};
947
947
  const scheduledTasks = createScheduledTasks(workflows);
948
948
  for (const workflow of workflows) {
949
- const wrapperPath = path26.join(generatedDir, `${safeFileName(workflow.id)}.mjs`);
950
- await fs8.writeFile(wrapperPath, createNitroTaskWrapper(workflow), "utf8");
949
+ const wrapperPath = path27.join(generatedDir, `${safeFileName(workflow.id)}.mjs`);
950
+ await fs9.writeFile(wrapperPath, createNitroTaskWrapper(workflow), "utf8");
951
951
  tasks[workflow.id] = {
952
952
  handler: wrapperPath,
953
953
  description: workflow.description || `Farm workflow ${workflow.id}`
954
954
  };
955
955
  }
956
- const handlerPath = path26.join(generatedDir, "http-handler.mjs");
957
- await fs8.writeFile(
956
+ const handlerPath = path27.join(generatedDir, "http-handler.mjs");
957
+ await fs9.writeFile(
958
958
  handlerPath,
959
959
  createNitroWorkflowHTTPHandler(
960
960
  workflowConfig,
@@ -963,8 +963,8 @@ async function prepareFarmWorkflowsForNitro(config) {
963
963
  ),
964
964
  "utf8"
965
965
  );
966
- const manifestPath = path26.join(generatedDir, "manifest.json");
967
- await fs8.writeFile(
966
+ const manifestPath = path27.join(generatedDir, "manifest.json");
967
+ await fs9.writeFile(
968
968
  manifestPath,
969
969
  JSON.stringify(
970
970
  {
@@ -1045,22 +1045,22 @@ function resolveWorkflowDefinition(module2) {
1045
1045
  return null;
1046
1046
  }
1047
1047
  async function findWorkflowFiles(root, dirs) {
1048
- const fs8 = await import("fs/promises");
1049
- const path26 = await import("path");
1048
+ const fs9 = await import("fs/promises");
1049
+ const path27 = await import("path");
1050
1050
  const files = [];
1051
1051
  for (const dir of dirs) {
1052
- const absoluteDir = path26.isAbsolute(dir) ? dir : path26.join(root, dir);
1052
+ const absoluteDir = path27.isAbsolute(dir) ? dir : path27.join(root, dir);
1053
1053
  if (!await pathExists(absoluteDir)) continue;
1054
1054
  await walkWorkflowDir(absoluteDir, files);
1055
1055
  }
1056
1056
  return files.sort();
1057
1057
  }
1058
1058
  async function walkWorkflowDir(dir, files) {
1059
- const fs8 = await import("fs/promises");
1060
- const path26 = await import("path");
1061
- const entries = await fs8.readdir(dir, { withFileTypes: true });
1059
+ const fs9 = await import("fs/promises");
1060
+ const path27 = await import("path");
1061
+ const entries = await fs9.readdir(dir, { withFileTypes: true });
1062
1062
  for (const entry of entries) {
1063
- const filePath = path26.join(dir, entry.name);
1063
+ const filePath = path27.join(dir, entry.name);
1064
1064
  if (entry.isDirectory()) {
1065
1065
  if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
1066
1066
  await walkWorkflowDir(filePath, files);
@@ -1072,20 +1072,20 @@ async function walkWorkflowDir(dir, files) {
1072
1072
  }
1073
1073
  }
1074
1074
  async function pathExists(filePath) {
1075
- const fs8 = await import("fs/promises");
1076
- return fs8.access(filePath).then(() => true).catch(() => false);
1075
+ const fs9 = await import("fs/promises");
1076
+ return fs9.access(filePath).then(() => true).catch(() => false);
1077
1077
  }
1078
1078
  function isWorkflowFile(fileName) {
1079
1079
  return /\.(?:ts|tsx|js|jsx|mjs|cjs)$/.test(fileName) && !/\.d\.[cm]?ts$/.test(fileName);
1080
1080
  }
1081
1081
  async function loadWorkflowModule(filePath, root) {
1082
- const fs8 = await import("fs/promises");
1083
- const path26 = await import("path");
1082
+ const fs9 = await import("fs/promises");
1083
+ const path27 = await import("path");
1084
1084
  const { pathToFileURL: pathToFileURL5 } = await import("url");
1085
1085
  const { build } = await import("esbuild");
1086
- const outDir = path26.join(root, ".farm", ".workflow-loader");
1087
- await fs8.mkdir(outDir, { recursive: true });
1088
- const outfile = path26.join(
1086
+ const outDir = path27.join(root, ".farm", ".workflow-loader");
1087
+ await fs9.mkdir(outDir, { recursive: true });
1088
+ const outfile = path27.join(
1089
1089
  outDir,
1090
1090
  `workflow-${Date.now()}-${Math.random().toString(36).slice(2)}.mjs`
1091
1091
  );
@@ -1109,7 +1109,7 @@ async function loadWorkflowModule(filePath, root) {
1109
1109
  `${pathToFileURL5(outfile).href}?t=${Date.now()}`
1110
1110
  );
1111
1111
  } finally {
1112
- await fs8.unlink(outfile).catch(() => void 0);
1112
+ await fs9.unlink(outfile).catch(() => void 0);
1113
1113
  }
1114
1114
  }
1115
1115
  function workflowIdFromFile(root, filePath) {
@@ -1384,7 +1384,7 @@ function normalizeCronJob(name, job) {
1384
1384
  if (!job || typeof job !== "object" || Array.isArray(job)) {
1385
1385
  throw new TypeError(`Farm cron ${JSON.stringify(name)} must be a configuration object.`);
1386
1386
  }
1387
- const path26 = normalizeCronPath(name, job.path);
1387
+ const path27 = normalizeCronPath(name, job.path);
1388
1388
  const rawSchedule = Array.isArray(job.schedule) ? job.schedule : [job.schedule];
1389
1389
  const schedule = [...new Set(rawSchedule.map((value) => normalizeCronExpression(name, value)))];
1390
1390
  if (schedule.length === 0) {
@@ -1393,7 +1393,7 @@ function normalizeCronJob(name, job) {
1393
1393
  return {
1394
1394
  name,
1395
1395
  schedule,
1396
- path: path26,
1396
+ path: path27,
1397
1397
  description: job.description?.trim() || void 0
1398
1398
  };
1399
1399
  }
@@ -1401,13 +1401,13 @@ function normalizeCronPath(name, value) {
1401
1401
  if (typeof value !== "string" || !value.trim().startsWith("/")) {
1402
1402
  throw new TypeError(`Farm cron ${JSON.stringify(name)} path must start with "/".`);
1403
1403
  }
1404
- const path26 = value.trim();
1405
- if (path26.startsWith("//") || path26.includes("?") || path26.includes("#")) {
1404
+ const path27 = value.trim();
1405
+ if (path27.startsWith("//") || path27.includes("?") || path27.includes("#")) {
1406
1406
  throw new TypeError(
1407
1407
  `Farm cron ${JSON.stringify(name)} path must be an application pathname without a host, query, or hash.`
1408
1408
  );
1409
1409
  }
1410
- return path26.length > 1 ? path26.replace(/\/+$/, "") : path26;
1410
+ return path27.length > 1 ? path27.replace(/\/+$/, "") : path27;
1411
1411
  }
1412
1412
  function normalizeCronExpression(name, value) {
1413
1413
  if (typeof value !== "string") {
@@ -2243,7 +2243,7 @@ var init_server_action_security = __esm({
2243
2243
 
2244
2244
  // src/image-config.ts
2245
2245
  function resolveFarmImageConfig(config) {
2246
- const path26 = normalizeImagePath(config?.path ?? DEFAULT_FARM_IMAGE_PATH);
2246
+ const path27 = normalizeImagePath(config?.path ?? DEFAULT_FARM_IMAGE_PATH);
2247
2247
  const deviceSizes = normalizeIntegerList(
2248
2248
  config?.deviceSizes ?? DEFAULT_FARM_IMAGE_DEVICE_SIZES,
2249
2249
  "images.deviceSizes"
@@ -2271,7 +2271,7 @@ function resolveFarmImageConfig(config) {
2271
2271
  );
2272
2272
  return Object.freeze({
2273
2273
  provider: config?.provider ?? "auto",
2274
- path: path26,
2274
+ path: path27,
2275
2275
  domains: Object.freeze([
2276
2276
  ...new Set(
2277
2277
  (config?.domains ?? []).map((domain) => domain.trim().toLowerCase()).filter(Boolean)
@@ -2310,11 +2310,11 @@ function getPublicFarmImageConfig(config) {
2310
2310
  };
2311
2311
  }
2312
2312
  function normalizeImagePath(value) {
2313
- const path26 = value.trim().replace(/\/+$/, "") || "/";
2314
- if (!path26.startsWith("/") || path26.includes("?") || path26.includes("#")) {
2313
+ const path27 = value.trim().replace(/\/+$/, "") || "/";
2314
+ if (!path27.startsWith("/") || path27.includes("?") || path27.includes("#")) {
2315
2315
  throw new TypeError("images.path must be an absolute pathname without a query or hash");
2316
2316
  }
2317
- return path26;
2317
+ return path27;
2318
2318
  }
2319
2319
  function normalizeIntegerList(values, name, max) {
2320
2320
  if (values.length === 0) {
@@ -3164,9 +3164,9 @@ function getFarmIntegrationPluginOwner(plugin) {
3164
3164
  const value = plugin[FARM_INTEGRATION_PLUGIN_OWNER];
3165
3165
  return value && typeof value === "object" ? value : void 0;
3166
3166
  }
3167
- function defineTypedIntegrationRoute(method, path26, input) {
3167
+ function defineTypedIntegrationRoute(method, path27, input) {
3168
3168
  return {
3169
- path: path26,
3169
+ path: path27,
3170
3170
  method,
3171
3171
  middleware: input.middleware,
3172
3172
  before: input.before,
@@ -3176,7 +3176,7 @@ function defineTypedIntegrationRoute(method, path26, input) {
3176
3176
  input: normalizeIntegrationRouteInputSchemas(input),
3177
3177
  handler: input.handler,
3178
3178
  __operation: defineIntegrationAPIOperation({
3179
- path: path26,
3179
+ path: path27,
3180
3180
  method,
3181
3181
  bodyFormat: input.bodyFormat,
3182
3182
  responseFormat: input.responseFormat,
@@ -3188,52 +3188,52 @@ function defineTypedIntegrationRoute(method, path26, input) {
3188
3188
  }
3189
3189
  function createIntegrationRouteFactory() {
3190
3190
  return {
3191
- get(path26, input) {
3191
+ get(path27, input) {
3192
3192
  return defineTypedIntegrationRoute(
3193
3193
  "GET",
3194
- path26,
3194
+ path27,
3195
3195
  input
3196
3196
  );
3197
3197
  },
3198
- post(path26, input) {
3198
+ post(path27, input) {
3199
3199
  return defineTypedIntegrationRoute(
3200
3200
  "POST",
3201
- path26,
3201
+ path27,
3202
3202
  {
3203
3203
  bodyFormat: "json",
3204
3204
  ...input
3205
3205
  }
3206
3206
  );
3207
3207
  },
3208
- put(path26, input) {
3208
+ put(path27, input) {
3209
3209
  return defineTypedIntegrationRoute(
3210
3210
  "PUT",
3211
- path26,
3211
+ path27,
3212
3212
  {
3213
3213
  bodyFormat: "json",
3214
3214
  ...input
3215
3215
  }
3216
3216
  );
3217
3217
  },
3218
- patch(path26, input) {
3219
- return defineTypedIntegrationRoute("PATCH", path26, {
3218
+ patch(path27, input) {
3219
+ return defineTypedIntegrationRoute("PATCH", path27, {
3220
3220
  bodyFormat: "json",
3221
3221
  ...input
3222
3222
  });
3223
3223
  },
3224
- delete(path26, input) {
3225
- return defineTypedIntegrationRoute("DELETE", path26, {
3224
+ delete(path27, input) {
3225
+ return defineTypedIntegrationRoute("DELETE", path27, {
3226
3226
  bodyFormat: "json",
3227
3227
  ...input
3228
3228
  });
3229
3229
  },
3230
- options(path26, input) {
3231
- return defineTypedIntegrationRoute("OPTIONS", path26, input);
3230
+ options(path27, input) {
3231
+ return defineTypedIntegrationRoute("OPTIONS", path27, input);
3232
3232
  },
3233
- head(path26, input) {
3233
+ head(path27, input) {
3234
3234
  return defineTypedIntegrationRoute(
3235
3235
  "HEAD",
3236
- path26,
3236
+ path27,
3237
3237
  input
3238
3238
  );
3239
3239
  }
@@ -3570,8 +3570,8 @@ function normalizeIntegrationValidationIssues(source, error) {
3570
3570
  }
3571
3571
  ];
3572
3572
  }
3573
- function normalizeIntegrationValidationPath(path26) {
3574
- return (path26 || []).map((segment) => {
3573
+ function normalizeIntegrationValidationPath(path27) {
3574
+ return (path27 || []).map((segment) => {
3575
3575
  const key = typeof segment === "object" && segment !== null && "key" in segment ? segment.key : segment;
3576
3576
  return typeof key === "symbol" ? key.description || key.toString() : key;
3577
3577
  });
@@ -4274,8 +4274,8 @@ function createFarmDeploymentMismatchResponse(mismatch) {
4274
4274
  }
4275
4275
  );
4276
4276
  }
4277
- function createFarmDeploymentCookie(deploymentId, path26 = "/", secure = false) {
4278
- const normalizedPath = path26.startsWith("/") ? path26 : `/${path26}`;
4277
+ function createFarmDeploymentCookie(deploymentId, path27 = "/", secure = false) {
4278
+ const normalizedPath = path27.startsWith("/") ? path27 : `/${path27}`;
4279
4279
  return [
4280
4280
  `${FARM_DEPLOYMENT_COOKIE}=${encodeURIComponent(deploymentId)}`,
4281
4281
  `Path=${normalizedPath}`,
@@ -4444,6 +4444,52 @@ var init_config = __esm({
4444
4444
  }
4445
4445
  });
4446
4446
 
4447
+ // src/theme/config.ts
4448
+ function resolveFarmThemeConfig(config, basePath = "/") {
4449
+ if (config && "enabled" in config) {
4450
+ return config;
4451
+ }
4452
+ if (!config) {
4453
+ return {
4454
+ enabled: false,
4455
+ default: "system",
4456
+ storageKey: DEFAULT_FARM_THEME_STORAGE_KEY,
4457
+ cookiePath: normalizeCookiePath(basePath)
4458
+ };
4459
+ }
4460
+ const storageKey = config.storageKey?.trim() || DEFAULT_FARM_THEME_STORAGE_KEY;
4461
+ if (!STORAGE_KEY_PATTERN.test(storageKey)) {
4462
+ throw new Error(
4463
+ "theme.storageKey may only contain letters, numbers, dots, underscores, and hyphens."
4464
+ );
4465
+ }
4466
+ const defaultTheme = config.default ?? "system";
4467
+ if (defaultTheme !== "light" && defaultTheme !== "dark" && defaultTheme !== "system") {
4468
+ throw new Error('theme.default must be "light", "dark", or "system".');
4469
+ }
4470
+ return {
4471
+ enabled: true,
4472
+ default: defaultTheme,
4473
+ storageKey,
4474
+ cookiePath: normalizeCookiePath(basePath)
4475
+ };
4476
+ }
4477
+ function normalizeCookiePath(basePath) {
4478
+ const normalized = `/${basePath}`.replace(/\/{2,}/g, "/");
4479
+ if (normalized === "/") return normalized;
4480
+ return normalized.replace(/\/$/, "");
4481
+ }
4482
+ var DEFAULT_FARM_THEME_STORAGE_KEY, STORAGE_KEY_PATTERN;
4483
+ var init_config2 = __esm({
4484
+ "src/theme/config.ts"() {
4485
+ "use strict";
4486
+ DEFAULT_FARM_THEME_STORAGE_KEY = "farm-theme";
4487
+ STORAGE_KEY_PATTERN = /^[A-Za-z0-9._-]+$/;
4488
+ __name(resolveFarmThemeConfig, "resolveFarmThemeConfig");
4489
+ __name(normalizeCookiePath, "normalizeCookiePath");
4490
+ }
4491
+ });
4492
+
4447
4493
  // src/devtools-config.ts
4448
4494
  function resolveFarmDevtoolsConfig(config, mode = "development") {
4449
4495
  if (mode !== "development" || config === false) {
@@ -4806,11 +4852,11 @@ var init_type_generator = __esm({
4806
4852
  routeGroups.get(key).push(route);
4807
4853
  }
4808
4854
  const nestedStructure = {};
4809
- for (const [path26, routeList] of routeGroups) {
4855
+ for (const [path27, routeList] of routeGroups) {
4810
4856
  const route = routeList[0];
4811
4857
  const importPath = this.getRouteImportPath(route, options.outFile);
4812
4858
  const routeName = this.pathToRouteName(route.path);
4813
- const cleanPath = path26 === "/api" ? "" : path26.replace(/^\/api\//, "");
4859
+ const cleanPath = path27 === "/api" ? "" : path27.replace(/^\/api\//, "");
4814
4860
  const parts = cleanPath ? cleanPath.split("/") : [];
4815
4861
  const allMethods = routeList.flatMap((r) => r.methods);
4816
4862
  for (const method of allMethods) {
@@ -4869,8 +4915,8 @@ ${typeExports}
4869
4915
  const relativeImport = (0, import_path7.relative)((0, import_path7.dirname)(outFile), route.filePath).replace(/\\/g, "/").replace(/\.(ts|tsx|js|jsx)$/, "");
4870
4916
  return relativeImport.startsWith(".") ? relativeImport : `./${relativeImport}`;
4871
4917
  }
4872
- pathToRouteName(path26) {
4873
- return (path26 === "/api" ? "root" : path26.replace(/^\/api\//, "")).replace(/\//g, "_").replace(/[^a-zA-Z0-9_]/g, "");
4918
+ pathToRouteName(path27) {
4919
+ return (path27 === "/api" ? "root" : path27.replace(/^\/api\//, "")).replace(/\//g, "_").replace(/[^a-zA-Z0-9_]/g, "");
4874
4920
  }
4875
4921
  structureToTypeString(obj, indent) {
4876
4922
  const spaces = " ".repeat(indent);
@@ -4890,15 +4936,15 @@ ${typeExports}
4890
4936
  toTypePropertyKey(key) {
4891
4937
  return /^[$A-Z_][0-9A-Z_$]*$/i.test(key) ? key : JSON.stringify(key);
4892
4938
  }
4893
- getBaseExportName(path26) {
4894
- const cleanPath = path26.replace(/^\/api\//, "");
4939
+ getBaseExportName(path27) {
4940
+ const cleanPath = path27.replace(/^\/api\//, "");
4895
4941
  if (cleanPath === "") {
4896
4942
  return "api";
4897
4943
  }
4898
4944
  return cleanPath;
4899
4945
  }
4900
- getExportName(path26, method) {
4901
- const cleanPath = path26.replace(/^\/api\//, "");
4946
+ getExportName(path27, method) {
4947
+ const cleanPath = path27.replace(/^\/api\//, "");
4902
4948
  if (cleanPath === "") {
4903
4949
  return method.toLowerCase();
4904
4950
  }
@@ -9207,37 +9253,37 @@ function sanitizeDocsConfig(config) {
9207
9253
  return cloneSerializable(config) || {};
9208
9254
  }
9209
9255
  async function findDocsConfigPath(rootDir, configPath) {
9210
- const { existsSync: existsSync16 } = await import("fs");
9256
+ const { existsSync: existsSync17 } = await import("fs");
9211
9257
  const root = import_path9.default.resolve(rootDir || process.cwd());
9212
9258
  if (configPath) {
9213
9259
  const resolvedPath = import_path9.default.isAbsolute(configPath) ? configPath : import_path9.default.join(root, configPath);
9214
- if (!existsSync16(resolvedPath)) {
9260
+ if (!existsSync17(resolvedPath)) {
9215
9261
  throw new Error(`Could not find docs config at ${configPath}.`);
9216
9262
  }
9217
9263
  return import_path9.default.resolve(resolvedPath);
9218
9264
  }
9219
9265
  for (const filename of DOCS_CONFIG_FILENAMES) {
9220
9266
  const resolvedPath = import_path9.default.join(root, filename);
9221
- if (existsSync16(resolvedPath)) {
9267
+ if (existsSync17(resolvedPath)) {
9222
9268
  return resolvedPath;
9223
9269
  }
9224
9270
  }
9225
9271
  return void 0;
9226
9272
  }
9227
9273
  async function loadDocsConfig(rootDir, configPath) {
9228
- const fs8 = await import("fs/promises");
9274
+ const fs9 = await import("fs/promises");
9229
9275
  const { pathToFileURL: pathToFileURL5 } = await import("url");
9230
9276
  const root = import_path9.default.resolve(rootDir || process.cwd());
9231
9277
  const resolvedPath = await findDocsConfigPath(root, configPath);
9232
9278
  if (!resolvedPath) return void 0;
9233
9279
  try {
9234
9280
  if (resolvedPath.endsWith(".json")) {
9235
- const content = await fs8.readFile(resolvedPath, "utf8");
9281
+ const content = await fs9.readFile(resolvedPath, "utf8");
9236
9282
  return { config: JSON.parse(content), configPath: resolvedPath };
9237
9283
  }
9238
9284
  const { build } = await import("esbuild");
9239
9285
  const configCacheDir = import_path9.default.join(root, ".farm", ".config-loader");
9240
- await fs8.mkdir(configCacheDir, { recursive: true });
9286
+ await fs9.mkdir(configCacheDir, { recursive: true });
9241
9287
  const modulePath = import_path9.default.join(
9242
9288
  configCacheDir,
9243
9289
  `docs-config-${Date.now()}-${Math.random().toString(36).slice(2)}.mjs`
@@ -9263,7 +9309,7 @@ async function loadDocsConfig(rootDir, configPath) {
9263
9309
  moduleUrl
9264
9310
  );
9265
9311
  } finally {
9266
- await fs8.unlink(modulePath).catch(() => void 0);
9312
+ await fs9.unlink(modulePath).catch(() => void 0);
9267
9313
  }
9268
9314
  return {
9269
9315
  config: importedConfig.default || importedConfig,
@@ -9336,7 +9382,7 @@ async function resolveDocsConfig(userDocs, options = {}) {
9336
9382
  };
9337
9383
  }
9338
9384
  var import_path9, DOCS_CONFIG_FILENAMES;
9339
- var init_config2 = __esm({
9385
+ var init_config3 = __esm({
9340
9386
  "src/config.ts"() {
9341
9387
  "use strict";
9342
9388
  init_integrations();
@@ -9357,6 +9403,7 @@ var init_config2 = __esm({
9357
9403
  init_auth_config();
9358
9404
  init_preload();
9359
9405
  init_security();
9406
+ init_config2();
9360
9407
  init_config_entry();
9361
9408
  __name(getDeployTargetForPreset, "getDeployTargetForPreset");
9362
9409
  DOCS_CONFIG_FILENAMES = [
@@ -9851,7 +9898,7 @@ var init_api = __esm({
9851
9898
  "src/docs/api.ts"() {
9852
9899
  "use strict";
9853
9900
  import_docs2 = require("@farming-labs/docs");
9854
- init_config2();
9901
+ init_config3();
9855
9902
  init_handler();
9856
9903
  __name(isRecord4, "isRecord");
9857
9904
  __name(isResolvedDocsConfig2, "isResolvedDocsConfig");
@@ -10145,8 +10192,8 @@ var init_generator = __esm({
10145
10192
  }
10146
10193
  routeGroups.get(key).push(route);
10147
10194
  }
10148
- for (const [path26, routeList] of routeGroups) {
10149
- const openAPIPath = this.convertToOpenAPIPath(path26);
10195
+ for (const [path27, routeList] of routeGroups) {
10196
+ const openAPIPath = this.convertToOpenAPIPath(path27);
10150
10197
  spec.paths[openAPIPath] = {};
10151
10198
  for (const route of routeList) {
10152
10199
  for (const method of route.methods) {
@@ -10160,8 +10207,8 @@ var init_generator = __esm({
10160
10207
  /**
10161
10208
  * Convert Farm.js API path to OpenAPI path format
10162
10209
  */
10163
- convertToOpenAPIPath(path26) {
10164
- return path26.replace(/^\/api/, "");
10210
+ convertToOpenAPIPath(path27) {
10211
+ return path27.replace(/^\/api/, "");
10165
10212
  }
10166
10213
  /**
10167
10214
  * Extract request body schema from endpoint
@@ -10323,8 +10370,8 @@ var init_generator = __esm({
10323
10370
  /**
10324
10371
  * Generate operation summary
10325
10372
  */
10326
- generateSummary(path26, method) {
10327
- const cleanPath = path26.replace(/^\/api\//, "");
10373
+ generateSummary(path27, method) {
10374
+ const cleanPath = path27.replace(/^\/api\//, "");
10328
10375
  const pathParts = cleanPath.split("/");
10329
10376
  const lastPart = pathParts[pathParts.length - 1];
10330
10377
  const action = method === "GET" ? "Get" : method === "POST" ? "Create" : method === "PUT" ? "Update" : method === "DELETE" ? "Delete" : method === "PATCH" ? "Update" : method;
@@ -10333,22 +10380,22 @@ var init_generator = __esm({
10333
10380
  /**
10334
10381
  * Generate operation description
10335
10382
  */
10336
- generateDescription(path26, method) {
10337
- const cleanPath = path26.replace(/^\/api\//, "");
10383
+ generateDescription(path27, method) {
10384
+ const cleanPath = path27.replace(/^\/api\//, "");
10338
10385
  return `${method} ${cleanPath} endpoint`;
10339
10386
  }
10340
10387
  /**
10341
10388
  * Generate operation ID
10342
10389
  */
10343
- generateOperationId(path26, method) {
10344
- const cleanPath = path26.replace(/^\/api\//, "").replace(/\//g, "_");
10390
+ generateOperationId(path27, method) {
10391
+ const cleanPath = path27.replace(/^\/api\//, "").replace(/\//g, "_");
10345
10392
  return `${method.toLowerCase()}_${cleanPath}`;
10346
10393
  }
10347
10394
  /**
10348
10395
  * Generate tags for grouping operations
10349
10396
  */
10350
- generateTags(path26) {
10351
- const cleanPath = path26.replace(/^\/api\//, "");
10397
+ generateTags(path27) {
10398
+ const cleanPath = path27.replace(/^\/api\//, "");
10352
10399
  const pathParts = cleanPath.split("/");
10353
10400
  if (pathParts.length > 1) {
10354
10401
  return [pathParts[0]];
@@ -10360,13 +10407,13 @@ var init_generator = __esm({
10360
10407
  */
10361
10408
  async generateSpecFile(routes, outputPath) {
10362
10409
  const spec = await this.generateSpec(routes);
10363
- const fs8 = require("fs");
10364
- const path26 = require("path");
10365
- const dir = path26.dirname(outputPath);
10366
- if (!fs8.existsSync(dir)) {
10367
- fs8.mkdirSync(dir, { recursive: true });
10410
+ const fs9 = require("fs");
10411
+ const path27 = require("path");
10412
+ const dir = path27.dirname(outputPath);
10413
+ if (!fs9.existsSync(dir)) {
10414
+ fs9.mkdirSync(dir, { recursive: true });
10368
10415
  }
10369
- fs8.writeFileSync(outputPath, JSON.stringify(spec, null, 2));
10416
+ fs9.writeFileSync(outputPath, JSON.stringify(spec, null, 2));
10370
10417
  }
10371
10418
  };
10372
10419
  __name(_OpenAPIGenerator, "OpenAPIGenerator");
@@ -10836,7 +10883,7 @@ var init_devtools = __esm({
10836
10883
  "src/devtools.ts"() {
10837
10884
  "use strict";
10838
10885
  import_node_path14 = __toESM(require("path"));
10839
- init_config2();
10886
+ init_config3();
10840
10887
  init_cron();
10841
10888
  init_route_runtime();
10842
10889
  __name(normalizePath, "normalizePath");
@@ -12623,8 +12670,8 @@ function toViteModuleId(filePath, root) {
12623
12670
  __name(toViteModuleId, "toViteModuleId");
12624
12671
  async function fileExists(filePath) {
12625
12672
  try {
12626
- const fs8 = await import("fs/promises");
12627
- await fs8.access(filePath);
12673
+ const fs9 = await import("fs/promises");
12674
+ await fs9.access(filePath);
12628
12675
  return true;
12629
12676
  } catch {
12630
12677
  return false;
@@ -13893,7 +13940,7 @@ function normalizePositiveDuration(value, fallback, name) {
13893
13940
  }
13894
13941
  __name(normalizePositiveDuration, "normalizePositiveDuration");
13895
13942
  function delay(ms) {
13896
- return new Promise((resolve6) => setTimeout(resolve6, ms));
13943
+ return new Promise((resolve7) => setTimeout(resolve7, ms));
13897
13944
  }
13898
13945
  __name(delay, "delay");
13899
13946
  function normalizeCacheOptionsTags(options) {
@@ -14029,25 +14076,25 @@ function defineRoutes(input) {
14029
14076
  }
14030
14077
  __name(defineRoutes, "defineRoutes");
14031
14078
  var routesBuilder = {
14032
- page(path26, options) {
14079
+ page(path27, options) {
14033
14080
  return normalizeProgrammaticRoute({
14034
14081
  kind: "page",
14035
- path: path26,
14082
+ path: path27,
14036
14083
  ...options
14037
14084
  });
14038
14085
  },
14039
- layout(path26, options) {
14086
+ layout(path27, options) {
14040
14087
  return normalizeProgrammaticRoute({
14041
14088
  kind: "layout",
14042
- path: path26,
14089
+ path: path27,
14043
14090
  ...options
14044
14091
  });
14045
14092
  },
14046
- api(path26, options) {
14093
+ api(path27, options) {
14047
14094
  const { render, runtime, regions, maxDuration, ...methods } = options;
14048
14095
  return normalizeProgrammaticRoute({
14049
14096
  kind: "api",
14050
- path: path26,
14097
+ path: path27,
14051
14098
  render,
14052
14099
  runtime,
14053
14100
  regions,
@@ -14083,7 +14130,7 @@ function getProgrammaticRouteSearchClientOptions(search) {
14083
14130
  return Object.keys(options).length > 0 ? options : void 0;
14084
14131
  }
14085
14132
  __name(getProgrammaticRouteSearchClientOptions, "getProgrammaticRouteSearchClientOptions");
14086
- function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path26, routePath) {
14133
+ function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path27, routePath) {
14087
14134
  const schema = getProgrammaticRouteSearchSchema(searchConfig);
14088
14135
  const search = parseProgrammaticSchema(schema, rawSearch, "search", routePath);
14089
14136
  const options = getProgrammaticRouteSearchOptions(searchConfig);
@@ -14092,7 +14139,7 @@ function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path26, routePa
14092
14139
  schema,
14093
14140
  rawSearch,
14094
14141
  parsedSearch: search,
14095
- path: path26
14142
+ path: path27
14096
14143
  });
14097
14144
  return { search, canonicalPath };
14098
14145
  }
@@ -14275,7 +14322,7 @@ function createRouteModuleFromProgrammaticPage(route) {
14275
14322
  mod.__farmRouteData = route.data;
14276
14323
  mod.__farmRouteParsesProps = true;
14277
14324
  mod.__farmResolveRouteProps = (props) => resolveProgrammaticRouteProps(route, props);
14278
- mod.__farmResolveRouteCanonicalPath = (rawSearch, path26) => resolveProgrammaticRouteSearch(route.search, rawSearch, path26, route.path).canonicalPath;
14325
+ mod.__farmResolveRouteCanonicalPath = (rawSearch, path27) => resolveProgrammaticRouteSearch(route.search, rawSearch, path27, route.path).canonicalPath;
14279
14326
  }
14280
14327
  if (route.pending || route.error || route.notFound) {
14281
14328
  mod.__farmRouteComponents = {
@@ -15029,6 +15076,37 @@ function stripUseClientDirective(content) {
15029
15076
  return content.replace(/^\s*(["'])use client\1\s*;?\s*/, "");
15030
15077
  }
15031
15078
  __name(stripUseClientDirective, "stripUseClientDirective");
15079
+ function hasAsyncDefaultExport(content) {
15080
+ if (!content) return false;
15081
+ const tokens = tokenizeModuleSource(content);
15082
+ for (let index = 0; index < tokens.length - 2; index++) {
15083
+ const token = tokens[index];
15084
+ if (token.kind !== "identifier" || token.value !== "export") continue;
15085
+ if (tokens[index - 1]?.value === ".") continue;
15086
+ if (tokens[index + 1]?.value !== "default") continue;
15087
+ const exported = tokens[index + 2];
15088
+ if (exported.kind === "identifier" && exported.value === "async") {
15089
+ return true;
15090
+ }
15091
+ if (exported.kind === "identifier" && !["function", "class"].includes(exported.value) && tokens[index + 3]?.value !== "(" && isAsyncLocalDeclaration(tokens, exported.value)) {
15092
+ return true;
15093
+ }
15094
+ }
15095
+ return false;
15096
+ }
15097
+ __name(hasAsyncDefaultExport, "hasAsyncDefaultExport");
15098
+ function isAsyncLocalDeclaration(tokens, name) {
15099
+ for (let index = 0; index < tokens.length - 2; index++) {
15100
+ if (tokens[index].value === "async" && tokens[index + 1]?.value === "function" && tokens[index + 2]?.value === name) {
15101
+ return true;
15102
+ }
15103
+ if (tokens[index].value === name && tokens[index + 1]?.value === "=" && tokens[index + 2]?.value === "async") {
15104
+ return true;
15105
+ }
15106
+ }
15107
+ return false;
15108
+ }
15109
+ __name(isAsyncLocalDeclaration, "isAsyncLocalDeclaration");
15032
15110
  function parseClientModuleMetadata(content, inspectIslandExport) {
15033
15111
  if (!content) {
15034
15112
  return {
@@ -15084,6 +15162,14 @@ function inspectClientModuleMetadata(resolvedPath, root, visited, inspectIslandE
15084
15162
  }
15085
15163
  }
15086
15164
  const shouldHydrate = parsed.hasHydrateExport || importsClientBoundary;
15165
+ if (shouldHydrate && hasAsyncDefaultExport(content)) {
15166
+ return {
15167
+ isClientComponent: false,
15168
+ shouldHydrate: false,
15169
+ islandStrategy: null,
15170
+ suppressedAsyncHydration: true
15171
+ };
15172
+ }
15087
15173
  return {
15088
15174
  isClientComponent: false,
15089
15175
  shouldHydrate,
@@ -15799,6 +15885,7 @@ var _RouteManager = class _RouteManager {
15799
15885
  shouldHydrate: metadata.shouldHydrate,
15800
15886
  isClientComponent: metadata.isClientComponent,
15801
15887
  islandStrategy: metadata.islandStrategy,
15888
+ suppressedAsyncHydration: metadata.suppressedAsyncHydration,
15802
15889
  search: getProgrammaticRouteSearchClientOptions(programmaticPage?.search),
15803
15890
  segments: entry.route.segments.map((seg) => ({
15804
15891
  segment: seg.segment,
@@ -16504,6 +16591,16 @@ async function _runWithCurrentRequest(request, fn) {
16504
16591
  return requestStore.run(request, fn);
16505
16592
  }
16506
16593
  __name(_runWithCurrentRequest, "_runWithCurrentRequest");
16594
+ function getCurrentRequest() {
16595
+ const request = requestStore.getStore();
16596
+ if (!request) {
16597
+ throw new Error(
16598
+ "No current request is available. getCurrentRequest() can only be used during server rendering."
16599
+ );
16600
+ }
16601
+ return request;
16602
+ }
16603
+ __name(getCurrentRequest, "getCurrentRequest");
16507
16604
 
16508
16605
  // src/client/router.ts
16509
16606
  var import_react3 = require("react");
@@ -18910,18 +19007,146 @@ function DefaultNotFoundPage(_props) {
18910
19007
  }
18911
19008
  __name(DefaultNotFoundPage, "DefaultNotFoundPage");
18912
19009
 
19010
+ // src/theme/server-runtime.ts
19011
+ init_config2();
19012
+ var THEME_SCRIPT_ID = "farm-theme-script";
19013
+ var THEME_STYLE_ID = "farm-theme-style";
19014
+ function createFarmThemeDocumentParts(input, basePath = "/", serverTheme) {
19015
+ const config = resolveFarmThemeConfig(input, basePath);
19016
+ if (!config.enabled) return { attributes: "", head: "" };
19017
+ const hydrationTheme = serverTheme ?? config.default;
19018
+ const initialTheme = hydrationTheme === "system" ? "light" : hydrationTheme;
19019
+ const script = createFarmThemeBootstrapScript(config, hydrationTheme);
19020
+ return {
19021
+ attributes: ` data-theme="${initialTheme}"`,
19022
+ head: `<style id="${THEME_STYLE_ID}">:root[data-theme="light"]{color-scheme:light}:root[data-theme="dark"]{color-scheme:dark}</style><script id="${THEME_SCRIPT_ID}">${script}</script>`
19023
+ };
19024
+ }
19025
+ __name(createFarmThemeDocumentParts, "createFarmThemeDocumentParts");
19026
+ function createFarmThemeBootstrapScript(config, serverTheme = config.default) {
19027
+ return `(function(config,serverTheme){
19028
+ var isTheme=function(value){return value==="light"||value==="dark"||value==="system";};
19029
+ var decode=function(value){try{return decodeURIComponent(value);}catch(_error){return value;}};
19030
+ var readCookie=function(){var entries=document.cookie.split(";");for(var index=0;index<entries.length;index++){var entry=entries[index];var separator=entry.indexOf("=");if(separator<0)continue;if(decode(entry.slice(0,separator).trim())===config.storageKey)return decode(entry.slice(separator+1).trim());}};
19031
+ var media=window.matchMedia("(prefers-color-scheme: dark)");
19032
+ var resolveTheme=function(theme){return theme==="system"?(media.matches?"dark":"light"):theme;};
19033
+ var storedTheme=readCookie();
19034
+ var preference=isTheme(storedTheme)?storedTheme:config.default;
19035
+ var serverSnapshot={theme:serverTheme,resolvedTheme:serverTheme==="system"?undefined:serverTheme,mounted:false};
19036
+ var apply=function(){var resolvedTheme=resolveTheme(preference);document.documentElement.dataset.theme=resolvedTheme;var snapshot={theme:preference,resolvedTheme:resolvedTheme,mounted:true};if(window.__FARM_THEME__)window.__FARM_THEME__.snapshot=snapshot;return snapshot;};
19037
+ var emit=function(){var snapshot=apply();window.dispatchEvent(new CustomEvent("farm:themechange",{detail:snapshot}));};
19038
+ var persist=function(theme){var secure=window.location.protocol==="https:"?"; Secure":"";document.cookie=encodeURIComponent(config.storageKey)+"="+encodeURIComponent(theme)+"; Path="+config.cookiePath+"; Max-Age=31536000; SameSite=Lax"+secure;try{localStorage.setItem(config.storageKey,theme);}catch(_error){}};
19039
+ var setTheme=function(theme){if(!isTheme(theme))throw new TypeError("Unknown FARMJS theme: "+String(theme));preference=theme;persist(theme);emit();};
19040
+ var initialSnapshot={theme:preference,resolvedTheme:resolveTheme(preference),mounted:true};
19041
+ window.__FARM_THEME__={config:config,serverSnapshot:serverSnapshot,snapshot:initialSnapshot,setTheme:setTheme};
19042
+ document.documentElement.dataset.theme=initialSnapshot.resolvedTheme;
19043
+ var handleSystemChange=function(){if(preference==="system")emit();};
19044
+ if(typeof media.addEventListener==="function")media.addEventListener("change",handleSystemChange);else if(typeof media.addListener==="function")media.addListener(handleSystemChange);
19045
+ window.addEventListener("storage",function(event){if(event.key!==config.storageKey||!isTheme(event.newValue))return;preference=event.newValue;persist(preference);emit();});
19046
+ })(${serializeInlineValue(config)},${serializeInlineValue(serverTheme)});`;
19047
+ }
19048
+ __name(createFarmThemeBootstrapScript, "createFarmThemeBootstrapScript");
19049
+ function serializeInlineValue(value) {
19050
+ return JSON.stringify(value).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
19051
+ }
19052
+ __name(serializeInlineValue, "serializeInlineValue");
19053
+
19054
+ // src/theme/bridge.ts
19055
+ var FALLBACK_SERVER_SNAPSHOT = Object.freeze({
19056
+ theme: "system",
19057
+ resolvedTheme: void 0,
19058
+ mounted: false
19059
+ });
19060
+ var FARM_THEME_SERVER_SNAPSHOT_RESOLVER = /* @__PURE__ */ Symbol.for("farm.js.theme.server-snapshot-resolver");
19061
+ function _setFarmThemeServerSnapshotResolver(resolver) {
19062
+ globalThis[FARM_THEME_SERVER_SNAPSHOT_RESOLVER] = resolver;
19063
+ }
19064
+ __name(_setFarmThemeServerSnapshotResolver, "_setFarmThemeServerSnapshotResolver");
19065
+
19066
+ // src/theme/server.ts
19067
+ init_config2();
19068
+ var defaultThemeConfig = resolveFarmThemeConfig(void 0);
19069
+ function _setDefaultFarmThemeConfig(config, basePath = "/") {
19070
+ defaultThemeConfig = resolveFarmThemeConfig(config, basePath);
19071
+ }
19072
+ __name(_setDefaultFarmThemeConfig, "_setDefaultFarmThemeConfig");
19073
+ function getTheme(request = getCurrentRequest()) {
19074
+ return readFarmThemePreference(request, defaultThemeConfig);
19075
+ }
19076
+ __name(getTheme, "getTheme");
19077
+ function getThemeSnapshot(request = getCurrentRequest()) {
19078
+ const theme = readFarmThemePreference(request, defaultThemeConfig);
19079
+ return {
19080
+ theme,
19081
+ resolvedTheme: theme === "system" ? void 0 : theme,
19082
+ mounted: false
19083
+ };
19084
+ }
19085
+ __name(getThemeSnapshot, "getThemeSnapshot");
19086
+ function readFarmThemePreference(request, config) {
19087
+ if (!config.enabled) return config.default;
19088
+ const stored = readCookie3(request.headers.get("cookie"), config.storageKey);
19089
+ return isFarmThemePreference(stored) ? stored : config.default;
19090
+ }
19091
+ __name(readFarmThemePreference, "readFarmThemePreference");
19092
+ function readCookie3(cookieHeader, name) {
19093
+ if (!cookieHeader) return void 0;
19094
+ for (const entry of cookieHeader.split(";")) {
19095
+ const separator = entry.indexOf("=");
19096
+ if (separator < 0) continue;
19097
+ const key = decodeCookieValue(entry.slice(0, separator).trim());
19098
+ if (key !== name) continue;
19099
+ return decodeCookieValue(entry.slice(separator + 1).trim());
19100
+ }
19101
+ return void 0;
19102
+ }
19103
+ __name(readCookie3, "readCookie");
19104
+ function decodeCookieValue(value) {
19105
+ try {
19106
+ return decodeURIComponent(value);
19107
+ } catch {
19108
+ return value;
19109
+ }
19110
+ }
19111
+ __name(decodeCookieValue, "decodeCookieValue");
19112
+ function isFarmThemePreference(value) {
19113
+ return value === "light" || value === "dark" || value === "system";
19114
+ }
19115
+ __name(isFarmThemePreference, "isFarmThemePreference");
19116
+ _setFarmThemeServerSnapshotResolver(() => {
19117
+ try {
19118
+ return getThemeSnapshot();
19119
+ } catch {
19120
+ const theme = defaultThemeConfig.default;
19121
+ return {
19122
+ theme,
19123
+ resolvedTheme: theme === "system" ? void 0 : theme,
19124
+ mounted: false
19125
+ };
19126
+ }
19127
+ });
19128
+
18913
19129
  // src/server/renderer.ts
18914
19130
  var cachedClerkProvider = null;
18915
19131
  var importRuntimeModule = new Function("specifier", "return import(specifier);");
19132
+ var warnedSuppressedAsyncHydrationModules = /* @__PURE__ */ new Set();
19133
+ function warnSuppressedAsyncHydrationOnce(modulePath) {
19134
+ if (warnedSuppressedAsyncHydrationModules.has(modulePath)) return;
19135
+ warnedSuppressedAsyncHydrationModules.add(modulePath);
19136
+ logger.warn(
19137
+ `${modulePath} is an async server component that imports client components. React cannot hydrate async components in the browser, so this route stays server-rendered and its client imports are not interactive. Move the interactive UI into a "use client" child rendered by a synchronous page, or enable experimental server components support.`
19138
+ );
19139
+ }
19140
+ __name(warnSuppressedAsyncHydrationOnce, "warnSuppressedAsyncHydrationOnce");
18916
19141
  function hasRequestHeader(req, name) {
18917
19142
  const value = req.headers[name.toLowerCase()];
18918
19143
  return Array.isArray(value) ? value.length > 0 : Boolean(value);
18919
19144
  }
18920
19145
  __name(hasRequestHeader, "hasRequestHeader");
18921
- function serializeInlineValue(value) {
19146
+ function serializeInlineValue2(value) {
18922
19147
  return JSON.stringify(value).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
18923
19148
  }
18924
- __name(serializeInlineValue, "serializeInlineValue");
19149
+ __name(serializeInlineValue2, "serializeInlineValue");
18925
19150
  function escapeHtmlAttribute2(value) {
18926
19151
  return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
18927
19152
  }
@@ -19015,7 +19240,7 @@ function createDocumentFooter(options) {
19015
19240
  __name(createDocumentFooter, "createDocumentFooter");
19016
19241
  function createDeferredHydrationScript(records) {
19017
19242
  if (records.length === 0) return "";
19018
- return `<script>window.__FARM_DEFERRED_DATA__=${serializeInlineValue(
19243
+ return `<script>window.__FARM_DEFERRED_DATA__=${serializeInlineValue2(
19019
19244
  snapshotDeferredData(records)
19020
19245
  )};</script>`;
19021
19246
  }
@@ -19587,6 +19812,9 @@ var _ServerRenderer = class _ServerRenderer {
19587
19812
  })
19588
19813
  );
19589
19814
  const shouldHydrate = moduleMetadata.shouldHydrate;
19815
+ if (moduleMetadata.suppressedAsyncHydration) {
19816
+ warnSuppressedAsyncHydrationOnce(route.modulePath);
19817
+ }
19590
19818
  const layoutHydrationMetadata = layouts.map((layout2) => {
19591
19819
  const manifestEntry = routeManifest.layouts.find(
19592
19820
  (entry) => entry.pattern === layout2.pattern
@@ -20084,7 +20312,7 @@ var _ServerRenderer = class _ServerRenderer {
20084
20312
  }
20085
20313
  }
20086
20314
  async renderWithSSR(element, req, res, clearMiddlewareData, options = {}) {
20087
- return new Promise((resolve6, reject) => {
20315
+ return new Promise((resolve7, reject) => {
20088
20316
  const streamStartTime = Date.now();
20089
20317
  const observabilityRoute = options.observabilityRoute || req.__FARM_ROUTE__ || req.url || "/";
20090
20318
  const deploymentId = this.getDeploymentId();
@@ -20156,9 +20384,9 @@ var _ServerRenderer = class _ServerRenderer {
20156
20384
  slots: routeSlotPayload
20157
20385
  });
20158
20386
  const propsScript = `<script>
20159
- window.__FARM_PROPS__ = ${serializeInlineValue(deferredProps.data.page)};
20160
- window.__FARM_ROUTE_SLOTS__ = ${serializeInlineValue(deferredProps.data.slots)};
20161
- window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue(deploymentId)};
20387
+ window.__FARM_PROPS__ = ${serializeInlineValue2(deferredProps.data.page)};
20388
+ window.__FARM_ROUTE_SLOTS__ = ${serializeInlineValue2(deferredProps.data.slots)};
20389
+ window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue2(deploymentId)};
20162
20390
  window.__FARM_PATH__ = ${JSON.stringify(req.__FARM_ROUTE__ || req.url || "/")};
20163
20391
  window.__FARM_IS_CLIENT__ = ${JSON.stringify(isClientComponent)};
20164
20392
  window.__FARM_PAGE_SHOULD_HYDRATE__ = ${JSON.stringify(
@@ -20176,7 +20404,7 @@ window.__FARM_LOADING_MODULE__ = ${JSON.stringify(
20176
20404
  )};
20177
20405
  window.__FARM_MANIFEST__ = ${JSON.stringify(clientManifest)};
20178
20406
  window.__FARM_INTEGRATION_API_MANIFEST__ = ${JSON.stringify(getRegisteredIntegrationAPIManifest())};
20179
- ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(getFarmI18nClientSnapshot())};` : ""}
20407
+ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(getFarmI18nClientSnapshot())};` : ""}
20180
20408
  </script>`;
20181
20409
  const hydrationClickQueueScript = isClientComponent || req.__FARM_SHOULD_HYDRATE__ === true || req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ === true ? createPreHydrationClickQueueScript() : "";
20182
20410
  const {
@@ -20187,6 +20415,11 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
20187
20415
  const i18nSnapshot = getFarmI18nClientSnapshot();
20188
20416
  const i18nAlternateTags = i18nSnapshot ? renderI18nAlternateLinks(req.__FARM_ROUTE__ || req.url || "/", i18nSnapshot) : "";
20189
20417
  const fontHead = renderFarmFontDevHead(this.config.root || process.cwd());
20418
+ const themeDocument = createFarmThemeDocumentParts(
20419
+ this.config.theme,
20420
+ this.config.basePath,
20421
+ getTheme()
20422
+ );
20190
20423
  const streamRoot = import_react5.default.createElement("div", { style: { display: "contents" } }, element);
20191
20424
  const { pipe } = (0, import_server2.renderToPipeableStream)(streamRoot, {
20192
20425
  onShellReady() {
@@ -20200,8 +20433,9 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
20200
20433
  console.log(`[FARM STREAM] onShellReady at ${shellReadyMs}ms`);
20201
20434
  }
20202
20435
  const shell = `<!DOCTYPE html>
20203
- <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}>
20436
+ <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}${themeDocument.attributes}>
20204
20437
  <head>
20438
+ ${themeDocument.head}
20205
20439
  <meta charset="utf-8">
20206
20440
  <meta name="viewport" content="width=device-width, initial-scale=1">
20207
20441
  <meta name="farm-deployment-id" content="${escapeHtmlAttribute2(deploymentId)}">
@@ -20278,7 +20512,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
20278
20512
  route: observabilityRoute,
20279
20513
  durationMs: Date.now() - streamStartTime
20280
20514
  });
20281
- resolve6();
20515
+ resolve7();
20282
20516
  }
20283
20517
  });
20284
20518
  res.write(shell);
@@ -20403,15 +20637,21 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
20403
20637
  const i18nSnapshot = getFarmI18nClientSnapshot();
20404
20638
  const clientScript = isClientComponent ? ` <script type="module" src="/@farm/client.js"></script>` : "";
20405
20639
  const integrationManifestScript = `<script>
20406
- window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue(this.getDeploymentId())};
20640
+ window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue2(this.getDeploymentId())};
20407
20641
  window.__FARM_INTEGRATION_API_MANIFEST__ = ${JSON.stringify(getRegisteredIntegrationAPIManifest())};
20408
- ${i18nSnapshot ? `window.__FARM_I18N__ = ${serializeInlineValue(i18nSnapshot)};` : ""}
20642
+ ${i18nSnapshot ? `window.__FARM_I18N__ = ${serializeInlineValue2(i18nSnapshot)};` : ""}
20409
20643
  </script>`;
20410
20644
  const alternateLinks = i18nSnapshot ? renderI18nAlternateLinks(requestPath, i18nSnapshot) : "";
20411
20645
  const fontHead = renderFarmFontDevHead(this.config.root || process.cwd());
20646
+ const themeDocument = createFarmThemeDocumentParts(
20647
+ this.config.theme,
20648
+ this.config.basePath,
20649
+ getTheme()
20650
+ );
20412
20651
  return `<!DOCTYPE html>
20413
- <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}>
20652
+ <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}${themeDocument.attributes}>
20414
20653
  <head>
20654
+ ${themeDocument.head}
20415
20655
  <meta charset="utf-8">
20416
20656
  <meta name="viewport" content="width=device-width, initial-scale=1">
20417
20657
  <meta name="farm-deployment-id" content="${escapeHtmlAttribute2(this.getDeploymentId())}">
@@ -20458,6 +20698,7 @@ init_config();
20458
20698
  init_auth_config();
20459
20699
  init_preload();
20460
20700
  init_security();
20701
+ init_config2();
20461
20702
  var defaultDocsConfig = {
20462
20703
  enabled: false,
20463
20704
  entry: "/docs",
@@ -20471,6 +20712,7 @@ var _FarmApp = class _FarmApp {
20471
20712
  constructor(config = {}, viteServer) {
20472
20713
  this.config = this.normalizeConfig(config);
20473
20714
  configureFarmObservability(this.config.observability);
20715
+ _setDefaultFarmThemeConfig(this.config.theme);
20474
20716
  this.i18nRuntime = createFarmI18nRuntime(this.config.i18n);
20475
20717
  _setDefaultFarmI18nRuntime(this.i18nRuntime);
20476
20718
  this.viteServer = viteServer;
@@ -20529,6 +20771,7 @@ var _FarmApp = class _FarmApp {
20529
20771
  security: resolveFarmSecurityConfig(config.security),
20530
20772
  images: resolveFarmImageConfig(config.images),
20531
20773
  performance: resolveFarmPerformanceConfig(config.performance),
20774
+ theme: resolveFarmThemeConfig(config.theme, config.basePath || "/"),
20532
20775
  i18n: isResolvedI18nConfig(config.i18n) ? config.i18n : resolveFarmI18nConfig(config.i18n, {
20533
20776
  root,
20534
20777
  mode: process.env.NODE_ENV === "production" ? "production" : "development"
@@ -22791,8 +23034,8 @@ init_app_markdown();
22791
23034
  init_response();
22792
23035
  init_integrations();
22793
23036
  init_devtools_config();
22794
- var fs7 = __toESM(require("fs"));
22795
- var path25 = __toESM(require("path"));
23037
+ var fs8 = __toESM(require("fs"));
23038
+ var path26 = __toESM(require("path"));
22796
23039
  init_layers();
22797
23040
 
22798
23041
  // src/environment-vite.ts
@@ -23139,7 +23382,7 @@ function transformError(id, message) {
23139
23382
  __name(transformError, "transformError");
23140
23383
 
23141
23384
  // package.json
23142
- var version = "0.1.0-beta.22";
23385
+ var version = "0.1.0-beta.24";
23143
23386
 
23144
23387
  // src/version.ts
23145
23388
  var FARM_VERSION = version;
@@ -23173,8 +23416,8 @@ __name(reportAfterError, "reportAfterError");
23173
23416
  function createAfterRequestState(reportError = defaultAfterErrorReporter) {
23174
23417
  let resolveResponseFinished;
23175
23418
  let responseFinished = false;
23176
- const responseFinishedPromise = new Promise((resolve6) => {
23177
- resolveResponseFinished = resolve6;
23419
+ const responseFinishedPromise = new Promise((resolve7) => {
23420
+ resolveResponseFinished = resolve7;
23178
23421
  });
23179
23422
  const state = {
23180
23423
  completion: Promise.resolve(),
@@ -23245,6 +23488,34 @@ function _withAfterNodeMiddleware(handler) {
23245
23488
  }
23246
23489
  __name(_withAfterNodeMiddleware, "_withAfterNodeMiddleware");
23247
23490
 
23491
+ // src/dev-static.ts
23492
+ var fs7 = __toESM(require("fs"));
23493
+ var path17 = __toESM(require("path"));
23494
+ function devServableFileExists(pathname, baseDirs) {
23495
+ let decodedPathname;
23496
+ try {
23497
+ decodedPathname = decodeURIComponent(pathname);
23498
+ } catch {
23499
+ return false;
23500
+ }
23501
+ const relativePathname = decodedPathname.replace(/^\/+/, "");
23502
+ if (!relativePathname) return false;
23503
+ for (const baseDir of baseDirs) {
23504
+ if (typeof baseDir !== "string" || baseDir.length === 0) continue;
23505
+ const resolvedBase = path17.resolve(baseDir);
23506
+ const candidate = path17.resolve(resolvedBase, relativePathname);
23507
+ if (!candidate.startsWith(resolvedBase + path17.sep)) continue;
23508
+ try {
23509
+ if (fs7.existsSync(candidate) && fs7.statSync(candidate).isFile()) {
23510
+ return true;
23511
+ }
23512
+ } catch {
23513
+ }
23514
+ }
23515
+ return false;
23516
+ }
23517
+ __name(devServableFileExists, "devServableFileExists");
23518
+
23248
23519
  // src/vite.ts
23249
23520
  init_deployment();
23250
23521
  init_image_config();
@@ -23385,6 +23656,32 @@ __name(createFarmSourceAlias, "createFarmSourceAlias");
23385
23656
  // src/vite.ts
23386
23657
  init_fonts();
23387
23658
  init_server_http();
23659
+
23660
+ // src/theme/vite.ts
23661
+ init_config2();
23662
+ var FARM_DARK_VARIANT = '@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));';
23663
+ function createFarmThemeCssPlugin(input, basePath = "/") {
23664
+ const config = resolveFarmThemeConfig(input, basePath);
23665
+ return {
23666
+ name: "farm:theme-css",
23667
+ enforce: "pre",
23668
+ transform(code, id) {
23669
+ if (!config.enabled || !/\.css(?:\?.*)?$/.test(id) || !/@import\s+["']tailwindcss["']/.test(code) || /@custom-variant\s+dark\b/.test(code)) {
23670
+ return null;
23671
+ }
23672
+ return {
23673
+ code: `${code.trimEnd()}
23674
+
23675
+ ${FARM_DARK_VARIANT}
23676
+ `,
23677
+ map: null
23678
+ };
23679
+ }
23680
+ };
23681
+ }
23682
+ __name(createFarmThemeCssPlugin, "createFarmThemeCssPlugin");
23683
+
23684
+ // src/vite.ts
23388
23685
  var ALL_TYPE_ARTIFACTS = {
23389
23686
  routes: true,
23390
23687
  api: true,
@@ -23600,11 +23897,11 @@ function isPotentialProgrammaticRouteSourceFile(normalizedFile, srcDirSlug) {
23600
23897
  }
23601
23898
  __name(isPotentialProgrammaticRouteSourceFile, "isPotentialProgrammaticRouteSourceFile");
23602
23899
  function fileContainsProgrammaticPageRoute(file) {
23603
- if (!fs7.existsSync(file)) {
23900
+ if (!fs8.existsSync(file)) {
23604
23901
  return false;
23605
23902
  }
23606
23903
  try {
23607
- return scanProgrammaticPagePaths(fs7.readFileSync(file, "utf8")).length > 0;
23904
+ return scanProgrammaticPagePaths(fs8.readFileSync(file, "utf8")).length > 0;
23608
23905
  } catch {
23609
23906
  return false;
23610
23907
  }
@@ -23612,7 +23909,7 @@ function fileContainsProgrammaticPageRoute(file) {
23612
23909
  __name(fileContainsProgrammaticPageRoute, "fileContainsProgrammaticPageRoute");
23613
23910
  function rewriteEarlySsrRelativeImports(options) {
23614
23911
  const cleanId = options.id.split("?", 1)[0];
23615
- if (!path25.isAbsolute(cleanId) || cleanId.replace(/\\/g, "/").includes("/node_modules/")) {
23912
+ if (!path26.isAbsolute(cleanId) || cleanId.replace(/\\/g, "/").includes("/node_modules/")) {
23616
23913
  return null;
23617
23914
  }
23618
23915
  const replacements = [];
@@ -23632,7 +23929,7 @@ function rewriteEarlySsrRelativeImports(options) {
23632
23929
  const suffixIndex = source.value.search(/[?#]/);
23633
23930
  const sourcePath = suffixIndex === -1 ? source.value : source.value.slice(0, suffixIndex);
23634
23931
  const suffix = suffixIndex === -1 ? "" : source.value.slice(suffixIndex);
23635
- const resolvedPath = path25.resolve(path25.dirname(cleanId), sourcePath);
23932
+ const resolvedPath = path26.resolve(path26.dirname(cleanId), sourcePath);
23636
23933
  replacements.push({
23637
23934
  start: source.start,
23638
23935
  end: source.end,
@@ -23711,7 +24008,7 @@ function farmPlugin(options = {}, initialPluginManager) {
23711
24008
  ...layerRoots.length ? {
23712
24009
  server: {
23713
24010
  fs: {
23714
- allow: [path25.resolve(options.root || process.cwd()), ...layerRoots]
24011
+ allow: [path26.resolve(options.root || process.cwd()), ...layerRoots]
23715
24012
  }
23716
24013
  }
23717
24014
  } : {}
@@ -23742,13 +24039,13 @@ function farmPlugin(options = {}, initialPluginManager) {
23742
24039
  },
23743
24040
  server
23744
24041
  );
23745
- const globalsCSSPath = path25.join(server.config.root, "src/app/globals.css");
23746
- if (!fs7.existsSync(globalsCSSPath)) {
23747
- const appDir = path25.join(server.config.root, "src/app");
23748
- if (!fs7.existsSync(appDir)) {
23749
- fs7.mkdirSync(appDir, { recursive: true });
24042
+ const globalsCSSPath = path26.join(server.config.root, "src/app/globals.css");
24043
+ if (!fs8.existsSync(globalsCSSPath)) {
24044
+ const appDir = path26.join(server.config.root, "src/app");
24045
+ if (!fs8.existsSync(appDir)) {
24046
+ fs8.mkdirSync(appDir, { recursive: true });
23750
24047
  }
23751
- fs7.writeFileSync(globalsCSSPath, defaultGlobalCSS);
24048
+ fs8.writeFileSync(globalsCSSPath, defaultGlobalCSS);
23752
24049
  }
23753
24050
  await farmApp.initialize();
23754
24051
  const farmConfig = farmApp.getConfig();
@@ -23767,10 +24064,10 @@ function farmPlugin(options = {}, initialPluginManager) {
23767
24064
  });
23768
24065
  }
23769
24066
  const sourceRoots = getFarmSourceRoots(farmConfig);
23770
- server.watcher.add(sourceRoots.map((source) => path25.join(source.root, source.srcDir)));
24067
+ server.watcher.add(sourceRoots.map((source) => path26.join(source.root, source.srcDir)));
23771
24068
  if (farmConfig.i18n.enabled) {
23772
24069
  server.watcher.add(
23773
- farmConfig.i18n.messages.includes("{locale}") ? path25.dirname(farmConfig.i18n.messages) : farmConfig.i18n.messages
24070
+ farmConfig.i18n.messages.includes("{locale}") ? path26.dirname(farmConfig.i18n.messages) : farmConfig.i18n.messages
23774
24071
  );
23775
24072
  }
23776
24073
  const workflowConfig = farmConfig.workflows;
@@ -23780,7 +24077,7 @@ function farmPlugin(options = {}, initialPluginManager) {
23780
24077
  ...farmDocsDevRuntime?.getFarmDocsRouteTypeEntries(farmConfig.docs) ?? []
23781
24078
  ], "getExtraRouteTypes");
23782
24079
  const appDirSlugs = sourceRoots.map(
23783
- (source) => path25.join(source.root, source.srcDir, "app").replace(/\\/g, "/")
24080
+ (source) => path26.join(source.root, source.srcDir, "app").replace(/\\/g, "/")
23784
24081
  );
23785
24082
  const generateTypeArtifacts = /* @__PURE__ */ __name(async (reason, selection = ALL_TYPE_ARTIFACTS, log = false) => {
23786
24083
  try {
@@ -23820,7 +24117,7 @@ function farmPlugin(options = {}, initialPluginManager) {
23820
24117
  }, "generateTypeArtifacts");
23821
24118
  await generateTypeArtifacts("startup");
23822
24119
  const srcDirSlugs = sourceRoots.map(
23823
- (source) => path25.join(source.root, source.srcDir).replace(/\\/g, "/")
24120
+ (source) => path26.join(source.root, source.srcDir).replace(/\\/g, "/")
23824
24121
  );
23825
24122
  const layerConfigFiles = new Set(
23826
24123
  farmConfig.layers.map((layer) => layer.configFile?.replace(/\\/g, "/")).filter((file) => Boolean(file))
@@ -23938,7 +24235,7 @@ function farmPlugin(options = {}, initialPluginManager) {
23938
24235
  await apiRouteManager.discoverRoutes();
23939
24236
  let discoveredWorkflows = [];
23940
24237
  const hasWorkflowDirectory = workflowConfig.enabled && workflowConfig.dirs.some(
23941
- (dir) => fs7.existsSync(path25.isAbsolute(dir) ? dir : path25.join(farmConfig.root, dir))
24238
+ (dir) => fs8.existsSync(path26.isAbsolute(dir) ? dir : path26.join(farmConfig.root, dir))
23942
24239
  );
23943
24240
  if (hasWorkflowDirectory) {
23944
24241
  const { createFarmWorkflowRequestHandler: createFarmWorkflowRequestHandler2, discoverFarmWorkflows: discoverFarmWorkflows2 } = await loadFarmWorkflowsDevRuntime();
@@ -24172,12 +24469,12 @@ window.__FARM_MANIFEST__ = ${inlineValue({
24172
24469
  }
24173
24470
  }
24174
24471
  const farmDocsFontPath = farmDocsFontAssets.get(requestPathname);
24175
- if ((requestMethod === "GET" || requestMethod === "HEAD") && farmDocsFontPath && fs7.existsSync(farmDocsFontPath)) {
24472
+ if ((requestMethod === "GET" || requestMethod === "HEAD") && farmDocsFontPath && fs8.existsSync(farmDocsFontPath)) {
24176
24473
  res.statusCode = 200;
24177
24474
  res.setHeader("Content-Type", "font/woff2");
24178
24475
  res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
24179
24476
  if (requestMethod === "HEAD") res.end();
24180
- else fs7.createReadStream(farmDocsFontPath).pipe(res);
24477
+ else fs8.createReadStream(farmDocsFontPath).pipe(res);
24181
24478
  return;
24182
24479
  }
24183
24480
  if (requestMethod === "GET" && (requestPathname === FARM_DEVTOOLS_PATH || requestPathname === `${FARM_DEVTOOLS_PATH}.json`)) {
@@ -24275,7 +24572,7 @@ window.__FARM_MANIFEST__ = ${inlineValue({
24275
24572
  return null;
24276
24573
  }
24277
24574
  return {
24278
- source: await fs7.promises.readFile(sourcePath, "utf8"),
24575
+ source: await fs8.promises.readFile(sourcePath, "utf8"),
24279
24576
  filePath: sourcePath
24280
24577
  };
24281
24578
  }, "resolveSource")
@@ -24610,9 +24907,17 @@ window.__FARM_MANIFEST__ = ${inlineValue({
24610
24907
  res.end(JSON.stringify({ error: "API route not found", pathname: pathname2 }));
24611
24908
  return;
24612
24909
  }
24613
- if (req.url?.startsWith("/@") || req.url?.startsWith("/node_modules") || requestPathname.includes(".") && !requestPathname.endsWith(".html")) {
24910
+ if (req.url?.startsWith("/@") || req.url?.startsWith("/node_modules")) {
24614
24911
  return next();
24615
24912
  }
24913
+ if (requestPathname.includes(".") && !requestPathname.endsWith(".html")) {
24914
+ const matchesAppRoute = Boolean(
24915
+ farmApp?.getRouteManager()?.matchRoute(requestPathname)?.route
24916
+ );
24917
+ if (!matchesAppRoute || devServableFileExists(requestPathname, [server.config.publicDir, server.config.root])) {
24918
+ return next();
24919
+ }
24920
+ }
24616
24921
  if (req.url?.startsWith("/__farm/page-data")) {
24617
24922
  const urlObj = new URL(req.url, `http://${req.headers.host || "localhost:3000"}`);
24618
24923
  const targetPath = urlObj.searchParams.get("path") || "/";
@@ -25318,8 +25623,8 @@ if (import.meta.hot) {
25318
25623
  }
25319
25624
  logger.info(`Found ${ssgPages.length} SSG pages, ${ssrRoutes.length} SSR routes`);
25320
25625
  logger.info("Pre-rendering SSG pages...");
25321
- const outDir = path25.join(server?.config.root || process.cwd(), options.outDir || "dist");
25322
- const clientDir = path25.join(outDir, "client");
25626
+ const outDir = path26.join(server?.config.root || process.cwd(), options.outDir || "dist");
25627
+ const clientDir = path26.join(outDir, "client");
25323
25628
  for (const page2 of ssgPages) {
25324
25629
  try {
25325
25630
  const staticRequest = new Request(new URL(page2.urlPath, "http://farm.static"));
@@ -25371,9 +25676,9 @@ if (import.meta.hot) {
25371
25676
  <script type="module" src="/assets/client.js"></script>
25372
25677
  </body>
25373
25678
  </html>`;
25374
- const outputPath = page2.urlPath === "/" ? path25.join(clientDir, "index.html") : path25.join(clientDir, page2.urlPath + ".html");
25375
- fs7.mkdirSync(path25.dirname(outputPath), { recursive: true });
25376
- fs7.writeFileSync(outputPath, fullHtml);
25679
+ const outputPath = page2.urlPath === "/" ? path26.join(clientDir, "index.html") : path26.join(clientDir, page2.urlPath + ".html");
25680
+ fs8.mkdirSync(path26.dirname(outputPath), { recursive: true });
25681
+ fs8.writeFileSync(outputPath, fullHtml);
25377
25682
  const revalidateInfo = page2.revalidate ? ` (revalidate: ${page2.revalidate}s)` : "";
25378
25683
  logger.success(` \u2713 ${page2.urlPath}${revalidateInfo}`);
25379
25684
  });
@@ -25381,8 +25686,8 @@ if (import.meta.hot) {
25381
25686
  logger.error(` \u2717 ${page2.urlPath}: ${error}`);
25382
25687
  }
25383
25688
  }
25384
- const manifestPath = path25.join(outDir, "__ssg_manifest.json");
25385
- fs7.writeFileSync(
25689
+ const manifestPath = path26.join(outDir, "__ssg_manifest.json");
25690
+ fs8.writeFileSync(
25386
25691
  manifestPath,
25387
25692
  JSON.stringify(
25388
25693
  ssgPages.map((p) => ({
@@ -25417,9 +25722,9 @@ if (import.meta.hot) {
25417
25722
  }
25418
25723
  const currentFarmConfig = farmApp?.getConfig();
25419
25724
  const normalizedFile = file.replace(/\\/g, "/");
25420
- const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) => path25.join(source.root, source.srcDir).replace(/\\/g, "/")).find((sourceRoot) => normalizedFile.startsWith(`${sourceRoot}/`)) || null : null;
25725
+ const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) => path26.join(source.root, source.srcDir).replace(/\\/g, "/")).find((sourceRoot) => normalizedFile.startsWith(`${sourceRoot}/`)) || null : null;
25421
25726
  if (currentSrcRoot && normalizedFile.startsWith(`${currentSrcRoot}/`) && isProgrammaticRoutesFileName(normalizedFile)) {
25422
- logUpdate("PAGE", `updated ${path25.basename(file)}`);
25727
+ logUpdate("PAGE", `updated ${path26.basename(file)}`);
25423
25728
  for (const mod of modules) {
25424
25729
  server2.moduleGraph.invalidateModule(mod);
25425
25730
  }
@@ -26605,6 +26910,19 @@ async function tryHydrateImportedPage(
26605
26910
  const PageComponent = pageModule?.default;
26606
26911
  if (!PageComponent) return false;
26607
26912
 
26913
+ if (
26914
+ typeof PageComponent === 'function' &&
26915
+ PageComponent.constructor &&
26916
+ PageComponent.constructor.name === 'AsyncFunction'
26917
+ ) {
26918
+ console.warn(
26919
+ '[Farm.js] Skipping hydration for ' + modulePath +
26920
+ ': async server components cannot run in the browser. ' +
26921
+ 'Server-rendered HTML is preserved; move interactive UI into a "use client" child of a synchronous page.'
26922
+ );
26923
+ return false;
26924
+ }
26925
+
26608
26926
  currentPageComponent = PageComponent;
26609
26927
  currentPageProps = await buildRouteComponentProps(
26610
26928
  pageModule,
@@ -26771,14 +27089,22 @@ async function renderPage(pageData) {
26771
27089
  if (!doc.documentElement || !doc.body) return false;
26772
27090
 
26773
27091
  resetReactRoots();
27092
+ const activeFarmTheme =
27093
+ window.__FARM_THEME__?.snapshot?.resolvedTheme ||
27094
+ document.documentElement.getAttribute('data-theme');
26774
27095
  Array.from(document.documentElement.attributes).forEach(function(attr) {
27096
+ if (attr.name === 'data-theme') return;
26775
27097
  if (!doc.documentElement.hasAttribute(attr.name)) {
26776
27098
  document.documentElement.removeAttribute(attr.name);
26777
27099
  }
26778
27100
  });
26779
27101
  Array.from(doc.documentElement.attributes).forEach(function(attr) {
27102
+ if (attr.name === 'data-theme') return;
26780
27103
  document.documentElement.setAttribute(attr.name, attr.value);
26781
27104
  });
27105
+ if (activeFarmTheme) {
27106
+ document.documentElement.setAttribute('data-theme', activeFarmTheme);
27107
+ }
26782
27108
 
26783
27109
  document.head.innerHTML = doc.head ? doc.head.innerHTML : '';
26784
27110
  document.body.innerHTML = doc.body.innerHTML;
@@ -26787,6 +27113,7 @@ async function renderPage(pageData) {
26787
27113
 
26788
27114
  setTimeout(function() {
26789
27115
  Array.from(document.querySelectorAll('script')).forEach(function(script) {
27116
+ if (script.id === 'farm-theme-script') return;
26790
27117
  const freshScript = document.createElement('script');
26791
27118
  Array.from(script.attributes).forEach(function(attr) {
26792
27119
  freshScript.setAttribute(attr.name, attr.value);
@@ -27149,7 +27476,7 @@ function generateClientManifest(bundle) {
27149
27476
  __name(generateClientManifest, "generateClientManifest");
27150
27477
  async function defineConfig2(config = {}) {
27151
27478
  const tailwindcss = (await import("@tailwindcss/vite")).default;
27152
- const appRoot = path25.resolve(config.root || process.cwd());
27479
+ const appRoot = path26.resolve(config.root || process.cwd());
27153
27480
  if (config.extends?.length) {
27154
27481
  const { config: layeredConfig } = await Promise.resolve().then(() => (init_layers(), layers_exports)).then(
27155
27482
  ({ resolveFarmLayers: resolveFarmLayers2 }) => resolveFarmLayers2(config, {
@@ -27284,6 +27611,7 @@ async function defineConfig2(config = {}) {
27284
27611
  };
27285
27612
  return {
27286
27613
  plugins: [
27614
+ createFarmThemeCssPlugin(config.theme, config.basePath),
27287
27615
  tailwindcss(),
27288
27616
  viteBrowserExternalPlugin,
27289
27617
  farmI18nClientBridgePlugin(),