@farm.js/core 0.1.0-beta.11 → 0.1.0-beta.14
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-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-5EVQFRL2.mjs → chunk-ARCGE2VT.mjs} +2 -2
- package/dist/chunk-ARCGE2VT.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-77BOAQHI.mjs → chunk-PNFQQSRA.mjs} +754 -156
- package/dist/chunk-PNFQQSRA.mjs.map +1 -0
- package/dist/chunk-USLFXFFH.mjs +46 -0
- package/dist/chunk-USLFXFFH.mjs.map +1 -0
- package/dist/{chunk-4677KXB7.mjs → chunk-VUL55IAX.mjs} +368 -103
- package/dist/chunk-VUL55IAX.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 +2235 -689
- 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 +2062 -525
- 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 +1550 -348
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.mjs +9 -5
- package/dist/server.cjs +1663 -419
- 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 +1604 -358
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +9 -5
- package/package.json +10 -1
- package/types/client.d.ts +115 -4
- package/dist/after.d.mts +0 -25
- package/dist/after.d.ts +0 -25
- package/dist/agent-runtime.d.mts +0 -94
- package/dist/agent-runtime.d.ts +0 -94
- package/dist/api/route-manager.d.mts +0 -66
- package/dist/api/route-manager.d.ts +0 -66
- package/dist/api/runtime.d.mts +0 -3
- package/dist/api/runtime.d.ts +0 -3
- package/dist/api.d.mts +0 -48
- package/dist/api.d.ts +0 -48
- package/dist/app-BNE2FoZ4.d.mts +0 -302
- package/dist/app-DRGUmJ3s.d.ts +0 -302
- package/dist/app-markdown.d.mts +0 -22
- package/dist/app-markdown.d.ts +0 -22
- package/dist/cache.d.mts +0 -192
- package/dist/cache.d.ts +0 -192
- package/dist/chunk-4677KXB7.mjs.map +0 -1
- package/dist/chunk-4LND3PXF.mjs.map +0 -1
- package/dist/chunk-5EVQFRL2.mjs.map +0 -1
- package/dist/chunk-77BOAQHI.mjs.map +0 -1
- package/dist/chunk-AW6I64AP.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/client-BT1mFQas.d.mts +0 -447
- package/dist/client-Nn0q4eO4.d.ts +0 -447
- package/dist/client-cache-CIlyBlmx.d.ts +0 -6
- package/dist/client-cache-D-EZ7XVW.d.mts +0 -6
- package/dist/client-plugins-Bc5jHcNr.d.ts +0 -1927
- package/dist/client-plugins-jsk-ZLzJ.d.mts +0 -1927
- package/dist/client-plugins.d.mts +0 -22
- package/dist/client-plugins.d.ts +0 -22
- package/dist/client.d.mts +0 -447
- package/dist/client.d.ts +0 -447
- package/dist/config.d.mts +0 -29
- package/dist/config.d.ts +0 -29
- package/dist/cron.d.mts +0 -78
- package/dist/cron.d.ts +0 -78
- package/dist/deferred.d.mts +0 -42
- package/dist/deferred.d.ts +0 -42
- package/dist/deployment.d.mts +0 -34
- package/dist/deployment.d.ts +0 -34
- package/dist/docs.d.mts +0 -69
- package/dist/docs.d.ts +0 -69
- package/dist/env-types.d.mts +0 -12
- package/dist/env-types.d.ts +0 -12
- package/dist/env.d.mts +0 -45
- package/dist/env.d.ts +0 -45
- package/dist/environment/vite.d.mts +0 -22
- package/dist/environment/vite.d.ts +0 -22
- package/dist/environment.d.mts +0 -18
- package/dist/environment.d.ts +0 -18
- package/dist/font.d.mts +0 -70
- package/dist/font.d.ts +0 -70
- package/dist/headers.d.mts +0 -22
- package/dist/headers.d.ts +0 -22
- package/dist/i18n/client.d.mts +0 -32
- package/dist/i18n/client.d.ts +0 -32
- package/dist/i18n/index.d.mts +0 -20
- package/dist/i18n/index.d.ts +0 -20
- package/dist/i18n/server.d.mts +0 -30
- package/dist/i18n/server.d.ts +0 -30
- package/dist/image/server.d.mts +0 -37
- package/dist/image/server.d.ts +0 -37
- package/dist/image/sharp.d.mts +0 -7
- package/dist/image/sharp.d.ts +0 -7
- package/dist/image-config-Duob7wER.d.mts +0 -50
- package/dist/image-config-Duob7wER.d.ts +0 -50
- package/dist/image.d.mts +0 -39
- package/dist/image.d.ts +0 -39
- package/dist/index.d.mts +0 -455
- package/dist/index.d.ts +0 -455
- package/dist/integration-api-CHT2OKAf.d.mts +0 -93
- package/dist/integration-api-CHT2OKAf.d.ts +0 -93
- package/dist/integrations.d.mts +0 -22
- package/dist/integrations.d.ts +0 -22
- package/dist/internal/build-runtime.d.mts +0 -39
- package/dist/internal/build-runtime.d.ts +0 -39
- package/dist/internal/client-runtime.d.mts +0 -2
- package/dist/internal/client-runtime.d.ts +0 -2
- package/dist/internal/config-runtime.d.mts +0 -39
- package/dist/internal/config-runtime.d.ts +0 -39
- package/dist/internal/production-node-env.d.mts +0 -12
- package/dist/internal/production-node-env.d.ts +0 -12
- package/dist/internal/production-runtime.d.mts +0 -41
- package/dist/internal/production-runtime.d.ts +0 -41
- package/dist/markdown.d.mts +0 -60
- package/dist/markdown.d.ts +0 -60
- package/dist/metadata-7ffpT3jr.d.mts +0 -22
- package/dist/metadata-JHn-8eht.d.ts +0 -22
- package/dist/middleware.d.mts +0 -164
- package/dist/middleware.d.ts +0 -164
- package/dist/navigation-errors-Dvwpzaer.d.mts +0 -13
- package/dist/navigation-errors-Dvwpzaer.d.ts +0 -13
- package/dist/navigation.d.mts +0 -14
- package/dist/navigation.d.ts +0 -14
- package/dist/observability.d.mts +0 -335
- package/dist/observability.d.ts +0 -335
- package/dist/params-BALtrRim.d.ts +0 -15
- package/dist/params-ry-lxqmy.d.mts +0 -15
- package/dist/plugin-BJDf43dc.d.mts +0 -165
- package/dist/plugin-BJDf43dc.d.ts +0 -165
- package/dist/plugin.d.mts +0 -22
- package/dist/plugin.d.ts +0 -22
- package/dist/production-runtime-9KG7GuvW.d.ts +0 -79
- package/dist/production-runtime-B-fweKts.d.mts +0 -79
- package/dist/production-runtime-C_B79w2P.d.mts +0 -28
- package/dist/production-runtime-DDEM1D2q.d.ts +0 -28
- package/dist/query/client.d.mts +0 -61
- package/dist/query/client.d.ts +0 -61
- package/dist/query/index.d.mts +0 -90
- package/dist/query/index.d.ts +0 -90
- package/dist/query/parsers.d.mts +0 -25
- package/dist/query/parsers.d.ts +0 -25
- package/dist/query/server.d.mts +0 -55
- package/dist/query/server.d.ts +0 -55
- package/dist/request-Dsq4kGW0.d.mts +0 -6
- package/dist/request-udtobOLv.d.ts +0 -6
- package/dist/request.d.mts +0 -2
- package/dist/request.d.ts +0 -2
- package/dist/resolver-DJqjLMg_.d.mts +0 -14
- package/dist/resolver-IH4RmPEl.d.ts +0 -14
- package/dist/route-runtime-DoOHzCAD.d.mts +0 -38
- package/dist/route-runtime-DoOHzCAD.d.ts +0 -38
- package/dist/router.d.mts +0 -36
- package/dist/router.d.ts +0 -36
- package/dist/routes.d.mts +0 -224
- package/dist/routes.d.ts +0 -224
- package/dist/runtime-9nQjVM7X.d.mts +0 -206
- package/dist/runtime-Cxpq6xZN.d.mts +0 -27
- package/dist/runtime-DgeS2skB.d.ts +0 -206
- package/dist/runtime-bv63eUiO.d.ts +0 -27
- package/dist/server-action-security.d.mts +0 -43
- package/dist/server-action-security.d.ts +0 -43
- package/dist/server-fn-client.d.mts +0 -32
- package/dist/server-fn-client.d.ts +0 -32
- package/dist/server-fn.d.mts +0 -93
- package/dist/server-fn.d.ts +0 -93
- package/dist/server-plugins.d.mts +0 -55
- package/dist/server-plugins.d.ts +0 -55
- package/dist/server-query-client.d.mts +0 -50
- package/dist/server-query-client.d.ts +0 -50
- package/dist/server-query.d.mts +0 -36
- package/dist/server-query.d.ts +0 -36
- package/dist/server.d.mts +0 -48
- package/dist/server.d.ts +0 -48
- package/dist/storage.d.mts +0 -52
- package/dist/storage.d.ts +0 -52
- package/dist/testing.d.mts +0 -101
- package/dist/testing.d.ts +0 -101
- package/dist/transport-BmbGTXA5.d.mts +0 -49
- package/dist/transport-BmbGTXA5.d.ts +0 -49
- package/dist/types-BMxWr97v.d.mts +0 -81
- package/dist/types-BMxWr97v.d.ts +0 -81
- package/dist/types-C9N-nk5R.d.mts +0 -53
- package/dist/types-C9N-nk5R.d.ts +0 -53
- package/dist/types-D1A6-XvH.d.mts +0 -73
- package/dist/types-D1A6-XvH.d.ts +0 -73
- package/dist/utils-CA0z0c-2.d.ts +0 -23
- package/dist/utils-mYVkSOt2.d.mts +0 -23
- package/dist/version.d.mts +0 -3
- package/dist/version.d.ts +0 -3
- package/dist/vite.d.mts +0 -22
- package/dist/vite.d.ts +0 -22
- package/dist/workflows.d.mts +0 -110
- package/dist/workflows.d.ts +0 -110
- /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-ARCGE2VT.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";
|
|
@@ -2027,6 +2433,10 @@ ${FONT_SECTION_END}
|
|
|
2027
2433
|
fallback,
|
|
2028
2434
|
display,
|
|
2029
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
|
+
})),
|
|
2030
2440
|
weight: defaultWeight,
|
|
2031
2441
|
style: raw.style === void 0 ? void 0 : defaultStyle,
|
|
2032
2442
|
sources: normalizedSources
|
|
@@ -2123,7 +2533,7 @@ ${FONT_SECTION_END}
|
|
|
2123
2533
|
const normalizedExtension = extension.toLowerCase();
|
|
2124
2534
|
const hash = createHash2("sha256").update(bytes).digest("hex").slice(0, 12);
|
|
2125
2535
|
const baseName = sanitizeFileName(path4.basename(fileName, extension)) || "font";
|
|
2126
|
-
const outputFileName = `assets/fonts/${baseName}
|
|
2536
|
+
const outputFileName = `assets/fonts/${baseName}-h${hash}${normalizedExtension}`;
|
|
2127
2537
|
const key = `${hash}${normalizedExtension}`;
|
|
2128
2538
|
const existing = this.resources.get(key);
|
|
2129
2539
|
if (existing) return existing;
|
|
@@ -2393,7 +2803,8 @@ function serializeFontResult(font) {
|
|
|
2393
2803
|
fontFamily: stack,
|
|
2394
2804
|
...font.style ? { fontStyle: font.style } : {},
|
|
2395
2805
|
...font.weight !== void 0 && !String(font.weight).includes(" ") ? { fontWeight: font.weight } : {}
|
|
2396
|
-
}
|
|
2806
|
+
},
|
|
2807
|
+
preloads: font.preloadResources
|
|
2397
2808
|
});
|
|
2398
2809
|
}
|
|
2399
2810
|
__name(serializeFontResult, "serializeFontResult");
|
|
@@ -2813,7 +3224,7 @@ function createPPRRefreshScript() {
|
|
|
2813
3224
|
}
|
|
2814
3225
|
__name(createPPRRefreshScript, "createPPRRefreshScript");
|
|
2815
3226
|
function createPreHydrationClickQueueScript() {
|
|
2816
|
-
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>`;
|
|
2817
3228
|
}
|
|
2818
3229
|
__name(createPreHydrationClickQueueScript, "createPreHydrationClickQueueScript");
|
|
2819
3230
|
function searchParamsToObject(searchParams) {
|
|
@@ -3424,6 +3835,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
3424
3835
|
req.__FARM_ROUTE__ = pathname;
|
|
3425
3836
|
req.__FARM_IS_CLIENT_COMPONENT__ = isClientComponent;
|
|
3426
3837
|
req.__FARM_SHOULD_HYDRATE__ = shouldHydrate;
|
|
3838
|
+
req.__FARM_ISLAND_STRATEGY__ = moduleMetadata.islandStrategy;
|
|
3427
3839
|
req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ = hasHydratableRouteSlots;
|
|
3428
3840
|
req.__FARM_LOADING_MODULE_PATH__ = loadingBoundaryEntry?.modulePath ? loadingBoundaryEntry.modulePath.substring(
|
|
3429
3841
|
loadingBoundaryEntry.modulePath.indexOf("/src/app/")
|
|
@@ -3499,7 +3911,12 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
3499
3911
|
if (isClientComponent || shouldHydrate) {
|
|
3500
3912
|
pageElement = React.createElement(
|
|
3501
3913
|
"div",
|
|
3502
|
-
{
|
|
3914
|
+
{
|
|
3915
|
+
id: "__farm_page__",
|
|
3916
|
+
"data-farm-client": "true",
|
|
3917
|
+
"data-farm-island": "page",
|
|
3918
|
+
"data-farm-island-strategy": moduleMetadata.islandStrategy ?? "load"
|
|
3919
|
+
},
|
|
3503
3920
|
pageElement
|
|
3504
3921
|
);
|
|
3505
3922
|
}
|
|
@@ -3744,6 +4161,13 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
3744
4161
|
return reference;
|
|
3745
4162
|
}
|
|
3746
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
|
+
}
|
|
3747
4171
|
if (options.image.sourceType === "static") {
|
|
3748
4172
|
if (!options.image.staticInfo) {
|
|
3749
4173
|
throw new Error(`Static metadata image ${options.image.modulePath} is missing file info`);
|
|
@@ -3769,42 +4193,12 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
3769
4193
|
await this.writeMetadataImageResponse(req, res, handlerResult, imageModule);
|
|
3770
4194
|
}
|
|
3771
4195
|
async writeMetadataImageResponse(req, res, value, imageModule) {
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
res.end();
|
|
3779
|
-
return;
|
|
3780
|
-
}
|
|
3781
|
-
const body2 = Buffer.from(await value.arrayBuffer());
|
|
3782
|
-
res.write(body2);
|
|
3783
|
-
res.end();
|
|
3784
|
-
return;
|
|
3785
|
-
}
|
|
3786
|
-
const contentType = imageModule.contentType || "image/svg+xml; charset=utf-8";
|
|
3787
|
-
let body;
|
|
3788
|
-
if (typeof value === "string") {
|
|
3789
|
-
body = value;
|
|
3790
|
-
} else if (value instanceof ArrayBuffer) {
|
|
3791
|
-
body = Buffer.from(value);
|
|
3792
|
-
} else if (ArrayBuffer.isView(value)) {
|
|
3793
|
-
body = Buffer.from(value.buffer, value.byteOffset, value.byteLength);
|
|
3794
|
-
} else if (React.isValidElement(value)) {
|
|
3795
|
-
body = renderToStaticMarkup(value);
|
|
3796
|
-
} else {
|
|
3797
|
-
throw new Error("Metadata image must return a Response, string, bytes, or React element");
|
|
3798
|
-
}
|
|
3799
|
-
res.statusCode = res.statusCode || 200;
|
|
3800
|
-
res.setHeader("Content-Type", contentType);
|
|
3801
|
-
res.setHeader("Cache-Control", "public, max-age=0, must-revalidate");
|
|
3802
|
-
if (req.method === "HEAD") {
|
|
3803
|
-
res.end();
|
|
3804
|
-
return;
|
|
3805
|
-
}
|
|
3806
|
-
res.write(body);
|
|
3807
|
-
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);
|
|
3808
4202
|
}
|
|
3809
4203
|
async writeStaticMetadataImageResponse(req, res, image) {
|
|
3810
4204
|
const method = (req.method || "GET").toUpperCase();
|
|
@@ -3934,6 +4328,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
3934
4328
|
search: routeEntry.search,
|
|
3935
4329
|
isClientComponent: routeEntry.isClientComponent,
|
|
3936
4330
|
shouldHydrate: routeEntry.shouldHydrate,
|
|
4331
|
+
islandStrategy: routeEntry.islandStrategy,
|
|
3937
4332
|
preloads: [routeEntry.modulePath],
|
|
3938
4333
|
assets: []
|
|
3939
4334
|
};
|
|
@@ -3970,6 +4365,7 @@ window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue(deploymentId)};
|
|
|
3970
4365
|
window.__FARM_PATH__ = ${JSON.stringify(req.__FARM_ROUTE__ || req.url || "/")};
|
|
3971
4366
|
window.__FARM_IS_CLIENT__ = ${JSON.stringify(isClientComponent)};
|
|
3972
4367
|
window.__FARM_SHOULD_HYDRATE__ = ${JSON.stringify(req.__FARM_SHOULD_HYDRATE__ === true)};
|
|
4368
|
+
window.__FARM_ISLAND_STRATEGY__ = ${JSON.stringify(req.__FARM_ISLAND_STRATEGY__ || "load")};
|
|
3973
4369
|
window.__FARM_PAGE_MODULE__ = ${JSON.stringify(relativePath)};
|
|
3974
4370
|
window.__FARM_LOADING_MODULE__ = ${JSON.stringify(
|
|
3975
4371
|
req.__FARM_LOADING_MODULE_PATH__ || null
|
|
@@ -4330,6 +4726,7 @@ var _FarmApp = class _FarmApp {
|
|
|
4330
4726
|
context: config.context || (() => void 0),
|
|
4331
4727
|
serverActions: resolveServerActionsConfig(config.serverActions),
|
|
4332
4728
|
images: resolveFarmImageConfig(config.images),
|
|
4729
|
+
performance: resolveFarmPerformanceConfig(config.performance),
|
|
4333
4730
|
i18n: isResolvedI18nConfig(config.i18n) ? config.i18n : resolveFarmI18nConfig(config.i18n, {
|
|
4334
4731
|
root,
|
|
4335
4732
|
mode: process.env.NODE_ENV === "production" ? "production" : "development"
|
|
@@ -4793,39 +5190,48 @@ async function createRouteTypeDeclarations(options, outPath) {
|
|
|
4793
5190
|
const { root, srcDir = "src", extraRoutes = [], suppressLintOnLink = false } = options;
|
|
4794
5191
|
const sourceRoots = options.sourceRoots ?? [{ name: "project", root, srcDir, layer: false }];
|
|
4795
5192
|
const patterns = /* @__PURE__ */ new Set();
|
|
5193
|
+
const routeModulePatterns = /* @__PURE__ */ new Set();
|
|
4796
5194
|
const glob = await import("fast-glob");
|
|
4797
5195
|
for (const source of sourceRoots) {
|
|
4798
5196
|
const appDir = path7.join(source.root, source.srcDir, "app");
|
|
4799
5197
|
if (fs3.existsSync(appDir)) {
|
|
4800
|
-
const
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
5198
|
+
const routeModuleFiles = await glob.default(
|
|
5199
|
+
"**/{page,layout,loading,error}.{ts,tsx,js,jsx,md,mdx}",
|
|
5200
|
+
{
|
|
5201
|
+
cwd: appDir,
|
|
5202
|
+
absolute: false
|
|
5203
|
+
}
|
|
5204
|
+
);
|
|
5205
|
+
for (const file of routeModuleFiles) {
|
|
4805
5206
|
if (parseRouteSlotFile(file)) continue;
|
|
4806
5207
|
const route = parseRoutePath(file);
|
|
5208
|
+
const pattern = createRoutePattern(route);
|
|
5209
|
+
routeModulePatterns.add(pattern);
|
|
4807
5210
|
if (route.type === "page") {
|
|
4808
|
-
const pattern = createRoutePattern(route);
|
|
4809
5211
|
patterns.add(pattern);
|
|
4810
5212
|
}
|
|
4811
5213
|
}
|
|
4812
5214
|
}
|
|
4813
5215
|
for (const route of await discoverProgrammaticRoutePaths(source.root, source.srcDir)) {
|
|
4814
5216
|
patterns.add(route);
|
|
5217
|
+
routeModulePatterns.add(route);
|
|
4815
5218
|
}
|
|
4816
5219
|
}
|
|
4817
5220
|
for (const route of extraRoutes) {
|
|
4818
5221
|
if (route.startsWith("/")) {
|
|
4819
5222
|
patterns.add(route);
|
|
5223
|
+
routeModulePatterns.add(route);
|
|
4820
5224
|
}
|
|
4821
5225
|
}
|
|
4822
5226
|
const sortedPatterns = Array.from(patterns).sort();
|
|
4823
5227
|
const typeLiterals = Array.from(new Set(sortedPatterns.flatMap(routePatternToTsTypeLiterals)));
|
|
4824
5228
|
const patternLiterals = sortedPatterns.map(routePatternToRouteLiteral);
|
|
5229
|
+
const routeModulePatternLiterals = Array.from(routeModulePatterns).sort().map(routePatternToRouteLiteral);
|
|
4825
5230
|
const routePathType = suppressLintOnLink ? "string" : typeLiterals.length ? typeLiterals.join(" | ") : "never";
|
|
4826
5231
|
const routePatternType = suppressLintOnLink ? "string" : patternLiterals.length ? patternLiterals.join(" | ") : "never";
|
|
5232
|
+
const routeModulePatternType = routeModulePatternLiterals.length ? routeModulePatternLiterals.join(" | ") : "never";
|
|
4827
5233
|
const routeTypesImportPath = `./${path7.basename(outPath).replace(/\.d\.ts$/, "")}`;
|
|
4828
|
-
const
|
|
5234
|
+
const linkAugmentationBlock = suppressLintOnLink ? "" : `
|
|
4829
5235
|
declare module "@farm.js/core/client" {
|
|
4830
5236
|
interface LinkDefaultRoute {
|
|
4831
5237
|
_: import(${JSON.stringify(routeTypesImportPath)}).RoutePath;
|
|
@@ -4849,14 +5255,25 @@ declare module "@farm.js/core/dist/client.js" {
|
|
|
4849
5255
|
pattern: import(${JSON.stringify(routeTypesImportPath)}).RoutePattern;
|
|
4850
5256
|
}
|
|
4851
5257
|
}
|
|
5258
|
+
`;
|
|
5259
|
+
const routeModuleAugmentationBlock = `
|
|
5260
|
+
declare global {
|
|
5261
|
+
namespace FarmJS {
|
|
5262
|
+
interface RouteRegistry {
|
|
5263
|
+
pattern: import(${JSON.stringify(routeTypesImportPath)}).RouteModulePattern;
|
|
5264
|
+
}
|
|
5265
|
+
}
|
|
5266
|
+
}
|
|
4852
5267
|
`;
|
|
4853
5268
|
const content = `/**
|
|
4854
5269
|
* Auto-generated route types from src/app.
|
|
4855
|
-
* Link href
|
|
5270
|
+
* Link href and route component props are typed automatically from generated declarations.
|
|
5271
|
+
* Regenerated on dev start and when routes change.
|
|
4856
5272
|
* Set suppressLintOnLink: true in farm.config.ts to accept any string on Link href.
|
|
4857
5273
|
*/
|
|
4858
5274
|
export type RoutePath = ${routePathType};
|
|
4859
|
-
export type RoutePattern = ${routePatternType}
|
|
5275
|
+
export type RoutePattern = ${routePatternType};
|
|
5276
|
+
export type RouteModulePattern = ${routeModulePatternType};${linkAugmentationBlock}${routeModuleAugmentationBlock}
|
|
4860
5277
|
`;
|
|
4861
5278
|
return content;
|
|
4862
5279
|
}
|
|
@@ -5076,7 +5493,7 @@ __name(removeLegacyTypeArtifacts, "removeLegacyTypeArtifacts");
|
|
|
5076
5493
|
|
|
5077
5494
|
// src/vite.ts
|
|
5078
5495
|
import * as fs4 from "fs";
|
|
5079
|
-
import * as
|
|
5496
|
+
import * as path11 from "path";
|
|
5080
5497
|
|
|
5081
5498
|
// src/image-vite.ts
|
|
5082
5499
|
import { readFile as readFile4 } from "fs/promises";
|
|
@@ -5147,6 +5564,100 @@ async function createBlurDataURL(bytes) {
|
|
|
5147
5564
|
}
|
|
5148
5565
|
__name(createBlurDataURL, "createBlurDataURL");
|
|
5149
5566
|
|
|
5567
|
+
// src/server/vite-config.ts
|
|
5568
|
+
import path10 from "path";
|
|
5569
|
+
var FARM_CLIENT_ENTRY_PATTERN = "**/{page,layout,loading,error,not-found,default}.{js,jsx,ts,tsx}";
|
|
5570
|
+
var FARM_CLIENT_OPTIMIZE_DEPS_INCLUDE = [
|
|
5571
|
+
"react",
|
|
5572
|
+
"react-dom",
|
|
5573
|
+
"react-dom/client",
|
|
5574
|
+
"react/jsx-runtime",
|
|
5575
|
+
"react/jsx-dev-runtime",
|
|
5576
|
+
"@farm.js/core/client",
|
|
5577
|
+
"@farm.js/core/plugin/client",
|
|
5578
|
+
"@farm.js/core/deferred",
|
|
5579
|
+
"@farm.js/core/deployment",
|
|
5580
|
+
"@farm.js/core/i18n/client",
|
|
5581
|
+
"@farm.js/core/query/client",
|
|
5582
|
+
"@farm.js/core/server-fn/client",
|
|
5583
|
+
"@farm.js/core/server-query/client"
|
|
5584
|
+
];
|
|
5585
|
+
function createFarmClientOptimizeDepsEntries(projectRoot, appDirectories) {
|
|
5586
|
+
const resolvedProjectRoot = path10.resolve(projectRoot);
|
|
5587
|
+
return appDirectories.map((appDirectory) => {
|
|
5588
|
+
const relativeAppDirectory = path10.relative(resolvedProjectRoot, path10.resolve(appDirectory)).replace(/\\/g, "/");
|
|
5589
|
+
const prefix = relativeAppDirectory || ".";
|
|
5590
|
+
return `${prefix}/${FARM_CLIENT_ENTRY_PATTERN}`;
|
|
5591
|
+
});
|
|
5592
|
+
}
|
|
5593
|
+
__name(createFarmClientOptimizeDepsEntries, "createFarmClientOptimizeDepsEntries");
|
|
5594
|
+
function createFarmClientOptimizeDepsConfig(entries) {
|
|
5595
|
+
return {
|
|
5596
|
+
// Keep normal application dependency discovery for CJS-only packages, but
|
|
5597
|
+
// seed every Farm browser runtime so React is present in the first crawl.
|
|
5598
|
+
noDiscovery: false,
|
|
5599
|
+
// Waiting for the crawl avoids serving a partial optimizer generation and
|
|
5600
|
+
// then changing browser hashes while hydration is already in progress.
|
|
5601
|
+
holdUntilCrawlEnd: true,
|
|
5602
|
+
include: [...FARM_CLIENT_OPTIMIZE_DEPS_INCLUDE],
|
|
5603
|
+
// Farm's HTML boots through a virtual module and imports route UI lazily.
|
|
5604
|
+
// Explicit entries let Vite finish that crawl before a navigation can
|
|
5605
|
+
// rotate the optimizer hash underneath a hydrated React runtime.
|
|
5606
|
+
...entries?.length ? { entries: [...entries] } : {}
|
|
5607
|
+
};
|
|
5608
|
+
}
|
|
5609
|
+
__name(createFarmClientOptimizeDepsConfig, "createFarmClientOptimizeDepsConfig");
|
|
5610
|
+
function mergeNoExternal(farmValue, userValue) {
|
|
5611
|
+
if (farmValue === true || userValue === true) return true;
|
|
5612
|
+
const normalize = /* @__PURE__ */ __name((value) => value == null || value === true ? [] : Array.isArray(value) ? value : [value], "normalize");
|
|
5613
|
+
return Array.from(/* @__PURE__ */ new Set([...normalize(farmValue), ...normalize(userValue)]));
|
|
5614
|
+
}
|
|
5615
|
+
__name(mergeNoExternal, "mergeNoExternal");
|
|
5616
|
+
function mergeFarmViteConfig(farmConfig, userConfig = {}) {
|
|
5617
|
+
const noDiscovery = userConfig.optimizeDeps?.noDiscovery ?? farmConfig.optimizeDeps?.noDiscovery;
|
|
5618
|
+
const holdUntilCrawlEnd = userConfig.optimizeDeps?.holdUntilCrawlEnd ?? (userConfig.optimizeDeps?.noDiscovery === true ? false : farmConfig.optimizeDeps?.holdUntilCrawlEnd);
|
|
5619
|
+
return {
|
|
5620
|
+
...farmConfig,
|
|
5621
|
+
...userConfig,
|
|
5622
|
+
plugins: [...farmConfig.plugins || [], ...userConfig.plugins || []],
|
|
5623
|
+
server: {
|
|
5624
|
+
...farmConfig.server,
|
|
5625
|
+
...userConfig.server
|
|
5626
|
+
},
|
|
5627
|
+
resolve: {
|
|
5628
|
+
...farmConfig.resolve,
|
|
5629
|
+
...userConfig.resolve,
|
|
5630
|
+
dedupe: Array.from(
|
|
5631
|
+
/* @__PURE__ */ new Set([...farmConfig.resolve?.dedupe || [], ...userConfig.resolve?.dedupe || []])
|
|
5632
|
+
)
|
|
5633
|
+
},
|
|
5634
|
+
optimizeDeps: {
|
|
5635
|
+
...farmConfig.optimizeDeps,
|
|
5636
|
+
...userConfig.optimizeDeps,
|
|
5637
|
+
noDiscovery,
|
|
5638
|
+
holdUntilCrawlEnd,
|
|
5639
|
+
include: Array.from(
|
|
5640
|
+
/* @__PURE__ */ new Set([
|
|
5641
|
+
...farmConfig.optimizeDeps?.include || [],
|
|
5642
|
+
...userConfig.optimizeDeps?.include || []
|
|
5643
|
+
])
|
|
5644
|
+
),
|
|
5645
|
+
exclude: Array.from(
|
|
5646
|
+
/* @__PURE__ */ new Set([
|
|
5647
|
+
...farmConfig.optimizeDeps?.exclude || [],
|
|
5648
|
+
...userConfig.optimizeDeps?.exclude || []
|
|
5649
|
+
])
|
|
5650
|
+
)
|
|
5651
|
+
},
|
|
5652
|
+
ssr: {
|
|
5653
|
+
...farmConfig.ssr,
|
|
5654
|
+
...userConfig.ssr,
|
|
5655
|
+
noExternal: mergeNoExternal(farmConfig.ssr?.noExternal, userConfig.ssr?.noExternal)
|
|
5656
|
+
}
|
|
5657
|
+
};
|
|
5658
|
+
}
|
|
5659
|
+
__name(mergeFarmViteConfig, "mergeFarmViteConfig");
|
|
5660
|
+
|
|
5150
5661
|
// src/vite.ts
|
|
5151
5662
|
var ALL_TYPE_ARTIFACTS = {
|
|
5152
5663
|
routes: true,
|
|
@@ -5189,7 +5700,7 @@ function loadFarmWorkflowsDevRuntime() {
|
|
|
5189
5700
|
}
|
|
5190
5701
|
__name(loadFarmWorkflowsDevRuntime, "loadFarmWorkflowsDevRuntime");
|
|
5191
5702
|
function loadFarmDevtoolsSnapshotRuntime() {
|
|
5192
|
-
return import("./devtools-
|
|
5703
|
+
return import("./devtools-GAZ7F3KL.mjs");
|
|
5193
5704
|
}
|
|
5194
5705
|
__name(loadFarmDevtoolsSnapshotRuntime, "loadFarmDevtoolsSnapshotRuntime");
|
|
5195
5706
|
function loadFarmDevtoolsUIRuntime() {
|
|
@@ -5368,7 +5879,7 @@ function fileContainsProgrammaticPageRoute(file) {
|
|
|
5368
5879
|
__name(fileContainsProgrammaticPageRoute, "fileContainsProgrammaticPageRoute");
|
|
5369
5880
|
function rewriteEarlySsrRelativeImports(options) {
|
|
5370
5881
|
const cleanId = options.id.split("?", 1)[0];
|
|
5371
|
-
if (!
|
|
5882
|
+
if (!path11.isAbsolute(cleanId) || cleanId.replace(/\\/g, "/").includes("/node_modules/")) {
|
|
5372
5883
|
return null;
|
|
5373
5884
|
}
|
|
5374
5885
|
const replacements = [];
|
|
@@ -5388,7 +5899,7 @@ function rewriteEarlySsrRelativeImports(options) {
|
|
|
5388
5899
|
const suffixIndex = source.value.search(/[?#]/);
|
|
5389
5900
|
const sourcePath = suffixIndex === -1 ? source.value : source.value.slice(0, suffixIndex);
|
|
5390
5901
|
const suffix = suffixIndex === -1 ? "" : source.value.slice(suffixIndex);
|
|
5391
|
-
const resolvedPath =
|
|
5902
|
+
const resolvedPath = path11.resolve(path11.dirname(cleanId), sourcePath);
|
|
5392
5903
|
replacements.push({
|
|
5393
5904
|
start: source.start,
|
|
5394
5905
|
end: source.end,
|
|
@@ -5473,7 +5984,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5473
5984
|
...layerRoots.length ? {
|
|
5474
5985
|
server: {
|
|
5475
5986
|
fs: {
|
|
5476
|
-
allow: [
|
|
5987
|
+
allow: [path11.resolve(options.root || process.cwd()), ...layerRoots]
|
|
5477
5988
|
}
|
|
5478
5989
|
}
|
|
5479
5990
|
} : {}
|
|
@@ -5504,9 +6015,9 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5504
6015
|
},
|
|
5505
6016
|
server
|
|
5506
6017
|
);
|
|
5507
|
-
const globalsCSSPath =
|
|
6018
|
+
const globalsCSSPath = path11.join(server.config.root, "src/app/globals.css");
|
|
5508
6019
|
if (!fs4.existsSync(globalsCSSPath)) {
|
|
5509
|
-
const appDir =
|
|
6020
|
+
const appDir = path11.join(server.config.root, "src/app");
|
|
5510
6021
|
if (!fs4.existsSync(appDir)) {
|
|
5511
6022
|
fs4.mkdirSync(appDir, { recursive: true });
|
|
5512
6023
|
}
|
|
@@ -5528,10 +6039,10 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5528
6039
|
});
|
|
5529
6040
|
}
|
|
5530
6041
|
const sourceRoots = getFarmSourceRoots(farmConfig);
|
|
5531
|
-
server.watcher.add(sourceRoots.map((source) =>
|
|
6042
|
+
server.watcher.add(sourceRoots.map((source) => path11.join(source.root, source.srcDir)));
|
|
5532
6043
|
if (farmConfig.i18n.enabled) {
|
|
5533
6044
|
server.watcher.add(
|
|
5534
|
-
farmConfig.i18n.messages.includes("{locale}") ?
|
|
6045
|
+
farmConfig.i18n.messages.includes("{locale}") ? path11.dirname(farmConfig.i18n.messages) : farmConfig.i18n.messages
|
|
5535
6046
|
);
|
|
5536
6047
|
}
|
|
5537
6048
|
const workflowConfig = farmConfig.workflows;
|
|
@@ -5541,7 +6052,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5541
6052
|
...farmDocsDevRuntime?.getFarmDocsRouteTypeEntries(farmConfig.docs) ?? []
|
|
5542
6053
|
], "getExtraRouteTypes");
|
|
5543
6054
|
const appDirSlugs = sourceRoots.map(
|
|
5544
|
-
(source) =>
|
|
6055
|
+
(source) => path11.join(source.root, source.srcDir, "app").replace(/\\/g, "/")
|
|
5545
6056
|
);
|
|
5546
6057
|
const generateTypeArtifacts = /* @__PURE__ */ __name(async (reason, selection = ALL_TYPE_ARTIFACTS, log = false) => {
|
|
5547
6058
|
try {
|
|
@@ -5581,7 +6092,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5581
6092
|
}, "generateTypeArtifacts");
|
|
5582
6093
|
await generateTypeArtifacts("startup");
|
|
5583
6094
|
const srcDirSlugs = sourceRoots.map(
|
|
5584
|
-
(source) =>
|
|
6095
|
+
(source) => path11.join(source.root, source.srcDir).replace(/\\/g, "/")
|
|
5585
6096
|
);
|
|
5586
6097
|
const layerConfigFiles = new Set(
|
|
5587
6098
|
farmConfig.layers.map((layer) => layer.configFile?.replace(/\\/g, "/")).filter((file) => Boolean(file))
|
|
@@ -5699,7 +6210,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5699
6210
|
await apiRouteManager.discoverRoutes();
|
|
5700
6211
|
let discoveredWorkflows = [];
|
|
5701
6212
|
const hasWorkflowDirectory = workflowConfig.enabled && workflowConfig.dirs.some(
|
|
5702
|
-
(dir) => fs4.existsSync(
|
|
6213
|
+
(dir) => fs4.existsSync(path11.isAbsolute(dir) ? dir : path11.join(farmConfig.root, dir))
|
|
5703
6214
|
);
|
|
5704
6215
|
if (hasWorkflowDirectory) {
|
|
5705
6216
|
const { createFarmWorkflowRequestHandler, discoverFarmWorkflows } = await loadFarmWorkflowsDevRuntime();
|
|
@@ -5763,10 +6274,20 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5763
6274
|
logger.info(`Refreshed routes: ${reason}`);
|
|
5764
6275
|
}
|
|
5765
6276
|
}, "refreshRouteDiscovery");
|
|
6277
|
+
const farmDocsFontAssetList = farmDocsDevRuntime ? resolveFarmDocsFontAssets(farmConfig.root) : [];
|
|
5766
6278
|
const farmDocsHandler = farmDocsDevRuntime ? farmDocsDevRuntime.createFarmDocsHandler(farmConfig.docs, {
|
|
5767
6279
|
root: farmConfig.root,
|
|
5768
6280
|
srcDir: farmConfig.srcDir,
|
|
5769
|
-
clientEntry: "/@farm/client.js"
|
|
6281
|
+
clientEntry: "/@farm/client.js",
|
|
6282
|
+
fontAssets: toFarmDocsPublicFontAssets(farmDocsFontAssetList),
|
|
6283
|
+
resolveLayoutFonts: /* @__PURE__ */ __name(async (pathname) => {
|
|
6284
|
+
const layouts = routeManager.matchRoute(pathname).layouts;
|
|
6285
|
+
const layoutModules = await Promise.all(
|
|
6286
|
+
layouts.map((layout) => routeManager.loadLayoutModule(layout.modulePath))
|
|
6287
|
+
);
|
|
6288
|
+
return resolveFarmLayoutFonts(layoutModules);
|
|
6289
|
+
}, "resolveLayoutFonts"),
|
|
6290
|
+
fontStylesheetHref: "/@farm/fonts.css"
|
|
5770
6291
|
}) : null;
|
|
5771
6292
|
const farmDocsAPIHandler = farmDocsDevRuntime ? farmDocsDevRuntime.createFarmDocsAPIHandler({
|
|
5772
6293
|
rootDir: farmConfig.root,
|
|
@@ -5774,22 +6295,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5774
6295
|
docs: farmConfig.docs
|
|
5775
6296
|
}) : null;
|
|
5776
6297
|
const farmDocsFontAssets = new Map(
|
|
5777
|
-
|
|
5778
|
-
[
|
|
5779
|
-
"/assets/Geist-Variable-CrgPqtmy.woff2",
|
|
5780
|
-
path10.join(
|
|
5781
|
-
farmConfig.root,
|
|
5782
|
-
"node_modules/geist/dist/fonts/geist-sans/Geist-Variable.woff2"
|
|
5783
|
-
)
|
|
5784
|
-
],
|
|
5785
|
-
[
|
|
5786
|
-
"/assets/GeistMono-Variable-BNLlm6Cd.woff2",
|
|
5787
|
-
path10.join(
|
|
5788
|
-
farmConfig.root,
|
|
5789
|
-
"node_modules/geist/dist/fonts/geist-mono/GeistMono-Variable.woff2"
|
|
5790
|
-
)
|
|
5791
|
-
]
|
|
5792
|
-
] : []
|
|
6298
|
+
farmDocsFontAssetList.map(({ url, sourcePath }) => [url, sourcePath])
|
|
5793
6299
|
);
|
|
5794
6300
|
const logRequest = /* @__PURE__ */ __name((method, urlPath, tag) => {
|
|
5795
6301
|
try {
|
|
@@ -5853,11 +6359,12 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5853
6359
|
}
|
|
5854
6360
|
}
|
|
5855
6361
|
const farmDocsFontPath = farmDocsFontAssets.get(requestPathname);
|
|
5856
|
-
if (farmDocsFontPath && fs4.existsSync(farmDocsFontPath)) {
|
|
6362
|
+
if ((requestMethod === "GET" || requestMethod === "HEAD") && farmDocsFontPath && fs4.existsSync(farmDocsFontPath)) {
|
|
5857
6363
|
res.statusCode = 200;
|
|
5858
6364
|
res.setHeader("Content-Type", "font/woff2");
|
|
5859
6365
|
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
|
5860
|
-
|
|
6366
|
+
if (requestMethod === "HEAD") res.end();
|
|
6367
|
+
else fs4.createReadStream(farmDocsFontPath).pipe(res);
|
|
5861
6368
|
return;
|
|
5862
6369
|
}
|
|
5863
6370
|
if (requestMethod === "GET" && (requestPathname === FARM_DEVTOOLS_PATH || requestPathname === `${FARM_DEVTOOLS_PATH}.json`)) {
|
|
@@ -6463,6 +6970,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
6463
6970
|
modulePath: toUrlPath(route.modulePath),
|
|
6464
6971
|
isClientComponent: routeSlots.length > 0 ? false : isClientComponent,
|
|
6465
6972
|
shouldHydrate: shouldHydrate || routeSlots.some((slot) => slot.isClientComponent || slot.shouldHydrate),
|
|
6973
|
+
islandStrategy: moduleMetadata.islandStrategy,
|
|
6466
6974
|
metadata: {
|
|
6467
6975
|
title: mergedMetadata.title,
|
|
6468
6976
|
description: mergedMetadata.description
|
|
@@ -6847,6 +7355,7 @@ export const getManifest = () => ({
|
|
|
6847
7355
|
search: route.search,
|
|
6848
7356
|
isClientComponent: moduleMetadata.isClientComponent,
|
|
6849
7357
|
shouldHydrate: moduleMetadata.shouldHydrate,
|
|
7358
|
+
islandStrategy: moduleMetadata.islandStrategy,
|
|
6850
7359
|
preloads: [route.modulePath],
|
|
6851
7360
|
// In dev, preload is just the module
|
|
6852
7361
|
assets: []
|
|
@@ -6973,8 +7482,8 @@ if (import.meta.hot) {
|
|
|
6973
7482
|
}
|
|
6974
7483
|
logger.info(`Found ${ssgPages.length} SSG pages, ${ssrRoutes.length} SSR routes`);
|
|
6975
7484
|
logger.info("Pre-rendering SSG pages...");
|
|
6976
|
-
const outDir =
|
|
6977
|
-
const clientDir =
|
|
7485
|
+
const outDir = path11.join(server?.config.root || process.cwd(), options.outDir || "dist");
|
|
7486
|
+
const clientDir = path11.join(outDir, "client");
|
|
6978
7487
|
for (const page of ssgPages) {
|
|
6979
7488
|
try {
|
|
6980
7489
|
const staticRequest = new Request(new URL(page.urlPath, "http://farm.static"));
|
|
@@ -7026,8 +7535,8 @@ if (import.meta.hot) {
|
|
|
7026
7535
|
<script type="module" src="/assets/client.js"></script>
|
|
7027
7536
|
</body>
|
|
7028
7537
|
</html>`;
|
|
7029
|
-
const outputPath = page.urlPath === "/" ?
|
|
7030
|
-
fs4.mkdirSync(
|
|
7538
|
+
const outputPath = page.urlPath === "/" ? path11.join(clientDir, "index.html") : path11.join(clientDir, page.urlPath + ".html");
|
|
7539
|
+
fs4.mkdirSync(path11.dirname(outputPath), { recursive: true });
|
|
7031
7540
|
fs4.writeFileSync(outputPath, fullHtml);
|
|
7032
7541
|
const revalidateInfo = page.revalidate ? ` (revalidate: ${page.revalidate}s)` : "";
|
|
7033
7542
|
logger.success(` \u2713 ${page.urlPath}${revalidateInfo}`);
|
|
@@ -7036,7 +7545,7 @@ if (import.meta.hot) {
|
|
|
7036
7545
|
logger.error(` \u2717 ${page.urlPath}: ${error}`);
|
|
7037
7546
|
}
|
|
7038
7547
|
}
|
|
7039
|
-
const manifestPath =
|
|
7548
|
+
const manifestPath = path11.join(outDir, "__ssg_manifest.json");
|
|
7040
7549
|
fs4.writeFileSync(
|
|
7041
7550
|
manifestPath,
|
|
7042
7551
|
JSON.stringify(
|
|
@@ -7072,9 +7581,9 @@ if (import.meta.hot) {
|
|
|
7072
7581
|
}
|
|
7073
7582
|
const currentFarmConfig = farmApp?.getConfig();
|
|
7074
7583
|
const normalizedFile = file.replace(/\\/g, "/");
|
|
7075
|
-
const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) =>
|
|
7584
|
+
const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) => path11.join(source.root, source.srcDir).replace(/\\/g, "/")).find((sourceRoot) => normalizedFile.startsWith(`${sourceRoot}/`)) || null : null;
|
|
7076
7585
|
if (currentSrcRoot && normalizedFile.startsWith(`${currentSrcRoot}/`) && isProgrammaticRoutesFileName(normalizedFile)) {
|
|
7077
|
-
logUpdate("PAGE", `updated ${
|
|
7586
|
+
logUpdate("PAGE", `updated ${path11.basename(file)}`);
|
|
7078
7587
|
for (const mod of modules) {
|
|
7079
7588
|
server2.moduleGraph.invalidateModule(mod);
|
|
7080
7589
|
}
|
|
@@ -7471,6 +7980,7 @@ import React from 'react'
|
|
|
7471
7980
|
import { hydrateRoot, createRoot } from 'react-dom/client'
|
|
7472
7981
|
import { installChunkErrorRecovery, SPARouter } from '@farm.js/core/client'
|
|
7473
7982
|
import { createClientPluginManager } from '@farm.js/core/plugin/client'
|
|
7983
|
+
import { scheduleFarmIslandHydration } from '@farm.js/core/internal/client-runtime'
|
|
7474
7984
|
import { reviveDeferredData } from '@farm.js/core/deferred'
|
|
7475
7985
|
import {
|
|
7476
7986
|
createFarmDeploymentMismatchError,
|
|
@@ -7723,6 +8233,7 @@ class LegacyManifestSPARouter {
|
|
|
7723
8233
|
|
|
7724
8234
|
// Only prefetch routes that will hydrate on the client.
|
|
7725
8235
|
if (!match.route.isClientComponent && !match.route.shouldHydrate) return;
|
|
8236
|
+
if (match.route.islandStrategy && match.route.islandStrategy !== 'load') return;
|
|
7726
8237
|
|
|
7727
8238
|
const modulePath = match.route.modulePath;
|
|
7728
8239
|
if (this.moduleCache.has(modulePath)) return;
|
|
@@ -7867,6 +8378,12 @@ let hasClientTakenOver = false;
|
|
|
7867
8378
|
const routeSlotRoots = new Map();
|
|
7868
8379
|
const routeSlotDefinitions = new Map();
|
|
7869
8380
|
let activeRouteInterception = null;
|
|
8381
|
+
let pendingPageHydrationController = null;
|
|
8382
|
+
|
|
8383
|
+
function cancelPendingPageHydration() {
|
|
8384
|
+
pendingPageHydrationController?.abort();
|
|
8385
|
+
pendingPageHydrationController = null;
|
|
8386
|
+
}
|
|
7870
8387
|
|
|
7871
8388
|
function normalizeServerProps(rawProps) {
|
|
7872
8389
|
const props = rawProps && typeof rawProps === 'object' ? { ...rawProps } : {};
|
|
@@ -7935,7 +8452,11 @@ async function hydrateInitialRouteSlots() {
|
|
|
7935
8452
|
routeSlotDefinitions.set(getRouteSlotKey(slot), slot);
|
|
7936
8453
|
if (!slot.isClientComponent && !slot.shouldHydrate) continue;
|
|
7937
8454
|
try {
|
|
7938
|
-
|
|
8455
|
+
const slotHydrated = await renderRouteSlot(slot, 'hydrate');
|
|
8456
|
+
hydrated = slotHydrated || hydrated;
|
|
8457
|
+
if (slotHydrated) {
|
|
8458
|
+
replayPreHydrationClicks(document.getElementById(slot.containerId));
|
|
8459
|
+
}
|
|
7939
8460
|
} catch (error) {
|
|
7940
8461
|
console.warn('[Farm.js] Could not hydrate route slot:', slot.name, error);
|
|
7941
8462
|
}
|
|
@@ -8006,16 +8527,29 @@ function applyCanonicalPathFromProps(props) {
|
|
|
8006
8527
|
window.history.replaceState({ ...(window.history.state || {}), path: canonicalPath }, '', canonicalPath);
|
|
8007
8528
|
}
|
|
8008
8529
|
|
|
8009
|
-
function replayPreHydrationClicks() {
|
|
8010
|
-
|
|
8011
|
-
|
|
8530
|
+
function replayPreHydrationClicks(container = null) {
|
|
8531
|
+
if (!container) {
|
|
8532
|
+
markFarmHydrated();
|
|
8533
|
+
} else {
|
|
8534
|
+
container.dataset.farmIslandHydrated = 'true';
|
|
8535
|
+
}
|
|
8012
8536
|
|
|
8013
8537
|
const queue = Array.isArray(window.__FARM_PREHYDRATION_CLICK_QUEUE__)
|
|
8014
8538
|
? window.__FARM_PREHYDRATION_CLICK_QUEUE__
|
|
8015
8539
|
: [];
|
|
8016
8540
|
if (queue.length === 0) return;
|
|
8017
8541
|
|
|
8018
|
-
const queuedClicks =
|
|
8542
|
+
const queuedClicks = [];
|
|
8543
|
+
const remainingClicks = [];
|
|
8544
|
+
for (const queuedClick of queue) {
|
|
8545
|
+
const target = queuedClick?.target;
|
|
8546
|
+
if (!container || (target instanceof Node && container.contains(target))) {
|
|
8547
|
+
queuedClicks.push(queuedClick);
|
|
8548
|
+
} else {
|
|
8549
|
+
remainingClicks.push(queuedClick);
|
|
8550
|
+
}
|
|
8551
|
+
}
|
|
8552
|
+
queue.splice(0, queue.length, ...remainingClicks);
|
|
8019
8553
|
for (const queuedClick of queuedClicks) {
|
|
8020
8554
|
const target = queuedClick?.target;
|
|
8021
8555
|
if (!target || typeof target.click !== 'function') continue;
|
|
@@ -8024,6 +8558,11 @@ function replayPreHydrationClicks() {
|
|
|
8024
8558
|
}
|
|
8025
8559
|
}
|
|
8026
8560
|
|
|
8561
|
+
function markFarmHydrated() {
|
|
8562
|
+
window.__FARM_HYDRATED__ = true;
|
|
8563
|
+
document.documentElement.dataset.farmHydrated = 'true';
|
|
8564
|
+
}
|
|
8565
|
+
|
|
8027
8566
|
async function buildClientHydrationElement(PageComponent, pageProps) {
|
|
8028
8567
|
let element = React.createElement(PageComponent, pageProps);
|
|
8029
8568
|
const loadingModulePath = window.__FARM_LOADING_MODULE__;
|
|
@@ -8166,9 +8705,10 @@ async function tryHydrateImportedPage(
|
|
|
8166
8705
|
layouts,
|
|
8167
8706
|
useHydrate = false,
|
|
8168
8707
|
existingProps = null,
|
|
8708
|
+
signal = null,
|
|
8169
8709
|
) {
|
|
8170
8710
|
const modulePath = route?.modulePath;
|
|
8171
|
-
if (!modulePath) {
|
|
8711
|
+
if (!modulePath || signal?.aborted) {
|
|
8172
8712
|
return false;
|
|
8173
8713
|
}
|
|
8174
8714
|
|
|
@@ -8177,6 +8717,7 @@ async function tryHydrateImportedPage(
|
|
|
8177
8717
|
pageModule = await import(/* @vite-ignore */ modulePath);
|
|
8178
8718
|
pageModuleCache.set(modulePath, pageModule);
|
|
8179
8719
|
}
|
|
8720
|
+
if (signal?.aborted || !container?.isConnected) return false;
|
|
8180
8721
|
|
|
8181
8722
|
const PageComponent = pageModule?.default;
|
|
8182
8723
|
if (!PageComponent) {
|
|
@@ -8191,6 +8732,7 @@ async function tryHydrateImportedPage(
|
|
|
8191
8732
|
window.location.pathname,
|
|
8192
8733
|
existingProps,
|
|
8193
8734
|
);
|
|
8735
|
+
if (signal?.aborted || !container?.isConnected) return false;
|
|
8194
8736
|
|
|
8195
8737
|
const wrappedElement = useHydrate && container?.id === '__farm_page__'
|
|
8196
8738
|
? wrapWithIntegrationProviders(
|
|
@@ -8201,6 +8743,7 @@ async function tryHydrateImportedPage(
|
|
|
8201
8743
|
currentPageProps,
|
|
8202
8744
|
layouts,
|
|
8203
8745
|
);
|
|
8746
|
+
if (signal?.aborted || !container?.isConnected) return false;
|
|
8204
8747
|
|
|
8205
8748
|
if (useHydrate) {
|
|
8206
8749
|
try {
|
|
@@ -8231,6 +8774,7 @@ async function tryHydrateImportedPage(
|
|
|
8231
8774
|
async function renderPage(pageData) {
|
|
8232
8775
|
const container = document.getElementById('root');
|
|
8233
8776
|
if (!container) return;
|
|
8777
|
+
cancelPendingPageHydration();
|
|
8234
8778
|
const destination = window.location.pathname + window.location.search;
|
|
8235
8779
|
|
|
8236
8780
|
if (pageData.interception) {
|
|
@@ -8247,6 +8791,7 @@ async function renderPage(pageData) {
|
|
|
8247
8791
|
modulePath: pageData.modulePath,
|
|
8248
8792
|
isClientComponent: pageData.isClientComponent === true,
|
|
8249
8793
|
shouldHydrate: pageData.shouldHydrate === true,
|
|
8794
|
+
islandStrategy: pageData.islandStrategy || 'load',
|
|
8250
8795
|
};
|
|
8251
8796
|
const params = pageData.props?.params || {};
|
|
8252
8797
|
const layouts = (pageData.layoutModules || []).map((modulePath, index) => ({
|
|
@@ -8446,14 +8991,6 @@ async function hydrate() {
|
|
|
8446
8991
|
}
|
|
8447
8992
|
|
|
8448
8993
|
try {
|
|
8449
|
-
// Pre-load layout for SPA navigation
|
|
8450
|
-
try {
|
|
8451
|
-
const layoutModule = await import(/* @vite-ignore */ '/src/app/layout.tsx');
|
|
8452
|
-
LayoutComponent = layoutModule.default;
|
|
8453
|
-
} catch (e) {
|
|
8454
|
-
console.warn('[Farm.js] Could not preload layout:', e);
|
|
8455
|
-
}
|
|
8456
|
-
|
|
8457
8994
|
// Check if this is a client component (set by SSR)
|
|
8458
8995
|
const isClientComponent = window.__FARM_IS_CLIENT__ === true;
|
|
8459
8996
|
const modulePath = window.__FARM_PAGE_MODULE__;
|
|
@@ -8501,34 +9038,88 @@ async function hydrate() {
|
|
|
8501
9038
|
return
|
|
8502
9039
|
}
|
|
8503
9040
|
|
|
8504
|
-
const
|
|
8505
|
-
|
|
8506
|
-
|
|
8507
|
-
|
|
9041
|
+
const currentRoute = findRoute(window.location.pathname)?.route;
|
|
9042
|
+
const islandStrategy = window.__FARM_ISLAND_STRATEGY__ || currentRoute?.islandStrategy || 'load';
|
|
9043
|
+
pageContainer.dataset.farmIsland = 'page';
|
|
9044
|
+
pageContainer.dataset.farmIslandStrategy = islandStrategy;
|
|
8508
9045
|
|
|
8509
|
-
|
|
9046
|
+
const hydrationPathname = window.location.pathname;
|
|
9047
|
+
const hydrationController = new AbortController();
|
|
9048
|
+
pendingPageHydrationController = hydrationController;
|
|
8510
9049
|
try {
|
|
8511
|
-
|
|
8512
|
-
pageContainer,
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
8522
|
-
|
|
8523
|
-
}
|
|
9050
|
+
await scheduleFarmIslandHydration({
|
|
9051
|
+
container: pageContainer,
|
|
9052
|
+
strategy: islandStrategy,
|
|
9053
|
+
signal: hydrationController.signal,
|
|
9054
|
+
hydrate: async () => {
|
|
9055
|
+
if (
|
|
9056
|
+
hydrationController.signal.aborted ||
|
|
9057
|
+
!pageContainer.isConnected ||
|
|
9058
|
+
window.location.pathname !== hydrationPathname
|
|
9059
|
+
) {
|
|
9060
|
+
return;
|
|
9061
|
+
}
|
|
8524
9062
|
|
|
8525
|
-
|
|
8526
|
-
|
|
8527
|
-
|
|
8528
|
-
|
|
8529
|
-
|
|
9063
|
+
// Layout code is only needed when this route boundary actually hydrates.
|
|
9064
|
+
try {
|
|
9065
|
+
const layoutModule = await import(/* @vite-ignore */ '/src/app/layout.tsx');
|
|
9066
|
+
LayoutComponent = layoutModule.default;
|
|
9067
|
+
} catch (e) {
|
|
9068
|
+
console.warn('[Farm.js] Could not preload layout:', e);
|
|
9069
|
+
}
|
|
9070
|
+
if (hydrationController.signal.aborted || !pageContainer.isConnected) return;
|
|
9071
|
+
|
|
9072
|
+
const hydrationSession = await farmClientRuntime.beginHydration({
|
|
9073
|
+
container: pageContainer,
|
|
9074
|
+
mode: shouldHydrate ? 'hydrate' : 'render',
|
|
9075
|
+
});
|
|
9076
|
+
|
|
9077
|
+
let hydrated = false;
|
|
9078
|
+
try {
|
|
9079
|
+
if (hydrationController.signal.aborted || !pageContainer.isConnected) {
|
|
9080
|
+
await farmClientRuntime.failHydration(
|
|
9081
|
+
hydrationSession,
|
|
9082
|
+
new DOMException('Route hydration was cancelled', 'AbortError'),
|
|
9083
|
+
);
|
|
9084
|
+
return;
|
|
9085
|
+
}
|
|
9086
|
+
hydrated = await tryHydrateImportedPage(
|
|
9087
|
+
pageContainer,
|
|
9088
|
+
{ modulePath },
|
|
9089
|
+
currentPageProps.params || {},
|
|
9090
|
+
layouts,
|
|
9091
|
+
shouldHydrate,
|
|
9092
|
+
currentPageProps,
|
|
9093
|
+
hydrationController.signal,
|
|
9094
|
+
);
|
|
9095
|
+
if (hydrationController.signal.aborted || !pageContainer.isConnected) {
|
|
9096
|
+
await farmClientRuntime.failHydration(
|
|
9097
|
+
hydrationSession,
|
|
9098
|
+
new DOMException('Route hydration was cancelled', 'AbortError'),
|
|
9099
|
+
);
|
|
9100
|
+
return;
|
|
9101
|
+
}
|
|
9102
|
+
await farmClientRuntime.completeHydration(hydrationSession);
|
|
9103
|
+
} catch (error) {
|
|
9104
|
+
await farmClientRuntime.failHydration(hydrationSession, error);
|
|
9105
|
+
throw error;
|
|
9106
|
+
}
|
|
9107
|
+
|
|
9108
|
+
if (hydrated) {
|
|
9109
|
+
// The scheduler owns queue draining and exactly-once click replay.
|
|
9110
|
+
markFarmHydrated();
|
|
9111
|
+
console.log('[Farm.js] \u2705 Hydrated:', modulePath, '(' + islandStrategy + ')');
|
|
9112
|
+
return;
|
|
9113
|
+
}
|
|
8530
9114
|
|
|
8531
|
-
|
|
9115
|
+
console.log('[Farm.js] Server component - SPA router ready')
|
|
9116
|
+
},
|
|
9117
|
+
});
|
|
9118
|
+
} finally {
|
|
9119
|
+
if (pendingPageHydrationController === hydrationController) {
|
|
9120
|
+
pendingPageHydrationController = null;
|
|
9121
|
+
}
|
|
9122
|
+
}
|
|
8532
9123
|
} catch (error) {
|
|
8533
9124
|
console.error('[Farm.js] Hydration error:', error)
|
|
8534
9125
|
}
|
|
@@ -8634,7 +9225,7 @@ function generateClientManifest(bundle) {
|
|
|
8634
9225
|
__name(generateClientManifest, "generateClientManifest");
|
|
8635
9226
|
async function defineConfig(config = {}) {
|
|
8636
9227
|
const tailwindcss = (await import("@tailwindcss/vite")).default;
|
|
8637
|
-
const appRoot =
|
|
9228
|
+
const appRoot = path11.resolve(config.root || process.cwd());
|
|
8638
9229
|
if (config.extends?.length) {
|
|
8639
9230
|
const { config: layeredConfig } = await import("./layers-VWVDTPUZ.mjs").then(
|
|
8640
9231
|
({ resolveFarmLayers }) => resolveFarmLayers(config, {
|
|
@@ -8779,13 +9370,16 @@ async function defineConfig(config = {}) {
|
|
|
8779
9370
|
customLogger: farmLogger,
|
|
8780
9371
|
clearScreen: false,
|
|
8781
9372
|
optimizeDeps: {
|
|
8782
|
-
|
|
8783
|
-
|
|
8784
|
-
|
|
8785
|
-
|
|
8786
|
-
|
|
8787
|
-
|
|
8788
|
-
|
|
9373
|
+
...createFarmClientOptimizeDepsConfig(
|
|
9374
|
+
createFarmClientOptimizeDepsEntries(
|
|
9375
|
+
appRoot,
|
|
9376
|
+
getFarmAppDirectories({ ...config, root: appRoot })
|
|
9377
|
+
)
|
|
9378
|
+
),
|
|
9379
|
+
// Pre-bundle every framework client-runtime entry with React. Without
|
|
9380
|
+
// this, Vite can discover a linked Farm entry after the page has loaded,
|
|
9381
|
+
// regenerate the optimizer browser hash, and leave React DOM holding a
|
|
9382
|
+
// different React module instance from a client component.
|
|
8789
9383
|
// Exclude server-side packages from browser bundling
|
|
8790
9384
|
exclude: [
|
|
8791
9385
|
"@farm.js/core/server",
|
|
@@ -8820,7 +9414,7 @@ async function defineConfig(config = {}) {
|
|
|
8820
9414
|
// Stub out problematic server-only modules during dev mode
|
|
8821
9415
|
alias: {
|
|
8822
9416
|
...getFarmLayerAliases(config.layers),
|
|
8823
|
-
"@":
|
|
9417
|
+
"@": path11.resolve(appRoot, "src"),
|
|
8824
9418
|
// Nitro internals that should not be resolved in browser
|
|
8825
9419
|
"supports-color": "data:text/javascript,export default false; export const supportsColor = false; export const stdout = false; export const stderr = false;",
|
|
8826
9420
|
"@poppinss/dumper": "data:text/javascript,export default {};",
|
|
@@ -8842,6 +9436,7 @@ __name(defineConfig, "defineConfig");
|
|
|
8842
9436
|
export {
|
|
8843
9437
|
resolveRouteRenderingConfig,
|
|
8844
9438
|
resolveRouteRenderingConfigFromFile,
|
|
9439
|
+
analyzeStaticRouteCandidate,
|
|
8845
9440
|
parseRouteRenderingDirective,
|
|
8846
9441
|
collectSSGPages,
|
|
8847
9442
|
isSSGModule,
|
|
@@ -8864,9 +9459,12 @@ export {
|
|
|
8864
9459
|
createFarmImageTypeDeclarations,
|
|
8865
9460
|
generateFarmI18nTypes,
|
|
8866
9461
|
generateFarmTypeArtifacts,
|
|
9462
|
+
createFarmClientOptimizeDepsEntries,
|
|
9463
|
+
createFarmClientOptimizeDepsConfig,
|
|
9464
|
+
mergeFarmViteConfig,
|
|
8867
9465
|
farmI18nClientBridgePlugin,
|
|
8868
9466
|
rewriteEarlySsrRelativeImports,
|
|
8869
9467
|
farmPlugin,
|
|
8870
9468
|
defineConfig
|
|
8871
9469
|
};
|
|
8872
|
-
//# sourceMappingURL=chunk-
|
|
9470
|
+
//# sourceMappingURL=chunk-PNFQQSRA.mjs.map
|