@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/plugin.cjs CHANGED
@@ -785,11 +785,11 @@ function resolveFarmServerHealthConfig(config) {
785
785
  return Object.freeze({ enabled: true, livenessPath, readinessPath });
786
786
  }
787
787
  function normalizeHealthPath(value, optionName) {
788
- const path26 = value.trim();
789
- if (!path26.startsWith("/") || path26.includes("?") || path26.includes("#") || path26.includes("*")) {
788
+ const path27 = value.trim();
789
+ if (!path27.startsWith("/") || path27.includes("?") || path27.includes("#") || path27.includes("*")) {
790
790
  throw new TypeError(`${optionName} must be an absolute pathname without a query or wildcard`);
791
791
  }
792
- return path26.length > 1 ? path26.replace(/\/+$/, "") || "/" : path26;
792
+ return path27.length > 1 ? path27.replace(/\/+$/, "") || "/" : path27;
793
793
  }
794
794
  function parseBodySizeLimit(value, optionName = "bodySizeLimit") {
795
795
  if (typeof value === "number") {
@@ -886,7 +886,7 @@ async function readNodeRequestBody(request, limit) {
886
886
  request.resume?.();
887
887
  throw error;
888
888
  }
889
- return await new Promise((resolve6, reject) => {
889
+ return await new Promise((resolve7, reject) => {
890
890
  const chunks = [];
891
891
  let total = 0;
892
892
  let settled = false;
@@ -915,7 +915,7 @@ async function readNodeRequestBody(request, limit) {
915
915
  if (settled) return;
916
916
  settled = true;
917
917
  cleanup();
918
- resolve6(Buffer.concat(chunks, total));
918
+ resolve7(Buffer.concat(chunks, total));
919
919
  }, "onEnd");
920
920
  const onError = /* @__PURE__ */ __name((error) => rejectOnce(error), "onError");
921
921
  request.on("data", onData);
@@ -1144,22 +1144,22 @@ async function prepareFarmWorkflowsForNitro(config) {
1144
1144
  }
1145
1145
  const root = config.root || process.cwd();
1146
1146
  const distDir = config.distDir || ".farm";
1147
- const fs8 = await import("fs/promises");
1148
- const path26 = await import("path");
1149
- const generatedDir = path26.join(root, distDir, ".nitro", "farm-workflows");
1150
- await fs8.mkdir(generatedDir, { recursive: true });
1147
+ const fs9 = await import("fs/promises");
1148
+ const path27 = await import("path");
1149
+ const generatedDir = path27.join(root, distDir, ".nitro", "farm-workflows");
1150
+ await fs9.mkdir(generatedDir, { recursive: true });
1151
1151
  const tasks = {};
1152
1152
  const scheduledTasks = createScheduledTasks(workflows);
1153
1153
  for (const workflow of workflows) {
1154
- const wrapperPath = path26.join(generatedDir, `${safeFileName(workflow.id)}.mjs`);
1155
- await fs8.writeFile(wrapperPath, createNitroTaskWrapper(workflow), "utf8");
1154
+ const wrapperPath = path27.join(generatedDir, `${safeFileName(workflow.id)}.mjs`);
1155
+ await fs9.writeFile(wrapperPath, createNitroTaskWrapper(workflow), "utf8");
1156
1156
  tasks[workflow.id] = {
1157
1157
  handler: wrapperPath,
1158
1158
  description: workflow.description || `Farm workflow ${workflow.id}`
1159
1159
  };
1160
1160
  }
1161
- const handlerPath = path26.join(generatedDir, "http-handler.mjs");
1162
- await fs8.writeFile(
1161
+ const handlerPath = path27.join(generatedDir, "http-handler.mjs");
1162
+ await fs9.writeFile(
1163
1163
  handlerPath,
1164
1164
  createNitroWorkflowHTTPHandler(
1165
1165
  workflowConfig,
@@ -1168,8 +1168,8 @@ async function prepareFarmWorkflowsForNitro(config) {
1168
1168
  ),
1169
1169
  "utf8"
1170
1170
  );
1171
- const manifestPath = path26.join(generatedDir, "manifest.json");
1172
- await fs8.writeFile(
1171
+ const manifestPath = path27.join(generatedDir, "manifest.json");
1172
+ await fs9.writeFile(
1173
1173
  manifestPath,
1174
1174
  JSON.stringify(
1175
1175
  {
@@ -1250,22 +1250,22 @@ function resolveWorkflowDefinition(module2) {
1250
1250
  return null;
1251
1251
  }
1252
1252
  async function findWorkflowFiles(root, dirs) {
1253
- const fs8 = await import("fs/promises");
1254
- const path26 = await import("path");
1253
+ const fs9 = await import("fs/promises");
1254
+ const path27 = await import("path");
1255
1255
  const files = [];
1256
1256
  for (const dir of dirs) {
1257
- const absoluteDir = path26.isAbsolute(dir) ? dir : path26.join(root, dir);
1257
+ const absoluteDir = path27.isAbsolute(dir) ? dir : path27.join(root, dir);
1258
1258
  if (!await pathExists(absoluteDir)) continue;
1259
1259
  await walkWorkflowDir(absoluteDir, files);
1260
1260
  }
1261
1261
  return files.sort();
1262
1262
  }
1263
1263
  async function walkWorkflowDir(dir, files) {
1264
- const fs8 = await import("fs/promises");
1265
- const path26 = await import("path");
1266
- const entries = await fs8.readdir(dir, { withFileTypes: true });
1264
+ const fs9 = await import("fs/promises");
1265
+ const path27 = await import("path");
1266
+ const entries = await fs9.readdir(dir, { withFileTypes: true });
1267
1267
  for (const entry of entries) {
1268
- const filePath = path26.join(dir, entry.name);
1268
+ const filePath = path27.join(dir, entry.name);
1269
1269
  if (entry.isDirectory()) {
1270
1270
  if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
1271
1271
  await walkWorkflowDir(filePath, files);
@@ -1277,20 +1277,20 @@ async function walkWorkflowDir(dir, files) {
1277
1277
  }
1278
1278
  }
1279
1279
  async function pathExists(filePath) {
1280
- const fs8 = await import("fs/promises");
1281
- return fs8.access(filePath).then(() => true).catch(() => false);
1280
+ const fs9 = await import("fs/promises");
1281
+ return fs9.access(filePath).then(() => true).catch(() => false);
1282
1282
  }
1283
1283
  function isWorkflowFile(fileName) {
1284
1284
  return /\.(?:ts|tsx|js|jsx|mjs|cjs)$/.test(fileName) && !/\.d\.[cm]?ts$/.test(fileName);
1285
1285
  }
1286
1286
  async function loadWorkflowModule(filePath, root) {
1287
- const fs8 = await import("fs/promises");
1288
- const path26 = await import("path");
1287
+ const fs9 = await import("fs/promises");
1288
+ const path27 = await import("path");
1289
1289
  const { pathToFileURL: pathToFileURL5 } = await import("url");
1290
1290
  const { build } = await import("esbuild");
1291
- const outDir = path26.join(root, ".farm", ".workflow-loader");
1292
- await fs8.mkdir(outDir, { recursive: true });
1293
- const outfile = path26.join(
1291
+ const outDir = path27.join(root, ".farm", ".workflow-loader");
1292
+ await fs9.mkdir(outDir, { recursive: true });
1293
+ const outfile = path27.join(
1294
1294
  outDir,
1295
1295
  `workflow-${Date.now()}-${Math.random().toString(36).slice(2)}.mjs`
1296
1296
  );
@@ -1314,7 +1314,7 @@ async function loadWorkflowModule(filePath, root) {
1314
1314
  `${pathToFileURL5(outfile).href}?t=${Date.now()}`
1315
1315
  );
1316
1316
  } finally {
1317
- await fs8.unlink(outfile).catch(() => void 0);
1317
+ await fs9.unlink(outfile).catch(() => void 0);
1318
1318
  }
1319
1319
  }
1320
1320
  function workflowIdFromFile(root, filePath) {
@@ -1589,7 +1589,7 @@ function normalizeCronJob(name, job) {
1589
1589
  if (!job || typeof job !== "object" || Array.isArray(job)) {
1590
1590
  throw new TypeError(`Farm cron ${JSON.stringify(name)} must be a configuration object.`);
1591
1591
  }
1592
- const path26 = normalizeCronPath(name, job.path);
1592
+ const path27 = normalizeCronPath(name, job.path);
1593
1593
  const rawSchedule = Array.isArray(job.schedule) ? job.schedule : [job.schedule];
1594
1594
  const schedule = [...new Set(rawSchedule.map((value) => normalizeCronExpression(name, value)))];
1595
1595
  if (schedule.length === 0) {
@@ -1598,7 +1598,7 @@ function normalizeCronJob(name, job) {
1598
1598
  return {
1599
1599
  name,
1600
1600
  schedule,
1601
- path: path26,
1601
+ path: path27,
1602
1602
  description: job.description?.trim() || void 0
1603
1603
  };
1604
1604
  }
@@ -1606,13 +1606,13 @@ function normalizeCronPath(name, value) {
1606
1606
  if (typeof value !== "string" || !value.trim().startsWith("/")) {
1607
1607
  throw new TypeError(`Farm cron ${JSON.stringify(name)} path must start with "/".`);
1608
1608
  }
1609
- const path26 = value.trim();
1610
- if (path26.startsWith("//") || path26.includes("?") || path26.includes("#")) {
1609
+ const path27 = value.trim();
1610
+ if (path27.startsWith("//") || path27.includes("?") || path27.includes("#")) {
1611
1611
  throw new TypeError(
1612
1612
  `Farm cron ${JSON.stringify(name)} path must be an application pathname without a host, query, or hash.`
1613
1613
  );
1614
1614
  }
1615
- return path26.length > 1 ? path26.replace(/\/+$/, "") : path26;
1615
+ return path27.length > 1 ? path27.replace(/\/+$/, "") : path27;
1616
1616
  }
1617
1617
  function normalizeCronExpression(name, value) {
1618
1618
  if (typeof value !== "string") {
@@ -2448,7 +2448,7 @@ var init_server_action_security = __esm({
2448
2448
 
2449
2449
  // src/image-config.ts
2450
2450
  function resolveFarmImageConfig(config) {
2451
- const path26 = normalizeImagePath(config?.path ?? DEFAULT_FARM_IMAGE_PATH);
2451
+ const path27 = normalizeImagePath(config?.path ?? DEFAULT_FARM_IMAGE_PATH);
2452
2452
  const deviceSizes = normalizeIntegerList(
2453
2453
  config?.deviceSizes ?? DEFAULT_FARM_IMAGE_DEVICE_SIZES,
2454
2454
  "images.deviceSizes"
@@ -2476,7 +2476,7 @@ function resolveFarmImageConfig(config) {
2476
2476
  );
2477
2477
  return Object.freeze({
2478
2478
  provider: config?.provider ?? "auto",
2479
- path: path26,
2479
+ path: path27,
2480
2480
  domains: Object.freeze([
2481
2481
  ...new Set(
2482
2482
  (config?.domains ?? []).map((domain) => domain.trim().toLowerCase()).filter(Boolean)
@@ -2515,11 +2515,11 @@ function getPublicFarmImageConfig(config) {
2515
2515
  };
2516
2516
  }
2517
2517
  function normalizeImagePath(value) {
2518
- const path26 = value.trim().replace(/\/+$/, "") || "/";
2519
- if (!path26.startsWith("/") || path26.includes("?") || path26.includes("#")) {
2518
+ const path27 = value.trim().replace(/\/+$/, "") || "/";
2519
+ if (!path27.startsWith("/") || path27.includes("?") || path27.includes("#")) {
2520
2520
  throw new TypeError("images.path must be an absolute pathname without a query or hash");
2521
2521
  }
2522
- return path26;
2522
+ return path27;
2523
2523
  }
2524
2524
  function normalizeIntegerList(values, name, max) {
2525
2525
  if (values.length === 0) {
@@ -2872,9 +2872,9 @@ function getFarmIntegrationPluginOwner(plugin) {
2872
2872
  const value = plugin[FARM_INTEGRATION_PLUGIN_OWNER];
2873
2873
  return value && typeof value === "object" ? value : void 0;
2874
2874
  }
2875
- function defineTypedIntegrationRoute(method, path26, input) {
2875
+ function defineTypedIntegrationRoute(method, path27, input) {
2876
2876
  return {
2877
- path: path26,
2877
+ path: path27,
2878
2878
  method,
2879
2879
  middleware: input.middleware,
2880
2880
  before: input.before,
@@ -2884,7 +2884,7 @@ function defineTypedIntegrationRoute(method, path26, input) {
2884
2884
  input: normalizeIntegrationRouteInputSchemas(input),
2885
2885
  handler: input.handler,
2886
2886
  __operation: defineIntegrationAPIOperation({
2887
- path: path26,
2887
+ path: path27,
2888
2888
  method,
2889
2889
  bodyFormat: input.bodyFormat,
2890
2890
  responseFormat: input.responseFormat,
@@ -2896,52 +2896,52 @@ function defineTypedIntegrationRoute(method, path26, input) {
2896
2896
  }
2897
2897
  function createIntegrationRouteFactory() {
2898
2898
  return {
2899
- get(path26, input) {
2899
+ get(path27, input) {
2900
2900
  return defineTypedIntegrationRoute(
2901
2901
  "GET",
2902
- path26,
2902
+ path27,
2903
2903
  input
2904
2904
  );
2905
2905
  },
2906
- post(path26, input) {
2906
+ post(path27, input) {
2907
2907
  return defineTypedIntegrationRoute(
2908
2908
  "POST",
2909
- path26,
2909
+ path27,
2910
2910
  {
2911
2911
  bodyFormat: "json",
2912
2912
  ...input
2913
2913
  }
2914
2914
  );
2915
2915
  },
2916
- put(path26, input) {
2916
+ put(path27, input) {
2917
2917
  return defineTypedIntegrationRoute(
2918
2918
  "PUT",
2919
- path26,
2919
+ path27,
2920
2920
  {
2921
2921
  bodyFormat: "json",
2922
2922
  ...input
2923
2923
  }
2924
2924
  );
2925
2925
  },
2926
- patch(path26, input) {
2927
- return defineTypedIntegrationRoute("PATCH", path26, {
2926
+ patch(path27, input) {
2927
+ return defineTypedIntegrationRoute("PATCH", path27, {
2928
2928
  bodyFormat: "json",
2929
2929
  ...input
2930
2930
  });
2931
2931
  },
2932
- delete(path26, input) {
2933
- return defineTypedIntegrationRoute("DELETE", path26, {
2932
+ delete(path27, input) {
2933
+ return defineTypedIntegrationRoute("DELETE", path27, {
2934
2934
  bodyFormat: "json",
2935
2935
  ...input
2936
2936
  });
2937
2937
  },
2938
- options(path26, input) {
2939
- return defineTypedIntegrationRoute("OPTIONS", path26, input);
2938
+ options(path27, input) {
2939
+ return defineTypedIntegrationRoute("OPTIONS", path27, input);
2940
2940
  },
2941
- head(path26, input) {
2941
+ head(path27, input) {
2942
2942
  return defineTypedIntegrationRoute(
2943
2943
  "HEAD",
2944
- path26,
2944
+ path27,
2945
2945
  input
2946
2946
  );
2947
2947
  }
@@ -3278,8 +3278,8 @@ function normalizeIntegrationValidationIssues(source, error) {
3278
3278
  }
3279
3279
  ];
3280
3280
  }
3281
- function normalizeIntegrationValidationPath(path26) {
3282
- return (path26 || []).map((segment) => {
3281
+ function normalizeIntegrationValidationPath(path27) {
3282
+ return (path27 || []).map((segment) => {
3283
3283
  const key = typeof segment === "object" && segment !== null && "key" in segment ? segment.key : segment;
3284
3284
  return typeof key === "symbol" ? key.description || key.toString() : key;
3285
3285
  });
@@ -3982,8 +3982,8 @@ function createFarmDeploymentMismatchResponse(mismatch) {
3982
3982
  }
3983
3983
  );
3984
3984
  }
3985
- function createFarmDeploymentCookie(deploymentId, path26 = "/", secure = false) {
3986
- const normalizedPath = path26.startsWith("/") ? path26 : `/${path26}`;
3985
+ function createFarmDeploymentCookie(deploymentId, path27 = "/", secure = false) {
3986
+ const normalizedPath = path27.startsWith("/") ? path27 : `/${path27}`;
3987
3987
  return [
3988
3988
  `${FARM_DEPLOYMENT_COOKIE}=${encodeURIComponent(deploymentId)}`,
3989
3989
  `Path=${normalizedPath}`,
@@ -4152,6 +4152,52 @@ var init_config = __esm({
4152
4152
  }
4153
4153
  });
4154
4154
 
4155
+ // src/theme/config.ts
4156
+ function resolveFarmThemeConfig(config, basePath = "/") {
4157
+ if (config && "enabled" in config) {
4158
+ return config;
4159
+ }
4160
+ if (!config) {
4161
+ return {
4162
+ enabled: false,
4163
+ default: "system",
4164
+ storageKey: DEFAULT_FARM_THEME_STORAGE_KEY,
4165
+ cookiePath: normalizeCookiePath(basePath)
4166
+ };
4167
+ }
4168
+ const storageKey = config.storageKey?.trim() || DEFAULT_FARM_THEME_STORAGE_KEY;
4169
+ if (!STORAGE_KEY_PATTERN.test(storageKey)) {
4170
+ throw new Error(
4171
+ "theme.storageKey may only contain letters, numbers, dots, underscores, and hyphens."
4172
+ );
4173
+ }
4174
+ const defaultTheme = config.default ?? "system";
4175
+ if (defaultTheme !== "light" && defaultTheme !== "dark" && defaultTheme !== "system") {
4176
+ throw new Error('theme.default must be "light", "dark", or "system".');
4177
+ }
4178
+ return {
4179
+ enabled: true,
4180
+ default: defaultTheme,
4181
+ storageKey,
4182
+ cookiePath: normalizeCookiePath(basePath)
4183
+ };
4184
+ }
4185
+ function normalizeCookiePath(basePath) {
4186
+ const normalized = `/${basePath}`.replace(/\/{2,}/g, "/");
4187
+ if (normalized === "/") return normalized;
4188
+ return normalized.replace(/\/$/, "");
4189
+ }
4190
+ var DEFAULT_FARM_THEME_STORAGE_KEY, STORAGE_KEY_PATTERN;
4191
+ var init_config2 = __esm({
4192
+ "src/theme/config.ts"() {
4193
+ "use strict";
4194
+ DEFAULT_FARM_THEME_STORAGE_KEY = "farm-theme";
4195
+ STORAGE_KEY_PATTERN = /^[A-Za-z0-9._-]+$/;
4196
+ __name(resolveFarmThemeConfig, "resolveFarmThemeConfig");
4197
+ __name(normalizeCookiePath, "normalizeCookiePath");
4198
+ }
4199
+ });
4200
+
4155
4201
  // src/devtools-config.ts
4156
4202
  function resolveFarmDevtoolsConfig(config, mode = "development") {
4157
4203
  if (mode !== "development" || config === false) {
@@ -4514,11 +4560,11 @@ var init_type_generator = __esm({
4514
4560
  routeGroups.get(key).push(route);
4515
4561
  }
4516
4562
  const nestedStructure = {};
4517
- for (const [path26, routeList] of routeGroups) {
4563
+ for (const [path27, routeList] of routeGroups) {
4518
4564
  const route = routeList[0];
4519
4565
  const importPath = this.getRouteImportPath(route, options.outFile);
4520
4566
  const routeName = this.pathToRouteName(route.path);
4521
- const cleanPath = path26 === "/api" ? "" : path26.replace(/^\/api\//, "");
4567
+ const cleanPath = path27 === "/api" ? "" : path27.replace(/^\/api\//, "");
4522
4568
  const parts = cleanPath ? cleanPath.split("/") : [];
4523
4569
  const allMethods = routeList.flatMap((r) => r.methods);
4524
4570
  for (const method of allMethods) {
@@ -4577,8 +4623,8 @@ ${typeExports}
4577
4623
  const relativeImport = (0, import_path7.relative)((0, import_path7.dirname)(outFile), route.filePath).replace(/\\/g, "/").replace(/\.(ts|tsx|js|jsx)$/, "");
4578
4624
  return relativeImport.startsWith(".") ? relativeImport : `./${relativeImport}`;
4579
4625
  }
4580
- pathToRouteName(path26) {
4581
- return (path26 === "/api" ? "root" : path26.replace(/^\/api\//, "")).replace(/\//g, "_").replace(/[^a-zA-Z0-9_]/g, "");
4626
+ pathToRouteName(path27) {
4627
+ return (path27 === "/api" ? "root" : path27.replace(/^\/api\//, "")).replace(/\//g, "_").replace(/[^a-zA-Z0-9_]/g, "");
4582
4628
  }
4583
4629
  structureToTypeString(obj, indent) {
4584
4630
  const spaces = " ".repeat(indent);
@@ -4598,15 +4644,15 @@ ${typeExports}
4598
4644
  toTypePropertyKey(key) {
4599
4645
  return /^[$A-Z_][0-9A-Z_$]*$/i.test(key) ? key : JSON.stringify(key);
4600
4646
  }
4601
- getBaseExportName(path26) {
4602
- const cleanPath = path26.replace(/^\/api\//, "");
4647
+ getBaseExportName(path27) {
4648
+ const cleanPath = path27.replace(/^\/api\//, "");
4603
4649
  if (cleanPath === "") {
4604
4650
  return "api";
4605
4651
  }
4606
4652
  return cleanPath;
4607
4653
  }
4608
- getExportName(path26, method) {
4609
- const cleanPath = path26.replace(/^\/api\//, "");
4654
+ getExportName(path27, method) {
4655
+ const cleanPath = path27.replace(/^\/api\//, "");
4610
4656
  if (cleanPath === "") {
4611
4657
  return method.toLowerCase();
4612
4658
  }
@@ -8805,37 +8851,37 @@ function sanitizeDocsConfig(config) {
8805
8851
  return cloneSerializable(config) || {};
8806
8852
  }
8807
8853
  async function findDocsConfigPath(rootDir, configPath) {
8808
- const { existsSync: existsSync16 } = await import("fs");
8854
+ const { existsSync: existsSync17 } = await import("fs");
8809
8855
  const root = import_path9.default.resolve(rootDir || process.cwd());
8810
8856
  if (configPath) {
8811
8857
  const resolvedPath = import_path9.default.isAbsolute(configPath) ? configPath : import_path9.default.join(root, configPath);
8812
- if (!existsSync16(resolvedPath)) {
8858
+ if (!existsSync17(resolvedPath)) {
8813
8859
  throw new Error(`Could not find docs config at ${configPath}.`);
8814
8860
  }
8815
8861
  return import_path9.default.resolve(resolvedPath);
8816
8862
  }
8817
8863
  for (const filename of DOCS_CONFIG_FILENAMES) {
8818
8864
  const resolvedPath = import_path9.default.join(root, filename);
8819
- if (existsSync16(resolvedPath)) {
8865
+ if (existsSync17(resolvedPath)) {
8820
8866
  return resolvedPath;
8821
8867
  }
8822
8868
  }
8823
8869
  return void 0;
8824
8870
  }
8825
8871
  async function loadDocsConfig(rootDir, configPath) {
8826
- const fs8 = await import("fs/promises");
8872
+ const fs9 = await import("fs/promises");
8827
8873
  const { pathToFileURL: pathToFileURL5 } = await import("url");
8828
8874
  const root = import_path9.default.resolve(rootDir || process.cwd());
8829
8875
  const resolvedPath = await findDocsConfigPath(root, configPath);
8830
8876
  if (!resolvedPath) return void 0;
8831
8877
  try {
8832
8878
  if (resolvedPath.endsWith(".json")) {
8833
- const content = await fs8.readFile(resolvedPath, "utf8");
8879
+ const content = await fs9.readFile(resolvedPath, "utf8");
8834
8880
  return { config: JSON.parse(content), configPath: resolvedPath };
8835
8881
  }
8836
8882
  const { build } = await import("esbuild");
8837
8883
  const configCacheDir = import_path9.default.join(root, ".farm", ".config-loader");
8838
- await fs8.mkdir(configCacheDir, { recursive: true });
8884
+ await fs9.mkdir(configCacheDir, { recursive: true });
8839
8885
  const modulePath = import_path9.default.join(
8840
8886
  configCacheDir,
8841
8887
  `docs-config-${Date.now()}-${Math.random().toString(36).slice(2)}.mjs`
@@ -8861,7 +8907,7 @@ async function loadDocsConfig(rootDir, configPath) {
8861
8907
  moduleUrl
8862
8908
  );
8863
8909
  } finally {
8864
- await fs8.unlink(modulePath).catch(() => void 0);
8910
+ await fs9.unlink(modulePath).catch(() => void 0);
8865
8911
  }
8866
8912
  return {
8867
8913
  config: importedConfig.default || importedConfig,
@@ -8934,7 +8980,7 @@ async function resolveDocsConfig(userDocs, options = {}) {
8934
8980
  };
8935
8981
  }
8936
8982
  var import_path9, DOCS_CONFIG_FILENAMES;
8937
- var init_config2 = __esm({
8983
+ var init_config3 = __esm({
8938
8984
  "src/config.ts"() {
8939
8985
  "use strict";
8940
8986
  init_integrations();
@@ -8955,6 +9001,7 @@ var init_config2 = __esm({
8955
9001
  init_auth_config();
8956
9002
  init_preload();
8957
9003
  init_security();
9004
+ init_config2();
8958
9005
  init_config_entry();
8959
9006
  __name(getDeployTargetForPreset, "getDeployTargetForPreset");
8960
9007
  DOCS_CONFIG_FILENAMES = [
@@ -9449,7 +9496,7 @@ var init_api = __esm({
9449
9496
  "src/docs/api.ts"() {
9450
9497
  "use strict";
9451
9498
  import_docs2 = require("@farming-labs/docs");
9452
- init_config2();
9499
+ init_config3();
9453
9500
  init_handler();
9454
9501
  __name(isRecord4, "isRecord");
9455
9502
  __name(isResolvedDocsConfig2, "isResolvedDocsConfig");
@@ -9743,8 +9790,8 @@ var init_generator = __esm({
9743
9790
  }
9744
9791
  routeGroups.get(key).push(route);
9745
9792
  }
9746
- for (const [path26, routeList] of routeGroups) {
9747
- const openAPIPath = this.convertToOpenAPIPath(path26);
9793
+ for (const [path27, routeList] of routeGroups) {
9794
+ const openAPIPath = this.convertToOpenAPIPath(path27);
9748
9795
  spec.paths[openAPIPath] = {};
9749
9796
  for (const route of routeList) {
9750
9797
  for (const method of route.methods) {
@@ -9758,8 +9805,8 @@ var init_generator = __esm({
9758
9805
  /**
9759
9806
  * Convert Farm.js API path to OpenAPI path format
9760
9807
  */
9761
- convertToOpenAPIPath(path26) {
9762
- return path26.replace(/^\/api/, "");
9808
+ convertToOpenAPIPath(path27) {
9809
+ return path27.replace(/^\/api/, "");
9763
9810
  }
9764
9811
  /**
9765
9812
  * Extract request body schema from endpoint
@@ -9921,8 +9968,8 @@ var init_generator = __esm({
9921
9968
  /**
9922
9969
  * Generate operation summary
9923
9970
  */
9924
- generateSummary(path26, method) {
9925
- const cleanPath = path26.replace(/^\/api\//, "");
9971
+ generateSummary(path27, method) {
9972
+ const cleanPath = path27.replace(/^\/api\//, "");
9926
9973
  const pathParts = cleanPath.split("/");
9927
9974
  const lastPart = pathParts[pathParts.length - 1];
9928
9975
  const action = method === "GET" ? "Get" : method === "POST" ? "Create" : method === "PUT" ? "Update" : method === "DELETE" ? "Delete" : method === "PATCH" ? "Update" : method;
@@ -9931,22 +9978,22 @@ var init_generator = __esm({
9931
9978
  /**
9932
9979
  * Generate operation description
9933
9980
  */
9934
- generateDescription(path26, method) {
9935
- const cleanPath = path26.replace(/^\/api\//, "");
9981
+ generateDescription(path27, method) {
9982
+ const cleanPath = path27.replace(/^\/api\//, "");
9936
9983
  return `${method} ${cleanPath} endpoint`;
9937
9984
  }
9938
9985
  /**
9939
9986
  * Generate operation ID
9940
9987
  */
9941
- generateOperationId(path26, method) {
9942
- const cleanPath = path26.replace(/^\/api\//, "").replace(/\//g, "_");
9988
+ generateOperationId(path27, method) {
9989
+ const cleanPath = path27.replace(/^\/api\//, "").replace(/\//g, "_");
9943
9990
  return `${method.toLowerCase()}_${cleanPath}`;
9944
9991
  }
9945
9992
  /**
9946
9993
  * Generate tags for grouping operations
9947
9994
  */
9948
- generateTags(path26) {
9949
- const cleanPath = path26.replace(/^\/api\//, "");
9995
+ generateTags(path27) {
9996
+ const cleanPath = path27.replace(/^\/api\//, "");
9950
9997
  const pathParts = cleanPath.split("/");
9951
9998
  if (pathParts.length > 1) {
9952
9999
  return [pathParts[0]];
@@ -9958,13 +10005,13 @@ var init_generator = __esm({
9958
10005
  */
9959
10006
  async generateSpecFile(routes, outputPath) {
9960
10007
  const spec = await this.generateSpec(routes);
9961
- const fs8 = require("fs");
9962
- const path26 = require("path");
9963
- const dir = path26.dirname(outputPath);
9964
- if (!fs8.existsSync(dir)) {
9965
- fs8.mkdirSync(dir, { recursive: true });
10008
+ const fs9 = require("fs");
10009
+ const path27 = require("path");
10010
+ const dir = path27.dirname(outputPath);
10011
+ if (!fs9.existsSync(dir)) {
10012
+ fs9.mkdirSync(dir, { recursive: true });
9966
10013
  }
9967
- fs8.writeFileSync(outputPath, JSON.stringify(spec, null, 2));
10014
+ fs9.writeFileSync(outputPath, JSON.stringify(spec, null, 2));
9968
10015
  }
9969
10016
  };
9970
10017
  __name(_OpenAPIGenerator, "OpenAPIGenerator");
@@ -10434,7 +10481,7 @@ var init_devtools = __esm({
10434
10481
  "src/devtools.ts"() {
10435
10482
  "use strict";
10436
10483
  import_node_path14 = __toESM(require("path"));
10437
- init_config2();
10484
+ init_config3();
10438
10485
  init_cron();
10439
10486
  init_route_runtime();
10440
10487
  __name(normalizePath, "normalizePath");
@@ -12224,8 +12271,8 @@ function toViteModuleId(filePath, root) {
12224
12271
  __name(toViteModuleId, "toViteModuleId");
12225
12272
  async function fileExists(filePath) {
12226
12273
  try {
12227
- const fs8 = await import("fs/promises");
12228
- await fs8.access(filePath);
12274
+ const fs9 = await import("fs/promises");
12275
+ await fs9.access(filePath);
12229
12276
  return true;
12230
12277
  } catch {
12231
12278
  return false;
@@ -13494,7 +13541,7 @@ function normalizePositiveDuration(value, fallback, name) {
13494
13541
  }
13495
13542
  __name(normalizePositiveDuration, "normalizePositiveDuration");
13496
13543
  function delay(ms) {
13497
- return new Promise((resolve6) => setTimeout(resolve6, ms));
13544
+ return new Promise((resolve7) => setTimeout(resolve7, ms));
13498
13545
  }
13499
13546
  __name(delay, "delay");
13500
13547
  function normalizeCacheOptionsTags(options) {
@@ -13630,25 +13677,25 @@ function defineRoutes(input) {
13630
13677
  }
13631
13678
  __name(defineRoutes, "defineRoutes");
13632
13679
  var routesBuilder = {
13633
- page(path26, options) {
13680
+ page(path27, options) {
13634
13681
  return normalizeProgrammaticRoute({
13635
13682
  kind: "page",
13636
- path: path26,
13683
+ path: path27,
13637
13684
  ...options
13638
13685
  });
13639
13686
  },
13640
- layout(path26, options) {
13687
+ layout(path27, options) {
13641
13688
  return normalizeProgrammaticRoute({
13642
13689
  kind: "layout",
13643
- path: path26,
13690
+ path: path27,
13644
13691
  ...options
13645
13692
  });
13646
13693
  },
13647
- api(path26, options) {
13694
+ api(path27, options) {
13648
13695
  const { render, runtime, regions, maxDuration, ...methods } = options;
13649
13696
  return normalizeProgrammaticRoute({
13650
13697
  kind: "api",
13651
- path: path26,
13698
+ path: path27,
13652
13699
  render,
13653
13700
  runtime,
13654
13701
  regions,
@@ -13684,7 +13731,7 @@ function getProgrammaticRouteSearchClientOptions(search) {
13684
13731
  return Object.keys(options).length > 0 ? options : void 0;
13685
13732
  }
13686
13733
  __name(getProgrammaticRouteSearchClientOptions, "getProgrammaticRouteSearchClientOptions");
13687
- function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path26, routePath) {
13734
+ function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path27, routePath) {
13688
13735
  const schema = getProgrammaticRouteSearchSchema(searchConfig);
13689
13736
  const search = parseProgrammaticSchema(schema, rawSearch, "search", routePath);
13690
13737
  const options = getProgrammaticRouteSearchOptions(searchConfig);
@@ -13693,7 +13740,7 @@ function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path26, routePa
13693
13740
  schema,
13694
13741
  rawSearch,
13695
13742
  parsedSearch: search,
13696
- path: path26
13743
+ path: path27
13697
13744
  });
13698
13745
  return { search, canonicalPath };
13699
13746
  }
@@ -13876,7 +13923,7 @@ function createRouteModuleFromProgrammaticPage(route) {
13876
13923
  mod.__farmRouteData = route.data;
13877
13924
  mod.__farmRouteParsesProps = true;
13878
13925
  mod.__farmResolveRouteProps = (props) => resolveProgrammaticRouteProps(route, props);
13879
- mod.__farmResolveRouteCanonicalPath = (rawSearch, path26) => resolveProgrammaticRouteSearch(route.search, rawSearch, path26, route.path).canonicalPath;
13926
+ mod.__farmResolveRouteCanonicalPath = (rawSearch, path27) => resolveProgrammaticRouteSearch(route.search, rawSearch, path27, route.path).canonicalPath;
13880
13927
  }
13881
13928
  if (route.pending || route.error || route.notFound) {
13882
13929
  mod.__farmRouteComponents = {
@@ -14630,6 +14677,37 @@ function stripUseClientDirective(content) {
14630
14677
  return content.replace(/^\s*(["'])use client\1\s*;?\s*/, "");
14631
14678
  }
14632
14679
  __name(stripUseClientDirective, "stripUseClientDirective");
14680
+ function hasAsyncDefaultExport(content) {
14681
+ if (!content) return false;
14682
+ const tokens = tokenizeModuleSource(content);
14683
+ for (let index = 0; index < tokens.length - 2; index++) {
14684
+ const token = tokens[index];
14685
+ if (token.kind !== "identifier" || token.value !== "export") continue;
14686
+ if (tokens[index - 1]?.value === ".") continue;
14687
+ if (tokens[index + 1]?.value !== "default") continue;
14688
+ const exported = tokens[index + 2];
14689
+ if (exported.kind === "identifier" && exported.value === "async") {
14690
+ return true;
14691
+ }
14692
+ if (exported.kind === "identifier" && !["function", "class"].includes(exported.value) && tokens[index + 3]?.value !== "(" && isAsyncLocalDeclaration(tokens, exported.value)) {
14693
+ return true;
14694
+ }
14695
+ }
14696
+ return false;
14697
+ }
14698
+ __name(hasAsyncDefaultExport, "hasAsyncDefaultExport");
14699
+ function isAsyncLocalDeclaration(tokens, name) {
14700
+ for (let index = 0; index < tokens.length - 2; index++) {
14701
+ if (tokens[index].value === "async" && tokens[index + 1]?.value === "function" && tokens[index + 2]?.value === name) {
14702
+ return true;
14703
+ }
14704
+ if (tokens[index].value === name && tokens[index + 1]?.value === "=" && tokens[index + 2]?.value === "async") {
14705
+ return true;
14706
+ }
14707
+ }
14708
+ return false;
14709
+ }
14710
+ __name(isAsyncLocalDeclaration, "isAsyncLocalDeclaration");
14633
14711
  function parseClientModuleMetadata(content, inspectIslandExport) {
14634
14712
  if (!content) {
14635
14713
  return {
@@ -14685,6 +14763,14 @@ function inspectClientModuleMetadata(resolvedPath, root, visited, inspectIslandE
14685
14763
  }
14686
14764
  }
14687
14765
  const shouldHydrate = parsed.hasHydrateExport || importsClientBoundary;
14766
+ if (shouldHydrate && hasAsyncDefaultExport(content)) {
14767
+ return {
14768
+ isClientComponent: false,
14769
+ shouldHydrate: false,
14770
+ islandStrategy: null,
14771
+ suppressedAsyncHydration: true
14772
+ };
14773
+ }
14688
14774
  return {
14689
14775
  isClientComponent: false,
14690
14776
  shouldHydrate,
@@ -15400,6 +15486,7 @@ var _RouteManager = class _RouteManager {
15400
15486
  shouldHydrate: metadata.shouldHydrate,
15401
15487
  isClientComponent: metadata.isClientComponent,
15402
15488
  islandStrategy: metadata.islandStrategy,
15489
+ suppressedAsyncHydration: metadata.suppressedAsyncHydration,
15403
15490
  search: getProgrammaticRouteSearchClientOptions(programmaticPage?.search),
15404
15491
  segments: entry.route.segments.map((seg) => ({
15405
15492
  segment: seg.segment,
@@ -16105,6 +16192,16 @@ async function _runWithCurrentRequest(request, fn) {
16105
16192
  return requestStore.run(request, fn);
16106
16193
  }
16107
16194
  __name(_runWithCurrentRequest, "_runWithCurrentRequest");
16195
+ function getCurrentRequest() {
16196
+ const request = requestStore.getStore();
16197
+ if (!request) {
16198
+ throw new Error(
16199
+ "No current request is available. getCurrentRequest() can only be used during server rendering."
16200
+ );
16201
+ }
16202
+ return request;
16203
+ }
16204
+ __name(getCurrentRequest, "getCurrentRequest");
16108
16205
 
16109
16206
  // src/client/router.ts
16110
16207
  var import_react3 = require("react");
@@ -18511,18 +18608,146 @@ function DefaultNotFoundPage(_props) {
18511
18608
  }
18512
18609
  __name(DefaultNotFoundPage, "DefaultNotFoundPage");
18513
18610
 
18611
+ // src/theme/server-runtime.ts
18612
+ init_config2();
18613
+ var THEME_SCRIPT_ID = "farm-theme-script";
18614
+ var THEME_STYLE_ID = "farm-theme-style";
18615
+ function createFarmThemeDocumentParts(input, basePath = "/", serverTheme) {
18616
+ const config = resolveFarmThemeConfig(input, basePath);
18617
+ if (!config.enabled) return { attributes: "", head: "" };
18618
+ const hydrationTheme = serverTheme ?? config.default;
18619
+ const initialTheme = hydrationTheme === "system" ? "light" : hydrationTheme;
18620
+ const script = createFarmThemeBootstrapScript(config, hydrationTheme);
18621
+ return {
18622
+ attributes: ` data-theme="${initialTheme}"`,
18623
+ 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>`
18624
+ };
18625
+ }
18626
+ __name(createFarmThemeDocumentParts, "createFarmThemeDocumentParts");
18627
+ function createFarmThemeBootstrapScript(config, serverTheme = config.default) {
18628
+ return `(function(config,serverTheme){
18629
+ var isTheme=function(value){return value==="light"||value==="dark"||value==="system";};
18630
+ var decode=function(value){try{return decodeURIComponent(value);}catch(_error){return value;}};
18631
+ 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());}};
18632
+ var media=window.matchMedia("(prefers-color-scheme: dark)");
18633
+ var resolveTheme=function(theme){return theme==="system"?(media.matches?"dark":"light"):theme;};
18634
+ var storedTheme=readCookie();
18635
+ var preference=isTheme(storedTheme)?storedTheme:config.default;
18636
+ var serverSnapshot={theme:serverTheme,resolvedTheme:serverTheme==="system"?undefined:serverTheme,mounted:false};
18637
+ 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;};
18638
+ var emit=function(){var snapshot=apply();window.dispatchEvent(new CustomEvent("farm:themechange",{detail:snapshot}));};
18639
+ 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){}};
18640
+ var setTheme=function(theme){if(!isTheme(theme))throw new TypeError("Unknown FARMJS theme: "+String(theme));preference=theme;persist(theme);emit();};
18641
+ var initialSnapshot={theme:preference,resolvedTheme:resolveTheme(preference),mounted:true};
18642
+ window.__FARM_THEME__={config:config,serverSnapshot:serverSnapshot,snapshot:initialSnapshot,setTheme:setTheme};
18643
+ document.documentElement.dataset.theme=initialSnapshot.resolvedTheme;
18644
+ var handleSystemChange=function(){if(preference==="system")emit();};
18645
+ if(typeof media.addEventListener==="function")media.addEventListener("change",handleSystemChange);else if(typeof media.addListener==="function")media.addListener(handleSystemChange);
18646
+ window.addEventListener("storage",function(event){if(event.key!==config.storageKey||!isTheme(event.newValue))return;preference=event.newValue;persist(preference);emit();});
18647
+ })(${serializeInlineValue(config)},${serializeInlineValue(serverTheme)});`;
18648
+ }
18649
+ __name(createFarmThemeBootstrapScript, "createFarmThemeBootstrapScript");
18650
+ function serializeInlineValue(value) {
18651
+ return JSON.stringify(value).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
18652
+ }
18653
+ __name(serializeInlineValue, "serializeInlineValue");
18654
+
18655
+ // src/theme/bridge.ts
18656
+ var FALLBACK_SERVER_SNAPSHOT = Object.freeze({
18657
+ theme: "system",
18658
+ resolvedTheme: void 0,
18659
+ mounted: false
18660
+ });
18661
+ var FARM_THEME_SERVER_SNAPSHOT_RESOLVER = /* @__PURE__ */ Symbol.for("farm.js.theme.server-snapshot-resolver");
18662
+ function _setFarmThemeServerSnapshotResolver(resolver) {
18663
+ globalThis[FARM_THEME_SERVER_SNAPSHOT_RESOLVER] = resolver;
18664
+ }
18665
+ __name(_setFarmThemeServerSnapshotResolver, "_setFarmThemeServerSnapshotResolver");
18666
+
18667
+ // src/theme/server.ts
18668
+ init_config2();
18669
+ var defaultThemeConfig = resolveFarmThemeConfig(void 0);
18670
+ function _setDefaultFarmThemeConfig(config, basePath = "/") {
18671
+ defaultThemeConfig = resolveFarmThemeConfig(config, basePath);
18672
+ }
18673
+ __name(_setDefaultFarmThemeConfig, "_setDefaultFarmThemeConfig");
18674
+ function getTheme(request = getCurrentRequest()) {
18675
+ return readFarmThemePreference(request, defaultThemeConfig);
18676
+ }
18677
+ __name(getTheme, "getTheme");
18678
+ function getThemeSnapshot(request = getCurrentRequest()) {
18679
+ const theme = readFarmThemePreference(request, defaultThemeConfig);
18680
+ return {
18681
+ theme,
18682
+ resolvedTheme: theme === "system" ? void 0 : theme,
18683
+ mounted: false
18684
+ };
18685
+ }
18686
+ __name(getThemeSnapshot, "getThemeSnapshot");
18687
+ function readFarmThemePreference(request, config) {
18688
+ if (!config.enabled) return config.default;
18689
+ const stored = readCookie3(request.headers.get("cookie"), config.storageKey);
18690
+ return isFarmThemePreference(stored) ? stored : config.default;
18691
+ }
18692
+ __name(readFarmThemePreference, "readFarmThemePreference");
18693
+ function readCookie3(cookieHeader, name) {
18694
+ if (!cookieHeader) return void 0;
18695
+ for (const entry of cookieHeader.split(";")) {
18696
+ const separator = entry.indexOf("=");
18697
+ if (separator < 0) continue;
18698
+ const key = decodeCookieValue(entry.slice(0, separator).trim());
18699
+ if (key !== name) continue;
18700
+ return decodeCookieValue(entry.slice(separator + 1).trim());
18701
+ }
18702
+ return void 0;
18703
+ }
18704
+ __name(readCookie3, "readCookie");
18705
+ function decodeCookieValue(value) {
18706
+ try {
18707
+ return decodeURIComponent(value);
18708
+ } catch {
18709
+ return value;
18710
+ }
18711
+ }
18712
+ __name(decodeCookieValue, "decodeCookieValue");
18713
+ function isFarmThemePreference(value) {
18714
+ return value === "light" || value === "dark" || value === "system";
18715
+ }
18716
+ __name(isFarmThemePreference, "isFarmThemePreference");
18717
+ _setFarmThemeServerSnapshotResolver(() => {
18718
+ try {
18719
+ return getThemeSnapshot();
18720
+ } catch {
18721
+ const theme = defaultThemeConfig.default;
18722
+ return {
18723
+ theme,
18724
+ resolvedTheme: theme === "system" ? void 0 : theme,
18725
+ mounted: false
18726
+ };
18727
+ }
18728
+ });
18729
+
18514
18730
  // src/server/renderer.ts
18515
18731
  var cachedClerkProvider = null;
18516
18732
  var importRuntimeModule = new Function("specifier", "return import(specifier);");
18733
+ var warnedSuppressedAsyncHydrationModules = /* @__PURE__ */ new Set();
18734
+ function warnSuppressedAsyncHydrationOnce(modulePath) {
18735
+ if (warnedSuppressedAsyncHydrationModules.has(modulePath)) return;
18736
+ warnedSuppressedAsyncHydrationModules.add(modulePath);
18737
+ logger.warn(
18738
+ `${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.`
18739
+ );
18740
+ }
18741
+ __name(warnSuppressedAsyncHydrationOnce, "warnSuppressedAsyncHydrationOnce");
18517
18742
  function hasRequestHeader(req, name) {
18518
18743
  const value = req.headers[name.toLowerCase()];
18519
18744
  return Array.isArray(value) ? value.length > 0 : Boolean(value);
18520
18745
  }
18521
18746
  __name(hasRequestHeader, "hasRequestHeader");
18522
- function serializeInlineValue(value) {
18747
+ function serializeInlineValue2(value) {
18523
18748
  return JSON.stringify(value).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
18524
18749
  }
18525
- __name(serializeInlineValue, "serializeInlineValue");
18750
+ __name(serializeInlineValue2, "serializeInlineValue");
18526
18751
  function escapeHtmlAttribute2(value) {
18527
18752
  return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
18528
18753
  }
@@ -18616,7 +18841,7 @@ function createDocumentFooter(options) {
18616
18841
  __name(createDocumentFooter, "createDocumentFooter");
18617
18842
  function createDeferredHydrationScript(records) {
18618
18843
  if (records.length === 0) return "";
18619
- return `<script>window.__FARM_DEFERRED_DATA__=${serializeInlineValue(
18844
+ return `<script>window.__FARM_DEFERRED_DATA__=${serializeInlineValue2(
18620
18845
  snapshotDeferredData(records)
18621
18846
  )};</script>`;
18622
18847
  }
@@ -19188,6 +19413,9 @@ var _ServerRenderer = class _ServerRenderer {
19188
19413
  })
19189
19414
  );
19190
19415
  const shouldHydrate = moduleMetadata.shouldHydrate;
19416
+ if (moduleMetadata.suppressedAsyncHydration) {
19417
+ warnSuppressedAsyncHydrationOnce(route.modulePath);
19418
+ }
19191
19419
  const layoutHydrationMetadata = layouts.map((layout2) => {
19192
19420
  const manifestEntry = routeManifest.layouts.find(
19193
19421
  (entry) => entry.pattern === layout2.pattern
@@ -19685,7 +19913,7 @@ var _ServerRenderer = class _ServerRenderer {
19685
19913
  }
19686
19914
  }
19687
19915
  async renderWithSSR(element, req, res, clearMiddlewareData, options = {}) {
19688
- return new Promise((resolve6, reject) => {
19916
+ return new Promise((resolve7, reject) => {
19689
19917
  const streamStartTime = Date.now();
19690
19918
  const observabilityRoute = options.observabilityRoute || req.__FARM_ROUTE__ || req.url || "/";
19691
19919
  const deploymentId = this.getDeploymentId();
@@ -19757,9 +19985,9 @@ var _ServerRenderer = class _ServerRenderer {
19757
19985
  slots: routeSlotPayload
19758
19986
  });
19759
19987
  const propsScript = `<script>
19760
- window.__FARM_PROPS__ = ${serializeInlineValue(deferredProps.data.page)};
19761
- window.__FARM_ROUTE_SLOTS__ = ${serializeInlineValue(deferredProps.data.slots)};
19762
- window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue(deploymentId)};
19988
+ window.__FARM_PROPS__ = ${serializeInlineValue2(deferredProps.data.page)};
19989
+ window.__FARM_ROUTE_SLOTS__ = ${serializeInlineValue2(deferredProps.data.slots)};
19990
+ window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue2(deploymentId)};
19763
19991
  window.__FARM_PATH__ = ${JSON.stringify(req.__FARM_ROUTE__ || req.url || "/")};
19764
19992
  window.__FARM_IS_CLIENT__ = ${JSON.stringify(isClientComponent)};
19765
19993
  window.__FARM_PAGE_SHOULD_HYDRATE__ = ${JSON.stringify(
@@ -19777,7 +20005,7 @@ window.__FARM_LOADING_MODULE__ = ${JSON.stringify(
19777
20005
  )};
19778
20006
  window.__FARM_MANIFEST__ = ${JSON.stringify(clientManifest)};
19779
20007
  window.__FARM_INTEGRATION_API_MANIFEST__ = ${JSON.stringify(getRegisteredIntegrationAPIManifest())};
19780
- ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(getFarmI18nClientSnapshot())};` : ""}
20008
+ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(getFarmI18nClientSnapshot())};` : ""}
19781
20009
  </script>`;
19782
20010
  const hydrationClickQueueScript = isClientComponent || req.__FARM_SHOULD_HYDRATE__ === true || req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ === true ? createPreHydrationClickQueueScript() : "";
19783
20011
  const {
@@ -19788,6 +20016,11 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
19788
20016
  const i18nSnapshot = getFarmI18nClientSnapshot();
19789
20017
  const i18nAlternateTags = i18nSnapshot ? renderI18nAlternateLinks(req.__FARM_ROUTE__ || req.url || "/", i18nSnapshot) : "";
19790
20018
  const fontHead = renderFarmFontDevHead(this.config.root || process.cwd());
20019
+ const themeDocument = createFarmThemeDocumentParts(
20020
+ this.config.theme,
20021
+ this.config.basePath,
20022
+ getTheme()
20023
+ );
19791
20024
  const streamRoot = import_react5.default.createElement("div", { style: { display: "contents" } }, element);
19792
20025
  const { pipe } = (0, import_server2.renderToPipeableStream)(streamRoot, {
19793
20026
  onShellReady() {
@@ -19801,8 +20034,9 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
19801
20034
  console.log(`[FARM STREAM] onShellReady at ${shellReadyMs}ms`);
19802
20035
  }
19803
20036
  const shell = `<!DOCTYPE html>
19804
- <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}>
20037
+ <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}${themeDocument.attributes}>
19805
20038
  <head>
20039
+ ${themeDocument.head}
19806
20040
  <meta charset="utf-8">
19807
20041
  <meta name="viewport" content="width=device-width, initial-scale=1">
19808
20042
  <meta name="farm-deployment-id" content="${escapeHtmlAttribute2(deploymentId)}">
@@ -19879,7 +20113,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
19879
20113
  route: observabilityRoute,
19880
20114
  durationMs: Date.now() - streamStartTime
19881
20115
  });
19882
- resolve6();
20116
+ resolve7();
19883
20117
  }
19884
20118
  });
19885
20119
  res.write(shell);
@@ -20004,15 +20238,21 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
20004
20238
  const i18nSnapshot = getFarmI18nClientSnapshot();
20005
20239
  const clientScript = isClientComponent ? ` <script type="module" src="/@farm/client.js"></script>` : "";
20006
20240
  const integrationManifestScript = `<script>
20007
- window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue(this.getDeploymentId())};
20241
+ window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue2(this.getDeploymentId())};
20008
20242
  window.__FARM_INTEGRATION_API_MANIFEST__ = ${JSON.stringify(getRegisteredIntegrationAPIManifest())};
20009
- ${i18nSnapshot ? `window.__FARM_I18N__ = ${serializeInlineValue(i18nSnapshot)};` : ""}
20243
+ ${i18nSnapshot ? `window.__FARM_I18N__ = ${serializeInlineValue2(i18nSnapshot)};` : ""}
20010
20244
  </script>`;
20011
20245
  const alternateLinks = i18nSnapshot ? renderI18nAlternateLinks(requestPath, i18nSnapshot) : "";
20012
20246
  const fontHead = renderFarmFontDevHead(this.config.root || process.cwd());
20247
+ const themeDocument = createFarmThemeDocumentParts(
20248
+ this.config.theme,
20249
+ this.config.basePath,
20250
+ getTheme()
20251
+ );
20013
20252
  return `<!DOCTYPE html>
20014
- <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}>
20253
+ <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}${themeDocument.attributes}>
20015
20254
  <head>
20255
+ ${themeDocument.head}
20016
20256
  <meta charset="utf-8">
20017
20257
  <meta name="viewport" content="width=device-width, initial-scale=1">
20018
20258
  <meta name="farm-deployment-id" content="${escapeHtmlAttribute2(this.getDeploymentId())}">
@@ -20059,6 +20299,7 @@ init_config();
20059
20299
  init_auth_config();
20060
20300
  init_preload();
20061
20301
  init_security();
20302
+ init_config2();
20062
20303
  var defaultDocsConfig = {
20063
20304
  enabled: false,
20064
20305
  entry: "/docs",
@@ -20072,6 +20313,7 @@ var _FarmApp = class _FarmApp {
20072
20313
  constructor(config = {}, viteServer) {
20073
20314
  this.config = this.normalizeConfig(config);
20074
20315
  configureFarmObservability(this.config.observability);
20316
+ _setDefaultFarmThemeConfig(this.config.theme);
20075
20317
  this.i18nRuntime = createFarmI18nRuntime(this.config.i18n);
20076
20318
  _setDefaultFarmI18nRuntime(this.i18nRuntime);
20077
20319
  this.viteServer = viteServer;
@@ -20130,6 +20372,7 @@ var _FarmApp = class _FarmApp {
20130
20372
  security: resolveFarmSecurityConfig(config.security),
20131
20373
  images: resolveFarmImageConfig(config.images),
20132
20374
  performance: resolveFarmPerformanceConfig(config.performance),
20375
+ theme: resolveFarmThemeConfig(config.theme, config.basePath || "/"),
20133
20376
  i18n: isResolvedI18nConfig(config.i18n) ? config.i18n : resolveFarmI18nConfig(config.i18n, {
20134
20377
  root,
20135
20378
  mode: process.env.NODE_ENV === "production" ? "production" : "development"
@@ -22392,8 +22635,8 @@ init_app_markdown();
22392
22635
  init_response();
22393
22636
  init_integrations();
22394
22637
  init_devtools_config();
22395
- var fs7 = __toESM(require("fs"));
22396
- var path25 = __toESM(require("path"));
22638
+ var fs8 = __toESM(require("fs"));
22639
+ var path26 = __toESM(require("path"));
22397
22640
  init_layers();
22398
22641
 
22399
22642
  // src/after.ts
@@ -22425,8 +22668,8 @@ __name(reportAfterError, "reportAfterError");
22425
22668
  function createAfterRequestState(reportError = defaultAfterErrorReporter) {
22426
22669
  let resolveResponseFinished;
22427
22670
  let responseFinished = false;
22428
- const responseFinishedPromise = new Promise((resolve6) => {
22429
- resolveResponseFinished = resolve6;
22671
+ const responseFinishedPromise = new Promise((resolve7) => {
22672
+ resolveResponseFinished = resolve7;
22430
22673
  });
22431
22674
  const state = {
22432
22675
  completion: Promise.resolve(),
@@ -22497,6 +22740,34 @@ function _withAfterNodeMiddleware(handler) {
22497
22740
  }
22498
22741
  __name(_withAfterNodeMiddleware, "_withAfterNodeMiddleware");
22499
22742
 
22743
+ // src/dev-static.ts
22744
+ var fs7 = __toESM(require("fs"));
22745
+ var path17 = __toESM(require("path"));
22746
+ function devServableFileExists(pathname, baseDirs) {
22747
+ let decodedPathname;
22748
+ try {
22749
+ decodedPathname = decodeURIComponent(pathname);
22750
+ } catch {
22751
+ return false;
22752
+ }
22753
+ const relativePathname = decodedPathname.replace(/^\/+/, "");
22754
+ if (!relativePathname) return false;
22755
+ for (const baseDir of baseDirs) {
22756
+ if (typeof baseDir !== "string" || baseDir.length === 0) continue;
22757
+ const resolvedBase = path17.resolve(baseDir);
22758
+ const candidate = path17.resolve(resolvedBase, relativePathname);
22759
+ if (!candidate.startsWith(resolvedBase + path17.sep)) continue;
22760
+ try {
22761
+ if (fs7.existsSync(candidate) && fs7.statSync(candidate).isFile()) {
22762
+ return true;
22763
+ }
22764
+ } catch {
22765
+ }
22766
+ }
22767
+ return false;
22768
+ }
22769
+ __name(devServableFileExists, "devServableFileExists");
22770
+
22500
22771
  // src/vite.ts
22501
22772
  init_deployment();
22502
22773
  init_image_config();
@@ -22590,6 +22861,11 @@ var import_node_path9 = __toESM(require("path"));
22590
22861
  // src/vite.ts
22591
22862
  init_fonts();
22592
22863
  init_server_http();
22864
+
22865
+ // src/theme/vite.ts
22866
+ init_config2();
22867
+
22868
+ // src/vite.ts
22593
22869
  var ALL_TYPE_ARTIFACTS = {
22594
22870
  routes: true,
22595
22871
  api: true,
@@ -22787,11 +23063,11 @@ function isPotentialProgrammaticRouteSourceFile(normalizedFile, srcDirSlug) {
22787
23063
  }
22788
23064
  __name(isPotentialProgrammaticRouteSourceFile, "isPotentialProgrammaticRouteSourceFile");
22789
23065
  function fileContainsProgrammaticPageRoute(file) {
22790
- if (!fs7.existsSync(file)) {
23066
+ if (!fs8.existsSync(file)) {
22791
23067
  return false;
22792
23068
  }
22793
23069
  try {
22794
- return scanProgrammaticPagePaths(fs7.readFileSync(file, "utf8")).length > 0;
23070
+ return scanProgrammaticPagePaths(fs8.readFileSync(file, "utf8")).length > 0;
22795
23071
  } catch {
22796
23072
  return false;
22797
23073
  }
@@ -22799,7 +23075,7 @@ function fileContainsProgrammaticPageRoute(file) {
22799
23075
  __name(fileContainsProgrammaticPageRoute, "fileContainsProgrammaticPageRoute");
22800
23076
  function rewriteEarlySsrRelativeImports(options) {
22801
23077
  const cleanId = options.id.split("?", 1)[0];
22802
- if (!path25.isAbsolute(cleanId) || cleanId.replace(/\\/g, "/").includes("/node_modules/")) {
23078
+ if (!path26.isAbsolute(cleanId) || cleanId.replace(/\\/g, "/").includes("/node_modules/")) {
22803
23079
  return null;
22804
23080
  }
22805
23081
  const replacements = [];
@@ -22819,7 +23095,7 @@ function rewriteEarlySsrRelativeImports(options) {
22819
23095
  const suffixIndex = source.value.search(/[?#]/);
22820
23096
  const sourcePath = suffixIndex === -1 ? source.value : source.value.slice(0, suffixIndex);
22821
23097
  const suffix = suffixIndex === -1 ? "" : source.value.slice(suffixIndex);
22822
- const resolvedPath = path25.resolve(path25.dirname(cleanId), sourcePath);
23098
+ const resolvedPath = path26.resolve(path26.dirname(cleanId), sourcePath);
22823
23099
  replacements.push({
22824
23100
  start: source.start,
22825
23101
  end: source.end,
@@ -22898,7 +23174,7 @@ function farmPlugin(options = {}, initialPluginManager) {
22898
23174
  ...layerRoots.length ? {
22899
23175
  server: {
22900
23176
  fs: {
22901
- allow: [path25.resolve(options.root || process.cwd()), ...layerRoots]
23177
+ allow: [path26.resolve(options.root || process.cwd()), ...layerRoots]
22902
23178
  }
22903
23179
  }
22904
23180
  } : {}
@@ -22929,13 +23205,13 @@ function farmPlugin(options = {}, initialPluginManager) {
22929
23205
  },
22930
23206
  server
22931
23207
  );
22932
- const globalsCSSPath = path25.join(server.config.root, "src/app/globals.css");
22933
- if (!fs7.existsSync(globalsCSSPath)) {
22934
- const appDir = path25.join(server.config.root, "src/app");
22935
- if (!fs7.existsSync(appDir)) {
22936
- fs7.mkdirSync(appDir, { recursive: true });
23208
+ const globalsCSSPath = path26.join(server.config.root, "src/app/globals.css");
23209
+ if (!fs8.existsSync(globalsCSSPath)) {
23210
+ const appDir = path26.join(server.config.root, "src/app");
23211
+ if (!fs8.existsSync(appDir)) {
23212
+ fs8.mkdirSync(appDir, { recursive: true });
22937
23213
  }
22938
- fs7.writeFileSync(globalsCSSPath, defaultGlobalCSS);
23214
+ fs8.writeFileSync(globalsCSSPath, defaultGlobalCSS);
22939
23215
  }
22940
23216
  await farmApp.initialize();
22941
23217
  const farmConfig = farmApp.getConfig();
@@ -22954,10 +23230,10 @@ function farmPlugin(options = {}, initialPluginManager) {
22954
23230
  });
22955
23231
  }
22956
23232
  const sourceRoots = getFarmSourceRoots(farmConfig);
22957
- server.watcher.add(sourceRoots.map((source) => path25.join(source.root, source.srcDir)));
23233
+ server.watcher.add(sourceRoots.map((source) => path26.join(source.root, source.srcDir)));
22958
23234
  if (farmConfig.i18n.enabled) {
22959
23235
  server.watcher.add(
22960
- farmConfig.i18n.messages.includes("{locale}") ? path25.dirname(farmConfig.i18n.messages) : farmConfig.i18n.messages
23236
+ farmConfig.i18n.messages.includes("{locale}") ? path26.dirname(farmConfig.i18n.messages) : farmConfig.i18n.messages
22961
23237
  );
22962
23238
  }
22963
23239
  const workflowConfig = farmConfig.workflows;
@@ -22967,7 +23243,7 @@ function farmPlugin(options = {}, initialPluginManager) {
22967
23243
  ...farmDocsDevRuntime?.getFarmDocsRouteTypeEntries(farmConfig.docs) ?? []
22968
23244
  ], "getExtraRouteTypes");
22969
23245
  const appDirSlugs = sourceRoots.map(
22970
- (source) => path25.join(source.root, source.srcDir, "app").replace(/\\/g, "/")
23246
+ (source) => path26.join(source.root, source.srcDir, "app").replace(/\\/g, "/")
22971
23247
  );
22972
23248
  const generateTypeArtifacts = /* @__PURE__ */ __name(async (reason, selection = ALL_TYPE_ARTIFACTS, log = false) => {
22973
23249
  try {
@@ -23007,7 +23283,7 @@ function farmPlugin(options = {}, initialPluginManager) {
23007
23283
  }, "generateTypeArtifacts");
23008
23284
  await generateTypeArtifacts("startup");
23009
23285
  const srcDirSlugs = sourceRoots.map(
23010
- (source) => path25.join(source.root, source.srcDir).replace(/\\/g, "/")
23286
+ (source) => path26.join(source.root, source.srcDir).replace(/\\/g, "/")
23011
23287
  );
23012
23288
  const layerConfigFiles = new Set(
23013
23289
  farmConfig.layers.map((layer) => layer.configFile?.replace(/\\/g, "/")).filter((file) => Boolean(file))
@@ -23125,7 +23401,7 @@ function farmPlugin(options = {}, initialPluginManager) {
23125
23401
  await apiRouteManager.discoverRoutes();
23126
23402
  let discoveredWorkflows = [];
23127
23403
  const hasWorkflowDirectory = workflowConfig.enabled && workflowConfig.dirs.some(
23128
- (dir) => fs7.existsSync(path25.isAbsolute(dir) ? dir : path25.join(farmConfig.root, dir))
23404
+ (dir) => fs8.existsSync(path26.isAbsolute(dir) ? dir : path26.join(farmConfig.root, dir))
23129
23405
  );
23130
23406
  if (hasWorkflowDirectory) {
23131
23407
  const { createFarmWorkflowRequestHandler: createFarmWorkflowRequestHandler2, discoverFarmWorkflows: discoverFarmWorkflows2 } = await loadFarmWorkflowsDevRuntime();
@@ -23359,12 +23635,12 @@ window.__FARM_MANIFEST__ = ${inlineValue({
23359
23635
  }
23360
23636
  }
23361
23637
  const farmDocsFontPath = farmDocsFontAssets.get(requestPathname);
23362
- if ((requestMethod === "GET" || requestMethod === "HEAD") && farmDocsFontPath && fs7.existsSync(farmDocsFontPath)) {
23638
+ if ((requestMethod === "GET" || requestMethod === "HEAD") && farmDocsFontPath && fs8.existsSync(farmDocsFontPath)) {
23363
23639
  res.statusCode = 200;
23364
23640
  res.setHeader("Content-Type", "font/woff2");
23365
23641
  res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
23366
23642
  if (requestMethod === "HEAD") res.end();
23367
- else fs7.createReadStream(farmDocsFontPath).pipe(res);
23643
+ else fs8.createReadStream(farmDocsFontPath).pipe(res);
23368
23644
  return;
23369
23645
  }
23370
23646
  if (requestMethod === "GET" && (requestPathname === FARM_DEVTOOLS_PATH || requestPathname === `${FARM_DEVTOOLS_PATH}.json`)) {
@@ -23462,7 +23738,7 @@ window.__FARM_MANIFEST__ = ${inlineValue({
23462
23738
  return null;
23463
23739
  }
23464
23740
  return {
23465
- source: await fs7.promises.readFile(sourcePath, "utf8"),
23741
+ source: await fs8.promises.readFile(sourcePath, "utf8"),
23466
23742
  filePath: sourcePath
23467
23743
  };
23468
23744
  }, "resolveSource")
@@ -23797,9 +24073,17 @@ window.__FARM_MANIFEST__ = ${inlineValue({
23797
24073
  res.end(JSON.stringify({ error: "API route not found", pathname: pathname2 }));
23798
24074
  return;
23799
24075
  }
23800
- if (req.url?.startsWith("/@") || req.url?.startsWith("/node_modules") || requestPathname.includes(".") && !requestPathname.endsWith(".html")) {
24076
+ if (req.url?.startsWith("/@") || req.url?.startsWith("/node_modules")) {
23801
24077
  return next();
23802
24078
  }
24079
+ if (requestPathname.includes(".") && !requestPathname.endsWith(".html")) {
24080
+ const matchesAppRoute = Boolean(
24081
+ farmApp?.getRouteManager()?.matchRoute(requestPathname)?.route
24082
+ );
24083
+ if (!matchesAppRoute || devServableFileExists(requestPathname, [server.config.publicDir, server.config.root])) {
24084
+ return next();
24085
+ }
24086
+ }
23803
24087
  if (req.url?.startsWith("/__farm/page-data")) {
23804
24088
  const urlObj = new URL(req.url, `http://${req.headers.host || "localhost:3000"}`);
23805
24089
  const targetPath = urlObj.searchParams.get("path") || "/";
@@ -24505,8 +24789,8 @@ if (import.meta.hot) {
24505
24789
  }
24506
24790
  logger.info(`Found ${ssgPages.length} SSG pages, ${ssrRoutes.length} SSR routes`);
24507
24791
  logger.info("Pre-rendering SSG pages...");
24508
- const outDir = path25.join(server?.config.root || process.cwd(), options.outDir || "dist");
24509
- const clientDir = path25.join(outDir, "client");
24792
+ const outDir = path26.join(server?.config.root || process.cwd(), options.outDir || "dist");
24793
+ const clientDir = path26.join(outDir, "client");
24510
24794
  for (const page2 of ssgPages) {
24511
24795
  try {
24512
24796
  const staticRequest = new Request(new URL(page2.urlPath, "http://farm.static"));
@@ -24558,9 +24842,9 @@ if (import.meta.hot) {
24558
24842
  <script type="module" src="/assets/client.js"></script>
24559
24843
  </body>
24560
24844
  </html>`;
24561
- const outputPath = page2.urlPath === "/" ? path25.join(clientDir, "index.html") : path25.join(clientDir, page2.urlPath + ".html");
24562
- fs7.mkdirSync(path25.dirname(outputPath), { recursive: true });
24563
- fs7.writeFileSync(outputPath, fullHtml);
24845
+ const outputPath = page2.urlPath === "/" ? path26.join(clientDir, "index.html") : path26.join(clientDir, page2.urlPath + ".html");
24846
+ fs8.mkdirSync(path26.dirname(outputPath), { recursive: true });
24847
+ fs8.writeFileSync(outputPath, fullHtml);
24564
24848
  const revalidateInfo = page2.revalidate ? ` (revalidate: ${page2.revalidate}s)` : "";
24565
24849
  logger.success(` \u2713 ${page2.urlPath}${revalidateInfo}`);
24566
24850
  });
@@ -24568,8 +24852,8 @@ if (import.meta.hot) {
24568
24852
  logger.error(` \u2717 ${page2.urlPath}: ${error}`);
24569
24853
  }
24570
24854
  }
24571
- const manifestPath = path25.join(outDir, "__ssg_manifest.json");
24572
- fs7.writeFileSync(
24855
+ const manifestPath = path26.join(outDir, "__ssg_manifest.json");
24856
+ fs8.writeFileSync(
24573
24857
  manifestPath,
24574
24858
  JSON.stringify(
24575
24859
  ssgPages.map((p) => ({
@@ -24604,9 +24888,9 @@ if (import.meta.hot) {
24604
24888
  }
24605
24889
  const currentFarmConfig = farmApp?.getConfig();
24606
24890
  const normalizedFile = file.replace(/\\/g, "/");
24607
- const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) => path25.join(source.root, source.srcDir).replace(/\\/g, "/")).find((sourceRoot) => normalizedFile.startsWith(`${sourceRoot}/`)) || null : null;
24891
+ const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) => path26.join(source.root, source.srcDir).replace(/\\/g, "/")).find((sourceRoot) => normalizedFile.startsWith(`${sourceRoot}/`)) || null : null;
24608
24892
  if (currentSrcRoot && normalizedFile.startsWith(`${currentSrcRoot}/`) && isProgrammaticRoutesFileName(normalizedFile)) {
24609
- logUpdate("PAGE", `updated ${path25.basename(file)}`);
24893
+ logUpdate("PAGE", `updated ${path26.basename(file)}`);
24610
24894
  for (const mod of modules) {
24611
24895
  server2.moduleGraph.invalidateModule(mod);
24612
24896
  }
@@ -25792,6 +26076,19 @@ async function tryHydrateImportedPage(
25792
26076
  const PageComponent = pageModule?.default;
25793
26077
  if (!PageComponent) return false;
25794
26078
 
26079
+ if (
26080
+ typeof PageComponent === 'function' &&
26081
+ PageComponent.constructor &&
26082
+ PageComponent.constructor.name === 'AsyncFunction'
26083
+ ) {
26084
+ console.warn(
26085
+ '[Farm.js] Skipping hydration for ' + modulePath +
26086
+ ': async server components cannot run in the browser. ' +
26087
+ 'Server-rendered HTML is preserved; move interactive UI into a "use client" child of a synchronous page.'
26088
+ );
26089
+ return false;
26090
+ }
26091
+
25795
26092
  currentPageComponent = PageComponent;
25796
26093
  currentPageProps = await buildRouteComponentProps(
25797
26094
  pageModule,
@@ -25958,14 +26255,22 @@ async function renderPage(pageData) {
25958
26255
  if (!doc.documentElement || !doc.body) return false;
25959
26256
 
25960
26257
  resetReactRoots();
26258
+ const activeFarmTheme =
26259
+ window.__FARM_THEME__?.snapshot?.resolvedTheme ||
26260
+ document.documentElement.getAttribute('data-theme');
25961
26261
  Array.from(document.documentElement.attributes).forEach(function(attr) {
26262
+ if (attr.name === 'data-theme') return;
25962
26263
  if (!doc.documentElement.hasAttribute(attr.name)) {
25963
26264
  document.documentElement.removeAttribute(attr.name);
25964
26265
  }
25965
26266
  });
25966
26267
  Array.from(doc.documentElement.attributes).forEach(function(attr) {
26268
+ if (attr.name === 'data-theme') return;
25967
26269
  document.documentElement.setAttribute(attr.name, attr.value);
25968
26270
  });
26271
+ if (activeFarmTheme) {
26272
+ document.documentElement.setAttribute('data-theme', activeFarmTheme);
26273
+ }
25969
26274
 
25970
26275
  document.head.innerHTML = doc.head ? doc.head.innerHTML : '';
25971
26276
  document.body.innerHTML = doc.body.innerHTML;
@@ -25974,6 +26279,7 @@ async function renderPage(pageData) {
25974
26279
 
25975
26280
  setTimeout(function() {
25976
26281
  Array.from(document.querySelectorAll('script')).forEach(function(script) {
26282
+ if (script.id === 'farm-theme-script') return;
25977
26283
  const freshScript = document.createElement('script');
25978
26284
  Array.from(script.attributes).forEach(function(attr) {
25979
26285
  freshScript.setAttribute(attr.name, attr.value);