@farm.js/core 0.1.0-beta.10 → 0.1.0-beta.13
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.
- package/dist/{chunk-3QDB3IA6.mjs → chunk-3WIRO3N7.mjs} +2 -2
- package/dist/chunk-3WIRO3N7.mjs.map +1 -0
- package/dist/chunk-53MVSX3R.mjs +168 -0
- package/dist/chunk-53MVSX3R.mjs.map +1 -0
- package/dist/{chunk-AW6I64AP.mjs → chunk-6ZXIQSXE.mjs} +16 -1
- package/dist/chunk-6ZXIQSXE.mjs.map +1 -0
- package/dist/chunk-7ZVN3YZI.mjs +333 -0
- package/dist/chunk-7ZVN3YZI.mjs.map +1 -0
- package/dist/{chunk-7N62DNSO.mjs → chunk-H3TE3LOV.mjs} +2 -2
- package/dist/{chunk-QTZZ2ISQ.mjs → chunk-KLA67WKG.mjs} +1 -1
- package/dist/chunk-KLA67WKG.mjs.map +1 -0
- package/dist/{chunk-K5ZTUF22.mjs → chunk-L2PE36GQ.mjs} +7 -3
- package/dist/chunk-L2PE36GQ.mjs.map +1 -0
- package/dist/{chunk-4LND3PXF.mjs → chunk-OPHK6OJN.mjs} +513 -48
- package/dist/chunk-OPHK6OJN.mjs.map +1 -0
- package/dist/chunk-USLFXFFH.mjs +46 -0
- package/dist/chunk-USLFXFFH.mjs.map +1 -0
- package/dist/{chunk-DTOWEQRV.mjs → chunk-VSDZEB5M.mjs} +368 -103
- package/dist/chunk-VSDZEB5M.mjs.map +1 -0
- package/dist/{chunk-E2AI2CW7.mjs → chunk-Z3YG4OZT.mjs} +727 -148
- package/dist/chunk-Z3YG4OZT.mjs.map +1 -0
- package/dist/client.cjs.map +1 -1
- package/dist/client.mjs +1 -1
- package/dist/{devtools-A22KUJZT.mjs → devtools-GAZ7F3KL.mjs} +4 -3
- package/dist/{devtools-A22KUJZT.mjs.map → devtools-GAZ7F3KL.mjs.map} +1 -1
- package/dist/docs.cjs +622 -124
- package/dist/docs.cjs.map +1 -1
- package/dist/docs.mjs +5 -3
- package/dist/font.cjs +19 -2
- package/dist/font.cjs.map +1 -1
- package/dist/font.mjs +7 -3
- package/dist/index.cjs +2208 -681
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +27 -19
- package/dist/index.mjs.map +1 -1
- package/dist/internal/build-runtime.cjs +2035 -517
- package/dist/internal/build-runtime.cjs.map +1 -1
- package/dist/internal/build-runtime.mjs +13 -10
- package/dist/internal/client-runtime.cjs +169 -2
- package/dist/internal/client-runtime.cjs.map +1 -1
- package/dist/internal/client-runtime.mjs +170 -2
- package/dist/internal/client-runtime.mjs.map +1 -1
- package/dist/internal/config-runtime.cjs +22 -0
- package/dist/internal/config-runtime.cjs.map +1 -1
- package/dist/internal/config-runtime.mjs +3 -2
- package/dist/internal/metadata-image-runtime.cjs +199 -0
- package/dist/internal/metadata-image-runtime.cjs.map +1 -0
- package/dist/internal/metadata-image-runtime.mjs +8 -0
- package/dist/internal/metadata-image-runtime.mjs.map +1 -0
- package/dist/internal/production-runtime.cjs +310 -0
- package/dist/internal/production-runtime.cjs.map +1 -1
- package/dist/internal/production-runtime.mjs +10 -0
- package/dist/internal/production-runtime.mjs.map +1 -1
- package/dist/navigation.cjs.map +1 -1
- package/dist/navigation.mjs +2 -2
- package/dist/plugin.cjs +1523 -340
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.mjs +9 -5
- package/dist/server.cjs +1636 -411
- package/dist/server.cjs.map +1 -1
- package/dist/server.mjs +17 -19
- package/dist/server.mjs.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.mjs +1 -1
- package/dist/vite.cjs +1577 -350
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +9 -5
- package/package.json +10 -1
- package/dist/chunk-3QDB3IA6.mjs.map +0 -1
- package/dist/chunk-4LND3PXF.mjs.map +0 -1
- package/dist/chunk-AW6I64AP.mjs.map +0 -1
- package/dist/chunk-DTOWEQRV.mjs.map +0 -1
- package/dist/chunk-E2AI2CW7.mjs.map +0 -1
- package/dist/chunk-K5ZTUF22.mjs.map +0 -1
- package/dist/chunk-QM746KUO.mjs +0 -56
- package/dist/chunk-QM746KUO.mjs.map +0 -1
- package/dist/chunk-QTZZ2ISQ.mjs.map +0 -1
- /package/dist/{chunk-7N62DNSO.mjs.map → chunk-H3TE3LOV.mjs.map} +0 -0
|
@@ -6,6 +6,12 @@ import {
|
|
|
6
6
|
mergeMetadata,
|
|
7
7
|
renderMetadataHead
|
|
8
8
|
} from "./chunk-FRPWCMMG.mjs";
|
|
9
|
+
import {
|
|
10
|
+
createFarmMetadataImageResponse
|
|
11
|
+
} from "./chunk-53MVSX3R.mjs";
|
|
12
|
+
import {
|
|
13
|
+
resolveFarmLayoutFonts
|
|
14
|
+
} from "./chunk-6ZXIQSXE.mjs";
|
|
9
15
|
import {
|
|
10
16
|
farmEnvironmentFunctionsPlugin
|
|
11
17
|
} from "./chunk-V6WE6JSZ.mjs";
|
|
@@ -24,9 +30,18 @@ import {
|
|
|
24
30
|
isFarmNotFoundError,
|
|
25
31
|
isFarmRedirectError
|
|
26
32
|
} from "./chunk-7HO6AEOP.mjs";
|
|
33
|
+
import {
|
|
34
|
+
resolveFarmDocsFontAssets,
|
|
35
|
+
toFarmDocsPublicFontAssets
|
|
36
|
+
} from "./chunk-USLFXFFH.mjs";
|
|
27
37
|
import {
|
|
28
38
|
resolveFarmAuthConfig
|
|
29
39
|
} from "./chunk-I4CUBGVF.mjs";
|
|
40
|
+
import {
|
|
41
|
+
FARM_DEVTOOLS_LAUNCH_PARAM,
|
|
42
|
+
FARM_DEVTOOLS_PATH,
|
|
43
|
+
resolveFarmDevtoolsConfig
|
|
44
|
+
} from "./chunk-7MABZJIM.mjs";
|
|
30
45
|
import {
|
|
31
46
|
normalizeRouteRules
|
|
32
47
|
} from "./chunk-YW7OBE6Q.mjs";
|
|
@@ -36,10 +51,8 @@ import {
|
|
|
36
51
|
getFarmSourceRoots
|
|
37
52
|
} from "./chunk-74YTBPTY.mjs";
|
|
38
53
|
import {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
resolveFarmDevtoolsConfig
|
|
42
|
-
} from "./chunk-7MABZJIM.mjs";
|
|
54
|
+
resolveFarmPerformanceConfig
|
|
55
|
+
} from "./chunk-7ZVN3YZI.mjs";
|
|
43
56
|
import {
|
|
44
57
|
getPublicFarmImageConfig,
|
|
45
58
|
resolveFarmImageConfig
|
|
@@ -147,7 +160,7 @@ import {
|
|
|
147
160
|
} from "./chunk-RHIFZZUI.mjs";
|
|
148
161
|
import {
|
|
149
162
|
FARM_VERSION
|
|
150
|
-
} from "./chunk-
|
|
163
|
+
} from "./chunk-3WIRO3N7.mjs";
|
|
151
164
|
import {
|
|
152
165
|
FARM_DEPLOYMENT_ID_HEADER,
|
|
153
166
|
createFarmDeploymentCookie,
|
|
@@ -185,6 +198,22 @@ import { readFile } from "fs/promises";
|
|
|
185
198
|
var OPTIONAL_CATCH_ALL_SEGMENT = /^\[\[\.\.\.([^\]]+)\]\]$/;
|
|
186
199
|
var REQUIRED_CATCH_ALL_SEGMENT = /^\[\.\.\.([^\]]+)\]$/;
|
|
187
200
|
var REQUIRED_DYNAMIC_SEGMENT = /^\[([^\]]+)\]$/;
|
|
201
|
+
var REQUEST_API_LABELS = /* @__PURE__ */ new Map([
|
|
202
|
+
["cookies", "request cookies"],
|
|
203
|
+
["headers", "request headers"],
|
|
204
|
+
["getCurrentRequest", "the current Request"],
|
|
205
|
+
["useSearchParams", "URL search parameters"],
|
|
206
|
+
["auth", "request authentication"],
|
|
207
|
+
["getServerSession", "request authentication"],
|
|
208
|
+
["getSession", "request authentication"],
|
|
209
|
+
["currentUser", "request authentication"]
|
|
210
|
+
]);
|
|
211
|
+
var ROUTE_PROP_LABELS = /* @__PURE__ */ new Map([
|
|
212
|
+
["searchParams", "URL search parameters"],
|
|
213
|
+
["middleware", "middleware request data"],
|
|
214
|
+
["middlewareData", "middleware request data"],
|
|
215
|
+
["context", "request context"]
|
|
216
|
+
]);
|
|
188
217
|
function resolveRouteRenderingConfig(mod, source) {
|
|
189
218
|
const directiveConfig = parseRouteRenderingDirective(source);
|
|
190
219
|
let ssg = directiveConfig?.ssg ?? false;
|
|
@@ -237,6 +266,221 @@ async function resolveRouteRenderingConfigFromFile(mod, filePath) {
|
|
|
237
266
|
return resolveRouteRenderingConfig(mod, source);
|
|
238
267
|
}
|
|
239
268
|
__name(resolveRouteRenderingConfigFromFile, "resolveRouteRenderingConfigFromFile");
|
|
269
|
+
function analyzeStaticRouteCandidate(mod, source, options = {}) {
|
|
270
|
+
const blockers = [];
|
|
271
|
+
if (!source) {
|
|
272
|
+
blockers.push("route source is unavailable");
|
|
273
|
+
}
|
|
274
|
+
if (options.isDynamic) {
|
|
275
|
+
blockers.push("the route has dynamic path segments");
|
|
276
|
+
}
|
|
277
|
+
if (hasExplicitRenderingConfig(mod, source)) {
|
|
278
|
+
blockers.push("the route already has explicit rendering config");
|
|
279
|
+
}
|
|
280
|
+
if (source) {
|
|
281
|
+
blockers.push(...findRequestBoundSourceBlockers(source));
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
candidate: blockers.length === 0,
|
|
285
|
+
blockers
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
__name(analyzeStaticRouteCandidate, "analyzeStaticRouteCandidate");
|
|
289
|
+
function findRequestBoundSourceBlockers(source) {
|
|
290
|
+
const blockers = /* @__PURE__ */ new Set();
|
|
291
|
+
const code = stripCommentsAndLiteralContents(source);
|
|
292
|
+
const sourceWithoutComments = stripComments(source);
|
|
293
|
+
for (const binding of readRequestApiImportBindings(sourceWithoutComments)) {
|
|
294
|
+
if (new RegExp(`\\b${escapeRegExp(binding.local)}\\s*(?:\\?\\.\\s*)?\\(`).test(code)) {
|
|
295
|
+
blockers.add(`the route reads ${binding.label}`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
for (const namespace of readNamespaceImportBindings(sourceWithoutComments)) {
|
|
299
|
+
for (const [name, label] of REQUEST_API_LABELS) {
|
|
300
|
+
if (new RegExp(
|
|
301
|
+
`\\b${escapeRegExp(namespace)}\\s*(?:\\?\\.\\s*|\\.\\s*)${name}\\s*(?:\\?\\.\\s*)?\\(`
|
|
302
|
+
).test(code)) {
|
|
303
|
+
blockers.add(`the route reads ${label}`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const params = readDefaultRouteParameters(code);
|
|
308
|
+
if (params) {
|
|
309
|
+
for (const [name, label] of ROUTE_PROP_LABELS) {
|
|
310
|
+
if (new RegExp(`\\b${name}\\b`).test(params)) {
|
|
311
|
+
blockers.add(`the route reads ${label}`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
const propsName = params.match(/^\s*([A-Za-z_$][\w$]*)\s*(?::|,|$)/)?.[1];
|
|
315
|
+
if (propsName) {
|
|
316
|
+
for (const [name, label] of ROUTE_PROP_LABELS) {
|
|
317
|
+
if (new RegExp(`\\b${escapeRegExp(propsName)}\\s*\\.\\s*${name}\\b`).test(code)) {
|
|
318
|
+
blockers.add(`the route reads ${label}`);
|
|
319
|
+
}
|
|
320
|
+
if (new RegExp(`\\{[^}]*\\b${name}\\b[^}]*\\}\\s*=\\s*${escapeRegExp(propsName)}\\b`).test(
|
|
321
|
+
code
|
|
322
|
+
)) {
|
|
323
|
+
blockers.add(`the route reads ${label}`);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return [...blockers];
|
|
329
|
+
}
|
|
330
|
+
__name(findRequestBoundSourceBlockers, "findRequestBoundSourceBlockers");
|
|
331
|
+
function readRequestApiImportBindings(source) {
|
|
332
|
+
const bindings = [];
|
|
333
|
+
for (const clause of readStaticImportClauses(source)) {
|
|
334
|
+
const namedGroup = clause.match(/\{([\s\S]*?)\}/)?.[1];
|
|
335
|
+
for (const rawSpecifier of (namedGroup ?? "").split(",")) {
|
|
336
|
+
const specifier = rawSpecifier.trim().replace(/^type\s+/, "");
|
|
337
|
+
const imported = specifier.match(/^([A-Za-z_$][\w$]*)(?:\s+as\s+([A-Za-z_$][\w$]*))?$/);
|
|
338
|
+
if (!imported?.[1]) continue;
|
|
339
|
+
const label = REQUEST_API_LABELS.get(imported[1]);
|
|
340
|
+
if (label) bindings.push({ local: imported[2] ?? imported[1], label });
|
|
341
|
+
}
|
|
342
|
+
const local = clause.match(/^\s*([A-Za-z_$][\w$]*)\s*(?:,|$)/)?.[1];
|
|
343
|
+
if (local) {
|
|
344
|
+
const label = REQUEST_API_LABELS.get(local);
|
|
345
|
+
if (label) bindings.push({ local, label });
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return bindings;
|
|
349
|
+
}
|
|
350
|
+
__name(readRequestApiImportBindings, "readRequestApiImportBindings");
|
|
351
|
+
function readNamespaceImportBindings(source) {
|
|
352
|
+
return readStaticImportClauses(source).map((clause) => clause.match(/\*\s*as\s*([A-Za-z_$][\w$]*)/)?.[1]).filter((binding) => Boolean(binding));
|
|
353
|
+
}
|
|
354
|
+
__name(readNamespaceImportBindings, "readNamespaceImportBindings");
|
|
355
|
+
function readStaticImportClauses(source) {
|
|
356
|
+
return [...source.matchAll(/\bimport\s+(?!\()([\s\S]*?)\s+from\s*["'][^"']+["']/g)].map((match) => match[1]).filter((clause) => Boolean(clause));
|
|
357
|
+
}
|
|
358
|
+
__name(readStaticImportClauses, "readStaticImportClauses");
|
|
359
|
+
function readDefaultRouteParameters(code) {
|
|
360
|
+
const inlineParams = code.match(/\bexport\s+default\s+(?:async\s+)?function\b[^(]*\(([^)]*)\)/)?.[1] ?? code.match(/\bexport\s+default\s+(?:async\s+)?\(([^)]*)\)\s*=>/)?.[1];
|
|
361
|
+
if (inlineParams !== void 0) return inlineParams;
|
|
362
|
+
const binding = code.match(/\bexport\s+default\s+([A-Za-z_$][\w$]*)\s*;?/)?.[1] ?? code.match(/\bexport\s*\{\s*([A-Za-z_$][\w$]*)\s+as\s+default\s*\}/)?.[1];
|
|
363
|
+
if (!binding) return void 0;
|
|
364
|
+
const escapedBinding = escapeRegExp(binding);
|
|
365
|
+
return code.match(new RegExp(`\\bfunction\\s+${escapedBinding}\\s*\\(([^)]*)\\)`))?.[1] ?? code.match(
|
|
366
|
+
new RegExp(
|
|
367
|
+
`\\b(?:const|let|var)\\s+${escapedBinding}\\s*=\\s*(?:async\\s+)?\\(([^)]*)\\)\\s*=>`
|
|
368
|
+
)
|
|
369
|
+
)?.[1] ?? code.match(
|
|
370
|
+
new RegExp(`\\b(?:const|let|var)\\s+${escapedBinding}\\s*=\\s*function\\s*\\(([^)]*)\\)`)
|
|
371
|
+
)?.[1];
|
|
372
|
+
}
|
|
373
|
+
__name(readDefaultRouteParameters, "readDefaultRouteParameters");
|
|
374
|
+
function stripCommentsAndLiteralContents(source) {
|
|
375
|
+
return sanitizeSource(source, true);
|
|
376
|
+
}
|
|
377
|
+
__name(stripCommentsAndLiteralContents, "stripCommentsAndLiteralContents");
|
|
378
|
+
function stripComments(source) {
|
|
379
|
+
return sanitizeSource(source, false);
|
|
380
|
+
}
|
|
381
|
+
__name(stripComments, "stripComments");
|
|
382
|
+
function sanitizeSource(source, maskLiterals) {
|
|
383
|
+
const output = [...source];
|
|
384
|
+
const mask = /* @__PURE__ */ __name((index) => {
|
|
385
|
+
if (output[index] !== "\n" && output[index] !== "\r") output[index] = " ";
|
|
386
|
+
}, "mask");
|
|
387
|
+
const scanQuoted = /* @__PURE__ */ __name((start, quote) => {
|
|
388
|
+
let index = start;
|
|
389
|
+
if (maskLiterals) mask(index);
|
|
390
|
+
index += 1;
|
|
391
|
+
while (index < source.length) {
|
|
392
|
+
if (source[index] === "\\") {
|
|
393
|
+
if (maskLiterals) mask(index);
|
|
394
|
+
if (index + 1 < source.length && maskLiterals) mask(index + 1);
|
|
395
|
+
index += 2;
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
const character = source[index];
|
|
399
|
+
if (maskLiterals) mask(index);
|
|
400
|
+
index += 1;
|
|
401
|
+
if (character === quote) break;
|
|
402
|
+
}
|
|
403
|
+
return index;
|
|
404
|
+
}, "scanQuoted");
|
|
405
|
+
const scanCode = /* @__PURE__ */ __name((start, stopAtTemplateBrace) => {
|
|
406
|
+
let index = start;
|
|
407
|
+
let braceDepth = 0;
|
|
408
|
+
while (index < source.length) {
|
|
409
|
+
const character = source[index];
|
|
410
|
+
const next = source[index + 1];
|
|
411
|
+
if (character === "/" && next === "/") {
|
|
412
|
+
while (index < source.length && source[index] !== "\n" && source[index] !== "\r") {
|
|
413
|
+
mask(index++);
|
|
414
|
+
}
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
if (character === "/" && next === "*") {
|
|
418
|
+
mask(index++);
|
|
419
|
+
mask(index++);
|
|
420
|
+
while (index < source.length) {
|
|
421
|
+
const closesComment = source[index] === "*" && source[index + 1] === "/";
|
|
422
|
+
mask(index++);
|
|
423
|
+
if (closesComment) {
|
|
424
|
+
mask(index++);
|
|
425
|
+
break;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
if (character === "'" || character === '"') {
|
|
431
|
+
index = scanQuoted(index, character);
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
if (character === "`") {
|
|
435
|
+
if (maskLiterals) mask(index);
|
|
436
|
+
index += 1;
|
|
437
|
+
while (index < source.length) {
|
|
438
|
+
if (source[index] === "\\") {
|
|
439
|
+
if (maskLiterals) mask(index);
|
|
440
|
+
if (index + 1 < source.length && maskLiterals) mask(index + 1);
|
|
441
|
+
index += 2;
|
|
442
|
+
} else if (source[index] === "`") {
|
|
443
|
+
if (maskLiterals) mask(index);
|
|
444
|
+
index += 1;
|
|
445
|
+
break;
|
|
446
|
+
} else if (source[index] === "$" && source[index + 1] === "{") {
|
|
447
|
+
if (maskLiterals) {
|
|
448
|
+
mask(index);
|
|
449
|
+
mask(index + 1);
|
|
450
|
+
}
|
|
451
|
+
index = scanCode(index + 2, true);
|
|
452
|
+
} else {
|
|
453
|
+
if (maskLiterals) mask(index);
|
|
454
|
+
index += 1;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
459
|
+
if (character === "{") {
|
|
460
|
+
braceDepth += 1;
|
|
461
|
+
} else if (character === "}") {
|
|
462
|
+
if (stopAtTemplateBrace && braceDepth === 0) {
|
|
463
|
+
if (maskLiterals) mask(index);
|
|
464
|
+
return index + 1;
|
|
465
|
+
}
|
|
466
|
+
braceDepth = Math.max(0, braceDepth - 1);
|
|
467
|
+
}
|
|
468
|
+
index += 1;
|
|
469
|
+
}
|
|
470
|
+
return index;
|
|
471
|
+
}, "scanCode");
|
|
472
|
+
scanCode(0, false);
|
|
473
|
+
return output.join("");
|
|
474
|
+
}
|
|
475
|
+
__name(sanitizeSource, "sanitizeSource");
|
|
476
|
+
function escapeRegExp(value) {
|
|
477
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
478
|
+
}
|
|
479
|
+
__name(escapeRegExp, "escapeRegExp");
|
|
480
|
+
function hasExplicitRenderingConfig(mod, source) {
|
|
481
|
+
return typeof mod?.ssg === "boolean" || typeof mod?.ppr === "boolean" || typeof mod?.experimental_ppr === "boolean" || typeof mod?.revalidate !== "undefined" || typeof mod?.dynamic !== "undefined" || typeof parseRouteRenderingDirective(source) !== "undefined";
|
|
482
|
+
}
|
|
483
|
+
__name(hasExplicitRenderingConfig, "hasExplicitRenderingConfig");
|
|
240
484
|
function parseRouteRenderingDirective(source) {
|
|
241
485
|
if (!source) {
|
|
242
486
|
return void 0;
|
|
@@ -368,9 +612,10 @@ function skipHorizontalWhitespace(source, start) {
|
|
|
368
612
|
return index;
|
|
369
613
|
}
|
|
370
614
|
__name(skipHorizontalWhitespace, "skipHorizontalWhitespace");
|
|
371
|
-
async function collectSSGPages(routes, loadModule) {
|
|
615
|
+
async function collectSSGPages(routes, loadModule, options = {}) {
|
|
372
616
|
const ssgPages = [];
|
|
373
617
|
const ssrRoutes = [];
|
|
618
|
+
const staticCandidateRoutes = [];
|
|
374
619
|
for (const route of routes) {
|
|
375
620
|
try {
|
|
376
621
|
const mod = await loadModule(route.filePath);
|
|
@@ -378,7 +623,8 @@ async function collectSSGPages(routes, loadModule) {
|
|
|
378
623
|
ssrRoutes.push(route.path);
|
|
379
624
|
continue;
|
|
380
625
|
}
|
|
381
|
-
const
|
|
626
|
+
const source = await readFile(route.filePath, "utf8").catch(() => void 0);
|
|
627
|
+
const rendering = resolveRouteRenderingConfig(mod, source);
|
|
382
628
|
if (rendering.ssg) {
|
|
383
629
|
if (route.isDynamic) {
|
|
384
630
|
const getStaticPaths = mod.getStaticPaths || mod.generateStaticParams;
|
|
@@ -405,12 +651,26 @@ async function collectSSGPages(routes, loadModule) {
|
|
|
405
651
|
}
|
|
406
652
|
} else {
|
|
407
653
|
ssrRoutes.push(route.path);
|
|
654
|
+
if (options.suggestStaticRendering !== false && analyzeStaticRouteCandidate(mod, source, { isDynamic: route.isDynamic }).candidate) {
|
|
655
|
+
staticCandidateRoutes.push(route.path);
|
|
656
|
+
}
|
|
408
657
|
}
|
|
409
658
|
} catch (error) {
|
|
410
659
|
console.error(`Error processing route ${route.path}:`, error);
|
|
411
660
|
ssrRoutes.push(route.path);
|
|
412
661
|
}
|
|
413
662
|
}
|
|
663
|
+
if (staticCandidateRoutes.length > 0) {
|
|
664
|
+
const visibleRoutes = staticCandidateRoutes.slice(0, 10);
|
|
665
|
+
const remainingCount = staticCandidateRoutes.length - visibleRoutes.length;
|
|
666
|
+
const remainingSuffix = remainingCount > 0 ? `
|
|
667
|
+
\u2026and ${remainingCount} more` : "";
|
|
668
|
+
console.warn(
|
|
669
|
+
`[Farm.js] ${staticCandidateRoutes.length} route${staticCandidateRoutes.length === 1 ? " appears" : "s appear"} eligible for static rendering:
|
|
670
|
+
${visibleRoutes.join("\n ")}${remainingSuffix}
|
|
671
|
+
Add \`export const dynamic = "force-static";\` after verifying that imported code does not read cookies, headers, authentication, or other request data.`
|
|
672
|
+
);
|
|
673
|
+
}
|
|
414
674
|
return { ssg: ssgPages, ssr: ssrRoutes };
|
|
415
675
|
}
|
|
416
676
|
__name(collectSSGPages, "collectSSGPages");
|
|
@@ -558,6 +818,15 @@ import path3 from "path";
|
|
|
558
818
|
import fs from "fs";
|
|
559
819
|
import path from "path";
|
|
560
820
|
import { fileURLToPath } from "url";
|
|
821
|
+
|
|
822
|
+
// src/island.ts
|
|
823
|
+
var FARM_ISLAND_STRATEGIES = ["load", "interaction", "visible", "idle"];
|
|
824
|
+
function isFarmIslandStrategy(value) {
|
|
825
|
+
return FARM_ISLAND_STRATEGIES.includes(value);
|
|
826
|
+
}
|
|
827
|
+
__name(isFarmIslandStrategy, "isFarmIslandStrategy");
|
|
828
|
+
|
|
829
|
+
// src/utils/client-component.ts
|
|
561
830
|
function readIfExists(filePath) {
|
|
562
831
|
try {
|
|
563
832
|
if (!filePath || !fs.existsSync(filePath)) {
|
|
@@ -628,56 +897,186 @@ function hasHydrateExport(content) {
|
|
|
628
897
|
return /\bexport\s+const\s+hydrate\s*=\s*true\b/.test(content) || /\bexport\s*\{\s*hydrate\s*\}\b/.test(content);
|
|
629
898
|
}
|
|
630
899
|
__name(hasHydrateExport, "hasHydrateExport");
|
|
900
|
+
function tokenizeModuleSource(content) {
|
|
901
|
+
const tokens = [];
|
|
902
|
+
let index = 0;
|
|
903
|
+
let line = 1;
|
|
904
|
+
while (index < content.length) {
|
|
905
|
+
const character = content[index];
|
|
906
|
+
if (/\s/.test(character)) {
|
|
907
|
+
if (character === "\n") line++;
|
|
908
|
+
index++;
|
|
909
|
+
continue;
|
|
910
|
+
}
|
|
911
|
+
if (character === "/" && content[index + 1] === "/") {
|
|
912
|
+
index += 2;
|
|
913
|
+
while (index < content.length && content[index] !== "\n") index++;
|
|
914
|
+
continue;
|
|
915
|
+
}
|
|
916
|
+
if (character === "/" && content[index + 1] === "*") {
|
|
917
|
+
index += 2;
|
|
918
|
+
while (index < content.length) {
|
|
919
|
+
if (content[index] === "\n") line++;
|
|
920
|
+
if (content[index] === "*" && content[index + 1] === "/") {
|
|
921
|
+
index += 2;
|
|
922
|
+
break;
|
|
923
|
+
}
|
|
924
|
+
index++;
|
|
925
|
+
}
|
|
926
|
+
continue;
|
|
927
|
+
}
|
|
928
|
+
if (character === '"' || character === "'") {
|
|
929
|
+
const quote = character;
|
|
930
|
+
const tokenLine = line;
|
|
931
|
+
let value = "";
|
|
932
|
+
index++;
|
|
933
|
+
while (index < content.length) {
|
|
934
|
+
const next = content[index];
|
|
935
|
+
if (next === "\\") {
|
|
936
|
+
value += next;
|
|
937
|
+
if (index + 1 < content.length) value += content[index + 1];
|
|
938
|
+
index += 2;
|
|
939
|
+
continue;
|
|
940
|
+
}
|
|
941
|
+
if (next === quote) {
|
|
942
|
+
index++;
|
|
943
|
+
break;
|
|
944
|
+
}
|
|
945
|
+
if (next === "\n") line++;
|
|
946
|
+
value += next;
|
|
947
|
+
index++;
|
|
948
|
+
}
|
|
949
|
+
tokens.push({ kind: "string", value, line: tokenLine });
|
|
950
|
+
continue;
|
|
951
|
+
}
|
|
952
|
+
if (character === "`") {
|
|
953
|
+
index++;
|
|
954
|
+
while (index < content.length) {
|
|
955
|
+
const next = content[index];
|
|
956
|
+
if (next === "\\") {
|
|
957
|
+
index += 2;
|
|
958
|
+
continue;
|
|
959
|
+
}
|
|
960
|
+
if (next === "`") {
|
|
961
|
+
index++;
|
|
962
|
+
break;
|
|
963
|
+
}
|
|
964
|
+
if (next === "\n") line++;
|
|
965
|
+
index++;
|
|
966
|
+
}
|
|
967
|
+
continue;
|
|
968
|
+
}
|
|
969
|
+
if (/[A-Za-z_$]/.test(character)) {
|
|
970
|
+
const start = index++;
|
|
971
|
+
while (index < content.length && /[\w$]/.test(content[index])) index++;
|
|
972
|
+
tokens.push({ kind: "identifier", value: content.slice(start, index), line });
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
975
|
+
tokens.push({ kind: "punctuation", value: character, line });
|
|
976
|
+
index++;
|
|
977
|
+
}
|
|
978
|
+
return tokens;
|
|
979
|
+
}
|
|
980
|
+
__name(tokenizeModuleSource, "tokenizeModuleSource");
|
|
981
|
+
function isIslandExportStart(tokens, index) {
|
|
982
|
+
const token = tokens[index];
|
|
983
|
+
const previous = tokens[index - 1];
|
|
984
|
+
const startsStatement = !previous || previous.value === ";" || previous.value === "{" || previous.value === "}" || token.line > previous.line;
|
|
985
|
+
return startsStatement && token.value === "export" && tokens[index + 1]?.value === "const" && tokens[index + 2]?.value === "island";
|
|
986
|
+
}
|
|
987
|
+
__name(isIslandExportStart, "isIslandExportStart");
|
|
988
|
+
function getIslandStrategyExport(content) {
|
|
989
|
+
if (!content) return null;
|
|
990
|
+
const tokens = tokenizeModuleSource(content);
|
|
991
|
+
for (let index = 0; index < tokens.length - 2; index++) {
|
|
992
|
+
if (!isIslandExportStart(tokens, index)) continue;
|
|
993
|
+
let valueIndex = index + 3;
|
|
994
|
+
if (tokens[valueIndex]?.value === ":") {
|
|
995
|
+
while (valueIndex < tokens.length && tokens[valueIndex].value !== "=") valueIndex++;
|
|
996
|
+
}
|
|
997
|
+
if (tokens[valueIndex]?.value !== "=") break;
|
|
998
|
+
valueIndex++;
|
|
999
|
+
const literal = tokens[valueIndex];
|
|
1000
|
+
if (!literal || literal.kind !== "string" || !isFarmIslandStrategy(literal.value)) break;
|
|
1001
|
+
let trailingIndex = valueIndex + 1;
|
|
1002
|
+
if (tokens[trailingIndex]?.value === "as" && tokens[trailingIndex + 1]?.value === "const") {
|
|
1003
|
+
trailingIndex += 2;
|
|
1004
|
+
}
|
|
1005
|
+
const trailing = tokens[trailingIndex];
|
|
1006
|
+
if (trailing && trailing.value !== ";" && trailing.line === literal.line) break;
|
|
1007
|
+
return literal.value;
|
|
1008
|
+
}
|
|
1009
|
+
if (tokens.some((_token, index) => isIslandExportStart(tokens, index))) {
|
|
1010
|
+
throw new Error(
|
|
1011
|
+
'Farm island configuration must be a static "load", "interaction", "visible", or "idle" string literal.'
|
|
1012
|
+
);
|
|
1013
|
+
}
|
|
1014
|
+
return null;
|
|
1015
|
+
}
|
|
1016
|
+
__name(getIslandStrategyExport, "getIslandStrategyExport");
|
|
631
1017
|
function stripUseClientDirective(content) {
|
|
632
1018
|
return content.replace(/^\s*(["'])use client\1\s*;?\s*/, "");
|
|
633
1019
|
}
|
|
634
1020
|
__name(stripUseClientDirective, "stripUseClientDirective");
|
|
635
|
-
function parseClientModuleMetadata(content) {
|
|
1021
|
+
function parseClientModuleMetadata(content, inspectIslandExport) {
|
|
636
1022
|
if (!content) {
|
|
637
1023
|
return {
|
|
638
1024
|
isClientComponent: false,
|
|
639
|
-
hasHydrateExport: false
|
|
1025
|
+
hasHydrateExport: false,
|
|
1026
|
+
islandStrategy: null
|
|
640
1027
|
};
|
|
641
1028
|
}
|
|
1029
|
+
const isClientComponent = hasUseClientDirective(content);
|
|
1030
|
+
const hasHydrate = hasHydrateExport(content);
|
|
642
1031
|
return {
|
|
643
|
-
isClientComponent
|
|
644
|
-
hasHydrateExport:
|
|
1032
|
+
isClientComponent,
|
|
1033
|
+
hasHydrateExport: hasHydrate,
|
|
1034
|
+
islandStrategy: inspectIslandExport || isClientComponent || hasHydrate ? getIslandStrategyExport(content) : null
|
|
645
1035
|
};
|
|
646
1036
|
}
|
|
647
1037
|
__name(parseClientModuleMetadata, "parseClientModuleMetadata");
|
|
648
1038
|
function getClientModuleMetadata(modulePath, root) {
|
|
649
1039
|
const resolvedPath = resolveModuleSourcePath(modulePath, root);
|
|
650
|
-
return inspectClientModuleMetadata(resolvedPath, root, /* @__PURE__ */ new Set());
|
|
1040
|
+
return inspectClientModuleMetadata(resolvedPath, root, /* @__PURE__ */ new Set(), true);
|
|
651
1041
|
}
|
|
652
1042
|
__name(getClientModuleMetadata, "getClientModuleMetadata");
|
|
653
|
-
function inspectClientModuleMetadata(resolvedPath, root, visited) {
|
|
1043
|
+
function inspectClientModuleMetadata(resolvedPath, root, visited, inspectIslandExport) {
|
|
654
1044
|
if (!resolvedPath || visited.has(resolvedPath)) {
|
|
655
1045
|
return {
|
|
656
1046
|
isClientComponent: false,
|
|
657
|
-
shouldHydrate: false
|
|
1047
|
+
shouldHydrate: false,
|
|
1048
|
+
islandStrategy: null
|
|
658
1049
|
};
|
|
659
1050
|
}
|
|
660
1051
|
visited.add(resolvedPath);
|
|
661
1052
|
const content = readIfExists(resolvedPath);
|
|
662
|
-
const parsed = parseClientModuleMetadata(content);
|
|
1053
|
+
const parsed = parseClientModuleMetadata(content, inspectIslandExport);
|
|
663
1054
|
if (parsed.isClientComponent) {
|
|
664
1055
|
return {
|
|
665
1056
|
isClientComponent: true,
|
|
666
|
-
shouldHydrate: true
|
|
1057
|
+
shouldHydrate: true,
|
|
1058
|
+
islandStrategy: parsed.islandStrategy ?? "load"
|
|
667
1059
|
};
|
|
668
1060
|
}
|
|
669
1061
|
let importsClientBoundary = false;
|
|
1062
|
+
let importedIslandStrategy = null;
|
|
670
1063
|
for (const specifier of getRelativeImportSpecifiers(content)) {
|
|
671
1064
|
const importedPath = resolveImportedModuleSourcePath(resolvedPath, specifier, root);
|
|
672
|
-
const importedMetadata = inspectClientModuleMetadata(importedPath, root, visited);
|
|
1065
|
+
const importedMetadata = inspectClientModuleMetadata(importedPath, root, visited, false);
|
|
673
1066
|
if (importedMetadata.isClientComponent || importedMetadata.shouldHydrate) {
|
|
674
1067
|
importsClientBoundary = true;
|
|
675
|
-
|
|
1068
|
+
if (importedIslandStrategy === null) {
|
|
1069
|
+
importedIslandStrategy = importedMetadata.islandStrategy;
|
|
1070
|
+
} else if (importedIslandStrategy !== importedMetadata.islandStrategy) {
|
|
1071
|
+
importedIslandStrategy = "load";
|
|
1072
|
+
}
|
|
676
1073
|
}
|
|
677
1074
|
}
|
|
1075
|
+
const shouldHydrate = parsed.hasHydrateExport || importsClientBoundary;
|
|
678
1076
|
return {
|
|
679
1077
|
isClientComponent: false,
|
|
680
|
-
shouldHydrate
|
|
1078
|
+
shouldHydrate,
|
|
1079
|
+
islandStrategy: shouldHydrate ? parsed.islandStrategy ?? importedIslandStrategy ?? "load" : null
|
|
681
1080
|
};
|
|
682
1081
|
}
|
|
683
1082
|
__name(inspectClientModuleMetadata, "inspectClientModuleMetadata");
|
|
@@ -855,6 +1254,10 @@ function parseInterceptionMarker(segment) {
|
|
|
855
1254
|
__name(parseInterceptionMarker, "parseInterceptionMarker");
|
|
856
1255
|
|
|
857
1256
|
// src/routing/route-manager.ts
|
|
1257
|
+
function shouldSuggestStaticRenderingForI18n(i18n) {
|
|
1258
|
+
return !i18n || i18n.routing === "prefix-always" || i18n.routing === "prefix-except-default" && i18n.detection.every((signal) => signal === "url");
|
|
1259
|
+
}
|
|
1260
|
+
__name(shouldSuggestStaticRenderingForI18n, "shouldSuggestStaticRenderingForI18n");
|
|
858
1261
|
function routeSpecificity(entry) {
|
|
859
1262
|
return entry.route.segments.reduce((score, segment) => {
|
|
860
1263
|
if (!segment.isDynamic) return score + 100;
|
|
@@ -1098,6 +1501,7 @@ var _RouteManager = class _RouteManager {
|
|
|
1098
1501
|
modulePath: toUrlPath(entry.modulePath),
|
|
1099
1502
|
shouldHydrate: metadata.shouldHydrate,
|
|
1100
1503
|
isClientComponent: metadata.isClientComponent,
|
|
1504
|
+
islandStrategy: metadata.islandStrategy,
|
|
1101
1505
|
search: getProgrammaticRouteSearchClientOptions(programmaticPage?.search),
|
|
1102
1506
|
segments: entry.route.segments.map((seg) => ({
|
|
1103
1507
|
segment: seg.segment,
|
|
@@ -1560,8 +1964,10 @@ var _RouteManager = class _RouteManager {
|
|
|
1560
1964
|
isDynamic: entry.route.segments.some((seg) => seg.isDynamic),
|
|
1561
1965
|
pattern: entry.pattern
|
|
1562
1966
|
}));
|
|
1563
|
-
const result = await collectSSGPages(routes, (filePath) => this.loadRouteModule(filePath));
|
|
1564
1967
|
const i18n = this.getI18nConfig();
|
|
1968
|
+
const result = await collectSSGPages(routes, (filePath) => this.loadRouteModule(filePath), {
|
|
1969
|
+
suggestStaticRendering: shouldSuggestStaticRenderingForI18n(i18n)
|
|
1970
|
+
});
|
|
1565
1971
|
if (!i18n) {
|
|
1566
1972
|
return result;
|
|
1567
1973
|
}
|
|
@@ -1693,7 +2099,7 @@ __name(safeGlobFiles, "safeGlobFiles");
|
|
|
1693
2099
|
|
|
1694
2100
|
// src/server/renderer.ts
|
|
1695
2101
|
import React from "react";
|
|
1696
|
-
import { renderToPipeableStream
|
|
2102
|
+
import { renderToPipeableStream } from "react-dom/server";
|
|
1697
2103
|
import * as fs2 from "fs";
|
|
1698
2104
|
import * as path5 from "path";
|
|
1699
2105
|
import { Writable } from "stream";
|
|
@@ -1844,7 +2250,8 @@ __name(transformFarmFontCalls, "transformFarmFontCalls");
|
|
|
1844
2250
|
function renderFarmFontDevHead(root) {
|
|
1845
2251
|
const registry = registries.get(normalizeRoot(root));
|
|
1846
2252
|
if (!registry || registry.production || registry.size === 0) return "";
|
|
1847
|
-
return registry.renderPreloadTags(false)
|
|
2253
|
+
return `${registry.renderPreloadTags(false)}
|
|
2254
|
+
<link rel="stylesheet" href="/@farm/fonts.css">`;
|
|
1848
2255
|
}
|
|
1849
2256
|
__name(renderFarmFontDevHead, "renderFarmFontDevHead");
|
|
1850
2257
|
var _FarmFontRegistry = class _FarmFontRegistry {
|
|
@@ -2026,6 +2433,10 @@ ${FONT_SECTION_END}
|
|
|
2026
2433
|
fallback,
|
|
2027
2434
|
display,
|
|
2028
2435
|
preload: raw.preload !== false,
|
|
2436
|
+
preloadResources: raw.preload === false ? [] : normalizedSources.map(({ resource }) => ({
|
|
2437
|
+
href: resourceUrl(resource, production, this.basePath),
|
|
2438
|
+
type: fontContentType(resource.extension)
|
|
2439
|
+
})),
|
|
2029
2440
|
weight: defaultWeight,
|
|
2030
2441
|
style: raw.style === void 0 ? void 0 : defaultStyle,
|
|
2031
2442
|
sources: normalizedSources
|
|
@@ -2122,7 +2533,7 @@ ${FONT_SECTION_END}
|
|
|
2122
2533
|
const normalizedExtension = extension.toLowerCase();
|
|
2123
2534
|
const hash = createHash2("sha256").update(bytes).digest("hex").slice(0, 12);
|
|
2124
2535
|
const baseName = sanitizeFileName(path4.basename(fileName, extension)) || "font";
|
|
2125
|
-
const outputFileName = `assets/fonts/${baseName}
|
|
2536
|
+
const outputFileName = `assets/fonts/${baseName}-h${hash}${normalizedExtension}`;
|
|
2126
2537
|
const key = `${hash}${normalizedExtension}`;
|
|
2127
2538
|
const existing = this.resources.get(key);
|
|
2128
2539
|
if (existing) return existing;
|
|
@@ -2392,7 +2803,8 @@ function serializeFontResult(font) {
|
|
|
2392
2803
|
fontFamily: stack,
|
|
2393
2804
|
...font.style ? { fontStyle: font.style } : {},
|
|
2394
2805
|
...font.weight !== void 0 && !String(font.weight).includes(" ") ? { fontWeight: font.weight } : {}
|
|
2395
|
-
}
|
|
2806
|
+
},
|
|
2807
|
+
preloads: font.preloadResources
|
|
2396
2808
|
});
|
|
2397
2809
|
}
|
|
2398
2810
|
__name(serializeFontResult, "serializeFontResult");
|
|
@@ -2812,7 +3224,7 @@ function createPPRRefreshScript() {
|
|
|
2812
3224
|
}
|
|
2813
3225
|
__name(createPPRRefreshScript, "createPPRRefreshScript");
|
|
2814
3226
|
function createPreHydrationClickQueueScript() {
|
|
2815
|
-
return `<script>(function(){if(window.__FARM_PREHYDRATION_CLICK_QUEUE__)return;var queue=[];window.__FARM_PREHYDRATION_CLICK_QUEUE__=queue;window.__FARM_HYDRATED__=false;document.documentElement.dataset.farmHydrated="false";function isModified(event){return !!(event.metaKey||event.altKey||event.ctrlKey||event.shiftKey)}function closestQueuedTarget(target){while(target&&target!==document.documentElement){if(target.matches&&target.matches('button,[role="button"],input[type="button"],input[type="submit"],input[type="reset"]'))return target;target=target.parentElement}return null}document.addEventListener("click",function(event){if(window.__FARM_HYDRATED__)return;if(event.defaultPrevented||event.button!==0||isModified(event))return;var target=closestQueuedTarget(event.target);if(!target||target.closest&&target.closest("a[href]"))return;if(queue.some(function(item){return item.target===target}))return;queue.push({target:target,createdAt:Date.now()});event.preventDefault();event.stopImmediatePropagation()},true);})();</script>`;
|
|
3227
|
+
return `<script>(function(){if(window.__FARM_PREHYDRATION_CLICK_QUEUE__)return;var queue=[];window.__FARM_PREHYDRATION_CLICK_QUEUE__=queue;window.__FARM_HYDRATED__=false;document.documentElement.dataset.farmHydrated="false";function isModified(event){return !!(event.metaKey||event.altKey||event.ctrlKey||event.shiftKey)}function closestQueuedTarget(target){while(target&&target!==document.documentElement){if(target.matches&&target.matches('button,[role="button"],input[type="button"],input[type="submit"],input[type="reset"]'))return target;target=target.parentElement}return null}document.addEventListener("click",function(event){if(window.__FARM_HYDRATED__)return;if(event.defaultPrevented||event.button!==0||isModified(event))return;var target=closestQueuedTarget(event.target);if(!target||target.closest&&target.closest("a[href]")||target.closest&&target.closest('[data-farm-island-hydrated="true"]'))return;if(queue.some(function(item){return item.target===target}))return;queue.push({target:target,createdAt:Date.now()});document.dispatchEvent(new CustomEvent("farm:island-interaction",{detail:{target:target}}));event.preventDefault();event.stopImmediatePropagation()},true);})();</script>`;
|
|
2816
3228
|
}
|
|
2817
3229
|
__name(createPreHydrationClickQueueScript, "createPreHydrationClickQueueScript");
|
|
2818
3230
|
function searchParamsToObject(searchParams) {
|
|
@@ -3423,6 +3835,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
3423
3835
|
req.__FARM_ROUTE__ = pathname;
|
|
3424
3836
|
req.__FARM_IS_CLIENT_COMPONENT__ = isClientComponent;
|
|
3425
3837
|
req.__FARM_SHOULD_HYDRATE__ = shouldHydrate;
|
|
3838
|
+
req.__FARM_ISLAND_STRATEGY__ = moduleMetadata.islandStrategy;
|
|
3426
3839
|
req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ = hasHydratableRouteSlots;
|
|
3427
3840
|
req.__FARM_LOADING_MODULE_PATH__ = loadingBoundaryEntry?.modulePath ? loadingBoundaryEntry.modulePath.substring(
|
|
3428
3841
|
loadingBoundaryEntry.modulePath.indexOf("/src/app/")
|
|
@@ -3498,7 +3911,12 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
3498
3911
|
if (isClientComponent || shouldHydrate) {
|
|
3499
3912
|
pageElement = React.createElement(
|
|
3500
3913
|
"div",
|
|
3501
|
-
{
|
|
3914
|
+
{
|
|
3915
|
+
id: "__farm_page__",
|
|
3916
|
+
"data-farm-client": "true",
|
|
3917
|
+
"data-farm-island": "page",
|
|
3918
|
+
"data-farm-island-strategy": moduleMetadata.islandStrategy ?? "load"
|
|
3919
|
+
},
|
|
3502
3920
|
pageElement
|
|
3503
3921
|
);
|
|
3504
3922
|
}
|
|
@@ -3743,6 +4161,13 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
3743
4161
|
return reference;
|
|
3744
4162
|
}
|
|
3745
4163
|
async renderMetadataImage(req, res, options) {
|
|
4164
|
+
const method = (req.method || "GET").toUpperCase();
|
|
4165
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
4166
|
+
res.statusCode = 405;
|
|
4167
|
+
res.setHeader("Allow", "GET, HEAD");
|
|
4168
|
+
res.end();
|
|
4169
|
+
return;
|
|
4170
|
+
}
|
|
3746
4171
|
if (options.image.sourceType === "static") {
|
|
3747
4172
|
if (!options.image.staticInfo) {
|
|
3748
4173
|
throw new Error(`Static metadata image ${options.image.modulePath} is missing file info`);
|
|
@@ -3768,42 +4193,12 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
3768
4193
|
await this.writeMetadataImageResponse(req, res, handlerResult, imageModule);
|
|
3769
4194
|
}
|
|
3770
4195
|
async writeMetadataImageResponse(req, res, value, imageModule) {
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
res.end();
|
|
3778
|
-
return;
|
|
3779
|
-
}
|
|
3780
|
-
const body2 = Buffer.from(await value.arrayBuffer());
|
|
3781
|
-
res.write(body2);
|
|
3782
|
-
res.end();
|
|
3783
|
-
return;
|
|
3784
|
-
}
|
|
3785
|
-
const contentType = imageModule.contentType || "image/svg+xml; charset=utf-8";
|
|
3786
|
-
let body;
|
|
3787
|
-
if (typeof value === "string") {
|
|
3788
|
-
body = value;
|
|
3789
|
-
} else if (value instanceof ArrayBuffer) {
|
|
3790
|
-
body = Buffer.from(value);
|
|
3791
|
-
} else if (ArrayBuffer.isView(value)) {
|
|
3792
|
-
body = Buffer.from(value.buffer, value.byteOffset, value.byteLength);
|
|
3793
|
-
} else if (React.isValidElement(value)) {
|
|
3794
|
-
body = renderToStaticMarkup(value);
|
|
3795
|
-
} else {
|
|
3796
|
-
throw new Error("Metadata image must return a Response, string, bytes, or React element");
|
|
3797
|
-
}
|
|
3798
|
-
res.statusCode = res.statusCode || 200;
|
|
3799
|
-
res.setHeader("Content-Type", contentType);
|
|
3800
|
-
res.setHeader("Cache-Control", "public, max-age=0, must-revalidate");
|
|
3801
|
-
if (req.method === "HEAD") {
|
|
3802
|
-
res.end();
|
|
3803
|
-
return;
|
|
3804
|
-
}
|
|
3805
|
-
res.write(body);
|
|
3806
|
-
res.end();
|
|
4196
|
+
const ifNoneMatch = req.headers["if-none-match"];
|
|
4197
|
+
const response = await createFarmMetadataImageResponse(value, imageModule, {
|
|
4198
|
+
method: req.method,
|
|
4199
|
+
ifNoneMatch: Array.isArray(ifNoneMatch) ? ifNoneMatch[0] : ifNoneMatch
|
|
4200
|
+
});
|
|
4201
|
+
await sendWebResponse(res, response);
|
|
3807
4202
|
}
|
|
3808
4203
|
async writeStaticMetadataImageResponse(req, res, image) {
|
|
3809
4204
|
const method = (req.method || "GET").toUpperCase();
|
|
@@ -3933,6 +4328,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
3933
4328
|
search: routeEntry.search,
|
|
3934
4329
|
isClientComponent: routeEntry.isClientComponent,
|
|
3935
4330
|
shouldHydrate: routeEntry.shouldHydrate,
|
|
4331
|
+
islandStrategy: routeEntry.islandStrategy,
|
|
3936
4332
|
preloads: [routeEntry.modulePath],
|
|
3937
4333
|
assets: []
|
|
3938
4334
|
};
|
|
@@ -3969,6 +4365,7 @@ window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue(deploymentId)};
|
|
|
3969
4365
|
window.__FARM_PATH__ = ${JSON.stringify(req.__FARM_ROUTE__ || req.url || "/")};
|
|
3970
4366
|
window.__FARM_IS_CLIENT__ = ${JSON.stringify(isClientComponent)};
|
|
3971
4367
|
window.__FARM_SHOULD_HYDRATE__ = ${JSON.stringify(req.__FARM_SHOULD_HYDRATE__ === true)};
|
|
4368
|
+
window.__FARM_ISLAND_STRATEGY__ = ${JSON.stringify(req.__FARM_ISLAND_STRATEGY__ || "load")};
|
|
3972
4369
|
window.__FARM_PAGE_MODULE__ = ${JSON.stringify(relativePath)};
|
|
3973
4370
|
window.__FARM_LOADING_MODULE__ = ${JSON.stringify(
|
|
3974
4371
|
req.__FARM_LOADING_MODULE_PATH__ || null
|
|
@@ -4329,6 +4726,7 @@ var _FarmApp = class _FarmApp {
|
|
|
4329
4726
|
context: config.context || (() => void 0),
|
|
4330
4727
|
serverActions: resolveServerActionsConfig(config.serverActions),
|
|
4331
4728
|
images: resolveFarmImageConfig(config.images),
|
|
4729
|
+
performance: resolveFarmPerformanceConfig(config.performance),
|
|
4332
4730
|
i18n: isResolvedI18nConfig(config.i18n) ? config.i18n : resolveFarmI18nConfig(config.i18n, {
|
|
4333
4731
|
root,
|
|
4334
4732
|
mode: process.env.NODE_ENV === "production" ? "production" : "development"
|
|
@@ -5075,7 +5473,7 @@ __name(removeLegacyTypeArtifacts, "removeLegacyTypeArtifacts");
|
|
|
5075
5473
|
|
|
5076
5474
|
// src/vite.ts
|
|
5077
5475
|
import * as fs4 from "fs";
|
|
5078
|
-
import * as
|
|
5476
|
+
import * as path11 from "path";
|
|
5079
5477
|
|
|
5080
5478
|
// src/image-vite.ts
|
|
5081
5479
|
import { readFile as readFile4 } from "fs/promises";
|
|
@@ -5146,6 +5544,100 @@ async function createBlurDataURL(bytes) {
|
|
|
5146
5544
|
}
|
|
5147
5545
|
__name(createBlurDataURL, "createBlurDataURL");
|
|
5148
5546
|
|
|
5547
|
+
// src/server/vite-config.ts
|
|
5548
|
+
import path10 from "path";
|
|
5549
|
+
var FARM_CLIENT_ENTRY_PATTERN = "**/{page,layout,loading,error,not-found,default}.{js,jsx,ts,tsx}";
|
|
5550
|
+
var FARM_CLIENT_OPTIMIZE_DEPS_INCLUDE = [
|
|
5551
|
+
"react",
|
|
5552
|
+
"react-dom",
|
|
5553
|
+
"react-dom/client",
|
|
5554
|
+
"react/jsx-runtime",
|
|
5555
|
+
"react/jsx-dev-runtime",
|
|
5556
|
+
"@farm.js/core/client",
|
|
5557
|
+
"@farm.js/core/plugin/client",
|
|
5558
|
+
"@farm.js/core/deferred",
|
|
5559
|
+
"@farm.js/core/deployment",
|
|
5560
|
+
"@farm.js/core/i18n/client",
|
|
5561
|
+
"@farm.js/core/query/client",
|
|
5562
|
+
"@farm.js/core/server-fn/client",
|
|
5563
|
+
"@farm.js/core/server-query/client"
|
|
5564
|
+
];
|
|
5565
|
+
function createFarmClientOptimizeDepsEntries(projectRoot, appDirectories) {
|
|
5566
|
+
const resolvedProjectRoot = path10.resolve(projectRoot);
|
|
5567
|
+
return appDirectories.map((appDirectory) => {
|
|
5568
|
+
const relativeAppDirectory = path10.relative(resolvedProjectRoot, path10.resolve(appDirectory)).replace(/\\/g, "/");
|
|
5569
|
+
const prefix = relativeAppDirectory || ".";
|
|
5570
|
+
return `${prefix}/${FARM_CLIENT_ENTRY_PATTERN}`;
|
|
5571
|
+
});
|
|
5572
|
+
}
|
|
5573
|
+
__name(createFarmClientOptimizeDepsEntries, "createFarmClientOptimizeDepsEntries");
|
|
5574
|
+
function createFarmClientOptimizeDepsConfig(entries) {
|
|
5575
|
+
return {
|
|
5576
|
+
// Keep normal application dependency discovery for CJS-only packages, but
|
|
5577
|
+
// seed every Farm browser runtime so React is present in the first crawl.
|
|
5578
|
+
noDiscovery: false,
|
|
5579
|
+
// Waiting for the crawl avoids serving a partial optimizer generation and
|
|
5580
|
+
// then changing browser hashes while hydration is already in progress.
|
|
5581
|
+
holdUntilCrawlEnd: true,
|
|
5582
|
+
include: [...FARM_CLIENT_OPTIMIZE_DEPS_INCLUDE],
|
|
5583
|
+
// Farm's HTML boots through a virtual module and imports route UI lazily.
|
|
5584
|
+
// Explicit entries let Vite finish that crawl before a navigation can
|
|
5585
|
+
// rotate the optimizer hash underneath a hydrated React runtime.
|
|
5586
|
+
...entries?.length ? { entries: [...entries] } : {}
|
|
5587
|
+
};
|
|
5588
|
+
}
|
|
5589
|
+
__name(createFarmClientOptimizeDepsConfig, "createFarmClientOptimizeDepsConfig");
|
|
5590
|
+
function mergeNoExternal(farmValue, userValue) {
|
|
5591
|
+
if (farmValue === true || userValue === true) return true;
|
|
5592
|
+
const normalize = /* @__PURE__ */ __name((value) => value == null || value === true ? [] : Array.isArray(value) ? value : [value], "normalize");
|
|
5593
|
+
return Array.from(/* @__PURE__ */ new Set([...normalize(farmValue), ...normalize(userValue)]));
|
|
5594
|
+
}
|
|
5595
|
+
__name(mergeNoExternal, "mergeNoExternal");
|
|
5596
|
+
function mergeFarmViteConfig(farmConfig, userConfig = {}) {
|
|
5597
|
+
const noDiscovery = userConfig.optimizeDeps?.noDiscovery ?? farmConfig.optimizeDeps?.noDiscovery;
|
|
5598
|
+
const holdUntilCrawlEnd = userConfig.optimizeDeps?.holdUntilCrawlEnd ?? (userConfig.optimizeDeps?.noDiscovery === true ? false : farmConfig.optimizeDeps?.holdUntilCrawlEnd);
|
|
5599
|
+
return {
|
|
5600
|
+
...farmConfig,
|
|
5601
|
+
...userConfig,
|
|
5602
|
+
plugins: [...farmConfig.plugins || [], ...userConfig.plugins || []],
|
|
5603
|
+
server: {
|
|
5604
|
+
...farmConfig.server,
|
|
5605
|
+
...userConfig.server
|
|
5606
|
+
},
|
|
5607
|
+
resolve: {
|
|
5608
|
+
...farmConfig.resolve,
|
|
5609
|
+
...userConfig.resolve,
|
|
5610
|
+
dedupe: Array.from(
|
|
5611
|
+
/* @__PURE__ */ new Set([...farmConfig.resolve?.dedupe || [], ...userConfig.resolve?.dedupe || []])
|
|
5612
|
+
)
|
|
5613
|
+
},
|
|
5614
|
+
optimizeDeps: {
|
|
5615
|
+
...farmConfig.optimizeDeps,
|
|
5616
|
+
...userConfig.optimizeDeps,
|
|
5617
|
+
noDiscovery,
|
|
5618
|
+
holdUntilCrawlEnd,
|
|
5619
|
+
include: Array.from(
|
|
5620
|
+
/* @__PURE__ */ new Set([
|
|
5621
|
+
...farmConfig.optimizeDeps?.include || [],
|
|
5622
|
+
...userConfig.optimizeDeps?.include || []
|
|
5623
|
+
])
|
|
5624
|
+
),
|
|
5625
|
+
exclude: Array.from(
|
|
5626
|
+
/* @__PURE__ */ new Set([
|
|
5627
|
+
...farmConfig.optimizeDeps?.exclude || [],
|
|
5628
|
+
...userConfig.optimizeDeps?.exclude || []
|
|
5629
|
+
])
|
|
5630
|
+
)
|
|
5631
|
+
},
|
|
5632
|
+
ssr: {
|
|
5633
|
+
...farmConfig.ssr,
|
|
5634
|
+
...userConfig.ssr,
|
|
5635
|
+
noExternal: mergeNoExternal(farmConfig.ssr?.noExternal, userConfig.ssr?.noExternal)
|
|
5636
|
+
}
|
|
5637
|
+
};
|
|
5638
|
+
}
|
|
5639
|
+
__name(mergeFarmViteConfig, "mergeFarmViteConfig");
|
|
5640
|
+
|
|
5149
5641
|
// src/vite.ts
|
|
5150
5642
|
var ALL_TYPE_ARTIFACTS = {
|
|
5151
5643
|
routes: true,
|
|
@@ -5188,7 +5680,7 @@ function loadFarmWorkflowsDevRuntime() {
|
|
|
5188
5680
|
}
|
|
5189
5681
|
__name(loadFarmWorkflowsDevRuntime, "loadFarmWorkflowsDevRuntime");
|
|
5190
5682
|
function loadFarmDevtoolsSnapshotRuntime() {
|
|
5191
|
-
return import("./devtools-
|
|
5683
|
+
return import("./devtools-GAZ7F3KL.mjs");
|
|
5192
5684
|
}
|
|
5193
5685
|
__name(loadFarmDevtoolsSnapshotRuntime, "loadFarmDevtoolsSnapshotRuntime");
|
|
5194
5686
|
function loadFarmDevtoolsUIRuntime() {
|
|
@@ -5367,7 +5859,7 @@ function fileContainsProgrammaticPageRoute(file) {
|
|
|
5367
5859
|
__name(fileContainsProgrammaticPageRoute, "fileContainsProgrammaticPageRoute");
|
|
5368
5860
|
function rewriteEarlySsrRelativeImports(options) {
|
|
5369
5861
|
const cleanId = options.id.split("?", 1)[0];
|
|
5370
|
-
if (!
|
|
5862
|
+
if (!path11.isAbsolute(cleanId) || cleanId.replace(/\\/g, "/").includes("/node_modules/")) {
|
|
5371
5863
|
return null;
|
|
5372
5864
|
}
|
|
5373
5865
|
const replacements = [];
|
|
@@ -5387,7 +5879,7 @@ function rewriteEarlySsrRelativeImports(options) {
|
|
|
5387
5879
|
const suffixIndex = source.value.search(/[?#]/);
|
|
5388
5880
|
const sourcePath = suffixIndex === -1 ? source.value : source.value.slice(0, suffixIndex);
|
|
5389
5881
|
const suffix = suffixIndex === -1 ? "" : source.value.slice(suffixIndex);
|
|
5390
|
-
const resolvedPath =
|
|
5882
|
+
const resolvedPath = path11.resolve(path11.dirname(cleanId), sourcePath);
|
|
5391
5883
|
replacements.push({
|
|
5392
5884
|
start: source.start,
|
|
5393
5885
|
end: source.end,
|
|
@@ -5472,7 +5964,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5472
5964
|
...layerRoots.length ? {
|
|
5473
5965
|
server: {
|
|
5474
5966
|
fs: {
|
|
5475
|
-
allow: [
|
|
5967
|
+
allow: [path11.resolve(options.root || process.cwd()), ...layerRoots]
|
|
5476
5968
|
}
|
|
5477
5969
|
}
|
|
5478
5970
|
} : {}
|
|
@@ -5503,9 +5995,9 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5503
5995
|
},
|
|
5504
5996
|
server
|
|
5505
5997
|
);
|
|
5506
|
-
const globalsCSSPath =
|
|
5998
|
+
const globalsCSSPath = path11.join(server.config.root, "src/app/globals.css");
|
|
5507
5999
|
if (!fs4.existsSync(globalsCSSPath)) {
|
|
5508
|
-
const appDir =
|
|
6000
|
+
const appDir = path11.join(server.config.root, "src/app");
|
|
5509
6001
|
if (!fs4.existsSync(appDir)) {
|
|
5510
6002
|
fs4.mkdirSync(appDir, { recursive: true });
|
|
5511
6003
|
}
|
|
@@ -5527,10 +6019,10 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5527
6019
|
});
|
|
5528
6020
|
}
|
|
5529
6021
|
const sourceRoots = getFarmSourceRoots(farmConfig);
|
|
5530
|
-
server.watcher.add(sourceRoots.map((source) =>
|
|
6022
|
+
server.watcher.add(sourceRoots.map((source) => path11.join(source.root, source.srcDir)));
|
|
5531
6023
|
if (farmConfig.i18n.enabled) {
|
|
5532
6024
|
server.watcher.add(
|
|
5533
|
-
farmConfig.i18n.messages.includes("{locale}") ?
|
|
6025
|
+
farmConfig.i18n.messages.includes("{locale}") ? path11.dirname(farmConfig.i18n.messages) : farmConfig.i18n.messages
|
|
5534
6026
|
);
|
|
5535
6027
|
}
|
|
5536
6028
|
const workflowConfig = farmConfig.workflows;
|
|
@@ -5540,7 +6032,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5540
6032
|
...farmDocsDevRuntime?.getFarmDocsRouteTypeEntries(farmConfig.docs) ?? []
|
|
5541
6033
|
], "getExtraRouteTypes");
|
|
5542
6034
|
const appDirSlugs = sourceRoots.map(
|
|
5543
|
-
(source) =>
|
|
6035
|
+
(source) => path11.join(source.root, source.srcDir, "app").replace(/\\/g, "/")
|
|
5544
6036
|
);
|
|
5545
6037
|
const generateTypeArtifacts = /* @__PURE__ */ __name(async (reason, selection = ALL_TYPE_ARTIFACTS, log = false) => {
|
|
5546
6038
|
try {
|
|
@@ -5580,7 +6072,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5580
6072
|
}, "generateTypeArtifacts");
|
|
5581
6073
|
await generateTypeArtifacts("startup");
|
|
5582
6074
|
const srcDirSlugs = sourceRoots.map(
|
|
5583
|
-
(source) =>
|
|
6075
|
+
(source) => path11.join(source.root, source.srcDir).replace(/\\/g, "/")
|
|
5584
6076
|
);
|
|
5585
6077
|
const layerConfigFiles = new Set(
|
|
5586
6078
|
farmConfig.layers.map((layer) => layer.configFile?.replace(/\\/g, "/")).filter((file) => Boolean(file))
|
|
@@ -5698,7 +6190,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5698
6190
|
await apiRouteManager.discoverRoutes();
|
|
5699
6191
|
let discoveredWorkflows = [];
|
|
5700
6192
|
const hasWorkflowDirectory = workflowConfig.enabled && workflowConfig.dirs.some(
|
|
5701
|
-
(dir) => fs4.existsSync(
|
|
6193
|
+
(dir) => fs4.existsSync(path11.isAbsolute(dir) ? dir : path11.join(farmConfig.root, dir))
|
|
5702
6194
|
);
|
|
5703
6195
|
if (hasWorkflowDirectory) {
|
|
5704
6196
|
const { createFarmWorkflowRequestHandler, discoverFarmWorkflows } = await loadFarmWorkflowsDevRuntime();
|
|
@@ -5762,10 +6254,20 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5762
6254
|
logger.info(`Refreshed routes: ${reason}`);
|
|
5763
6255
|
}
|
|
5764
6256
|
}, "refreshRouteDiscovery");
|
|
6257
|
+
const farmDocsFontAssetList = farmDocsDevRuntime ? resolveFarmDocsFontAssets(farmConfig.root) : [];
|
|
5765
6258
|
const farmDocsHandler = farmDocsDevRuntime ? farmDocsDevRuntime.createFarmDocsHandler(farmConfig.docs, {
|
|
5766
6259
|
root: farmConfig.root,
|
|
5767
6260
|
srcDir: farmConfig.srcDir,
|
|
5768
|
-
clientEntry: "/@farm/client.js"
|
|
6261
|
+
clientEntry: "/@farm/client.js",
|
|
6262
|
+
fontAssets: toFarmDocsPublicFontAssets(farmDocsFontAssetList),
|
|
6263
|
+
resolveLayoutFonts: /* @__PURE__ */ __name(async (pathname) => {
|
|
6264
|
+
const layouts = routeManager.matchRoute(pathname).layouts;
|
|
6265
|
+
const layoutModules = await Promise.all(
|
|
6266
|
+
layouts.map((layout) => routeManager.loadLayoutModule(layout.modulePath))
|
|
6267
|
+
);
|
|
6268
|
+
return resolveFarmLayoutFonts(layoutModules);
|
|
6269
|
+
}, "resolveLayoutFonts"),
|
|
6270
|
+
fontStylesheetHref: "/@farm/fonts.css"
|
|
5769
6271
|
}) : null;
|
|
5770
6272
|
const farmDocsAPIHandler = farmDocsDevRuntime ? farmDocsDevRuntime.createFarmDocsAPIHandler({
|
|
5771
6273
|
rootDir: farmConfig.root,
|
|
@@ -5773,22 +6275,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5773
6275
|
docs: farmConfig.docs
|
|
5774
6276
|
}) : null;
|
|
5775
6277
|
const farmDocsFontAssets = new Map(
|
|
5776
|
-
|
|
5777
|
-
[
|
|
5778
|
-
"/assets/Geist-Variable-CrgPqtmy.woff2",
|
|
5779
|
-
path10.join(
|
|
5780
|
-
farmConfig.root,
|
|
5781
|
-
"node_modules/geist/dist/fonts/geist-sans/Geist-Variable.woff2"
|
|
5782
|
-
)
|
|
5783
|
-
],
|
|
5784
|
-
[
|
|
5785
|
-
"/assets/GeistMono-Variable-BNLlm6Cd.woff2",
|
|
5786
|
-
path10.join(
|
|
5787
|
-
farmConfig.root,
|
|
5788
|
-
"node_modules/geist/dist/fonts/geist-mono/GeistMono-Variable.woff2"
|
|
5789
|
-
)
|
|
5790
|
-
]
|
|
5791
|
-
] : []
|
|
6278
|
+
farmDocsFontAssetList.map(({ url, sourcePath }) => [url, sourcePath])
|
|
5792
6279
|
);
|
|
5793
6280
|
const logRequest = /* @__PURE__ */ __name((method, urlPath, tag) => {
|
|
5794
6281
|
try {
|
|
@@ -5852,11 +6339,12 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5852
6339
|
}
|
|
5853
6340
|
}
|
|
5854
6341
|
const farmDocsFontPath = farmDocsFontAssets.get(requestPathname);
|
|
5855
|
-
if (farmDocsFontPath && fs4.existsSync(farmDocsFontPath)) {
|
|
6342
|
+
if ((requestMethod === "GET" || requestMethod === "HEAD") && farmDocsFontPath && fs4.existsSync(farmDocsFontPath)) {
|
|
5856
6343
|
res.statusCode = 200;
|
|
5857
6344
|
res.setHeader("Content-Type", "font/woff2");
|
|
5858
6345
|
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
|
5859
|
-
|
|
6346
|
+
if (requestMethod === "HEAD") res.end();
|
|
6347
|
+
else fs4.createReadStream(farmDocsFontPath).pipe(res);
|
|
5860
6348
|
return;
|
|
5861
6349
|
}
|
|
5862
6350
|
if (requestMethod === "GET" && (requestPathname === FARM_DEVTOOLS_PATH || requestPathname === `${FARM_DEVTOOLS_PATH}.json`)) {
|
|
@@ -6462,6 +6950,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
6462
6950
|
modulePath: toUrlPath(route.modulePath),
|
|
6463
6951
|
isClientComponent: routeSlots.length > 0 ? false : isClientComponent,
|
|
6464
6952
|
shouldHydrate: shouldHydrate || routeSlots.some((slot) => slot.isClientComponent || slot.shouldHydrate),
|
|
6953
|
+
islandStrategy: moduleMetadata.islandStrategy,
|
|
6465
6954
|
metadata: {
|
|
6466
6955
|
title: mergedMetadata.title,
|
|
6467
6956
|
description: mergedMetadata.description
|
|
@@ -6846,6 +7335,7 @@ export const getManifest = () => ({
|
|
|
6846
7335
|
search: route.search,
|
|
6847
7336
|
isClientComponent: moduleMetadata.isClientComponent,
|
|
6848
7337
|
shouldHydrate: moduleMetadata.shouldHydrate,
|
|
7338
|
+
islandStrategy: moduleMetadata.islandStrategy,
|
|
6849
7339
|
preloads: [route.modulePath],
|
|
6850
7340
|
// In dev, preload is just the module
|
|
6851
7341
|
assets: []
|
|
@@ -6972,8 +7462,8 @@ if (import.meta.hot) {
|
|
|
6972
7462
|
}
|
|
6973
7463
|
logger.info(`Found ${ssgPages.length} SSG pages, ${ssrRoutes.length} SSR routes`);
|
|
6974
7464
|
logger.info("Pre-rendering SSG pages...");
|
|
6975
|
-
const outDir =
|
|
6976
|
-
const clientDir =
|
|
7465
|
+
const outDir = path11.join(server?.config.root || process.cwd(), options.outDir || "dist");
|
|
7466
|
+
const clientDir = path11.join(outDir, "client");
|
|
6977
7467
|
for (const page of ssgPages) {
|
|
6978
7468
|
try {
|
|
6979
7469
|
const staticRequest = new Request(new URL(page.urlPath, "http://farm.static"));
|
|
@@ -7025,8 +7515,8 @@ if (import.meta.hot) {
|
|
|
7025
7515
|
<script type="module" src="/assets/client.js"></script>
|
|
7026
7516
|
</body>
|
|
7027
7517
|
</html>`;
|
|
7028
|
-
const outputPath = page.urlPath === "/" ?
|
|
7029
|
-
fs4.mkdirSync(
|
|
7518
|
+
const outputPath = page.urlPath === "/" ? path11.join(clientDir, "index.html") : path11.join(clientDir, page.urlPath + ".html");
|
|
7519
|
+
fs4.mkdirSync(path11.dirname(outputPath), { recursive: true });
|
|
7030
7520
|
fs4.writeFileSync(outputPath, fullHtml);
|
|
7031
7521
|
const revalidateInfo = page.revalidate ? ` (revalidate: ${page.revalidate}s)` : "";
|
|
7032
7522
|
logger.success(` \u2713 ${page.urlPath}${revalidateInfo}`);
|
|
@@ -7035,7 +7525,7 @@ if (import.meta.hot) {
|
|
|
7035
7525
|
logger.error(` \u2717 ${page.urlPath}: ${error}`);
|
|
7036
7526
|
}
|
|
7037
7527
|
}
|
|
7038
|
-
const manifestPath =
|
|
7528
|
+
const manifestPath = path11.join(outDir, "__ssg_manifest.json");
|
|
7039
7529
|
fs4.writeFileSync(
|
|
7040
7530
|
manifestPath,
|
|
7041
7531
|
JSON.stringify(
|
|
@@ -7071,9 +7561,9 @@ if (import.meta.hot) {
|
|
|
7071
7561
|
}
|
|
7072
7562
|
const currentFarmConfig = farmApp?.getConfig();
|
|
7073
7563
|
const normalizedFile = file.replace(/\\/g, "/");
|
|
7074
|
-
const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) =>
|
|
7564
|
+
const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) => path11.join(source.root, source.srcDir).replace(/\\/g, "/")).find((sourceRoot) => normalizedFile.startsWith(`${sourceRoot}/`)) || null : null;
|
|
7075
7565
|
if (currentSrcRoot && normalizedFile.startsWith(`${currentSrcRoot}/`) && isProgrammaticRoutesFileName(normalizedFile)) {
|
|
7076
|
-
logUpdate("PAGE", `updated ${
|
|
7566
|
+
logUpdate("PAGE", `updated ${path11.basename(file)}`);
|
|
7077
7567
|
for (const mod of modules) {
|
|
7078
7568
|
server2.moduleGraph.invalidateModule(mod);
|
|
7079
7569
|
}
|
|
@@ -7470,6 +7960,7 @@ import React from 'react'
|
|
|
7470
7960
|
import { hydrateRoot, createRoot } from 'react-dom/client'
|
|
7471
7961
|
import { installChunkErrorRecovery, SPARouter } from '@farm.js/core/client'
|
|
7472
7962
|
import { createClientPluginManager } from '@farm.js/core/plugin/client'
|
|
7963
|
+
import { scheduleFarmIslandHydration } from '@farm.js/core/internal/client-runtime'
|
|
7473
7964
|
import { reviveDeferredData } from '@farm.js/core/deferred'
|
|
7474
7965
|
import {
|
|
7475
7966
|
createFarmDeploymentMismatchError,
|
|
@@ -7722,6 +8213,7 @@ class LegacyManifestSPARouter {
|
|
|
7722
8213
|
|
|
7723
8214
|
// Only prefetch routes that will hydrate on the client.
|
|
7724
8215
|
if (!match.route.isClientComponent && !match.route.shouldHydrate) return;
|
|
8216
|
+
if (match.route.islandStrategy && match.route.islandStrategy !== 'load') return;
|
|
7725
8217
|
|
|
7726
8218
|
const modulePath = match.route.modulePath;
|
|
7727
8219
|
if (this.moduleCache.has(modulePath)) return;
|
|
@@ -7866,6 +8358,12 @@ let hasClientTakenOver = false;
|
|
|
7866
8358
|
const routeSlotRoots = new Map();
|
|
7867
8359
|
const routeSlotDefinitions = new Map();
|
|
7868
8360
|
let activeRouteInterception = null;
|
|
8361
|
+
let pendingPageHydrationController = null;
|
|
8362
|
+
|
|
8363
|
+
function cancelPendingPageHydration() {
|
|
8364
|
+
pendingPageHydrationController?.abort();
|
|
8365
|
+
pendingPageHydrationController = null;
|
|
8366
|
+
}
|
|
7869
8367
|
|
|
7870
8368
|
function normalizeServerProps(rawProps) {
|
|
7871
8369
|
const props = rawProps && typeof rawProps === 'object' ? { ...rawProps } : {};
|
|
@@ -7934,7 +8432,11 @@ async function hydrateInitialRouteSlots() {
|
|
|
7934
8432
|
routeSlotDefinitions.set(getRouteSlotKey(slot), slot);
|
|
7935
8433
|
if (!slot.isClientComponent && !slot.shouldHydrate) continue;
|
|
7936
8434
|
try {
|
|
7937
|
-
|
|
8435
|
+
const slotHydrated = await renderRouteSlot(slot, 'hydrate');
|
|
8436
|
+
hydrated = slotHydrated || hydrated;
|
|
8437
|
+
if (slotHydrated) {
|
|
8438
|
+
replayPreHydrationClicks(document.getElementById(slot.containerId));
|
|
8439
|
+
}
|
|
7938
8440
|
} catch (error) {
|
|
7939
8441
|
console.warn('[Farm.js] Could not hydrate route slot:', slot.name, error);
|
|
7940
8442
|
}
|
|
@@ -8005,16 +8507,29 @@ function applyCanonicalPathFromProps(props) {
|
|
|
8005
8507
|
window.history.replaceState({ ...(window.history.state || {}), path: canonicalPath }, '', canonicalPath);
|
|
8006
8508
|
}
|
|
8007
8509
|
|
|
8008
|
-
function replayPreHydrationClicks() {
|
|
8009
|
-
|
|
8010
|
-
|
|
8510
|
+
function replayPreHydrationClicks(container = null) {
|
|
8511
|
+
if (!container) {
|
|
8512
|
+
markFarmHydrated();
|
|
8513
|
+
} else {
|
|
8514
|
+
container.dataset.farmIslandHydrated = 'true';
|
|
8515
|
+
}
|
|
8011
8516
|
|
|
8012
8517
|
const queue = Array.isArray(window.__FARM_PREHYDRATION_CLICK_QUEUE__)
|
|
8013
8518
|
? window.__FARM_PREHYDRATION_CLICK_QUEUE__
|
|
8014
8519
|
: [];
|
|
8015
8520
|
if (queue.length === 0) return;
|
|
8016
8521
|
|
|
8017
|
-
const queuedClicks =
|
|
8522
|
+
const queuedClicks = [];
|
|
8523
|
+
const remainingClicks = [];
|
|
8524
|
+
for (const queuedClick of queue) {
|
|
8525
|
+
const target = queuedClick?.target;
|
|
8526
|
+
if (!container || (target instanceof Node && container.contains(target))) {
|
|
8527
|
+
queuedClicks.push(queuedClick);
|
|
8528
|
+
} else {
|
|
8529
|
+
remainingClicks.push(queuedClick);
|
|
8530
|
+
}
|
|
8531
|
+
}
|
|
8532
|
+
queue.splice(0, queue.length, ...remainingClicks);
|
|
8018
8533
|
for (const queuedClick of queuedClicks) {
|
|
8019
8534
|
const target = queuedClick?.target;
|
|
8020
8535
|
if (!target || typeof target.click !== 'function') continue;
|
|
@@ -8023,6 +8538,11 @@ function replayPreHydrationClicks() {
|
|
|
8023
8538
|
}
|
|
8024
8539
|
}
|
|
8025
8540
|
|
|
8541
|
+
function markFarmHydrated() {
|
|
8542
|
+
window.__FARM_HYDRATED__ = true;
|
|
8543
|
+
document.documentElement.dataset.farmHydrated = 'true';
|
|
8544
|
+
}
|
|
8545
|
+
|
|
8026
8546
|
async function buildClientHydrationElement(PageComponent, pageProps) {
|
|
8027
8547
|
let element = React.createElement(PageComponent, pageProps);
|
|
8028
8548
|
const loadingModulePath = window.__FARM_LOADING_MODULE__;
|
|
@@ -8165,9 +8685,10 @@ async function tryHydrateImportedPage(
|
|
|
8165
8685
|
layouts,
|
|
8166
8686
|
useHydrate = false,
|
|
8167
8687
|
existingProps = null,
|
|
8688
|
+
signal = null,
|
|
8168
8689
|
) {
|
|
8169
8690
|
const modulePath = route?.modulePath;
|
|
8170
|
-
if (!modulePath) {
|
|
8691
|
+
if (!modulePath || signal?.aborted) {
|
|
8171
8692
|
return false;
|
|
8172
8693
|
}
|
|
8173
8694
|
|
|
@@ -8176,6 +8697,7 @@ async function tryHydrateImportedPage(
|
|
|
8176
8697
|
pageModule = await import(/* @vite-ignore */ modulePath);
|
|
8177
8698
|
pageModuleCache.set(modulePath, pageModule);
|
|
8178
8699
|
}
|
|
8700
|
+
if (signal?.aborted || !container?.isConnected) return false;
|
|
8179
8701
|
|
|
8180
8702
|
const PageComponent = pageModule?.default;
|
|
8181
8703
|
if (!PageComponent) {
|
|
@@ -8190,6 +8712,7 @@ async function tryHydrateImportedPage(
|
|
|
8190
8712
|
window.location.pathname,
|
|
8191
8713
|
existingProps,
|
|
8192
8714
|
);
|
|
8715
|
+
if (signal?.aborted || !container?.isConnected) return false;
|
|
8193
8716
|
|
|
8194
8717
|
const wrappedElement = useHydrate && container?.id === '__farm_page__'
|
|
8195
8718
|
? wrapWithIntegrationProviders(
|
|
@@ -8200,6 +8723,7 @@ async function tryHydrateImportedPage(
|
|
|
8200
8723
|
currentPageProps,
|
|
8201
8724
|
layouts,
|
|
8202
8725
|
);
|
|
8726
|
+
if (signal?.aborted || !container?.isConnected) return false;
|
|
8203
8727
|
|
|
8204
8728
|
if (useHydrate) {
|
|
8205
8729
|
try {
|
|
@@ -8230,6 +8754,7 @@ async function tryHydrateImportedPage(
|
|
|
8230
8754
|
async function renderPage(pageData) {
|
|
8231
8755
|
const container = document.getElementById('root');
|
|
8232
8756
|
if (!container) return;
|
|
8757
|
+
cancelPendingPageHydration();
|
|
8233
8758
|
const destination = window.location.pathname + window.location.search;
|
|
8234
8759
|
|
|
8235
8760
|
if (pageData.interception) {
|
|
@@ -8246,6 +8771,7 @@ async function renderPage(pageData) {
|
|
|
8246
8771
|
modulePath: pageData.modulePath,
|
|
8247
8772
|
isClientComponent: pageData.isClientComponent === true,
|
|
8248
8773
|
shouldHydrate: pageData.shouldHydrate === true,
|
|
8774
|
+
islandStrategy: pageData.islandStrategy || 'load',
|
|
8249
8775
|
};
|
|
8250
8776
|
const params = pageData.props?.params || {};
|
|
8251
8777
|
const layouts = (pageData.layoutModules || []).map((modulePath, index) => ({
|
|
@@ -8445,14 +8971,6 @@ async function hydrate() {
|
|
|
8445
8971
|
}
|
|
8446
8972
|
|
|
8447
8973
|
try {
|
|
8448
|
-
// Pre-load layout for SPA navigation
|
|
8449
|
-
try {
|
|
8450
|
-
const layoutModule = await import(/* @vite-ignore */ '/src/app/layout.tsx');
|
|
8451
|
-
LayoutComponent = layoutModule.default;
|
|
8452
|
-
} catch (e) {
|
|
8453
|
-
console.warn('[Farm.js] Could not preload layout:', e);
|
|
8454
|
-
}
|
|
8455
|
-
|
|
8456
8974
|
// Check if this is a client component (set by SSR)
|
|
8457
8975
|
const isClientComponent = window.__FARM_IS_CLIENT__ === true;
|
|
8458
8976
|
const modulePath = window.__FARM_PAGE_MODULE__;
|
|
@@ -8500,34 +9018,88 @@ async function hydrate() {
|
|
|
8500
9018
|
return
|
|
8501
9019
|
}
|
|
8502
9020
|
|
|
8503
|
-
const
|
|
8504
|
-
|
|
8505
|
-
|
|
8506
|
-
|
|
9021
|
+
const currentRoute = findRoute(window.location.pathname)?.route;
|
|
9022
|
+
const islandStrategy = window.__FARM_ISLAND_STRATEGY__ || currentRoute?.islandStrategy || 'load';
|
|
9023
|
+
pageContainer.dataset.farmIsland = 'page';
|
|
9024
|
+
pageContainer.dataset.farmIslandStrategy = islandStrategy;
|
|
8507
9025
|
|
|
8508
|
-
|
|
9026
|
+
const hydrationPathname = window.location.pathname;
|
|
9027
|
+
const hydrationController = new AbortController();
|
|
9028
|
+
pendingPageHydrationController = hydrationController;
|
|
8509
9029
|
try {
|
|
8510
|
-
|
|
8511
|
-
pageContainer,
|
|
8512
|
-
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
8522
|
-
}
|
|
9030
|
+
await scheduleFarmIslandHydration({
|
|
9031
|
+
container: pageContainer,
|
|
9032
|
+
strategy: islandStrategy,
|
|
9033
|
+
signal: hydrationController.signal,
|
|
9034
|
+
hydrate: async () => {
|
|
9035
|
+
if (
|
|
9036
|
+
hydrationController.signal.aborted ||
|
|
9037
|
+
!pageContainer.isConnected ||
|
|
9038
|
+
window.location.pathname !== hydrationPathname
|
|
9039
|
+
) {
|
|
9040
|
+
return;
|
|
9041
|
+
}
|
|
8523
9042
|
|
|
8524
|
-
|
|
8525
|
-
|
|
8526
|
-
|
|
8527
|
-
|
|
8528
|
-
|
|
9043
|
+
// Layout code is only needed when this route boundary actually hydrates.
|
|
9044
|
+
try {
|
|
9045
|
+
const layoutModule = await import(/* @vite-ignore */ '/src/app/layout.tsx');
|
|
9046
|
+
LayoutComponent = layoutModule.default;
|
|
9047
|
+
} catch (e) {
|
|
9048
|
+
console.warn('[Farm.js] Could not preload layout:', e);
|
|
9049
|
+
}
|
|
9050
|
+
if (hydrationController.signal.aborted || !pageContainer.isConnected) return;
|
|
8529
9051
|
|
|
8530
|
-
|
|
9052
|
+
const hydrationSession = await farmClientRuntime.beginHydration({
|
|
9053
|
+
container: pageContainer,
|
|
9054
|
+
mode: shouldHydrate ? 'hydrate' : 'render',
|
|
9055
|
+
});
|
|
9056
|
+
|
|
9057
|
+
let hydrated = false;
|
|
9058
|
+
try {
|
|
9059
|
+
if (hydrationController.signal.aborted || !pageContainer.isConnected) {
|
|
9060
|
+
await farmClientRuntime.failHydration(
|
|
9061
|
+
hydrationSession,
|
|
9062
|
+
new DOMException('Route hydration was cancelled', 'AbortError'),
|
|
9063
|
+
);
|
|
9064
|
+
return;
|
|
9065
|
+
}
|
|
9066
|
+
hydrated = await tryHydrateImportedPage(
|
|
9067
|
+
pageContainer,
|
|
9068
|
+
{ modulePath },
|
|
9069
|
+
currentPageProps.params || {},
|
|
9070
|
+
layouts,
|
|
9071
|
+
shouldHydrate,
|
|
9072
|
+
currentPageProps,
|
|
9073
|
+
hydrationController.signal,
|
|
9074
|
+
);
|
|
9075
|
+
if (hydrationController.signal.aborted || !pageContainer.isConnected) {
|
|
9076
|
+
await farmClientRuntime.failHydration(
|
|
9077
|
+
hydrationSession,
|
|
9078
|
+
new DOMException('Route hydration was cancelled', 'AbortError'),
|
|
9079
|
+
);
|
|
9080
|
+
return;
|
|
9081
|
+
}
|
|
9082
|
+
await farmClientRuntime.completeHydration(hydrationSession);
|
|
9083
|
+
} catch (error) {
|
|
9084
|
+
await farmClientRuntime.failHydration(hydrationSession, error);
|
|
9085
|
+
throw error;
|
|
9086
|
+
}
|
|
9087
|
+
|
|
9088
|
+
if (hydrated) {
|
|
9089
|
+
// The scheduler owns queue draining and exactly-once click replay.
|
|
9090
|
+
markFarmHydrated();
|
|
9091
|
+
console.log('[Farm.js] \u2705 Hydrated:', modulePath, '(' + islandStrategy + ')');
|
|
9092
|
+
return;
|
|
9093
|
+
}
|
|
9094
|
+
|
|
9095
|
+
console.log('[Farm.js] Server component - SPA router ready')
|
|
9096
|
+
},
|
|
9097
|
+
});
|
|
9098
|
+
} finally {
|
|
9099
|
+
if (pendingPageHydrationController === hydrationController) {
|
|
9100
|
+
pendingPageHydrationController = null;
|
|
9101
|
+
}
|
|
9102
|
+
}
|
|
8531
9103
|
} catch (error) {
|
|
8532
9104
|
console.error('[Farm.js] Hydration error:', error)
|
|
8533
9105
|
}
|
|
@@ -8633,7 +9205,7 @@ function generateClientManifest(bundle) {
|
|
|
8633
9205
|
__name(generateClientManifest, "generateClientManifest");
|
|
8634
9206
|
async function defineConfig(config = {}) {
|
|
8635
9207
|
const tailwindcss = (await import("@tailwindcss/vite")).default;
|
|
8636
|
-
const appRoot =
|
|
9208
|
+
const appRoot = path11.resolve(config.root || process.cwd());
|
|
8637
9209
|
if (config.extends?.length) {
|
|
8638
9210
|
const { config: layeredConfig } = await import("./layers-VWVDTPUZ.mjs").then(
|
|
8639
9211
|
({ resolveFarmLayers }) => resolveFarmLayers(config, {
|
|
@@ -8778,13 +9350,16 @@ async function defineConfig(config = {}) {
|
|
|
8778
9350
|
customLogger: farmLogger,
|
|
8779
9351
|
clearScreen: false,
|
|
8780
9352
|
optimizeDeps: {
|
|
8781
|
-
|
|
8782
|
-
|
|
8783
|
-
|
|
8784
|
-
|
|
8785
|
-
|
|
8786
|
-
|
|
8787
|
-
|
|
9353
|
+
...createFarmClientOptimizeDepsConfig(
|
|
9354
|
+
createFarmClientOptimizeDepsEntries(
|
|
9355
|
+
appRoot,
|
|
9356
|
+
getFarmAppDirectories({ ...config, root: appRoot })
|
|
9357
|
+
)
|
|
9358
|
+
),
|
|
9359
|
+
// Pre-bundle every framework client-runtime entry with React. Without
|
|
9360
|
+
// this, Vite can discover a linked Farm entry after the page has loaded,
|
|
9361
|
+
// regenerate the optimizer browser hash, and leave React DOM holding a
|
|
9362
|
+
// different React module instance from a client component.
|
|
8788
9363
|
// Exclude server-side packages from browser bundling
|
|
8789
9364
|
exclude: [
|
|
8790
9365
|
"@farm.js/core/server",
|
|
@@ -8819,7 +9394,7 @@ async function defineConfig(config = {}) {
|
|
|
8819
9394
|
// Stub out problematic server-only modules during dev mode
|
|
8820
9395
|
alias: {
|
|
8821
9396
|
...getFarmLayerAliases(config.layers),
|
|
8822
|
-
"@":
|
|
9397
|
+
"@": path11.resolve(appRoot, "src"),
|
|
8823
9398
|
// Nitro internals that should not be resolved in browser
|
|
8824
9399
|
"supports-color": "data:text/javascript,export default false; export const supportsColor = false; export const stdout = false; export const stderr = false;",
|
|
8825
9400
|
"@poppinss/dumper": "data:text/javascript,export default {};",
|
|
@@ -8841,6 +9416,7 @@ __name(defineConfig, "defineConfig");
|
|
|
8841
9416
|
export {
|
|
8842
9417
|
resolveRouteRenderingConfig,
|
|
8843
9418
|
resolveRouteRenderingConfigFromFile,
|
|
9419
|
+
analyzeStaticRouteCandidate,
|
|
8844
9420
|
parseRouteRenderingDirective,
|
|
8845
9421
|
collectSSGPages,
|
|
8846
9422
|
isSSGModule,
|
|
@@ -8863,9 +9439,12 @@ export {
|
|
|
8863
9439
|
createFarmImageTypeDeclarations,
|
|
8864
9440
|
generateFarmI18nTypes,
|
|
8865
9441
|
generateFarmTypeArtifacts,
|
|
9442
|
+
createFarmClientOptimizeDepsEntries,
|
|
9443
|
+
createFarmClientOptimizeDepsConfig,
|
|
9444
|
+
mergeFarmViteConfig,
|
|
8866
9445
|
farmI18nClientBridgePlugin,
|
|
8867
9446
|
rewriteEarlySsrRelativeImports,
|
|
8868
9447
|
farmPlugin,
|
|
8869
9448
|
defineConfig
|
|
8870
9449
|
};
|
|
8871
|
-
//# sourceMappingURL=chunk-
|
|
9450
|
+
//# sourceMappingURL=chunk-Z3YG4OZT.mjs.map
|