@farm.js/core 0.1.48 → 0.1.49

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 (135) hide show
  1. package/dist/{agent-mcp-DAjB8Eyu.d.ts → agent-mcp-Bb8hnnqd.d.ts} +1 -1
  2. package/dist/{agent-mcp-CXN3g0eX.d.mts → agent-mcp-ir3v4fHf.d.mts} +1 -1
  3. package/dist/agent-runtime.d.mts +1 -1
  4. package/dist/agent-runtime.d.ts +1 -1
  5. package/dist/api/route-manager.d.mts +3 -3
  6. package/dist/api/route-manager.d.ts +3 -3
  7. package/dist/api/runtime.d.mts +2 -2
  8. package/dist/api/runtime.d.ts +2 -2
  9. package/dist/api.d.mts +3 -3
  10. package/dist/api.d.ts +3 -3
  11. package/dist/{app-DytgRPjJ.d.mts → app-DLzz02du.d.mts} +4 -4
  12. package/dist/{app-manifest-DPgW5ke5.d.mts → app-manifest-Crn8Qd3U.d.mts} +1 -1
  13. package/dist/{app-manifest-BUu7YGAx.d.ts → app-manifest-DNeTKMRL.d.ts} +1 -1
  14. package/dist/app-markdown.d.mts +2 -2
  15. package/dist/app-markdown.d.ts +2 -2
  16. package/dist/{app-VK9sHDn5.d.ts → app-y649szYm.d.ts} +4 -4
  17. package/dist/{chunk-Q2ZKQ6GD.cjs → chunk-4HM5B5RR.cjs} +62 -62
  18. package/dist/{chunk-MZZA6ZQV.mjs → chunk-7PZVXMWG.mjs} +4 -4
  19. package/dist/{chunk-HRLYO2XJ.mjs → chunk-ACI52TCN.mjs} +1 -1
  20. package/dist/{chunk-VDLF2DJA.cjs → chunk-AIHD6VME.cjs} +276 -91
  21. package/dist/{chunk-YSPMY4B7.cjs → chunk-C5S457CK.cjs} +170 -108
  22. package/dist/{chunk-NRFUVDTH.mjs → chunk-DGVVVYKD.mjs} +1 -1
  23. package/dist/{chunk-WUEDTW6E.cjs → chunk-FR4HJDI6.cjs} +21 -0
  24. package/dist/{chunk-HUL4LTC6.cjs → chunk-HTLCLOXQ.cjs} +63 -20
  25. package/dist/{chunk-N7SPZJLY.mjs → chunk-IVHPRF4W.mjs} +5 -5
  26. package/dist/{chunk-6M3HXUBQ.mjs → chunk-J27BZO67.mjs} +21 -0
  27. package/dist/{chunk-JLS6ZLFM.cjs → chunk-J5VCA45K.cjs} +1 -1
  28. package/dist/{chunk-ZGS3ZDF7.cjs → chunk-NPPT4RWF.cjs} +2 -2
  29. package/dist/{chunk-TFA6BUAE.cjs → chunk-OY5XDG24.cjs} +4 -4
  30. package/dist/{chunk-N6SIQJEJ.mjs → chunk-RYDDUCNJ.mjs} +54 -11
  31. package/dist/{chunk-C2R5RVLA.cjs → chunk-VCKGOXFI.cjs} +73 -1
  32. package/dist/{chunk-TQWGOQ7O.mjs → chunk-Z3BXMMFF.mjs} +80 -18
  33. package/dist/{chunk-NE33FRQ5.mjs → chunk-Z4LTSH7D.mjs} +207 -22
  34. package/dist/{chunk-NIPKC4DA.mjs → chunk-ZIBIE7AH.mjs} +72 -0
  35. package/dist/{client-plugins-BlEzV5FO.d.mts → client-plugins-BNBeyLMi.d.mts} +4 -2
  36. package/dist/{client-plugins-DqjCsKMN.d.ts → client-plugins-DFDQUI9Q.d.ts} +4 -2
  37. package/dist/client-plugins.d.mts +1 -1
  38. package/dist/client-plugins.d.ts +1 -1
  39. package/dist/client.d.mts +5 -5
  40. package/dist/client.d.ts +5 -5
  41. package/dist/config.d.mts +1 -1
  42. package/dist/config.d.ts +1 -1
  43. package/dist/desktop.d.mts +2 -2
  44. package/dist/desktop.d.ts +2 -2
  45. package/dist/{dev-guard-4NQ3LFO5.cjs → dev-guard-PLHL6OTJ.cjs} +3 -2
  46. package/dist/{dev-guard-MPZUJFIV.mjs → dev-guard-YO6KPIOQ.mjs} +2 -1
  47. package/dist/docs.d.mts +2 -2
  48. package/dist/docs.d.ts +2 -2
  49. package/dist/{index-CMigAr9f.d.mts → index-CeJ9_s9p.d.mts} +1 -1
  50. package/dist/{index-n3hjOvVC.d.ts → index-DBdiTkNc.d.ts} +1 -1
  51. package/dist/index.cjs +7 -7
  52. package/dist/index.d.mts +15 -15
  53. package/dist/index.d.ts +15 -15
  54. package/dist/index.mjs +6 -6
  55. package/dist/integrations.d.mts +1 -1
  56. package/dist/integrations.d.ts +1 -1
  57. package/dist/internal/app-markdown-runtime.d.mts +2 -2
  58. package/dist/internal/app-markdown-runtime.d.ts +2 -2
  59. package/dist/internal/build-runtime.cjs +9 -8
  60. package/dist/internal/build-runtime.d.mts +3 -3
  61. package/dist/internal/build-runtime.d.ts +3 -3
  62. package/dist/internal/build-runtime.mjs +8 -7
  63. package/dist/internal/client-error-overlay.cjs +4 -4
  64. package/dist/internal/client-error-overlay.mjs +1 -1
  65. package/dist/internal/compression-runtime.d.mts +1 -1
  66. package/dist/internal/compression-runtime.d.ts +1 -1
  67. package/dist/internal/config-runtime.d.mts +2 -2
  68. package/dist/internal/config-runtime.d.ts +2 -2
  69. package/dist/internal/desktop-guard.cjs +2 -2
  70. package/dist/internal/desktop-guard.d.mts +7 -0
  71. package/dist/internal/desktop-guard.d.ts +7 -0
  72. package/dist/internal/desktop-guard.mjs +1 -1
  73. package/dist/internal/infra-analytics-runtime.cjs +5 -5
  74. package/dist/internal/infra-analytics-runtime.mjs +3 -3
  75. package/dist/internal/islands-runtime.cjs +4 -1
  76. package/dist/internal/islands-runtime.d.mts +9 -12
  77. package/dist/internal/islands-runtime.d.ts +9 -12
  78. package/dist/internal/islands-runtime.mjs +5 -2
  79. package/dist/internal/product-telemetry-runtime.cjs +2 -2
  80. package/dist/internal/product-telemetry-runtime.mjs +1 -1
  81. package/dist/internal/production-runtime.cjs +4 -4
  82. package/dist/internal/production-runtime.d.mts +10 -10
  83. package/dist/internal/production-runtime.d.ts +10 -10
  84. package/dist/internal/production-runtime.mjs +3 -3
  85. package/dist/markdown.d.mts +1 -1
  86. package/dist/markdown.d.ts +1 -1
  87. package/dist/middleware.d.mts +3 -3
  88. package/dist/middleware.d.ts +3 -3
  89. package/dist/navigation.d.mts +4 -4
  90. package/dist/navigation.d.ts +4 -4
  91. package/dist/plugin.cjs +6 -6
  92. package/dist/plugin.d.mts +3 -3
  93. package/dist/plugin.d.ts +3 -3
  94. package/dist/plugin.mjs +5 -5
  95. package/dist/{production-runtime-YVDGYWBG.d.ts → production-runtime-B3qFFtKF.d.ts} +1 -1
  96. package/dist/{production-runtime-bWZJMcQb.d.mts → production-runtime-DcD-GRAv.d.mts} +1 -1
  97. package/dist/{programmatic-routes-client-BFKOTEXN.d.mts → programmatic-routes-client-DzbYGiZQ.d.mts} +2 -2
  98. package/dist/{programmatic-routes-client-DviwGeAv.d.ts → programmatic-routes-client-fD9f4XqU.d.ts} +2 -2
  99. package/dist/{render-plan-DqWXo3-B.d.ts → render-plan-B6cfssrr.d.ts} +1 -1
  100. package/dist/{render-plan-CS8l0zaK.d.mts → render-plan-DqJ51ufr.d.mts} +1 -1
  101. package/dist/renderer-client.d.mts +3 -3
  102. package/dist/renderer-client.d.ts +3 -3
  103. package/dist/{request-D4XqmnJF.d.mts → request-UuAxHn8h.d.mts} +1 -1
  104. package/dist/{request-CBrHpaCC.d.ts → request-jhvUMXRx.d.ts} +1 -1
  105. package/dist/request.d.mts +2 -2
  106. package/dist/request.d.ts +2 -2
  107. package/dist/{route-rendering-3pRPtyO2.d.mts → route-rendering-Cou00t1X.d.mts} +1 -1
  108. package/dist/{route-rendering-Bltnu8a3.d.ts → route-rendering-Sn50cYZf.d.ts} +1 -1
  109. package/dist/{router-BFSmKGtI.d.mts → router-0X9DCTcm.d.mts} +1 -1
  110. package/dist/{router-DDT7bkg7.d.ts → router-xwLvi48p.d.ts} +1 -1
  111. package/dist/routes.d.mts +1 -1
  112. package/dist/routes.d.ts +1 -1
  113. package/dist/{rsc-pipeline-ULFIB3UT.mjs → rsc-pipeline-F6ZPH5MU.mjs} +2 -1
  114. package/dist/{rsc-pipeline-4KOITP64.cjs → rsc-pipeline-VKHMABDJ.cjs} +3 -2
  115. package/dist/{runtime-Cpylaypt.d.mts → runtime-CMrsyChI.d.mts} +1 -1
  116. package/dist/{runtime-C6yG64je.d.ts → runtime-tkSXZiqO.d.ts} +1 -1
  117. package/dist/server-plugins.d.mts +2 -2
  118. package/dist/server-plugins.d.ts +2 -2
  119. package/dist/server.cjs +18 -18
  120. package/dist/server.d.mts +9 -9
  121. package/dist/server.d.ts +9 -9
  122. package/dist/server.mjs +7 -7
  123. package/dist/{spa-router-CKuS81mi.d.ts → spa-router-B06APnGK.d.ts} +2 -2
  124. package/dist/{spa-router-CkTPnA4L.d.mts → spa-router-B48EjsS1.d.mts} +2 -2
  125. package/dist/testing.d.mts +1 -1
  126. package/dist/testing.d.ts +1 -1
  127. package/dist/{utils-C0ORLYXc.d.ts → utils-C5fyK2tE.d.ts} +1 -1
  128. package/dist/{utils-IA9wVkef.d.mts → utils-hyAwmcN6.d.mts} +1 -1
  129. package/dist/version.cjs +2 -2
  130. package/dist/version.mjs +1 -1
  131. package/dist/vite.cjs +6 -6
  132. package/dist/vite.d.mts +4 -4
  133. package/dist/vite.d.ts +4 -4
  134. package/dist/vite.mjs +5 -5
  135. package/package.json +2 -2
@@ -23,7 +23,7 @@ import {
23
23
  } from "./chunk-LM2YOGDK.mjs";
24
24
  import {
25
25
  FARM_VERSION
26
- } from "./chunk-HRLYO2XJ.mjs";
26
+ } from "./chunk-ACI52TCN.mjs";
27
27
  import {
28
28
  applyFarmBasePath
29
29
  } from "./chunk-SF3JB56B.mjs";
@@ -10,6 +10,9 @@ var _chunkKZT2VHRQcjs = require('./chunk-KZT2VHRQ.cjs');
10
10
  var _chunk4S7M63WXcjs = require('./chunk-4S7M63WX.cjs');
11
11
 
12
12
 
13
+ var _chunkZBS3GOQZcjs = require('./chunk-ZBS3GOQZ.cjs');
14
+
15
+
13
16
  var _chunkIXSMFKZ2cjs = require('./chunk-IXSMFKZ2.cjs');
14
17
 
15
18
  // src/rsc-pipeline.ts
@@ -91,6 +94,7 @@ async function createFarmRscViteConfig(userConfig, options) {
91
94
  experimental: { ...userConfig.experimental, serverComponents: true },
92
95
  port: _nullishCoalesce(options.port, () => ( _optionalChain([userConfig, 'access', _3 => _3.server, 'optionalAccess', _4 => _4.port]))),
93
96
  plugins: [
97
+ ...options.command === "serve" && _chunkZBS3GOQZcjs.resolveFarmPlatform.call(void 0, ) === "desktop" ? [farmRscDesktopDevGuardPlugin(userConfig.basePath)] : [],
94
98
  ...tailwind ? [tailwind] : [],
95
99
  ...vitePlugins,
96
100
  viteRsc.default({ serverHandler: false, entries: FARM_RSC_ENTRIES }),
@@ -116,6 +120,23 @@ async function createFarmRscViteConfig(userConfig, options) {
116
120
  mode: options.command === "build" ? "production" : "development"
117
121
  };
118
122
  }
123
+ function farmRscDesktopDevGuardPlugin(basePath) {
124
+ return {
125
+ name: "farm:desktop-dev-guard",
126
+ enforce: "pre",
127
+ configureServer: {
128
+ order: "pre",
129
+ async handler(server) {
130
+ const { createFarmDesktopDevGuard } = await import("./dev-guard-PLHL6OTJ.cjs");
131
+ server.middlewares.use(
132
+ createFarmDesktopDevGuard(server, {
133
+ basePath: typeof basePath === "string" ? basePath : ""
134
+ })
135
+ );
136
+ }
137
+ }
138
+ };
139
+ }
119
140
  async function createFarmRscDevServer(userConfig, options) {
120
141
  const { createServer } = await import("vite");
121
142
  return createServer(await createFarmRscViteConfig(userConfig, { ...options, command: "serve" }));
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
- var _chunkZGS3ZDF7cjs = require('./chunk-ZGS3ZDF7.cjs');
3
+ var _chunkNPPT4RWFcjs = require('./chunk-NPPT4RWF.cjs');
4
4
 
5
5
 
6
6
  var _chunkWJFFPXCVcjs = require('./chunk-WJFFPXCV.cjs');
@@ -45,13 +45,12 @@ function resolveFarmInfraAnalytics(env = processEnv()) {
45
45
  if (!key || env[FARM_PRERENDER_ENV] === "1") return { off: null };
46
46
  const ingestionKey = INGESTION_KEY.test(key);
47
47
  const projectId = _optionalChain([env, 'access', _6 => _6.FARMJS_PROJECT_ID, 'optionalAccess', _7 => _7.trim, 'call', _8 => _8()]) || void 0;
48
- if (!ingestionKey && !projectId) return { off: null };
49
48
  if (!ingestionKey && !API_KEY.test(key)) {
50
49
  return {
51
50
  off: "FARMJS_API_KEY isn't a Farm Infra API key (farmjs_\u2026) or write-only key (fti_\u2026)"
52
51
  };
53
52
  }
54
- if (!ingestionKey && !PROJECT.test(projectId)) {
53
+ if (!ingestionKey && projectId && !PROJECT.test(projectId)) {
55
54
  return { off: "FARMJS_PROJECT_ID isn't a Farm Infra project ID (proj_\u2026)" };
56
55
  }
57
56
  if (env.FARMJS_ENVIRONMENT && !ENVIRONMENTS.includes(env.FARMJS_ENVIRONMENT)) {
@@ -71,7 +70,7 @@ function resolveFarmInfraAnalytics(env = processEnv()) {
71
70
  options: {
72
71
  endpoint: endpoint.href,
73
72
  key,
74
- ...ingestionKey ? {} : { projectId, environment: defaultFarmInfraEnvironment(env) }
73
+ ...ingestionKey ? {} : { ...projectId ? { projectId } : {}, environment: defaultFarmInfraEnvironment(env) }
75
74
  }
76
75
  };
77
76
  }
@@ -95,13 +94,45 @@ function retryAt(value, now) {
95
94
  const date = Date.parse(value);
96
95
  return Number.isFinite(date) ? Math.max(now, Math.min(date, now + 864e5)) : now;
97
96
  }
97
+ var REFUSALS = {
98
+ project: "project",
99
+ api_key_permission: "permission",
100
+ api_key_environment: "environment"
101
+ };
102
+ async function refusal(response) {
103
+ const reader = _optionalChain([response, 'access', _12 => _12.body, 'optionalAccess', _13 => _13.getReader, 'call', _14 => _14()]);
104
+ if (!reader) return void 0;
105
+ let text = "";
106
+ const decoder = new TextDecoder();
107
+ const deadline = Date.now() + 500;
108
+ try {
109
+ while (text.length < 1024 && Date.now() < deadline) {
110
+ let timer;
111
+ const chunk = await Promise.race([
112
+ reader.read(),
113
+ new Promise((resolve) => {
114
+ timer = setTimeout(() => resolve({ done: true }), deadline - Date.now());
115
+ })
116
+ ]).finally(() => clearTimeout(timer));
117
+ if (chunk.done) break;
118
+ text += decoder.decode(chunk.value, { stream: true });
119
+ }
120
+ const code = JSON.parse(text).error;
121
+ return typeof code === "string" && Object.prototype.hasOwnProperty.call(REFUSALS, code) ? REFUSALS[code] : void 0;
122
+ } catch (e2) {
123
+ return void 0;
124
+ } finally {
125
+ void reader.cancel().catch(() => {
126
+ });
127
+ }
128
+ }
98
129
  function createFarmInfraAnalyticsExporter(options, send = (input, init) => fetch(input, init)) {
99
130
  const requestHeaders = {
100
131
  "content-type": "application/json",
101
132
  authorization: `Bearer ${options.key}`
102
133
  };
103
134
  if (!INGESTION_KEY.test(options.key)) {
104
- requestHeaders["x-farm-project"] = options.projectId;
135
+ if (options.projectId) requestHeaders["x-farm-project"] = options.projectId;
105
136
  requestHeaders["x-farm-environment"] = _nullishCoalesce(options.environment, () => ( defaultFarmInfraEnvironment()));
106
137
  }
107
138
  const queue = [];
@@ -113,9 +144,9 @@ function createFarmInfraAnalyticsExporter(options, send = (input, init) => fetch
113
144
  let inFlight = /* @__PURE__ */ new Set();
114
145
  const diagnostic = (event) => {
115
146
  try {
116
- void Promise.resolve(_optionalChain([options, 'access', _12 => _12.onDiagnostic, 'optionalCall', _13 => _13(event)])).catch(() => {
147
+ void Promise.resolve(_optionalChain([options, 'access', _15 => _15.onDiagnostic, 'optionalCall', _16 => _16(event)])).catch(() => {
117
148
  });
118
- } catch (e2) {
149
+ } catch (e3) {
119
150
  }
120
151
  };
121
152
  const expired = (item, now) => !inFlight.has(item) && (now - item.enqueuedAt >= MAX_AGE || item.attempts >= MAX_ATTEMPTS);
@@ -161,7 +192,7 @@ function createFarmInfraAnalyticsExporter(options, send = (input, init) => fetch
161
192
  for (const item of batch) item.attempts++;
162
193
  inFlight = new Set(batch);
163
194
  active = new AbortController();
164
- const timeout = setTimeout(() => _optionalChain([active, 'optionalAccess', _14 => _14.abort, 'call', _15 => _15()]), Math.min(TIMEOUT, deadline - Date.now()));
195
+ const timeout = setTimeout(() => _optionalChain([active, 'optionalAccess', _17 => _17.abort, 'call', _18 => _18()]), Math.min(TIMEOUT, deadline - Date.now()));
165
196
  let status;
166
197
  try {
167
198
  const response = await send(options.endpoint, {
@@ -172,7 +203,8 @@ function createFarmInfraAnalyticsExporter(options, send = (input, init) => fetch
172
203
  body
173
204
  });
174
205
  status = response.status;
175
- void _optionalChain([response, 'access', _16 => _16.body, 'optionalAccess', _17 => _17.cancel, 'call', _18 => _18(), 'access', _19 => _19.catch, 'call', _20 => _20(() => {
206
+ const reason = status === 400 || status === 403 ? await refusal(response) : void 0;
207
+ void _optionalChain([response, 'access', _19 => _19.body, 'optionalAccess', _20 => _20.cancel, 'call', _21 => _21(), 'access', _22 => _22.catch, 'call', _23 => _23(() => {
176
208
  })]);
177
209
  if (response.ok) {
178
210
  remove(batch);
@@ -181,7 +213,7 @@ function createFarmInfraAnalyticsExporter(options, send = (input, init) => fetch
181
213
  if ([400, 401, 403, 404, 413, 415].includes(status) || status >= 300 && status < 400) {
182
214
  stopped = true;
183
215
  queue.length = 0;
184
- diagnostic({ code: "disabled", status });
216
+ diagnostic({ code: "disabled", status, ...reason ? { reason } : {} });
185
217
  break;
186
218
  }
187
219
  if (status !== 408 && status !== 429 && status < 500) {
@@ -190,7 +222,7 @@ function createFarmInfraAnalyticsExporter(options, send = (input, init) => fetch
190
222
  continue;
191
223
  }
192
224
  notBefore = Math.max(notBefore, retryAt(response.headers.get("retry-after"), Date.now()));
193
- } catch (e3) {
225
+ } catch (e4) {
194
226
  } finally {
195
227
  clearTimeout(timeout);
196
228
  active = void 0;
@@ -220,7 +252,7 @@ function createFarmInfraAnalyticsExporter(options, send = (input, init) => fetch
220
252
  closing = true;
221
253
  await flush();
222
254
  stopped = true;
223
- _optionalChain([active, 'optionalAccess', _21 => _21.abort, 'call', _22 => _22()]);
255
+ _optionalChain([active, 'optionalAccess', _24 => _24.abort, 'call', _25 => _25()]);
224
256
  if (queue.length) diagnostic({ code: "dropped", count: queue.length });
225
257
  queue.length = 0;
226
258
  }
@@ -241,7 +273,7 @@ function requestEvent(metadata, method, status, durationMs) {
241
273
  id: uuid(),
242
274
  requestId: metadata.id,
243
275
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
244
- route: routeTemplate(_chunkZGS3ZDF7cjs.getFarmRouteLabel.call(void 0, metadata.route)),
276
+ route: routeTemplate(_chunkNPPT4RWFcjs.getFarmRouteLabel.call(void 0, metadata.route)),
245
277
  agent: metadata.agent,
246
278
  kind: "request",
247
279
  method,
@@ -254,7 +286,7 @@ function toolEvent(metadata, event) {
254
286
  id: uuid(),
255
287
  requestId: metadata.id,
256
288
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
257
- route: routeTemplate(_chunkZGS3ZDF7cjs.getFarmRouteLabel.call(void 0, metadata.route)),
289
+ route: routeTemplate(_chunkNPPT4RWFcjs.getFarmRouteLabel.call(void 0, metadata.route)),
258
290
  agent: metadata.agent,
259
291
  kind: "mcp.tool",
260
292
  tool: event.tool,
@@ -270,7 +302,7 @@ function farmInfraAnalyticsPlugin(options, send) {
270
302
  setup(context) {
271
303
  const state = { exporter: createFarmInfraAnalyticsExporter(options, send) };
272
304
  context.lifecycle.onShutdown(async () => {
273
- _optionalChain([state, 'access', _23 => _23.unsubscribe, 'optionalCall', _24 => _24()]);
305
+ _optionalChain([state, 'access', _26 => _26.unsubscribe, 'optionalCall', _27 => _27()]);
274
306
  await state.exporter.close();
275
307
  });
276
308
  return state;
@@ -366,14 +398,25 @@ function linkedOptions(env, warn) {
366
398
  return {
367
399
  ...resolved.options,
368
400
  onDiagnostic(event) {
369
- if (event.code === "disabled") {
370
- warn(
371
- `[Farm] Farm Infra analytics stopped: Farm Infra answered ${event.status}. Check FARMJS_API_KEY and FARMJS_PROJECT_ID, then restart the server.`
372
- );
373
- }
401
+ if (event.code !== "disabled") return;
402
+ if (event.reason === "environment") return;
403
+ warn(`[Farm] Farm Infra analytics stopped: ${stopReason(event)}`);
374
404
  }
375
405
  };
376
406
  }
407
+ var KEYS_PAGE = "the API keys page (https://app.farmjs.dev/dashboard/settings)";
408
+ function stopReason(event) {
409
+ if (event.reason === "project") {
410
+ return "FARMJS_API_KEY reaches more than one project. Set FARMJS_PROJECT_ID or use a key scoped to one project, then restart the server.";
411
+ }
412
+ if (event.reason === "permission") {
413
+ return `this key can't send analytics. Create a Site analytics key on ${KEYS_PAGE}, set it as FARMJS_API_KEY, then restart the server.`;
414
+ }
415
+ if (event.status === 401) {
416
+ return `Farm Infra answered 401: FARMJS_API_KEY was revoked or has expired. Create a new Site analytics key on ${KEYS_PAGE}, then restart the server.`;
417
+ }
418
+ return `Farm Infra answered ${event.status}. Check FARMJS_API_KEY and FARMJS_PROJECT_ID, then restart the server.`;
419
+ }
377
420
  function createFarmInfraAnalyticsPlugin(env = processEnv(), warn = console.warn) {
378
421
  const options = linkedOptions(env, warn);
379
422
  return options ? farmInfraAnalyticsPlugin(options) : null;
@@ -34,7 +34,7 @@ import {
34
34
  resolveFarmIsolatedClientHydrationMode,
35
35
  resolveModuleSourcePath,
36
36
  stripUseClientDirective
37
- } from "./chunk-TQWGOQ7O.mjs";
37
+ } from "./chunk-Z3BXMMFF.mjs";
38
38
  import {
39
39
  loadTailwindVitePlugin
40
40
  } from "./chunk-XLLVWLWO.mjs";
@@ -55,7 +55,7 @@ import {
55
55
  parseFarmLayoutChainHeader,
56
56
  renderFarmLocaleAlternateLinks,
57
57
  stripRouteGroups
58
- } from "./chunk-NIPKC4DA.mjs";
58
+ } from "./chunk-ZIBIE7AH.mjs";
59
59
  import {
60
60
  FARM_API_CATALOG_PATH,
61
61
  createFarmAiCatalogResponse,
@@ -70,7 +70,7 @@ import {
70
70
  resolveFarmMCPRouteLabel,
71
71
  resolveFarmMarkdownRouteLabel,
72
72
  setFarmRouteLabel
73
- } from "./chunk-NRFUVDTH.mjs";
73
+ } from "./chunk-DGVVVYKD.mjs";
74
74
  import {
75
75
  FARM_DEFAULT_MCP_PATH
76
76
  } from "./chunk-KRRZJ77U.mjs";
@@ -233,7 +233,7 @@ import {
233
233
  } from "./chunk-LM2YOGDK.mjs";
234
234
  import {
235
235
  FARM_VERSION
236
- } from "./chunk-HRLYO2XJ.mjs";
236
+ } from "./chunk-ACI52TCN.mjs";
237
237
  import {
238
238
  DEFAULT_FARM_API_BASE_PATH
239
239
  } from "./chunk-BLD5GVCG.mjs";
@@ -1441,7 +1441,7 @@ function farmPlugin(options = {}, initialPluginManager) {
1441
1441
  },
1442
1442
  async configureServer(viteServer) {
1443
1443
  if (resolveFarmPlatform() === "desktop") {
1444
- const { createFarmDesktopDevGuard } = await import("./dev-guard-MPZUJFIV.mjs");
1444
+ const { createFarmDesktopDevGuard } = await import("./dev-guard-YO6KPIOQ.mjs");
1445
1445
  viteServer.middlewares.use(
1446
1446
  createFarmDesktopDevGuard(viteServer, { basePath: options.basePath || "" })
1447
1447
  );
@@ -8,6 +8,9 @@ import {
8
8
  import {
9
9
  loadFarmReactPlugin
10
10
  } from "./chunk-XLYXG73A.mjs";
11
+ import {
12
+ resolveFarmPlatform
13
+ } from "./chunk-LL7TDMOM.mjs";
11
14
  import {
12
15
  loadTailwindVitePlugin
13
16
  } from "./chunk-XLLVWLWO.mjs";
@@ -91,6 +94,7 @@ async function createFarmRscViteConfig(userConfig, options) {
91
94
  experimental: { ...userConfig.experimental, serverComponents: true },
92
95
  port: options.port ?? userConfig.server?.port,
93
96
  plugins: [
97
+ ...options.command === "serve" && resolveFarmPlatform() === "desktop" ? [farmRscDesktopDevGuardPlugin(userConfig.basePath)] : [],
94
98
  ...tailwind ? [tailwind] : [],
95
99
  ...vitePlugins,
96
100
  viteRsc.default({ serverHandler: false, entries: FARM_RSC_ENTRIES }),
@@ -116,6 +120,23 @@ async function createFarmRscViteConfig(userConfig, options) {
116
120
  mode: options.command === "build" ? "production" : "development"
117
121
  };
118
122
  }
123
+ function farmRscDesktopDevGuardPlugin(basePath) {
124
+ return {
125
+ name: "farm:desktop-dev-guard",
126
+ enforce: "pre",
127
+ configureServer: {
128
+ order: "pre",
129
+ async handler(server) {
130
+ const { createFarmDesktopDevGuard } = await import("./dev-guard-YO6KPIOQ.mjs");
131
+ server.middlewares.use(
132
+ createFarmDesktopDevGuard(server, {
133
+ basePath: typeof basePath === "string" ? basePath : ""
134
+ })
135
+ );
136
+ }
137
+ }
138
+ };
139
+ }
119
140
  async function createFarmRscDevServer(userConfig, options) {
120
141
  const { createServer } = await import("vite");
121
142
  return createServer(await createFarmRscViteConfig(userConfig, { ...options, command: "serve" }));
@@ -1,5 +1,5 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});// package.json
2
- var version = "0.1.48";
2
+ var version = "0.1.49";
3
3
 
4
4
  // src/version.ts
5
5
  var FARM_VERSION = version;
@@ -23,7 +23,7 @@ var _chunk5566GNEGcjs = require('./chunk-5566GNEG.cjs');
23
23
  var _chunkB5BBTPJQcjs = require('./chunk-B5BBTPJQ.cjs');
24
24
 
25
25
 
26
- var _chunkJLS6ZLFMcjs = require('./chunk-JLS6ZLFM.cjs');
26
+ var _chunkJ5VCA45Kcjs = require('./chunk-J5VCA45K.cjs');
27
27
 
28
28
 
29
29
  var _chunkD22BUQKWcjs = require('./chunk-D22BUQKW.cjs');
@@ -282,7 +282,7 @@ function createFarmAppManifest(input) {
282
282
  return {
283
283
  schemaVersion: 1,
284
284
  app: app ? {
285
- ...app.version ? { farm: _chunkJLS6ZLFMcjs.FARM_VERSION } : {},
285
+ ...app.version ? { farm: _chunkJ5VCA45Kcjs.FARM_VERSION } : {},
286
286
  ...app.renderer ? { renderer: input.renderer } : {},
287
287
  basePath: input.basePath,
288
288
  ...app.build ? { build: input.build } : {}
@@ -56,8 +56,8 @@ function createFarmDesktopGuard(options) {
56
56
  if (options.secret === options.handshakeToken) {
57
57
  throw new TypeError("[Farm] The desktop secret and handshake token must be different values.");
58
58
  }
59
- const { secret } = options;
60
- let handshakeToken = options.handshakeToken;
59
+ const { secret, handshakeToken } = options;
60
+ const handshakeState = _nullishCoalesce(options.handshakeState, () => ( {}));
61
61
  const basePath = normalizeBasePath(options.basePath);
62
62
  const handshakePath = `${basePath}${FARM_DESKTOP_HANDSHAKE_PATH}`;
63
63
  const home = `${basePath}/`;
@@ -81,10 +81,10 @@ function createFarmDesktopGuard(options) {
81
81
  if (pathname === handshakePath) {
82
82
  if (method !== "GET") return forbidden("handshake must be a GET");
83
83
  const token = _nullishCoalesce(new URLSearchParams(search).get(FARM_DESKTOP_HANDSHAKE_PARAM), () => ( ""));
84
- if (handshakeToken === void 0 || !_chunkSHIWRBFIcjs.farmSecretsMatch.call(void 0, token, handshakeToken)) {
84
+ if (handshakeState.handshakeUsed || !_chunkSHIWRBFIcjs.farmSecretsMatch.call(void 0, token, handshakeToken)) {
85
85
  return forbidden("invalid or used handshake token");
86
86
  }
87
- handshakeToken = void 0;
87
+ handshakeState.handshakeUsed = true;
88
88
  return new Response(null, {
89
89
  status: 303,
90
90
  headers: {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getFarmRouteLabel
3
- } from "./chunk-NRFUVDTH.mjs";
3
+ } from "./chunk-DGVVVYKD.mjs";
4
4
  import {
5
5
  classifyFarmAgent
6
6
  } from "./chunk-N77JBPLC.mjs";
@@ -45,13 +45,12 @@ function resolveFarmInfraAnalytics(env = processEnv()) {
45
45
  if (!key || env[FARM_PRERENDER_ENV] === "1") return { off: null };
46
46
  const ingestionKey = INGESTION_KEY.test(key);
47
47
  const projectId = env.FARMJS_PROJECT_ID?.trim() || void 0;
48
- if (!ingestionKey && !projectId) return { off: null };
49
48
  if (!ingestionKey && !API_KEY.test(key)) {
50
49
  return {
51
50
  off: "FARMJS_API_KEY isn't a Farm Infra API key (farmjs_\u2026) or write-only key (fti_\u2026)"
52
51
  };
53
52
  }
54
- if (!ingestionKey && !PROJECT.test(projectId)) {
53
+ if (!ingestionKey && projectId && !PROJECT.test(projectId)) {
55
54
  return { off: "FARMJS_PROJECT_ID isn't a Farm Infra project ID (proj_\u2026)" };
56
55
  }
57
56
  if (env.FARMJS_ENVIRONMENT && !ENVIRONMENTS.includes(env.FARMJS_ENVIRONMENT)) {
@@ -71,7 +70,7 @@ function resolveFarmInfraAnalytics(env = processEnv()) {
71
70
  options: {
72
71
  endpoint: endpoint.href,
73
72
  key,
74
- ...ingestionKey ? {} : { projectId, environment: defaultFarmInfraEnvironment(env) }
73
+ ...ingestionKey ? {} : { ...projectId ? { projectId } : {}, environment: defaultFarmInfraEnvironment(env) }
75
74
  }
76
75
  };
77
76
  }
@@ -95,13 +94,45 @@ function retryAt(value, now) {
95
94
  const date = Date.parse(value);
96
95
  return Number.isFinite(date) ? Math.max(now, Math.min(date, now + 864e5)) : now;
97
96
  }
97
+ var REFUSALS = {
98
+ project: "project",
99
+ api_key_permission: "permission",
100
+ api_key_environment: "environment"
101
+ };
102
+ async function refusal(response) {
103
+ const reader = response.body?.getReader();
104
+ if (!reader) return void 0;
105
+ let text = "";
106
+ const decoder = new TextDecoder();
107
+ const deadline = Date.now() + 500;
108
+ try {
109
+ while (text.length < 1024 && Date.now() < deadline) {
110
+ let timer;
111
+ const chunk = await Promise.race([
112
+ reader.read(),
113
+ new Promise((resolve) => {
114
+ timer = setTimeout(() => resolve({ done: true }), deadline - Date.now());
115
+ })
116
+ ]).finally(() => clearTimeout(timer));
117
+ if (chunk.done) break;
118
+ text += decoder.decode(chunk.value, { stream: true });
119
+ }
120
+ const code = JSON.parse(text).error;
121
+ return typeof code === "string" && Object.prototype.hasOwnProperty.call(REFUSALS, code) ? REFUSALS[code] : void 0;
122
+ } catch {
123
+ return void 0;
124
+ } finally {
125
+ void reader.cancel().catch(() => {
126
+ });
127
+ }
128
+ }
98
129
  function createFarmInfraAnalyticsExporter(options, send = (input, init) => fetch(input, init)) {
99
130
  const requestHeaders = {
100
131
  "content-type": "application/json",
101
132
  authorization: `Bearer ${options.key}`
102
133
  };
103
134
  if (!INGESTION_KEY.test(options.key)) {
104
- requestHeaders["x-farm-project"] = options.projectId;
135
+ if (options.projectId) requestHeaders["x-farm-project"] = options.projectId;
105
136
  requestHeaders["x-farm-environment"] = options.environment ?? defaultFarmInfraEnvironment();
106
137
  }
107
138
  const queue = [];
@@ -172,6 +203,7 @@ function createFarmInfraAnalyticsExporter(options, send = (input, init) => fetch
172
203
  body
173
204
  });
174
205
  status = response.status;
206
+ const reason = status === 400 || status === 403 ? await refusal(response) : void 0;
175
207
  void response.body?.cancel().catch(() => {
176
208
  });
177
209
  if (response.ok) {
@@ -181,7 +213,7 @@ function createFarmInfraAnalyticsExporter(options, send = (input, init) => fetch
181
213
  if ([400, 401, 403, 404, 413, 415].includes(status) || status >= 300 && status < 400) {
182
214
  stopped = true;
183
215
  queue.length = 0;
184
- diagnostic({ code: "disabled", status });
216
+ diagnostic({ code: "disabled", status, ...reason ? { reason } : {} });
185
217
  break;
186
218
  }
187
219
  if (status !== 408 && status !== 429 && status < 500) {
@@ -366,14 +398,25 @@ function linkedOptions(env, warn) {
366
398
  return {
367
399
  ...resolved.options,
368
400
  onDiagnostic(event) {
369
- if (event.code === "disabled") {
370
- warn(
371
- `[Farm] Farm Infra analytics stopped: Farm Infra answered ${event.status}. Check FARMJS_API_KEY and FARMJS_PROJECT_ID, then restart the server.`
372
- );
373
- }
401
+ if (event.code !== "disabled") return;
402
+ if (event.reason === "environment") return;
403
+ warn(`[Farm] Farm Infra analytics stopped: ${stopReason(event)}`);
374
404
  }
375
405
  };
376
406
  }
407
+ var KEYS_PAGE = "the API keys page (https://app.farmjs.dev/dashboard/settings)";
408
+ function stopReason(event) {
409
+ if (event.reason === "project") {
410
+ return "FARMJS_API_KEY reaches more than one project. Set FARMJS_PROJECT_ID or use a key scoped to one project, then restart the server.";
411
+ }
412
+ if (event.reason === "permission") {
413
+ return `this key can't send analytics. Create a Site analytics key on ${KEYS_PAGE}, set it as FARMJS_API_KEY, then restart the server.`;
414
+ }
415
+ if (event.status === 401) {
416
+ return `Farm Infra answered 401: FARMJS_API_KEY was revoked or has expired. Create a new Site analytics key on ${KEYS_PAGE}, then restart the server.`;
417
+ }
418
+ return `Farm Infra answered ${event.status}. Check FARMJS_API_KEY and FARMJS_PROJECT_ID, then restart the server.`;
419
+ }
377
420
  function createFarmInfraAnalyticsPlugin(env = processEnv(), warn = console.warn) {
378
421
  const options = linkedOptions(env, warn);
379
422
  return options ? farmInfraAnalyticsPlugin(options) : null;
@@ -300,6 +300,76 @@ function composeFarmFullDocument(documentHtml, assets) {
300
300
  return /^\s*<!doctype/i.test(html) ? html : `<!DOCTYPE html>
301
301
  ${html}`;
302
302
  }
303
+ var STREAMED_BODY_MARK = "<!--farm-streamed-body-->";
304
+ function openFarmStreamedDocument(opening, assets) {
305
+ const { hoisted } = peelDocumentPrefix(opening);
306
+ const start = opening.search(/<!doctype|<html[\s>]/i);
307
+ const document = restoreHoistedHead(opening.slice(Math.max(start, 0)), hoisted);
308
+ const rootOpened = !/<body\b[^>]*>\s*<div\b[^>]*\sid=["']root["']/i.test(document);
309
+ const composed = composeFarmFullDocument(
310
+ `${document}${STREAMED_BODY_MARK}</body></html>`,
311
+ assets
312
+ );
313
+ return { html: composed.slice(0, composed.indexOf(STREAMED_BODY_MARK)), rootOpened };
314
+ }
315
+ function createFarmStreamedDocumentTransform(open, fragmentShell) {
316
+ let opening = "";
317
+ let mode = "pending";
318
+ let opened = false;
319
+ let closed = false;
320
+ let rootOpened = false;
321
+ const write = (text) => {
322
+ if (mode === "fragment") return text;
323
+ if (!opened) {
324
+ opening += text;
325
+ if (mode === "pending") {
326
+ const prefix = classifyFarmDocumentPrefix(opening);
327
+ if (prefix === "pending") return "";
328
+ if (prefix === "fragment") {
329
+ mode = "fragment";
330
+ const held = opening;
331
+ opening = "";
332
+ return fragmentShell + held;
333
+ }
334
+ mode = "document";
335
+ }
336
+ if (!/<body\b[^>]*>/i.test(opening)) return "";
337
+ opened = true;
338
+ text = opening;
339
+ opening = "";
340
+ const closeAt = text.search(/<\/body>/i);
341
+ const head = closeAt >= 0 ? text.slice(0, closeAt) : text;
342
+ const document = open(head);
343
+ rootOpened = document.rootOpened;
344
+ text = document.html + (closeAt >= 0 ? text.slice(closeAt) : "");
345
+ }
346
+ if (!closed) {
347
+ const closeAt = text.search(/<\/body>/i);
348
+ if (closeAt >= 0) {
349
+ closed = true;
350
+ text = text.slice(0, closeAt) + text.slice(closeAt).replace(/^<\/body>\s*(?:<\/html>)?(?:\s*<\/div>)*/i, "");
351
+ }
352
+ }
353
+ return text;
354
+ };
355
+ return {
356
+ write,
357
+ end() {
358
+ if (mode === "pending") {
359
+ mode = "fragment";
360
+ const held2 = opening;
361
+ opening = "";
362
+ return { text: fragmentShell + held2, document: false, rootOpened: false };
363
+ }
364
+ if (mode === "fragment") return { text: "", document: false, rootOpened: false };
365
+ if (opened) return { text: "", document: true, rootOpened };
366
+ const held = opening;
367
+ opening = "";
368
+ const text = write(`${held}<body>`);
369
+ return { text, document: true, rootOpened };
370
+ }
371
+ };
372
+ }
303
373
 
304
374
  // src/middleware/may-handle.ts
305
375
  function hasFarmMiddlewareConfig(config) {
@@ -797,4 +867,6 @@ function serializeInlineValue(value) {
797
867
 
798
868
 
799
869
 
800
- exports.formatRouteSegment = formatRouteSegment; exports.createRouteDirectoryPattern = createRouteDirectoryPattern; exports.stripRouteGroups = stripRouteGroups; exports.getRouteGroupScope = getRouteGroupScope; exports.isInRouteGroupScope = isInRouteGroupScope; exports.getRouteDirectoryDepth = getRouteDirectoryDepth; exports.routeBoundaryCoversDirectory = routeBoundaryCoversDirectory; exports.createFarmLayoutSelector = createFarmLayoutSelector; exports.layoutsCanCoverSamePage = layoutsCanCoverSamePage; exports.getFarmServerTreeLayoutPatterns = getFarmServerTreeLayoutPatterns; exports.createFarmRouteRenderPlan = createFarmRouteRenderPlan; exports.getFarmFragmentCacheControl = getFarmFragmentCacheControl; exports.parseFarmLayoutChainHeader = parseFarmLayoutChainHeader; exports.getSharedLayoutPrefixLength = getSharedLayoutPrefixLength; exports.HOISTED_HEAD_ELEMENT = HOISTED_HEAD_ELEMENT; exports.extractFarmFullDocument = extractFarmFullDocument; exports.classifyFarmDocumentPrefix = classifyFarmDocumentPrefix; exports.removeFarmDocumentTitles = removeFarmDocumentTitles; exports.ensureFarmDocumentMeta = ensureFarmDocumentMeta; exports.composeFarmFullDocument = composeFarmFullDocument; exports.hasFarmMiddlewareConfig = hasFarmMiddlewareConfig; exports.configMiddlewareMayHandlePath = configMiddlewareMayHandlePath; exports.appMiddlewareMayHandlePath = appMiddlewareMayHandlePath; exports.farmPathGuardCoversPage = farmPathGuardCoversPage; exports.farmPathGuardCoversEndpoint = farmPathGuardCoversEndpoint; exports.renderFarmLocaleAlternateLinks = renderFarmLocaleAlternateLinks; exports.createLateRedirectRecovery = createLateRedirectRecovery; exports.createLateNotFoundRecovery = createLateNotFoundRecovery; exports.createFarmMetadataRouteResponse = createFarmMetadataRouteResponse; exports.resolveDefaultErrorStatus = resolveDefaultErrorStatus; exports.getDefaultErrorStatusText = getDefaultErrorStatusText; exports.createDefaultErrorMarkup = createDefaultErrorMarkup; exports.createFarmThemeDocumentParts = createFarmThemeDocumentParts; exports.applyFarmThemeDocument = applyFarmThemeDocument;
870
+
871
+
872
+ exports.formatRouteSegment = formatRouteSegment; exports.createRouteDirectoryPattern = createRouteDirectoryPattern; exports.stripRouteGroups = stripRouteGroups; exports.getRouteGroupScope = getRouteGroupScope; exports.isInRouteGroupScope = isInRouteGroupScope; exports.getRouteDirectoryDepth = getRouteDirectoryDepth; exports.routeBoundaryCoversDirectory = routeBoundaryCoversDirectory; exports.createFarmLayoutSelector = createFarmLayoutSelector; exports.layoutsCanCoverSamePage = layoutsCanCoverSamePage; exports.getFarmServerTreeLayoutPatterns = getFarmServerTreeLayoutPatterns; exports.createFarmRouteRenderPlan = createFarmRouteRenderPlan; exports.getFarmFragmentCacheControl = getFarmFragmentCacheControl; exports.parseFarmLayoutChainHeader = parseFarmLayoutChainHeader; exports.getSharedLayoutPrefixLength = getSharedLayoutPrefixLength; exports.HOISTED_HEAD_ELEMENT = HOISTED_HEAD_ELEMENT; exports.extractFarmFullDocument = extractFarmFullDocument; exports.classifyFarmDocumentPrefix = classifyFarmDocumentPrefix; exports.removeFarmDocumentTitles = removeFarmDocumentTitles; exports.ensureFarmDocumentMeta = ensureFarmDocumentMeta; exports.composeFarmFullDocument = composeFarmFullDocument; exports.openFarmStreamedDocument = openFarmStreamedDocument; exports.createFarmStreamedDocumentTransform = createFarmStreamedDocumentTransform; exports.hasFarmMiddlewareConfig = hasFarmMiddlewareConfig; exports.configMiddlewareMayHandlePath = configMiddlewareMayHandlePath; exports.appMiddlewareMayHandlePath = appMiddlewareMayHandlePath; exports.farmPathGuardCoversPage = farmPathGuardCoversPage; exports.farmPathGuardCoversEndpoint = farmPathGuardCoversEndpoint; exports.renderFarmLocaleAlternateLinks = renderFarmLocaleAlternateLinks; exports.createLateRedirectRecovery = createLateRedirectRecovery; exports.createLateNotFoundRecovery = createLateNotFoundRecovery; exports.createFarmMetadataRouteResponse = createFarmMetadataRouteResponse; exports.resolveDefaultErrorStatus = resolveDefaultErrorStatus; exports.getDefaultErrorStatusText = getDefaultErrorStatusText; exports.createDefaultErrorMarkup = createDefaultErrorMarkup; exports.createFarmThemeDocumentParts = createFarmThemeDocumentParts; exports.applyFarmThemeDocument = applyFarmThemeDocument;