@farm.js/core 0.1.0-beta.1 → 0.1.0-beta.4
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/README.md +1 -1
- package/dist/agent-runtime.d.mts +2 -1
- package/dist/agent-runtime.d.ts +2 -1
- package/dist/api/route-manager.cjs +410 -15
- package/dist/api/route-manager.cjs.map +1 -1
- package/dist/api/route-manager.d.mts +4 -2
- package/dist/api/route-manager.d.ts +4 -2
- package/dist/api/route-manager.mjs +9 -8
- package/dist/api/runtime.cjs +748 -9
- package/dist/api/runtime.cjs.map +1 -1
- package/dist/api/runtime.d.mts +3 -16
- package/dist/api/runtime.d.ts +3 -16
- package/dist/api/runtime.mjs +8 -1
- package/dist/api.cjs +1243 -342
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.mts +5 -147
- package/dist/api.d.ts +5 -147
- package/dist/api.mjs +51 -21
- package/dist/{app-CFRNJXP1.d.ts → app-BjN-da13.d.ts} +38 -3
- package/dist/{app-BiX4qb-d.d.mts → app-CakAr8Be.d.mts} +38 -3
- package/dist/app-markdown.cjs +1 -1
- package/dist/app-markdown.cjs.map +1 -1
- package/dist/app-markdown.d.mts +2 -1
- package/dist/app-markdown.d.ts +2 -1
- package/dist/app-markdown.mjs +1 -1
- package/dist/cache.cjs +414 -12
- package/dist/cache.cjs.map +1 -1
- package/dist/cache.d.mts +120 -6
- package/dist/cache.d.ts +120 -6
- package/dist/cache.mjs +11 -3
- package/dist/{chunk-Y7A27276.mjs → chunk-2CUKEMVR.mjs} +349 -15
- package/dist/chunk-2CUKEMVR.mjs.map +1 -0
- package/dist/{chunk-QF4PHCMA.mjs → chunk-2ED5Q2GH.mjs} +3 -3
- package/dist/chunk-2ED5Q2GH.mjs.map +1 -0
- package/dist/{chunk-GZP5W4K3.mjs → chunk-32W4QEJP.mjs} +1 -1
- package/dist/chunk-32W4QEJP.mjs.map +1 -0
- package/dist/{chunk-TRORP7E4.mjs → chunk-3U3ZUQAQ.mjs} +2 -2
- package/dist/{chunk-25D7G34K.mjs → chunk-65A7QIKI.mjs} +5 -5
- package/dist/{chunk-25D7G34K.mjs.map → chunk-65A7QIKI.mjs.map} +1 -1
- package/dist/{chunk-G3B5BRDY.mjs → chunk-AJWRO5WE.mjs} +539 -61
- package/dist/chunk-AJWRO5WE.mjs.map +1 -0
- package/dist/chunk-ALCLXXTY.mjs +187 -0
- package/dist/chunk-ALCLXXTY.mjs.map +1 -0
- package/dist/{chunk-CHFHNEMO.mjs → chunk-AOBXKNS5.mjs} +627 -84
- package/dist/chunk-AOBXKNS5.mjs.map +1 -0
- package/dist/{chunk-B6N4ZB2H.mjs → chunk-C2ROET2V.mjs} +3 -3
- package/dist/{chunk-JN3UU635.mjs → chunk-EJ7T4TPB.mjs} +2 -2
- package/dist/chunk-EJ7T4TPB.mjs.map +1 -0
- package/dist/{chunk-ZJQNATYV.mjs → chunk-FRPWCMMG.mjs} +3 -3
- package/dist/chunk-FRPWCMMG.mjs.map +1 -0
- package/dist/{chunk-QM6VV26B.mjs → chunk-GQVGIUSN.mjs} +3 -3
- package/dist/{chunk-QM6VV26B.mjs.map → chunk-GQVGIUSN.mjs.map} +1 -1
- package/dist/{chunk-UREJA4GZ.mjs → chunk-GXASWWJU.mjs} +1 -1
- package/dist/{chunk-UREJA4GZ.mjs.map → chunk-GXASWWJU.mjs.map} +1 -1
- package/dist/{chunk-3QJO55ZF.mjs → chunk-HNIQFZKB.mjs} +5 -3
- package/dist/{chunk-3QJO55ZF.mjs.map → chunk-HNIQFZKB.mjs.map} +1 -1
- package/dist/{chunk-PRNYWD7K.mjs → chunk-JDEOUK5V.mjs} +67 -239
- package/dist/chunk-JDEOUK5V.mjs.map +1 -0
- package/dist/{chunk-O3HADRW6.mjs → chunk-MIUW47JX.mjs} +2 -2
- package/dist/{chunk-O3HADRW6.mjs.map → chunk-MIUW47JX.mjs.map} +1 -1
- package/dist/{chunk-UHE2TTLK.mjs → chunk-NM3CRAAL.mjs} +9 -8
- package/dist/chunk-NM3CRAAL.mjs.map +1 -0
- package/dist/chunk-PFE6GMNE.mjs +603 -0
- package/dist/chunk-PFE6GMNE.mjs.map +1 -0
- package/dist/{chunk-S2XHZS7W.mjs → chunk-QGQX7SFC.mjs} +2 -2
- package/dist/chunk-QGQX7SFC.mjs.map +1 -0
- package/dist/{chunk-RKI6TN3A.mjs → chunk-QM746KUO.mjs} +9 -2
- package/dist/chunk-QM746KUO.mjs.map +1 -0
- package/dist/chunk-RBRLLZL5.mjs +81 -0
- package/dist/chunk-RBRLLZL5.mjs.map +1 -0
- package/dist/{chunk-HXP3ZSPC.mjs → chunk-SADGIRS2.mjs} +3 -3
- package/dist/{chunk-6XDUHOEM.mjs → chunk-TQAEEJB4.mjs} +3 -3
- package/dist/{chunk-AGS7UJ52.mjs → chunk-UB5UOSHB.mjs} +24 -12
- package/dist/chunk-UB5UOSHB.mjs.map +1 -0
- package/dist/{chunk-SXZTEK3V.mjs → chunk-UXUAWNO5.mjs} +2 -2
- package/dist/chunk-V3XURYJO.mjs +756 -0
- package/dist/chunk-V3XURYJO.mjs.map +1 -0
- package/dist/{chunk-TU4YJICB.mjs → chunk-VVKWFZAH.mjs} +41 -16
- package/dist/chunk-VVKWFZAH.mjs.map +1 -0
- package/dist/{chunk-JLWMCADZ.mjs → chunk-VY2UYN5R.mjs} +24 -4
- package/dist/chunk-VY2UYN5R.mjs.map +1 -0
- package/dist/{chunk-QFQRHRZS.mjs → chunk-W2CRQFF6.mjs} +151 -23
- package/dist/chunk-W2CRQFF6.mjs.map +1 -0
- package/dist/chunk-W4UIVMVI.mjs +10 -0
- package/dist/chunk-W4UIVMVI.mjs.map +1 -0
- package/dist/{chunk-Y2OJJD7R.mjs → chunk-XIVV5IWN.mjs} +7 -9
- package/dist/chunk-XIVV5IWN.mjs.map +1 -0
- package/dist/{chunk-OYXO65LI.mjs → chunk-YW7OBE6Q.mjs} +4 -4
- package/dist/chunk-YW7OBE6Q.mjs.map +1 -0
- package/dist/{chunk-YHU7SS6L.mjs → chunk-Z5CQMP54.mjs} +11 -11
- package/dist/{chunk-SOU3Q3ZA.mjs → chunk-ZZ57EH5Z.mjs} +1 -1
- package/dist/chunk-ZZ57EH5Z.mjs.map +1 -0
- package/dist/{client-D_yUjVhe.d.mts → client-BT1mFQas.d.mts} +55 -10
- package/dist/{client-Dkc03WP8.d.ts → client-Nn0q4eO4.d.ts} +55 -10
- package/dist/{client-plugins-BZnpeTGA.d.ts → client-plugins-Cw4qUGsw.d.ts} +7 -0
- package/dist/{client-plugins-g4bzuCmo.d.mts → client-plugins-DQQ1adXM.d.mts} +7 -0
- package/dist/client-plugins.d.mts +2 -1
- package/dist/client-plugins.d.ts +2 -1
- package/dist/client.cjs +922 -91
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.mts +121 -3
- package/dist/client.d.ts +121 -3
- package/dist/client.mjs +23 -16
- package/dist/config.d.mts +2 -1
- package/dist/config.d.ts +2 -1
- package/dist/cron.cjs.map +1 -1
- package/dist/cron.mjs +1 -1
- package/dist/{devtools-AE4RVXCM.mjs → devtools-LVC3VB5P.mjs} +10 -10
- package/dist/{devtools-client-6WPY2AQU.mjs → devtools-client-3XRTBND5.mjs} +2 -11
- package/dist/devtools-client-3XRTBND5.mjs.map +1 -0
- package/dist/docs.cjs +14 -2
- package/dist/docs.cjs.map +1 -1
- package/dist/docs.mjs +10 -10
- package/dist/i18n/server.cjs +2 -2
- package/dist/i18n/server.cjs.map +1 -1
- package/dist/i18n/server.mjs +1 -1
- package/dist/index.cjs +2852 -463
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +13 -12
- package/dist/index.d.ts +13 -12
- package/dist/index.mjs +152 -109
- package/dist/index.mjs.map +1 -1
- package/dist/integrations.d.mts +2 -1
- package/dist/integrations.d.ts +2 -1
- package/dist/internal/build-runtime.cjs +1616 -149
- package/dist/internal/build-runtime.cjs.map +1 -1
- package/dist/internal/build-runtime.d.mts +4 -3
- package/dist/internal/build-runtime.d.ts +4 -3
- package/dist/internal/build-runtime.mjs +27 -25
- package/dist/internal/client-runtime.cjs.map +1 -1
- package/dist/internal/client-runtime.mjs +1 -1
- package/dist/internal/config-runtime.cjs +13 -2
- package/dist/internal/config-runtime.cjs.map +1 -1
- package/dist/internal/config-runtime.d.mts +3 -2
- package/dist/internal/config-runtime.d.ts +3 -2
- package/dist/internal/config-runtime.mjs +9 -9
- package/dist/internal/production-runtime.cjs +285 -9
- package/dist/internal/production-runtime.cjs.map +1 -1
- package/dist/internal/production-runtime.d.mts +4 -4
- package/dist/internal/production-runtime.d.ts +4 -4
- package/dist/internal/production-runtime.mjs +10 -8
- package/dist/{metadata-DAXRaOHx.d.ts → metadata-BAPg_Nmo.d.ts} +1 -1
- package/dist/{metadata-C9NZxMDW.d.mts → metadata-_6i9oFG3.d.mts} +1 -1
- package/dist/middleware.cjs +2 -2
- package/dist/middleware.cjs.map +1 -1
- package/dist/middleware.d.mts +4 -3
- package/dist/middleware.d.ts +4 -3
- package/dist/middleware.mjs +3 -3
- package/dist/navigation.cjs +40 -15
- package/dist/navigation.cjs.map +1 -1
- package/dist/navigation.mjs +3 -3
- package/dist/{nitro-KME62MWG.mjs → nitro-QO5LV6QK.mjs} +11 -13
- package/dist/{nitro-KME62MWG.mjs.map → nitro-QO5LV6QK.mjs.map} +1 -1
- package/dist/plugin.cjs +1032 -92
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.mts +2 -1
- package/dist/plugin.d.ts +2 -1
- package/dist/plugin.mjs +23 -21
- package/dist/{production-runtime-DRkCHUvJ.d.ts → production-runtime-BoJDc5mc.d.ts} +1 -1
- package/dist/{production-runtime-flrjp_nC.d.mts → production-runtime-DPfgMV9Y.d.mts} +1 -1
- package/dist/routes.cjs +276 -6
- package/dist/routes.cjs.map +1 -1
- package/dist/routes.d.mts +1 -1
- package/dist/routes.d.ts +1 -1
- package/dist/routes.mjs +4 -4
- package/dist/runtime-9nQjVM7X.d.mts +206 -0
- package/dist/runtime-DgeS2skB.d.ts +206 -0
- package/dist/server-action-security.cjs +28 -10
- package/dist/server-action-security.cjs.map +1 -1
- package/dist/server-action-security.d.mts +2 -1
- package/dist/server-action-security.d.ts +2 -1
- package/dist/server-action-security.mjs +2 -2
- package/dist/server-fn-client.cjs.map +1 -1
- package/dist/server-fn-client.d.mts +1 -0
- package/dist/server-fn-client.d.ts +1 -0
- package/dist/server-fn-client.mjs +1 -1
- package/dist/server-fn.cjs +785 -3
- package/dist/server-fn.cjs.map +1 -1
- package/dist/server-fn.d.mts +10 -1
- package/dist/server-fn.d.ts +10 -1
- package/dist/server-fn.mjs +6 -3
- package/dist/server-plugins.d.mts +3 -2
- package/dist/server-plugins.d.ts +3 -2
- package/dist/server-query-client.cjs +278 -7
- package/dist/server-query-client.cjs.map +1 -1
- package/dist/server-query-client.mjs +4 -4
- package/dist/server-query.cjs +381 -10
- package/dist/server-query.cjs.map +1 -1
- package/dist/server-query.mjs +5 -5
- package/dist/server.cjs +1233 -118
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.mts +8 -7
- package/dist/server.d.ts +8 -7
- package/dist/server.mjs +53 -33
- package/dist/server.mjs.map +1 -1
- package/dist/testing.cjs +436 -25
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.mts +4 -3
- package/dist/testing.d.ts +4 -3
- package/dist/testing.mjs +19 -18
- package/dist/testing.mjs.map +1 -1
- package/dist/transport-BmbGTXA5.d.mts +49 -0
- package/dist/transport-BmbGTXA5.d.ts +49 -0
- package/dist/{utils-DOXXivjL.d.mts → utils-CHXlMDkg.d.mts} +1 -1
- package/dist/{utils-DA1yo54_.d.ts → utils-Drsyz1Vj.d.ts} +1 -1
- package/dist/version.cjs +36 -0
- package/dist/version.cjs.map +1 -0
- package/dist/version.d.mts +3 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.mjs +8 -0
- package/dist/version.mjs.map +1 -0
- package/dist/vite.cjs +1039 -93
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.mts +2 -1
- package/dist/vite.d.ts +2 -1
- package/dist/vite.mjs +23 -21
- package/dist/workflows.cjs +6 -8
- package/dist/workflows.cjs.map +1 -1
- package/dist/workflows.mjs +1 -1
- package/package.json +12 -5
- package/types/api.d.ts +44 -0
- package/types/client.d.ts +220 -16
- package/dist/chunk-4PTK6KT4.mjs +0 -364
- package/dist/chunk-4PTK6KT4.mjs.map +0 -1
- package/dist/chunk-AGS7UJ52.mjs.map +0 -1
- package/dist/chunk-CHFHNEMO.mjs.map +0 -1
- package/dist/chunk-EVGBEZDF.mjs +0 -215
- package/dist/chunk-EVGBEZDF.mjs.map +0 -1
- package/dist/chunk-G3B5BRDY.mjs.map +0 -1
- package/dist/chunk-GZP5W4K3.mjs.map +0 -1
- package/dist/chunk-JLWMCADZ.mjs.map +0 -1
- package/dist/chunk-JN3UU635.mjs.map +0 -1
- package/dist/chunk-OYXO65LI.mjs.map +0 -1
- package/dist/chunk-PRNYWD7K.mjs.map +0 -1
- package/dist/chunk-QF4PHCMA.mjs.map +0 -1
- package/dist/chunk-QFQRHRZS.mjs.map +0 -1
- package/dist/chunk-RKI6TN3A.mjs.map +0 -1
- package/dist/chunk-S2XHZS7W.mjs.map +0 -1
- package/dist/chunk-SOU3Q3ZA.mjs.map +0 -1
- package/dist/chunk-TU4YJICB.mjs.map +0 -1
- package/dist/chunk-TXCFGOHW.mjs +0 -42
- package/dist/chunk-TXCFGOHW.mjs.map +0 -1
- package/dist/chunk-UHE2TTLK.mjs.map +0 -1
- package/dist/chunk-Y2OJJD7R.mjs.map +0 -1
- package/dist/chunk-Y7A27276.mjs.map +0 -1
- package/dist/chunk-ZJQNATYV.mjs.map +0 -1
- package/dist/devtools-client-6WPY2AQU.mjs.map +0 -1
- /package/dist/{chunk-TRORP7E4.mjs.map → chunk-3U3ZUQAQ.mjs.map} +0 -0
- /package/dist/{chunk-B6N4ZB2H.mjs.map → chunk-C2ROET2V.mjs.map} +0 -0
- /package/dist/{chunk-HXP3ZSPC.mjs.map → chunk-SADGIRS2.mjs.map} +0 -0
- /package/dist/{chunk-6XDUHOEM.mjs.map → chunk-TQAEEJB4.mjs.map} +0 -0
- /package/dist/{chunk-SXZTEK3V.mjs.map → chunk-UXUAWNO5.mjs.map} +0 -0
- /package/dist/{chunk-YHU7SS6L.mjs.map → chunk-Z5CQMP54.mjs.map} +0 -0
- /package/dist/{devtools-AE4RVXCM.mjs.map → devtools-LVC3VB5P.mjs.map} +0 -0
|
@@ -2946,7 +2946,11 @@ async function prepareFarmWorkflowsForNitro(config) {
|
|
|
2946
2946
|
};
|
|
2947
2947
|
}
|
|
2948
2948
|
const handlerPath = path27.join(generatedDir, "http-handler.mjs");
|
|
2949
|
-
await fs8.writeFile(
|
|
2949
|
+
await fs8.writeFile(
|
|
2950
|
+
handlerPath,
|
|
2951
|
+
createNitroWorkflowHTTPHandler(workflowConfig, workflows),
|
|
2952
|
+
"utf8"
|
|
2953
|
+
);
|
|
2950
2954
|
const manifestPath = path27.join(generatedDir, "manifest.json");
|
|
2951
2955
|
await fs8.writeFile(
|
|
2952
2956
|
manifestPath,
|
|
@@ -3020,13 +3024,7 @@ function normalizeSchedule(schedule) {
|
|
|
3020
3024
|
return (Array.isArray(schedule) ? schedule : [schedule]).map((value) => value.trim()).filter(Boolean);
|
|
3021
3025
|
}
|
|
3022
3026
|
function resolveWorkflowDefinition(module2) {
|
|
3023
|
-
const candidates = [
|
|
3024
|
-
module2.default,
|
|
3025
|
-
module2.workflow,
|
|
3026
|
-
module2.cron,
|
|
3027
|
-
module2.task,
|
|
3028
|
-
module2.job
|
|
3029
|
-
];
|
|
3027
|
+
const candidates = [module2.default, module2.workflow, module2.cron, module2.task, module2.job];
|
|
3030
3028
|
for (const candidate of candidates) {
|
|
3031
3029
|
if (candidate && typeof candidate === "object" && typeof candidate.run === "function") {
|
|
3032
3030
|
return candidate;
|
|
@@ -3892,7 +3890,7 @@ function createFarmMarkdownRouteModule(input) {
|
|
|
3892
3890
|
...props,
|
|
3893
3891
|
components: {
|
|
3894
3892
|
...components,
|
|
3895
|
-
...props?.components
|
|
3893
|
+
...props?.components
|
|
3896
3894
|
}
|
|
3897
3895
|
})
|
|
3898
3896
|
);
|
|
@@ -4082,8 +4080,8 @@ function compareFarmRouteRuleSpecificity(left, right) {
|
|
|
4082
4080
|
}
|
|
4083
4081
|
function getFarmRouteRuleSpecificity(pattern) {
|
|
4084
4082
|
return normalizeRoutePattern(pattern).split("/").filter(Boolean).reduce((score, segment) => {
|
|
4085
|
-
if (segment === "**" ||
|
|
4086
|
-
if (segment === "*" ||
|
|
4083
|
+
if (segment === "**" || segment.startsWith("[[...")) return score + 1;
|
|
4084
|
+
if (segment === "*" || segment.startsWith("[...")) return score + 10;
|
|
4087
4085
|
if (/^\[.+\]$/.test(segment) || /^:.+$/.test(segment)) return score + 50;
|
|
4088
4086
|
return score + 100;
|
|
4089
4087
|
}, 0);
|
|
@@ -4145,7 +4143,7 @@ function routeRulesToHeaders(routeRules) {
|
|
|
4145
4143
|
for (const [source, rule] of Object.entries(routeRules)) {
|
|
4146
4144
|
const headers = {
|
|
4147
4145
|
...normalizeCorsHeaders(rule.cors),
|
|
4148
|
-
...rule.headers
|
|
4146
|
+
...rule.headers
|
|
4149
4147
|
};
|
|
4150
4148
|
const entries = Object.entries(headers);
|
|
4151
4149
|
if (entries.length === 0) continue;
|
|
@@ -4175,7 +4173,7 @@ function routeRulesToNitroRouteRules(routeRules) {
|
|
|
4175
4173
|
nitroRule.cors = true;
|
|
4176
4174
|
nitroRule.headers = {
|
|
4177
4175
|
...normalizeCorsHeaders(rule.cors),
|
|
4178
|
-
...rule.headers
|
|
4176
|
+
...rule.headers
|
|
4179
4177
|
};
|
|
4180
4178
|
}
|
|
4181
4179
|
delete nitroRule.render;
|
|
@@ -4227,22 +4225,50 @@ var init_route_rules = __esm({
|
|
|
4227
4225
|
// src/cache-invalidation.ts
|
|
4228
4226
|
function getFarmCacheInvalidationState() {
|
|
4229
4227
|
return globalState[FARM_CACHE_INVALIDATION_STATE] ?? (globalState[FARM_CACHE_INVALIDATION_STATE] = {
|
|
4230
|
-
listeners: /* @__PURE__ */ new Set()
|
|
4228
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
4229
|
+
taskListeners: /* @__PURE__ */ new Set()
|
|
4231
4230
|
});
|
|
4232
4231
|
}
|
|
4232
|
+
function encodeFarmCacheInvalidations(keys) {
|
|
4233
|
+
const normalized = Array.from(
|
|
4234
|
+
new Set(keys.filter((key) => typeof key === "string" && key.length > 0))
|
|
4235
|
+
);
|
|
4236
|
+
if (normalized.length === 0) return null;
|
|
4237
|
+
return encodeURIComponent(JSON.stringify(normalized));
|
|
4238
|
+
}
|
|
4239
|
+
function decodeFarmCacheInvalidations(value) {
|
|
4240
|
+
if (!value) return [];
|
|
4241
|
+
try {
|
|
4242
|
+
const parsed = JSON.parse(decodeURIComponent(value));
|
|
4243
|
+
return Array.isArray(parsed) ? Array.from(
|
|
4244
|
+
new Set(parsed.filter((key) => typeof key === "string" && key.length > 0))
|
|
4245
|
+
) : [];
|
|
4246
|
+
} catch {
|
|
4247
|
+
return [];
|
|
4248
|
+
}
|
|
4249
|
+
}
|
|
4233
4250
|
function subscribeFarmCacheInvalidation(listener) {
|
|
4234
4251
|
const state = getFarmCacheInvalidationState();
|
|
4235
4252
|
state.listeners.add(listener);
|
|
4236
4253
|
return () => state.listeners.delete(listener);
|
|
4237
4254
|
}
|
|
4238
|
-
|
|
4255
|
+
function subscribeFarmCacheTask(listener) {
|
|
4256
|
+
const state = getFarmCacheInvalidationState();
|
|
4257
|
+
state.taskListeners.add(listener);
|
|
4258
|
+
return () => state.taskListeners.delete(listener);
|
|
4259
|
+
}
|
|
4260
|
+
var FARM_CACHE_INVALIDATION_HEADER, FARM_CACHE_INVALIDATION_STATE, globalState;
|
|
4239
4261
|
var init_cache_invalidation = __esm({
|
|
4240
4262
|
"src/cache-invalidation.ts"() {
|
|
4241
4263
|
"use strict";
|
|
4264
|
+
FARM_CACHE_INVALIDATION_HEADER = "x-farm-cache-invalidations";
|
|
4242
4265
|
FARM_CACHE_INVALIDATION_STATE = /* @__PURE__ */ Symbol.for("farm.cacheInvalidationState");
|
|
4243
4266
|
globalState = globalThis;
|
|
4244
4267
|
__name(getFarmCacheInvalidationState, "getFarmCacheInvalidationState");
|
|
4268
|
+
__name(encodeFarmCacheInvalidations, "encodeFarmCacheInvalidations");
|
|
4269
|
+
__name(decodeFarmCacheInvalidations, "decodeFarmCacheInvalidations");
|
|
4245
4270
|
__name(subscribeFarmCacheInvalidation, "subscribeFarmCacheInvalidation");
|
|
4271
|
+
__name(subscribeFarmCacheTask, "subscribeFarmCacheTask");
|
|
4246
4272
|
}
|
|
4247
4273
|
});
|
|
4248
4274
|
|
|
@@ -4346,6 +4372,9 @@ var init_server_action_security = __esm({
|
|
|
4346
4372
|
subscribeFarmCacheInvalidation((key) => {
|
|
4347
4373
|
getServerActionExecutionContext()?.invalidations.add(key);
|
|
4348
4374
|
});
|
|
4375
|
+
subscribeFarmCacheTask((task) => {
|
|
4376
|
+
getServerActionExecutionContext()?.cacheTasks.add(task);
|
|
4377
|
+
});
|
|
4349
4378
|
__name(getServerActionStorage, "getServerActionStorage");
|
|
4350
4379
|
__name(parseBodySizeLimit, "parseBodySizeLimit");
|
|
4351
4380
|
__name(normalizeAllowedOriginPattern, "normalizeAllowedOriginPattern");
|
|
@@ -5503,6 +5532,7 @@ async function resolveConfig(userConfig, mode) {
|
|
|
5503
5532
|
observability: userConfig.observability ?? false,
|
|
5504
5533
|
devtools: resolveFarmDevtoolsConfig(userConfig.devtools, mode),
|
|
5505
5534
|
storage: userConfig.storage || {},
|
|
5535
|
+
cache: userConfig.cache || {},
|
|
5506
5536
|
suppressLintOnLink: userConfig.suppressLintOnLink ?? false,
|
|
5507
5537
|
experimental: {
|
|
5508
5538
|
serverComponents: false,
|
|
@@ -6297,6 +6327,9 @@ var init_bridge = __esm({
|
|
|
6297
6327
|
function getFarmDataCache() {
|
|
6298
6328
|
return sharedFarmDataCache;
|
|
6299
6329
|
}
|
|
6330
|
+
function configureFarmCache(config) {
|
|
6331
|
+
sharedFarmDataCache.configure(config);
|
|
6332
|
+
}
|
|
6300
6333
|
function createPathCacheTag(routePath) {
|
|
6301
6334
|
return `path:${normalizeRevalidatePath(routePath)}`;
|
|
6302
6335
|
}
|
|
@@ -6350,6 +6383,46 @@ function normalizeCacheTag(tag) {
|
|
|
6350
6383
|
}
|
|
6351
6384
|
return normalized;
|
|
6352
6385
|
}
|
|
6386
|
+
function normalizeCacheNamespace(namespace) {
|
|
6387
|
+
if (typeof namespace !== "string") {
|
|
6388
|
+
throw new TypeError("Cache namespace must be a string.");
|
|
6389
|
+
}
|
|
6390
|
+
const normalized = namespace.trim().replace(/:+$/g, "");
|
|
6391
|
+
if (!normalized) {
|
|
6392
|
+
throw new Error("Cache namespace cannot be empty.");
|
|
6393
|
+
}
|
|
6394
|
+
return normalized;
|
|
6395
|
+
}
|
|
6396
|
+
function normalizeAdapterVersion(value) {
|
|
6397
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
|
|
6398
|
+
}
|
|
6399
|
+
function normalizePositiveDuration(value, fallback, name) {
|
|
6400
|
+
if (value === void 0) return fallback;
|
|
6401
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
6402
|
+
throw new TypeError(`${name} must be a positive number of milliseconds.`);
|
|
6403
|
+
}
|
|
6404
|
+
return Math.floor(value);
|
|
6405
|
+
}
|
|
6406
|
+
function delay(ms) {
|
|
6407
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
6408
|
+
}
|
|
6409
|
+
function normalizeCacheOptionsTags(options) {
|
|
6410
|
+
const tags = /* @__PURE__ */ new Set();
|
|
6411
|
+
for (const tag of options.tags ?? []) {
|
|
6412
|
+
tags.add(normalizeCacheTag(tag));
|
|
6413
|
+
}
|
|
6414
|
+
for (const routePath of options.paths ?? []) {
|
|
6415
|
+
tags.add(createPathCacheTag(routePath));
|
|
6416
|
+
}
|
|
6417
|
+
return tags;
|
|
6418
|
+
}
|
|
6419
|
+
function assertFarmCacheEntry(entry, expectedKey) {
|
|
6420
|
+
if (!entry || typeof entry !== "object" || entry.key !== expectedKey || !Array.isArray(entry.tags) || typeof entry.createdAt !== "number") {
|
|
6421
|
+
throw new TypeError(
|
|
6422
|
+
`Cache adapter returned an invalid entry for ${JSON.stringify(expectedKey)}.`
|
|
6423
|
+
);
|
|
6424
|
+
}
|
|
6425
|
+
}
|
|
6353
6426
|
function getFunctionCacheIdentity(fn) {
|
|
6354
6427
|
if (fn.name) {
|
|
6355
6428
|
return `name:${fn.name}`;
|
|
@@ -6410,11 +6483,51 @@ var init_cache = __esm({
|
|
|
6410
6483
|
init_bridge();
|
|
6411
6484
|
init_cache_invalidation();
|
|
6412
6485
|
_FarmDataCache = class _FarmDataCache {
|
|
6413
|
-
constructor() {
|
|
6486
|
+
constructor(config = {}) {
|
|
6414
6487
|
this.entries = /* @__PURE__ */ new Map();
|
|
6415
6488
|
this.inflight = /* @__PURE__ */ new Map();
|
|
6416
6489
|
this.invalidatedTagVersions = /* @__PURE__ */ new Map();
|
|
6417
6490
|
this.version = 0;
|
|
6491
|
+
this.namespace = "farm";
|
|
6492
|
+
this.local = true;
|
|
6493
|
+
this.lease = {
|
|
6494
|
+
enabled: true,
|
|
6495
|
+
ttlMs: 1e4,
|
|
6496
|
+
waitTimeoutMs: 1e4,
|
|
6497
|
+
pollIntervalMs: 25
|
|
6498
|
+
};
|
|
6499
|
+
this.configure(config);
|
|
6500
|
+
}
|
|
6501
|
+
configure(config = {}) {
|
|
6502
|
+
this.adapter = config.adapter;
|
|
6503
|
+
this.namespace = normalizeCacheNamespace(config.namespace || "farm");
|
|
6504
|
+
this.local = !config.adapter;
|
|
6505
|
+
this.lease = config.lease === false ? { ...this.lease, enabled: false } : {
|
|
6506
|
+
enabled: true,
|
|
6507
|
+
ttlMs: normalizePositiveDuration(config.lease?.ttlMs, 1e4, "cache.lease.ttlMs"),
|
|
6508
|
+
waitTimeoutMs: normalizePositiveDuration(
|
|
6509
|
+
config.lease?.waitTimeoutMs,
|
|
6510
|
+
1e4,
|
|
6511
|
+
"cache.lease.waitTimeoutMs"
|
|
6512
|
+
),
|
|
6513
|
+
pollIntervalMs: normalizePositiveDuration(
|
|
6514
|
+
config.lease?.pollIntervalMs,
|
|
6515
|
+
25,
|
|
6516
|
+
"cache.lease.pollIntervalMs"
|
|
6517
|
+
)
|
|
6518
|
+
};
|
|
6519
|
+
if (!this.local) {
|
|
6520
|
+
this.entries.clear();
|
|
6521
|
+
this.inflight.clear();
|
|
6522
|
+
this.invalidatedTagVersions.clear();
|
|
6523
|
+
this.version = 0;
|
|
6524
|
+
}
|
|
6525
|
+
}
|
|
6526
|
+
get adapterName() {
|
|
6527
|
+
return this.adapter?.name || (this.adapter ? "custom" : "memory");
|
|
6528
|
+
}
|
|
6529
|
+
get hasAdapter() {
|
|
6530
|
+
return this.adapter !== void 0;
|
|
6418
6531
|
}
|
|
6419
6532
|
get size() {
|
|
6420
6533
|
return this.entries.size;
|
|
@@ -6450,6 +6563,45 @@ var init_cache = __esm({
|
|
|
6450
6563
|
});
|
|
6451
6564
|
return this.toPublicEntry(entry);
|
|
6452
6565
|
}
|
|
6566
|
+
async getEntryAsync(key, options = {}) {
|
|
6567
|
+
if (this.local) {
|
|
6568
|
+
const localEntry = this.getEntry(key, options);
|
|
6569
|
+
if (localEntry) return localEntry;
|
|
6570
|
+
}
|
|
6571
|
+
if (!this.adapter) {
|
|
6572
|
+
return this.local ? void 0 : this.getEntry(key, options);
|
|
6573
|
+
}
|
|
6574
|
+
const entry = await this.adapter.get(this.createAdapterKey(key));
|
|
6575
|
+
if (!entry) {
|
|
6576
|
+
emitFarmEvent({ type: "cache.miss", key });
|
|
6577
|
+
return void 0;
|
|
6578
|
+
}
|
|
6579
|
+
assertFarmCacheEntry(entry, key);
|
|
6580
|
+
const stale = await this.isAdapterEntryStale(entry, options.now);
|
|
6581
|
+
if (stale) {
|
|
6582
|
+
emitFarmEvent({
|
|
6583
|
+
type: "cache.stale",
|
|
6584
|
+
key,
|
|
6585
|
+
tags: [...entry.tags],
|
|
6586
|
+
revalidate: entry.revalidate
|
|
6587
|
+
});
|
|
6588
|
+
if (!options.allowStale) {
|
|
6589
|
+
emitFarmEvent({ type: "cache.miss", key, reason: "stale" });
|
|
6590
|
+
return void 0;
|
|
6591
|
+
}
|
|
6592
|
+
}
|
|
6593
|
+
emitFarmEvent({
|
|
6594
|
+
type: "cache.hit",
|
|
6595
|
+
key,
|
|
6596
|
+
tags: [...entry.tags],
|
|
6597
|
+
revalidate: entry.revalidate,
|
|
6598
|
+
stale
|
|
6599
|
+
});
|
|
6600
|
+
if (this.local && !stale) {
|
|
6601
|
+
this.hydrateLocalEntry(entry);
|
|
6602
|
+
}
|
|
6603
|
+
return { ...entry, key };
|
|
6604
|
+
}
|
|
6453
6605
|
set(key, value, options = {}) {
|
|
6454
6606
|
const tags = /* @__PURE__ */ new Set();
|
|
6455
6607
|
for (const tag of options.tags ?? []) {
|
|
@@ -6462,6 +6614,7 @@ var init_cache = __esm({
|
|
|
6462
6614
|
key,
|
|
6463
6615
|
value,
|
|
6464
6616
|
tags,
|
|
6617
|
+
tagVersions: void 0,
|
|
6465
6618
|
createdAt: options.createdAt ?? Date.now(),
|
|
6466
6619
|
createdVersion: ++this.version,
|
|
6467
6620
|
revalidate: normalizeRevalidate(options.revalidate)
|
|
@@ -6475,11 +6628,45 @@ var init_cache = __esm({
|
|
|
6475
6628
|
});
|
|
6476
6629
|
return this.toPublicEntry(entry);
|
|
6477
6630
|
}
|
|
6631
|
+
async setAsync(key, value, options = {}, tagVersions) {
|
|
6632
|
+
const tags = normalizeCacheOptionsTags(options);
|
|
6633
|
+
const capturedVersions = tagVersions ?? await this.getAdapterTagVersions(Array.from(tags.values()));
|
|
6634
|
+
const entry = {
|
|
6635
|
+
key,
|
|
6636
|
+
value,
|
|
6637
|
+
tags: Array.from(tags),
|
|
6638
|
+
tagVersions: capturedVersions,
|
|
6639
|
+
createdAt: options.createdAt ?? Date.now(),
|
|
6640
|
+
createdVersion: ++this.version,
|
|
6641
|
+
revalidate: normalizeRevalidate(options.revalidate)
|
|
6642
|
+
};
|
|
6643
|
+
if (this.local) {
|
|
6644
|
+
this.hydrateLocalEntry(entry);
|
|
6645
|
+
}
|
|
6646
|
+
if (this.adapter) {
|
|
6647
|
+
await this.adapter.set(this.createAdapterKey(key), entry);
|
|
6648
|
+
}
|
|
6649
|
+
emitFarmEvent({
|
|
6650
|
+
type: "cache.set",
|
|
6651
|
+
key,
|
|
6652
|
+
tags: [...entry.tags],
|
|
6653
|
+
revalidate: entry.revalidate
|
|
6654
|
+
});
|
|
6655
|
+
return entry;
|
|
6656
|
+
}
|
|
6478
6657
|
delete(key) {
|
|
6479
6658
|
const deleted = this.entries.delete(key);
|
|
6480
6659
|
emitFarmEvent({ type: "cache.delete", key, deleted });
|
|
6481
6660
|
return deleted;
|
|
6482
6661
|
}
|
|
6662
|
+
async deleteAsync(key) {
|
|
6663
|
+
const deleted = this.entries.delete(key);
|
|
6664
|
+
if (this.adapter) {
|
|
6665
|
+
await this.adapter.delete(this.createAdapterKey(key));
|
|
6666
|
+
}
|
|
6667
|
+
emitFarmEvent({ type: "cache.delete", key, deleted: this.adapter ? true : deleted });
|
|
6668
|
+
return this.adapter ? true : deleted;
|
|
6669
|
+
}
|
|
6483
6670
|
clear() {
|
|
6484
6671
|
const count = this.entries.size;
|
|
6485
6672
|
this.entries.clear();
|
|
@@ -6488,6 +6675,10 @@ var init_cache = __esm({
|
|
|
6488
6675
|
this.version = 0;
|
|
6489
6676
|
emitFarmEvent({ type: "cache.clear", count });
|
|
6490
6677
|
}
|
|
6678
|
+
async clearAsync() {
|
|
6679
|
+
this.clear();
|
|
6680
|
+
await this.adapter?.clear?.();
|
|
6681
|
+
}
|
|
6491
6682
|
isStale(entry, now = Date.now()) {
|
|
6492
6683
|
if (typeof entry.revalidate === "number" && entry.revalidate > 0 && now - entry.createdAt >= entry.revalidate * 1e3) {
|
|
6493
6684
|
return true;
|
|
@@ -6500,6 +6691,12 @@ var init_cache = __esm({
|
|
|
6500
6691
|
}
|
|
6501
6692
|
return false;
|
|
6502
6693
|
}
|
|
6694
|
+
async isStaleAsync(entry, now = Date.now()) {
|
|
6695
|
+
if (this.adapter) {
|
|
6696
|
+
return this.isAdapterEntryStale(entry, now);
|
|
6697
|
+
}
|
|
6698
|
+
return this.isStale(entry, now);
|
|
6699
|
+
}
|
|
6503
6700
|
revalidateTag(tag, options = {}) {
|
|
6504
6701
|
const normalized = normalizeCacheTag(tag);
|
|
6505
6702
|
const count = this.invalidateTag(normalized);
|
|
@@ -6508,6 +6705,15 @@ var init_cache = __esm({
|
|
|
6508
6705
|
);
|
|
6509
6706
|
return count;
|
|
6510
6707
|
}
|
|
6708
|
+
async revalidateTagAsync(tag, options = {}) {
|
|
6709
|
+
const normalized = normalizeCacheTag(tag);
|
|
6710
|
+
const count = this.invalidateTag(normalized);
|
|
6711
|
+
await this.adapter?.invalidateTags?.([this.createAdapterTag(normalized)]);
|
|
6712
|
+
emitFarmEvent(
|
|
6713
|
+
options.source === "updateTag" ? { type: "cache.updateTag", tag: normalized, count } : { type: "cache.revalidateTag", tag: normalized, profile: options.profile, count }
|
|
6714
|
+
);
|
|
6715
|
+
return count;
|
|
6716
|
+
}
|
|
6511
6717
|
revalidatePath(routePath) {
|
|
6512
6718
|
const normalizedPath = normalizeRevalidatePath(routePath);
|
|
6513
6719
|
const pathTag = createPathCacheTag(normalizedPath);
|
|
@@ -6524,8 +6730,25 @@ var init_cache = __esm({
|
|
|
6524
6730
|
}
|
|
6525
6731
|
return count;
|
|
6526
6732
|
}
|
|
6733
|
+
async revalidatePathAsync(routePath) {
|
|
6734
|
+
const normalizedPath = normalizeRevalidatePath(routePath);
|
|
6735
|
+
const pathTag = createPathCacheTag(normalizedPath);
|
|
6736
|
+
const pprCount = this.countEntriesForTags([pathTag, "ppr"]);
|
|
6737
|
+
const count = this.invalidateTag(pathTag);
|
|
6738
|
+
await this.adapter?.invalidateTags?.([this.createAdapterTag(pathTag)]);
|
|
6739
|
+
emitFarmEvent({ type: "cache.revalidatePath", path: normalizedPath, count });
|
|
6740
|
+
if (pprCount > 0) {
|
|
6741
|
+
emitFarmEvent({
|
|
6742
|
+
type: "ppr.shell.invalidated",
|
|
6743
|
+
route: normalizedPath,
|
|
6744
|
+
reason: "revalidatePath",
|
|
6745
|
+
count: pprCount
|
|
6746
|
+
});
|
|
6747
|
+
}
|
|
6748
|
+
return count;
|
|
6749
|
+
}
|
|
6527
6750
|
async getOrSet(key, producer, options = {}) {
|
|
6528
|
-
const cached = this.
|
|
6751
|
+
const cached = await this.getEntryAsync(key);
|
|
6529
6752
|
if (cached) {
|
|
6530
6753
|
return cached.value;
|
|
6531
6754
|
}
|
|
@@ -6534,10 +6757,8 @@ var init_cache = __esm({
|
|
|
6534
6757
|
emitFarmEvent({ type: "cache.dedupe", key });
|
|
6535
6758
|
return inflight;
|
|
6536
6759
|
}
|
|
6537
|
-
const
|
|
6538
|
-
|
|
6539
|
-
return value;
|
|
6540
|
-
}).catch((error) => {
|
|
6760
|
+
const tags = Array.from(normalizeCacheOptionsTags(options));
|
|
6761
|
+
const promise = this.fillCacheEntry(key, producer, options, tags).catch((error) => {
|
|
6541
6762
|
emitFarmEvent({ type: "cache.error", key, operation: "set", error });
|
|
6542
6763
|
throw error;
|
|
6543
6764
|
}).finally(() => {
|
|
@@ -6546,6 +6767,40 @@ var init_cache = __esm({
|
|
|
6546
6767
|
this.inflight.set(key, promise);
|
|
6547
6768
|
return promise;
|
|
6548
6769
|
}
|
|
6770
|
+
async fillCacheEntry(key, producer, options, tags) {
|
|
6771
|
+
const leaseKey = `${this.namespace}:lease:${key}`;
|
|
6772
|
+
let leaseToken;
|
|
6773
|
+
if (this.adapter?.acquireLease && this.adapter.releaseLease && this.lease.enabled) {
|
|
6774
|
+
leaseToken = await this.adapter.acquireLease(leaseKey, this.lease.ttlMs);
|
|
6775
|
+
if (!leaseToken) {
|
|
6776
|
+
const shared = await this.waitForAdapterEntry(key);
|
|
6777
|
+
if (shared) {
|
|
6778
|
+
emitFarmEvent({ type: "cache.dedupe", key });
|
|
6779
|
+
return shared.value;
|
|
6780
|
+
}
|
|
6781
|
+
leaseToken = await this.adapter.acquireLease(leaseKey, this.lease.ttlMs);
|
|
6782
|
+
}
|
|
6783
|
+
}
|
|
6784
|
+
try {
|
|
6785
|
+
const initialTagVersions = await this.getAdapterTagVersions(tags);
|
|
6786
|
+
const value = await producer();
|
|
6787
|
+
await this.setAsync(key, value, options, initialTagVersions);
|
|
6788
|
+
return value;
|
|
6789
|
+
} finally {
|
|
6790
|
+
if (leaseToken && this.adapter?.releaseLease) {
|
|
6791
|
+
await this.adapter.releaseLease(leaseKey, leaseToken);
|
|
6792
|
+
}
|
|
6793
|
+
}
|
|
6794
|
+
}
|
|
6795
|
+
async waitForAdapterEntry(key) {
|
|
6796
|
+
const deadline = Date.now() + this.lease.waitTimeoutMs;
|
|
6797
|
+
while (Date.now() < deadline) {
|
|
6798
|
+
await delay(this.lease.pollIntervalMs);
|
|
6799
|
+
const entry = await this.getEntryAsync(key);
|
|
6800
|
+
if (entry) return entry;
|
|
6801
|
+
}
|
|
6802
|
+
return void 0;
|
|
6803
|
+
}
|
|
6549
6804
|
countEntriesForTag(tag) {
|
|
6550
6805
|
let count = 0;
|
|
6551
6806
|
for (const entry of this.entries.values()) {
|
|
@@ -6573,11 +6828,53 @@ var init_cache = __esm({
|
|
|
6573
6828
|
key: entry.key,
|
|
6574
6829
|
value: entry.value,
|
|
6575
6830
|
tags: Array.from(entry.tags),
|
|
6831
|
+
tagVersions: entry.tagVersions,
|
|
6576
6832
|
createdAt: entry.createdAt,
|
|
6577
6833
|
createdVersion: entry.createdVersion,
|
|
6578
6834
|
revalidate: entry.revalidate
|
|
6579
6835
|
};
|
|
6580
6836
|
}
|
|
6837
|
+
hydrateLocalEntry(entry) {
|
|
6838
|
+
this.entries.set(entry.key, {
|
|
6839
|
+
key: entry.key,
|
|
6840
|
+
value: entry.value,
|
|
6841
|
+
tags: new Set(entry.tags.map(normalizeCacheTag)),
|
|
6842
|
+
tagVersions: entry.tagVersions,
|
|
6843
|
+
createdAt: entry.createdAt,
|
|
6844
|
+
createdVersion: entry.createdVersion ?? ++this.version,
|
|
6845
|
+
revalidate: normalizeRevalidate(entry.revalidate)
|
|
6846
|
+
});
|
|
6847
|
+
}
|
|
6848
|
+
createAdapterKey(key) {
|
|
6849
|
+
return `${this.namespace}:entry:${key}`;
|
|
6850
|
+
}
|
|
6851
|
+
createAdapterTag(tag) {
|
|
6852
|
+
return `${this.namespace}:tag:${tag}`;
|
|
6853
|
+
}
|
|
6854
|
+
async getAdapterTagVersions(tags) {
|
|
6855
|
+
if (!this.adapter?.getTagVersions || tags.length === 0) return {};
|
|
6856
|
+
const normalized = tags.map(normalizeCacheTag);
|
|
6857
|
+
const physicalTags = normalized.map((tag) => this.createAdapterTag(tag));
|
|
6858
|
+
const versions = await this.adapter.getTagVersions(physicalTags);
|
|
6859
|
+
return Object.fromEntries(
|
|
6860
|
+
normalized.map((tag, index) => [
|
|
6861
|
+
tag,
|
|
6862
|
+
normalizeAdapterVersion(versions[physicalTags[index]])
|
|
6863
|
+
])
|
|
6864
|
+
);
|
|
6865
|
+
}
|
|
6866
|
+
async isAdapterEntryStale(entry, now = Date.now()) {
|
|
6867
|
+
if (typeof entry.revalidate === "number" && entry.revalidate > 0 && now - entry.createdAt >= entry.revalidate * 1e3) {
|
|
6868
|
+
return true;
|
|
6869
|
+
}
|
|
6870
|
+
const currentVersions = await this.getAdapterTagVersions(entry.tags);
|
|
6871
|
+
for (const tag of entry.tags) {
|
|
6872
|
+
if (normalizeAdapterVersion(currentVersions[tag]) > normalizeAdapterVersion(entry.tagVersions?.[tag])) {
|
|
6873
|
+
return true;
|
|
6874
|
+
}
|
|
6875
|
+
}
|
|
6876
|
+
return false;
|
|
6877
|
+
}
|
|
6581
6878
|
};
|
|
6582
6879
|
__name(_FarmDataCache, "FarmDataCache");
|
|
6583
6880
|
FarmDataCache = _FarmDataCache;
|
|
@@ -6587,6 +6884,7 @@ var init_cache = __esm({
|
|
|
6587
6884
|
functionIds = /* @__PURE__ */ new WeakMap();
|
|
6588
6885
|
nextFunctionId = 0;
|
|
6589
6886
|
__name(getFarmDataCache, "getFarmDataCache");
|
|
6887
|
+
__name(configureFarmCache, "configureFarmCache");
|
|
6590
6888
|
__name(createPathCacheTag, "createPathCacheTag");
|
|
6591
6889
|
__name(createRouteDataCacheTag, "createRouteDataCacheTag");
|
|
6592
6890
|
__name(createRouteDataCacheKey, "createRouteDataCacheKey");
|
|
@@ -6594,6 +6892,12 @@ var init_cache = __esm({
|
|
|
6594
6892
|
__name(createFarmCacheKey, "createFarmCacheKey");
|
|
6595
6893
|
__name(normalizeRevalidate, "normalizeRevalidate");
|
|
6596
6894
|
__name(normalizeCacheTag, "normalizeCacheTag");
|
|
6895
|
+
__name(normalizeCacheNamespace, "normalizeCacheNamespace");
|
|
6896
|
+
__name(normalizeAdapterVersion, "normalizeAdapterVersion");
|
|
6897
|
+
__name(normalizePositiveDuration, "normalizePositiveDuration");
|
|
6898
|
+
__name(delay, "delay");
|
|
6899
|
+
__name(normalizeCacheOptionsTags, "normalizeCacheOptionsTags");
|
|
6900
|
+
__name(assertFarmCacheEntry, "assertFarmCacheEntry");
|
|
6597
6901
|
__name(getFunctionCacheIdentity, "getFunctionCacheIdentity");
|
|
6598
6902
|
__name(stableSerialize, "stableSerialize");
|
|
6599
6903
|
}
|
|
@@ -7715,6 +8019,83 @@ var init_routing = __esm({
|
|
|
7715
8019
|
}
|
|
7716
8020
|
});
|
|
7717
8021
|
|
|
8022
|
+
// src/routing/route-slots.ts
|
|
8023
|
+
function parseRouteSlotFile(filePath) {
|
|
8024
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
8025
|
+
const parts = normalized.split("/").filter(Boolean);
|
|
8026
|
+
const fileName = parts.at(-1) ?? "";
|
|
8027
|
+
const baseName = fileName.replace(/\.(tsx?|jsx?)$/, "");
|
|
8028
|
+
if (baseName !== "page" && baseName !== "default") return null;
|
|
8029
|
+
const slotIndex = parts.findIndex((part) => SLOT_SEGMENT.test(part));
|
|
8030
|
+
if (slotIndex < 0) return null;
|
|
8031
|
+
if (parts.slice(slotIndex + 1, -1).some((part) => SLOT_SEGMENT.test(part))) {
|
|
8032
|
+
throw new Error(`Nested route slots are not supported in "${filePath}"`);
|
|
8033
|
+
}
|
|
8034
|
+
const slotMatch = parts[slotIndex].match(SLOT_SEGMENT);
|
|
8035
|
+
const name = slotMatch?.[1];
|
|
8036
|
+
if (!name) return null;
|
|
8037
|
+
const ownerParts = parts.slice(0, slotIndex);
|
|
8038
|
+
const contentParts = parts.slice(slotIndex + 1, -1);
|
|
8039
|
+
const marker = parseInterceptionMarker(contentParts[0]);
|
|
8040
|
+
let targetBase = ownerParts;
|
|
8041
|
+
let targetParts = contentParts;
|
|
8042
|
+
if (marker) {
|
|
8043
|
+
targetBase = marker.root === true ? [] : ownerParts.slice(0, Math.max(0, ownerParts.length - marker.up));
|
|
8044
|
+
targetParts = [...marker.remainder ? [marker.remainder] : [], ...contentParts.slice(1)];
|
|
8045
|
+
}
|
|
8046
|
+
const ownerFile = [...ownerParts, "layout.tsx"].join("/");
|
|
8047
|
+
const routeFile = [
|
|
8048
|
+
...baseName === "default" ? ownerParts : targetBase,
|
|
8049
|
+
...baseName === "default" ? [] : targetParts,
|
|
8050
|
+
"page.tsx"
|
|
8051
|
+
].join("/");
|
|
8052
|
+
return {
|
|
8053
|
+
name,
|
|
8054
|
+
ownerRoute: parseRoutePath(ownerFile || "layout.tsx"),
|
|
8055
|
+
route: parseRoutePath(routeFile || "page.tsx"),
|
|
8056
|
+
interception: marker !== null,
|
|
8057
|
+
fallback: baseName === "default"
|
|
8058
|
+
};
|
|
8059
|
+
}
|
|
8060
|
+
function createRouteSlotContainerId(name, ownerPattern) {
|
|
8061
|
+
const owner = ownerPattern === "/" ? "root" : ownerPattern.replace(/^\//, "").replace(/[^A-Za-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
8062
|
+
return `__farm_slot_${name}_${owner || "root"}__`;
|
|
8063
|
+
}
|
|
8064
|
+
function parseInterceptionMarker(segment) {
|
|
8065
|
+
if (!segment) return null;
|
|
8066
|
+
if (segment.startsWith("(...)")) {
|
|
8067
|
+
return {
|
|
8068
|
+
up: 0,
|
|
8069
|
+
root: true,
|
|
8070
|
+
remainder: segment.slice(5)
|
|
8071
|
+
};
|
|
8072
|
+
}
|
|
8073
|
+
if (segment.startsWith("(.)")) {
|
|
8074
|
+
return {
|
|
8075
|
+
up: 0,
|
|
8076
|
+
remainder: segment.slice(3)
|
|
8077
|
+
};
|
|
8078
|
+
}
|
|
8079
|
+
let remainder = segment;
|
|
8080
|
+
let up = 0;
|
|
8081
|
+
while (remainder.startsWith("(..)")) {
|
|
8082
|
+
up += 1;
|
|
8083
|
+
remainder = remainder.slice(4);
|
|
8084
|
+
}
|
|
8085
|
+
return up > 0 ? { up, remainder } : null;
|
|
8086
|
+
}
|
|
8087
|
+
var SLOT_SEGMENT;
|
|
8088
|
+
var init_route_slots = __esm({
|
|
8089
|
+
"src/routing/route-slots.ts"() {
|
|
8090
|
+
"use strict";
|
|
8091
|
+
init_utils();
|
|
8092
|
+
SLOT_SEGMENT = /^@([A-Za-z][A-Za-z0-9_-]*)$/;
|
|
8093
|
+
__name(parseRouteSlotFile, "parseRouteSlotFile");
|
|
8094
|
+
__name(createRouteSlotContainerId, "createRouteSlotContainerId");
|
|
8095
|
+
__name(parseInterceptionMarker, "parseInterceptionMarker");
|
|
8096
|
+
}
|
|
8097
|
+
});
|
|
8098
|
+
|
|
7718
8099
|
// src/routing/route-manager.ts
|
|
7719
8100
|
function routeSpecificity(entry) {
|
|
7720
8101
|
return entry.route.segments.reduce((score, segment) => {
|
|
@@ -7786,11 +8167,13 @@ var init_route_manager = __esm({
|
|
|
7786
8167
|
init_static_metadata_image();
|
|
7787
8168
|
init_route_runtime();
|
|
7788
8169
|
init_routing();
|
|
8170
|
+
init_route_slots();
|
|
7789
8171
|
__name(routeSpecificity, "routeSpecificity");
|
|
7790
8172
|
_RouteManager = class _RouteManager {
|
|
7791
8173
|
constructor(config, viteServer) {
|
|
7792
8174
|
this.routes = /* @__PURE__ */ new Map();
|
|
7793
8175
|
this.layouts = /* @__PURE__ */ new Map();
|
|
8176
|
+
this.routeSlots = /* @__PURE__ */ new Map();
|
|
7794
8177
|
this.loadings = /* @__PURE__ */ new Map();
|
|
7795
8178
|
this.errors = /* @__PURE__ */ new Map();
|
|
7796
8179
|
this.metadataImages = /* @__PURE__ */ new Map();
|
|
@@ -7806,6 +8189,7 @@ var init_route_manager = __esm({
|
|
|
7806
8189
|
async discoverRoutes() {
|
|
7807
8190
|
this.routes.clear();
|
|
7808
8191
|
this.layouts.clear();
|
|
8192
|
+
this.routeSlots.clear();
|
|
7809
8193
|
this.loadings.clear();
|
|
7810
8194
|
this.errors.clear();
|
|
7811
8195
|
this.metadataImages.clear();
|
|
@@ -7816,6 +8200,13 @@ var init_route_manager = __esm({
|
|
|
7816
8200
|
await this.discoverFileRoutes(source);
|
|
7817
8201
|
await this.discoverProgrammaticRoutes(source);
|
|
7818
8202
|
}
|
|
8203
|
+
for (const slot of this.routeSlots.values()) {
|
|
8204
|
+
if (slot.interception && !this.routes.has(slot.pattern)) {
|
|
8205
|
+
throw new Error(
|
|
8206
|
+
`Intercepting route slot "${slot.name}" targets "${slot.pattern}", but no canonical page exists for that URL`
|
|
8207
|
+
);
|
|
8208
|
+
}
|
|
8209
|
+
}
|
|
7819
8210
|
this.routes = new Map(
|
|
7820
8211
|
Array.from(this.routes.entries()).sort(
|
|
7821
8212
|
([, left], [, right]) => routeSpecificity(right) - routeSpecificity(left)
|
|
@@ -7831,7 +8222,7 @@ var init_route_manager = __esm({
|
|
|
7831
8222
|
/**
|
|
7832
8223
|
* Find matching route for a given URL path
|
|
7833
8224
|
*/
|
|
7834
|
-
matchRoute(pathname) {
|
|
8225
|
+
matchRoute(pathname, options = {}) {
|
|
7835
8226
|
const routePathname = this.toRoutePathname(pathname);
|
|
7836
8227
|
const normalizedPath = routePathname === "/" ? "/" : routePathname.replace(/\/$/, "");
|
|
7837
8228
|
let matchedRoute = null;
|
|
@@ -7845,10 +8236,12 @@ var init_route_manager = __esm({
|
|
|
7845
8236
|
}
|
|
7846
8237
|
}
|
|
7847
8238
|
const layouts = this.findMatchingLayouts(normalizedPath);
|
|
8239
|
+
const slots = this.findMatchingRouteSlots(normalizedPath, options.interceptFrom);
|
|
7848
8240
|
return {
|
|
7849
8241
|
route: matchedRoute,
|
|
7850
8242
|
params,
|
|
7851
|
-
layouts
|
|
8243
|
+
layouts,
|
|
8244
|
+
slots
|
|
7852
8245
|
};
|
|
7853
8246
|
}
|
|
7854
8247
|
/**
|
|
@@ -7863,6 +8256,9 @@ var init_route_manager = __esm({
|
|
|
7863
8256
|
getLayouts() {
|
|
7864
8257
|
return new Map(this.layouts);
|
|
7865
8258
|
}
|
|
8259
|
+
getRouteSlots() {
|
|
8260
|
+
return new Map(this.routeSlots);
|
|
8261
|
+
}
|
|
7866
8262
|
/** Resolve route rules, inherited layouts, and the page export in precedence order. */
|
|
7867
8263
|
async resolveRouteRuntimeConfig(pattern) {
|
|
7868
8264
|
const routeEntry = this.routes.get(pattern);
|
|
@@ -8021,7 +8417,22 @@ var init_route_manager = __esm({
|
|
|
8021
8417
|
pattern: entry.pattern,
|
|
8022
8418
|
modulePath: toUrlPath(entry.modulePath)
|
|
8023
8419
|
}));
|
|
8024
|
-
|
|
8420
|
+
const slots = Array.from(this.routeSlots.values()).map((entry) => {
|
|
8421
|
+
const metadata = getClientModuleMetadata(entry.modulePath, projectRoot);
|
|
8422
|
+
return {
|
|
8423
|
+
name: entry.name,
|
|
8424
|
+
ownerPattern: entry.ownerPattern,
|
|
8425
|
+
pattern: entry.pattern,
|
|
8426
|
+
modulePath: toUrlPath(entry.modulePath),
|
|
8427
|
+
containerId: entry.containerId,
|
|
8428
|
+
interception: entry.interception,
|
|
8429
|
+
fallback: entry.fallback,
|
|
8430
|
+
shouldHydrate: metadata.shouldHydrate,
|
|
8431
|
+
isClientComponent: metadata.isClientComponent,
|
|
8432
|
+
segments: entry.route.segments
|
|
8433
|
+
};
|
|
8434
|
+
});
|
|
8435
|
+
return { routes, layouts, slots };
|
|
8025
8436
|
}
|
|
8026
8437
|
/**
|
|
8027
8438
|
* Load a route module dynamically
|
|
@@ -8098,6 +8509,7 @@ var init_route_manager = __esm({
|
|
|
8098
8509
|
async discoverFileRoutes(source) {
|
|
8099
8510
|
const appDir = resolveAppPath(source.root, source.srcDir, "app");
|
|
8100
8511
|
const pageFiles = await safeGlobFiles("**/page.{ts,tsx,js,jsx,md,mdx}", appDir);
|
|
8512
|
+
const slotDefaultFiles = await safeGlobFiles("**/@*/**/default.{ts,tsx,js,jsx}", appDir);
|
|
8101
8513
|
const layoutFiles = await safeGlobFiles("**/layout.{ts,tsx,js,jsx}", appDir);
|
|
8102
8514
|
const loadingFiles = await safeGlobFiles("**/loading.{ts,tsx,js,jsx}", appDir);
|
|
8103
8515
|
const errorFiles = await safeGlobFiles("**/error.{ts,tsx,js,jsx}", appDir);
|
|
@@ -8106,7 +8518,7 @@ var init_route_manager = __esm({
|
|
|
8106
8518
|
appDir
|
|
8107
8519
|
);
|
|
8108
8520
|
for (const [kind, files, target] of [
|
|
8109
|
-
["page", pageFiles, this.routes],
|
|
8521
|
+
["page", pageFiles.filter((file) => parseRouteSlotFile(file) === null), this.routes],
|
|
8110
8522
|
["layout", layoutFiles, this.layouts],
|
|
8111
8523
|
["loading", loadingFiles, this.loadings],
|
|
8112
8524
|
["error", errorFiles, this.errors]
|
|
@@ -8130,6 +8542,32 @@ var init_route_manager = __esm({
|
|
|
8130
8542
|
});
|
|
8131
8543
|
}
|
|
8132
8544
|
}
|
|
8545
|
+
for (const file of [...pageFiles, ...slotDefaultFiles]) {
|
|
8546
|
+
const slot = parseRouteSlotFile(file);
|
|
8547
|
+
if (!slot) continue;
|
|
8548
|
+
const modulePath = import_path6.default.join(appDir, file);
|
|
8549
|
+
const pattern = this.createRoutePattern(slot.route);
|
|
8550
|
+
const ownerPattern = this.createRoutePattern(slot.ownerRoute);
|
|
8551
|
+
const key = `${ownerPattern}:${slot.name}:${slot.interception ? "intercept" : "slot"}:${slot.fallback ? "default" : pattern}`;
|
|
8552
|
+
const existing = this.routeSlots.get(key);
|
|
8553
|
+
if (existing?.sourceRoot === source.root) {
|
|
8554
|
+
throw new Error(
|
|
8555
|
+
`Duplicate route slot "${slot.name}" for "${pattern}". Found both ${existing.modulePath} and ${modulePath}.`
|
|
8556
|
+
);
|
|
8557
|
+
}
|
|
8558
|
+
this.routeSlots.set(key, {
|
|
8559
|
+
route: slot.route,
|
|
8560
|
+
modulePath,
|
|
8561
|
+
pattern,
|
|
8562
|
+
source: "file",
|
|
8563
|
+
sourceRoot: source.root,
|
|
8564
|
+
name: slot.name,
|
|
8565
|
+
ownerPattern,
|
|
8566
|
+
interception: slot.interception,
|
|
8567
|
+
fallback: slot.fallback,
|
|
8568
|
+
containerId: createRouteSlotContainerId(slot.name, ownerPattern)
|
|
8569
|
+
});
|
|
8570
|
+
}
|
|
8133
8571
|
for (const file of metadataImageFiles) {
|
|
8134
8572
|
const fileBase = import_path6.default.basename(file, import_path6.default.extname(file));
|
|
8135
8573
|
const kind = fileBase === "twitter-image" ? "twitter" : "opengraph";
|
|
@@ -8255,6 +8693,71 @@ var init_route_manager = __esm({
|
|
|
8255
8693
|
}
|
|
8256
8694
|
return matchingLayouts;
|
|
8257
8695
|
}
|
|
8696
|
+
findMatchingRouteSlots(pathname, interceptFrom) {
|
|
8697
|
+
const groups = /* @__PURE__ */ new Map();
|
|
8698
|
+
for (const entry of this.routeSlots.values()) {
|
|
8699
|
+
if (!this.matchesRoutePrefix(pathname, entry.ownerPattern)) continue;
|
|
8700
|
+
const key = `${entry.ownerPattern}:${entry.name}`;
|
|
8701
|
+
const entries = groups.get(key) ?? [];
|
|
8702
|
+
entries.push(entry);
|
|
8703
|
+
groups.set(key, entries);
|
|
8704
|
+
}
|
|
8705
|
+
const normalizedFrom = interceptFrom ? this.toRoutePathname(new URL(interceptFrom, "http://farm.local").pathname) : void 0;
|
|
8706
|
+
const matches = [];
|
|
8707
|
+
for (const entries of groups.values()) {
|
|
8708
|
+
const candidates = entries.filter((entry) => !entry.fallback).filter(
|
|
8709
|
+
(entry) => !entry.interception || normalizedFrom !== void 0 && this.matchesRoutePrefix(normalizedFrom, entry.ownerPattern)
|
|
8710
|
+
).map((entry) => ({
|
|
8711
|
+
entry,
|
|
8712
|
+
match: matchRoute(pathname, entry.route.segments)
|
|
8713
|
+
})).filter((candidate) => candidate.match.matches).sort((left, right) => {
|
|
8714
|
+
if (left.entry.interception !== right.entry.interception) {
|
|
8715
|
+
return left.entry.interception ? -1 : 1;
|
|
8716
|
+
}
|
|
8717
|
+
return routeSpecificity(right.entry) - routeSpecificity(left.entry);
|
|
8718
|
+
});
|
|
8719
|
+
const selected = candidates[0];
|
|
8720
|
+
if (selected) {
|
|
8721
|
+
matches.push({
|
|
8722
|
+
name: selected.entry.name,
|
|
8723
|
+
ownerPattern: selected.entry.ownerPattern,
|
|
8724
|
+
containerId: selected.entry.containerId,
|
|
8725
|
+
interception: selected.entry.interception,
|
|
8726
|
+
fallback: false,
|
|
8727
|
+
route: selected.entry,
|
|
8728
|
+
params: selected.match.params
|
|
8729
|
+
});
|
|
8730
|
+
continue;
|
|
8731
|
+
}
|
|
8732
|
+
const fallback = entries.find((entry) => entry.fallback);
|
|
8733
|
+
if (fallback) {
|
|
8734
|
+
matches.push({
|
|
8735
|
+
name: fallback.name,
|
|
8736
|
+
ownerPattern: fallback.ownerPattern,
|
|
8737
|
+
containerId: fallback.containerId,
|
|
8738
|
+
interception: false,
|
|
8739
|
+
fallback: true,
|
|
8740
|
+
route: fallback,
|
|
8741
|
+
params: {}
|
|
8742
|
+
});
|
|
8743
|
+
}
|
|
8744
|
+
}
|
|
8745
|
+
return matches.sort((left, right) => {
|
|
8746
|
+
const ownerDifference = left.route.route.segments.length - right.route.route.segments.length;
|
|
8747
|
+
return ownerDifference || left.name.localeCompare(right.name);
|
|
8748
|
+
});
|
|
8749
|
+
}
|
|
8750
|
+
matchesRoutePrefix(pathname, pattern) {
|
|
8751
|
+
if (pattern === "/") return true;
|
|
8752
|
+
const patternSegments = parseRoutePath(`${pattern}/page.tsx`).segments;
|
|
8753
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
8754
|
+
if (patternSegments.length > pathSegments.length) return false;
|
|
8755
|
+
for (let index = 0; index < patternSegments.length; index++) {
|
|
8756
|
+
const segment = patternSegments[index];
|
|
8757
|
+
if (!segment.isDynamic && segment.segment !== pathSegments[index]) return false;
|
|
8758
|
+
}
|
|
8759
|
+
return true;
|
|
8760
|
+
}
|
|
8258
8761
|
findNearestBoundary(pathname, boundaries) {
|
|
8259
8762
|
const normalizedPath = pathname === "/" ? "/" : pathname.replace(/\/$/, "");
|
|
8260
8763
|
const pathSegments = normalizedPath.split("/").filter(Boolean);
|
|
@@ -8869,7 +9372,7 @@ function mergeMetadata(base, next) {
|
|
|
8869
9372
|
}
|
|
8870
9373
|
function addMetadataImageReference(metadata, reference) {
|
|
8871
9374
|
if (reference.kind === "opengraph") {
|
|
8872
|
-
const openGraph = { ...metadata.openGraph
|
|
9375
|
+
const openGraph = { ...metadata.openGraph };
|
|
8873
9376
|
if (!hasMetadataImages(openGraph.images) && !hasMetadataImages(openGraph.image)) {
|
|
8874
9377
|
openGraph.images = [
|
|
8875
9378
|
{
|
|
@@ -8886,7 +9389,7 @@ function addMetadataImageReference(metadata, reference) {
|
|
|
8886
9389
|
openGraph
|
|
8887
9390
|
};
|
|
8888
9391
|
}
|
|
8889
|
-
const twitter = { ...metadata.twitter
|
|
9392
|
+
const twitter = { ...metadata.twitter };
|
|
8890
9393
|
if (!hasMetadataImages(twitter.images)) {
|
|
8891
9394
|
twitter.images = [reference.href];
|
|
8892
9395
|
twitter.card = twitter.card || "summary_large_image";
|
|
@@ -9512,8 +10015,8 @@ var init_runtime = __esm({
|
|
|
9512
10015
|
cookie: this.config.cookie,
|
|
9513
10016
|
direction: getFarmLocaleDirection(resolution.locale, this.config.direction),
|
|
9514
10017
|
messages: {
|
|
9515
|
-
...this.catalogs[this.config.fallbackLocale]
|
|
9516
|
-
...this.catalogs[resolution.locale]
|
|
10018
|
+
...this.catalogs[this.config.fallbackLocale],
|
|
10019
|
+
...this.catalogs[resolution.locale]
|
|
9517
10020
|
}
|
|
9518
10021
|
};
|
|
9519
10022
|
}
|
|
@@ -9849,7 +10352,9 @@ var init_renderer = __esm({
|
|
|
9849
10352
|
async runWithRequestContext(request, fn) {
|
|
9850
10353
|
return _runWithCurrentRequest(
|
|
9851
10354
|
request,
|
|
9852
|
-
() => this.i18nRuntime?.config.enabled ? _runWithFarmI18nRequest(this.i18nRuntime, request, fn, {
|
|
10355
|
+
() => this.i18nRuntime?.config.enabled ? _runWithFarmI18nRequest(this.i18nRuntime, request, fn, {
|
|
10356
|
+
redirect: false
|
|
10357
|
+
}) : fn()
|
|
9853
10358
|
);
|
|
9854
10359
|
}
|
|
9855
10360
|
async resolveRouteContext(input) {
|
|
@@ -9872,11 +10377,11 @@ var init_renderer = __esm({
|
|
|
9872
10377
|
/**
|
|
9873
10378
|
* Check if a path should be served from SSG cache
|
|
9874
10379
|
*/
|
|
9875
|
-
shouldServeSSG(pathname) {
|
|
10380
|
+
async shouldServeSSG(pathname) {
|
|
9876
10381
|
const ssgPage = matchSSGPage(pathname, this.ssgManifest);
|
|
9877
10382
|
if (!ssgPage) return null;
|
|
9878
|
-
const cached = this.getCachedSSGPage(pathname);
|
|
9879
|
-
if (cached && this.dataCache.
|
|
10383
|
+
const cached = await this.getCachedSSGPage(pathname);
|
|
10384
|
+
if (cached && await this.dataCache.isStaleAsync(cached)) {
|
|
9880
10385
|
this.regenerateSSGPage(ssgPage);
|
|
9881
10386
|
}
|
|
9882
10387
|
return ssgPage;
|
|
@@ -9888,12 +10393,12 @@ var init_renderer = __esm({
|
|
|
9888
10393
|
return createFarmCacheKey(["ppr", normalizeRevalidatePath(pathname), search]);
|
|
9889
10394
|
}
|
|
9890
10395
|
getCachedSSGPage(urlPath) {
|
|
9891
|
-
return this.dataCache.
|
|
10396
|
+
return this.dataCache.getEntryAsync(this.getSSGCacheKey(urlPath), {
|
|
9892
10397
|
allowStale: true
|
|
9893
10398
|
});
|
|
9894
10399
|
}
|
|
9895
|
-
cacheSSGPage(page2, html, options) {
|
|
9896
|
-
this.dataCache.
|
|
10400
|
+
async cacheSSGPage(page2, html, options) {
|
|
10401
|
+
await this.dataCache.setAsync(
|
|
9897
10402
|
this.getSSGCacheKey(page2.urlPath),
|
|
9898
10403
|
{ html, document: options.document },
|
|
9899
10404
|
{
|
|
@@ -9905,11 +10410,11 @@ var init_renderer = __esm({
|
|
|
9905
10410
|
);
|
|
9906
10411
|
}
|
|
9907
10412
|
getCachedPPRShell(pathname, search) {
|
|
9908
|
-
return this.dataCache.
|
|
10413
|
+
return this.dataCache.getEntryAsync(this.getPPRCacheKey(pathname, search));
|
|
9909
10414
|
}
|
|
9910
|
-
cachePPRShell(options, html) {
|
|
10415
|
+
async cachePPRShell(options, html) {
|
|
9911
10416
|
const key = this.getPPRCacheKey(options.pathname, options.search);
|
|
9912
|
-
this.dataCache.
|
|
10417
|
+
await this.dataCache.setAsync(
|
|
9913
10418
|
key,
|
|
9914
10419
|
{ html },
|
|
9915
10420
|
{
|
|
@@ -10007,7 +10512,7 @@ var init_renderer = __esm({
|
|
|
10007
10512
|
}
|
|
10008
10513
|
const { renderToString } = await import("react-dom/server");
|
|
10009
10514
|
const html = renderToString(await this.wrapWithIntegrationProviders(pageElement));
|
|
10010
|
-
this.cacheSSGPage(page2, html, { document: false });
|
|
10515
|
+
await this.cacheSSGPage(page2, html, { document: false });
|
|
10011
10516
|
logger.info(`ISR: Regenerated ${page2.urlPath}`);
|
|
10012
10517
|
} catch (error) {
|
|
10013
10518
|
logger.error(`ISR regeneration failed for ${page2.urlPath}: ${error}`);
|
|
@@ -10021,7 +10526,7 @@ var init_renderer = __esm({
|
|
|
10021
10526
|
* Serve a pre-rendered SSG page
|
|
10022
10527
|
*/
|
|
10023
10528
|
async serveSSGPage(req, res, page2) {
|
|
10024
|
-
const cached = this.getCachedSSGPage(page2.urlPath);
|
|
10529
|
+
const cached = await this.getCachedSSGPage(page2.urlPath);
|
|
10025
10530
|
if (cached) {
|
|
10026
10531
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
10027
10532
|
res.setHeader("X-Farm-SSG", "cached");
|
|
@@ -10039,9 +10544,12 @@ var init_renderer = __esm({
|
|
|
10039
10544
|
if (fs2.existsSync(htmlPath)) {
|
|
10040
10545
|
const stat = fs2.statSync(htmlPath);
|
|
10041
10546
|
const html = fs2.readFileSync(htmlPath, "utf-8");
|
|
10042
|
-
this.cacheSSGPage(page2, html, {
|
|
10043
|
-
|
|
10044
|
-
|
|
10547
|
+
await this.cacheSSGPage(page2, html, {
|
|
10548
|
+
document: true,
|
|
10549
|
+
createdAt: stat.mtimeMs
|
|
10550
|
+
});
|
|
10551
|
+
const fileCacheEntry = await this.getCachedSSGPage(page2.urlPath);
|
|
10552
|
+
if (fileCacheEntry && await this.dataCache.isStaleAsync(fileCacheEntry)) {
|
|
10045
10553
|
this.regenerateSSGPage(page2);
|
|
10046
10554
|
}
|
|
10047
10555
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
@@ -10087,6 +10595,7 @@ var init_renderer = __esm({
|
|
|
10087
10595
|
let pathname = "/";
|
|
10088
10596
|
let params = {};
|
|
10089
10597
|
let layouts = [];
|
|
10598
|
+
let routeSlots = [];
|
|
10090
10599
|
let searchParamsObject = {};
|
|
10091
10600
|
let middlewareMap = /* @__PURE__ */ new Map();
|
|
10092
10601
|
let middlewareContext = /* @__PURE__ */ new Map();
|
|
@@ -10119,7 +10628,7 @@ var init_renderer = __esm({
|
|
|
10119
10628
|
}
|
|
10120
10629
|
this.applyDeploymentHeaders(req, res);
|
|
10121
10630
|
if (process.env.NODE_ENV === "production") {
|
|
10122
|
-
const ssgPage = this.shouldServeSSG(pathname);
|
|
10631
|
+
const ssgPage = await this.shouldServeSSG(pathname);
|
|
10123
10632
|
if (ssgPage) {
|
|
10124
10633
|
const served = await this.serveSSGPage(req, res, ssgPage);
|
|
10125
10634
|
if (served) {
|
|
@@ -10132,6 +10641,7 @@ var init_renderer = __esm({
|
|
|
10132
10641
|
const route = match.route;
|
|
10133
10642
|
params = match.params;
|
|
10134
10643
|
layouts = match.layouts;
|
|
10644
|
+
routeSlots = match.slots ?? [];
|
|
10135
10645
|
if (!route) {
|
|
10136
10646
|
emitFarmEvent({ type: "route.notFound", pathname });
|
|
10137
10647
|
await this.render404(req, res);
|
|
@@ -10148,7 +10658,9 @@ var init_renderer = __esm({
|
|
|
10148
10658
|
errorBoundaryEntry = this.routeManager.getMatchingError(pathname);
|
|
10149
10659
|
middlewareMap = toMiddlewareMap2(req.__FARM_MIDDLEWARE_DATA__);
|
|
10150
10660
|
middlewareContext = toMiddlewareMap2(req.__FARM_MIDDLEWARE_CONTEXT__);
|
|
10151
|
-
pluginExposedContext = getRequestContextSnapshot(req, {
|
|
10661
|
+
pluginExposedContext = getRequestContextSnapshot(req, {
|
|
10662
|
+
exposedOnly: true
|
|
10663
|
+
});
|
|
10152
10664
|
const currentRequest = createWebRequestFromFarmRequest(req);
|
|
10153
10665
|
const routeContext = await this.resolveRouteContext({
|
|
10154
10666
|
request: currentRequest,
|
|
@@ -10212,8 +10724,16 @@ var init_renderer = __esm({
|
|
|
10212
10724
|
revalidate: renderingConfig.revalidate
|
|
10213
10725
|
} : void 0;
|
|
10214
10726
|
if (renderingConfig.ppr && pprBypassReason) {
|
|
10215
|
-
emitFarmEvent({
|
|
10216
|
-
|
|
10727
|
+
emitFarmEvent({
|
|
10728
|
+
type: "ppr.shell.bypass",
|
|
10729
|
+
route: pathname,
|
|
10730
|
+
reason: pprBypassReason
|
|
10731
|
+
});
|
|
10732
|
+
emitFarmEvent({
|
|
10733
|
+
type: "cache.bypass",
|
|
10734
|
+
route: pathname,
|
|
10735
|
+
reason: pprBypassReason
|
|
10736
|
+
});
|
|
10217
10737
|
if (pprBypassReason === "refresh") {
|
|
10218
10738
|
pprRefreshRoute = pathname;
|
|
10219
10739
|
emitFarmEvent({ type: "ppr.refresh.start", route: pathname });
|
|
@@ -10221,14 +10741,22 @@ var init_renderer = __esm({
|
|
|
10221
10741
|
}
|
|
10222
10742
|
if (pprShellOptions) {
|
|
10223
10743
|
const pprCacheKey = this.getPPRCacheKey(pathname, url.search);
|
|
10224
|
-
const cachedPPRShell = this.getCachedPPRShell(pathname, url.search);
|
|
10744
|
+
const cachedPPRShell = await this.getCachedPPRShell(pathname, url.search);
|
|
10225
10745
|
if (cachedPPRShell) {
|
|
10226
|
-
emitFarmEvent({
|
|
10746
|
+
emitFarmEvent({
|
|
10747
|
+
type: "ppr.shell.hit",
|
|
10748
|
+
route: pathname,
|
|
10749
|
+
key: pprCacheKey
|
|
10750
|
+
});
|
|
10227
10751
|
this.serveCachedPPRShell(res, cachedPPRShell.value, renderingConfig.revalidate);
|
|
10228
10752
|
completeRender(res.statusCode || 200, pathname);
|
|
10229
10753
|
return;
|
|
10230
10754
|
}
|
|
10231
|
-
emitFarmEvent({
|
|
10755
|
+
emitFarmEvent({
|
|
10756
|
+
type: "ppr.shell.miss",
|
|
10757
|
+
route: pathname,
|
|
10758
|
+
key: pprCacheKey
|
|
10759
|
+
});
|
|
10232
10760
|
}
|
|
10233
10761
|
let LoadingFallbackComponent = null;
|
|
10234
10762
|
if (loadingBoundaryEntry) {
|
|
@@ -10252,14 +10780,77 @@ var init_renderer = __esm({
|
|
|
10252
10780
|
);
|
|
10253
10781
|
const moduleMetadata = routeManifestEntry || getClientModuleMetadata(route.modulePath, this.config.root);
|
|
10254
10782
|
const isClientComponent = moduleMetadata.isClientComponent;
|
|
10783
|
+
const renderedRouteSlots = await Promise.all(
|
|
10784
|
+
routeSlots.map(async (slot) => {
|
|
10785
|
+
const slotModule = await this.routeManager.loadRouteModule(slot.route.modulePath);
|
|
10786
|
+
if (!slotModule.default) {
|
|
10787
|
+
throw new Error(
|
|
10788
|
+
`Route slot "${slot.name}" module ${slot.route.modulePath} does not export a default component`
|
|
10789
|
+
);
|
|
10790
|
+
}
|
|
10791
|
+
const slotContext = await this.resolveRouteContext({
|
|
10792
|
+
request: currentRequest,
|
|
10793
|
+
rawRequest: req,
|
|
10794
|
+
params: slot.params,
|
|
10795
|
+
search: searchParamsObject,
|
|
10796
|
+
path: pathname
|
|
10797
|
+
});
|
|
10798
|
+
const rawSlotProps = withFarmRouteContext(
|
|
10799
|
+
{
|
|
10800
|
+
params: slot.params,
|
|
10801
|
+
searchParams: Promise.resolve(searchParamsObject),
|
|
10802
|
+
path: pathname,
|
|
10803
|
+
middleware: middlewareMap.size > 0 ? { data: middlewareMap } : void 0,
|
|
10804
|
+
context: pluginExposedContext.size > 0 ? { data: pluginExposedContext } : void 0
|
|
10805
|
+
},
|
|
10806
|
+
slotContext
|
|
10807
|
+
);
|
|
10808
|
+
const slotProps = await parseRouteModuleProps(slotModule, {
|
|
10809
|
+
props: rawSlotProps,
|
|
10810
|
+
search: searchParamsObject,
|
|
10811
|
+
routePath: slot.route.pattern
|
|
10812
|
+
});
|
|
10813
|
+
const metadata = getClientModuleMetadata(slot.route.modulePath, this.config.root);
|
|
10814
|
+
return {
|
|
10815
|
+
...slot,
|
|
10816
|
+
module: slotModule,
|
|
10817
|
+
props: slotProps,
|
|
10818
|
+
isClientComponent: metadata.isClientComponent,
|
|
10819
|
+
shouldHydrate: metadata.shouldHydrate
|
|
10820
|
+
};
|
|
10821
|
+
})
|
|
10822
|
+
);
|
|
10255
10823
|
const shouldHydrate = moduleMetadata.shouldHydrate;
|
|
10824
|
+
const hasHydratableRouteSlots = renderedRouteSlots.some(
|
|
10825
|
+
(slot) => slot.isClientComponent || slot.shouldHydrate
|
|
10826
|
+
);
|
|
10256
10827
|
req.__FARM_PAGE_PATH__ = route.modulePath;
|
|
10257
10828
|
req.__FARM_ROUTE__ = pathname;
|
|
10258
10829
|
req.__FARM_IS_CLIENT_COMPONENT__ = isClientComponent;
|
|
10259
10830
|
req.__FARM_SHOULD_HYDRATE__ = shouldHydrate;
|
|
10831
|
+
req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ = hasHydratableRouteSlots;
|
|
10260
10832
|
req.__FARM_LOADING_MODULE_PATH__ = loadingBoundaryEntry?.modulePath ? loadingBoundaryEntry.modulePath.substring(
|
|
10261
10833
|
loadingBoundaryEntry.modulePath.indexOf("/src/app/")
|
|
10262
10834
|
) : null;
|
|
10835
|
+
req.__FARM_ROUTE_SLOTS__ = renderedRouteSlots.map((slot) => ({
|
|
10836
|
+
name: slot.name,
|
|
10837
|
+
ownerPattern: slot.ownerPattern,
|
|
10838
|
+
containerId: slot.containerId,
|
|
10839
|
+
interception: slot.interception,
|
|
10840
|
+
fallback: slot.fallback,
|
|
10841
|
+
modulePath: slot.route.modulePath,
|
|
10842
|
+
isClientComponent: slot.isClientComponent,
|
|
10843
|
+
shouldHydrate: slot.shouldHydrate,
|
|
10844
|
+
props: {
|
|
10845
|
+
params: slot.props.params,
|
|
10846
|
+
search: slot.props.search,
|
|
10847
|
+
searchParams: slot.props.search,
|
|
10848
|
+
..."data" in slot.props ? { data: slot.props.data } : {},
|
|
10849
|
+
...slot.props.__farmCanonicalPath ? { __farmCanonicalPath: slot.props.__farmCanonicalPath } : {},
|
|
10850
|
+
...slot.props.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {},
|
|
10851
|
+
path: pathname
|
|
10852
|
+
}
|
|
10853
|
+
}));
|
|
10263
10854
|
req.__FARM_PROPS__ = {
|
|
10264
10855
|
params: pageProps.params,
|
|
10265
10856
|
search: pageProps.search,
|
|
@@ -10319,12 +10910,32 @@ var init_renderer = __esm({
|
|
|
10319
10910
|
let wrappedElement = pageElement;
|
|
10320
10911
|
for (let i = layoutModules.length - 1; i >= 0; i--) {
|
|
10321
10912
|
const layoutModule = layoutModules[i];
|
|
10913
|
+
const layoutEntry = layouts[i];
|
|
10322
10914
|
const LayoutComponent = layoutModule.default;
|
|
10915
|
+
const slotProps = {};
|
|
10916
|
+
for (const slot of renderedRouteSlots) {
|
|
10917
|
+
if (slot.ownerPattern !== layoutEntry.pattern) continue;
|
|
10918
|
+
let slotElement = import_react4.default.createElement(
|
|
10919
|
+
slot.module.default,
|
|
10920
|
+
slot.props
|
|
10921
|
+
);
|
|
10922
|
+
slotElement = import_react4.default.createElement(
|
|
10923
|
+
"div",
|
|
10924
|
+
{
|
|
10925
|
+
id: slot.containerId,
|
|
10926
|
+
"data-farm-route-slot": slot.name,
|
|
10927
|
+
"data-farm-slot-owner": slot.ownerPattern
|
|
10928
|
+
},
|
|
10929
|
+
slotElement
|
|
10930
|
+
);
|
|
10931
|
+
slotProps[slot.name] = slotElement;
|
|
10932
|
+
}
|
|
10323
10933
|
wrappedElement = import_react4.default.createElement(
|
|
10324
10934
|
LayoutComponent,
|
|
10325
10935
|
{
|
|
10326
10936
|
children: wrappedElement,
|
|
10327
|
-
params
|
|
10937
|
+
params,
|
|
10938
|
+
...slotProps
|
|
10328
10939
|
}
|
|
10329
10940
|
);
|
|
10330
10941
|
}
|
|
@@ -10361,7 +10972,10 @@ var init_renderer = __esm({
|
|
|
10361
10972
|
routeManifest,
|
|
10362
10973
|
captureStaticShell: Boolean(pprShellOptions),
|
|
10363
10974
|
observabilityRoute: pathname,
|
|
10364
|
-
onSuspenseHoleDetected: pprShellOptions ? () => emitFarmEvent({
|
|
10975
|
+
onSuspenseHoleDetected: pprShellOptions ? () => emitFarmEvent({
|
|
10976
|
+
type: "ppr.suspense.holeDetected",
|
|
10977
|
+
route: pathname
|
|
10978
|
+
}) : void 0,
|
|
10365
10979
|
onComplete: pprShellOptions && req.method !== "HEAD" ? (html) => this.cachePPRShell(pprShellOptions, html) : void 0
|
|
10366
10980
|
}
|
|
10367
10981
|
);
|
|
@@ -10409,7 +11023,11 @@ var init_renderer = __esm({
|
|
|
10409
11023
|
}
|
|
10410
11024
|
emitFarmEvent({ type: "render.error", route: pathname, error });
|
|
10411
11025
|
if (pprRefreshRoute) {
|
|
10412
|
-
emitFarmEvent({
|
|
11026
|
+
emitFarmEvent({
|
|
11027
|
+
type: "ppr.refresh.error",
|
|
11028
|
+
route: pprRefreshRoute,
|
|
11029
|
+
error
|
|
11030
|
+
});
|
|
10413
11031
|
}
|
|
10414
11032
|
logger.error(`Error rendering page: ${error}`);
|
|
10415
11033
|
if (res.headersSent || res.writableEnded) {
|
|
@@ -10462,7 +11080,9 @@ var init_renderer = __esm({
|
|
|
10462
11080
|
if (typeof layoutModule.generateMetadata === "function") {
|
|
10463
11081
|
metadata = mergeMetadata(
|
|
10464
11082
|
metadata,
|
|
10465
|
-
await layoutModule.generateMetadata({
|
|
11083
|
+
await layoutModule.generateMetadata({
|
|
11084
|
+
params: options.pageProps.params
|
|
11085
|
+
})
|
|
10466
11086
|
);
|
|
10467
11087
|
}
|
|
10468
11088
|
}
|
|
@@ -10693,7 +11313,13 @@ var init_renderer = __esm({
|
|
|
10693
11313
|
clientEntry: "/@farm/client.js",
|
|
10694
11314
|
routes: {},
|
|
10695
11315
|
layouts: {},
|
|
10696
|
-
|
|
11316
|
+
slots: [],
|
|
11317
|
+
sharedAssets: [
|
|
11318
|
+
{
|
|
11319
|
+
tag: "link",
|
|
11320
|
+
attrs: { rel: "stylesheet", href: "/src/app/globals.css" }
|
|
11321
|
+
}
|
|
11322
|
+
]
|
|
10697
11323
|
};
|
|
10698
11324
|
for (const routeEntry of manifest.routes) {
|
|
10699
11325
|
clientManifest.routes[routeEntry.pattern] = {
|
|
@@ -10715,9 +11341,26 @@ var init_renderer = __esm({
|
|
|
10715
11341
|
assets: []
|
|
10716
11342
|
};
|
|
10717
11343
|
}
|
|
10718
|
-
const
|
|
11344
|
+
for (const slotEntry of manifest.slots ?? []) {
|
|
11345
|
+
clientManifest.slots.push({
|
|
11346
|
+
...slotEntry,
|
|
11347
|
+
preloads: [slotEntry.modulePath],
|
|
11348
|
+
assets: []
|
|
11349
|
+
});
|
|
11350
|
+
}
|
|
11351
|
+
const routeSlotPayload = (req.__FARM_ROUTE_SLOTS__ || []).map(
|
|
11352
|
+
(slot) => ({
|
|
11353
|
+
...slot,
|
|
11354
|
+
modulePath: typeof slot.modulePath === "string" && slot.modulePath.startsWith(this.config.root) ? slot.modulePath.slice(this.config.root.length) : slot.modulePath
|
|
11355
|
+
})
|
|
11356
|
+
);
|
|
11357
|
+
const deferredProps = prepareDeferredData({
|
|
11358
|
+
page: req.__FARM_PROPS__ || {},
|
|
11359
|
+
slots: routeSlotPayload
|
|
11360
|
+
});
|
|
10719
11361
|
const propsScript = `<script>
|
|
10720
|
-
window.__FARM_PROPS__ = ${serializeInlineValue(deferredProps.data)};
|
|
11362
|
+
window.__FARM_PROPS__ = ${serializeInlineValue(deferredProps.data.page)};
|
|
11363
|
+
window.__FARM_ROUTE_SLOTS__ = ${serializeInlineValue(deferredProps.data.slots)};
|
|
10721
11364
|
window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue(deploymentId)};
|
|
10722
11365
|
window.__FARM_PATH__ = ${JSON.stringify(req.__FARM_ROUTE__ || req.url || "/")};
|
|
10723
11366
|
window.__FARM_IS_CLIENT__ = ${JSON.stringify(isClientComponent)};
|
|
@@ -10730,7 +11373,7 @@ window.__FARM_MANIFEST__ = ${JSON.stringify(clientManifest)};
|
|
|
10730
11373
|
window.__FARM_INTEGRATION_API_MANIFEST__ = ${JSON.stringify(getRegisteredIntegrationAPIManifest())};
|
|
10731
11374
|
${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(getFarmI18nClientSnapshot())};` : ""}
|
|
10732
11375
|
</script>`;
|
|
10733
|
-
const hydrationClickQueueScript = isClientComponent || req.__FARM_SHOULD_HYDRATE__ === true ? createPreHydrationClickQueueScript() : "";
|
|
11376
|
+
const hydrationClickQueueScript = isClientComponent || req.__FARM_SHOULD_HYDRATE__ === true || req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ === true ? createPreHydrationClickQueueScript() : "";
|
|
10734
11377
|
const {
|
|
10735
11378
|
title,
|
|
10736
11379
|
tags: metaTags,
|
|
@@ -10841,7 +11484,11 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
|
|
|
10841
11484
|
didError = true;
|
|
10842
11485
|
if (!isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
|
|
10843
11486
|
logger.error(`SSR shell error: ${error}`);
|
|
10844
|
-
emitFarmEvent({
|
|
11487
|
+
emitFarmEvent({
|
|
11488
|
+
type: "render.error",
|
|
11489
|
+
route: observabilityRoute,
|
|
11490
|
+
error
|
|
11491
|
+
});
|
|
10845
11492
|
}
|
|
10846
11493
|
if (clearMiddlewareData) {
|
|
10847
11494
|
clearMiddlewareData();
|
|
@@ -10852,7 +11499,11 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
|
|
|
10852
11499
|
didError = true;
|
|
10853
11500
|
if (!isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
|
|
10854
11501
|
logger.error(`SSR streaming error: ${error}`);
|
|
10855
|
-
emitFarmEvent({
|
|
11502
|
+
emitFarmEvent({
|
|
11503
|
+
type: "render.error",
|
|
11504
|
+
route: observabilityRoute,
|
|
11505
|
+
error
|
|
11506
|
+
});
|
|
10856
11507
|
}
|
|
10857
11508
|
}
|
|
10858
11509
|
});
|
|
@@ -11034,6 +11685,7 @@ var init_app = __esm({
|
|
|
11034
11685
|
init_devtools_config();
|
|
11035
11686
|
init_config();
|
|
11036
11687
|
init_server2();
|
|
11688
|
+
init_cache();
|
|
11037
11689
|
defaultDocsConfig = {
|
|
11038
11690
|
enabled: false,
|
|
11039
11691
|
entry: "/docs",
|
|
@@ -11048,17 +11700,14 @@ var init_app = __esm({
|
|
|
11048
11700
|
_setDefaultFarmI18nRuntime(this.i18nRuntime);
|
|
11049
11701
|
this.viteServer = viteServer;
|
|
11050
11702
|
this.routeManager = new RouteManager(this.config, viteServer);
|
|
11051
|
-
this.serverRenderer = new ServerRenderer(
|
|
11052
|
-
this.config,
|
|
11053
|
-
this.routeManager,
|
|
11054
|
-
this.i18nRuntime
|
|
11055
|
-
);
|
|
11703
|
+
this.serverRenderer = new ServerRenderer(this.config, this.routeManager, this.i18nRuntime);
|
|
11056
11704
|
}
|
|
11057
11705
|
async initialize() {
|
|
11058
11706
|
if (process.env.FARM_VERBOSE) {
|
|
11059
11707
|
logger.info("Initializing Farm.js application...");
|
|
11060
11708
|
}
|
|
11061
11709
|
await initStorage(this.config.storage);
|
|
11710
|
+
await configureFarmCache(this.config.cache);
|
|
11062
11711
|
await this.i18nRuntime.initialize();
|
|
11063
11712
|
await this.verifyAppStructure();
|
|
11064
11713
|
await this.routeManager.discoverRoutes();
|
|
@@ -11090,6 +11739,7 @@ var init_app = __esm({
|
|
|
11090
11739
|
preset: config.preset ?? "node-server",
|
|
11091
11740
|
deploy: config.deploy || {},
|
|
11092
11741
|
storage: config.storage || {},
|
|
11742
|
+
cache: config.cache || {},
|
|
11093
11743
|
integrations: config.integrations || {},
|
|
11094
11744
|
plugins: config.plugins || [],
|
|
11095
11745
|
migrations: config.migrations || { commands: [] },
|
|
@@ -11163,6 +11813,41 @@ var init_app = __esm({
|
|
|
11163
11813
|
}
|
|
11164
11814
|
});
|
|
11165
11815
|
|
|
11816
|
+
// src/api/transport.ts
|
|
11817
|
+
var init_transport = __esm({
|
|
11818
|
+
"src/api/transport.ts"() {
|
|
11819
|
+
"use strict";
|
|
11820
|
+
}
|
|
11821
|
+
});
|
|
11822
|
+
|
|
11823
|
+
// src/api/endpoint.ts
|
|
11824
|
+
function isEndpointFailure(value) {
|
|
11825
|
+
return value instanceof EndpointFailure;
|
|
11826
|
+
}
|
|
11827
|
+
var import_better_call, _EndpointFailure, EndpointFailure, EMPTY_ENDPOINT_MIDDLEWARE, EMPTY_ENDPOINT_CONTEXT;
|
|
11828
|
+
var init_endpoint = __esm({
|
|
11829
|
+
"src/api/endpoint.ts"() {
|
|
11830
|
+
"use strict";
|
|
11831
|
+
import_better_call = require("better-call");
|
|
11832
|
+
init_cache();
|
|
11833
|
+
init_transport();
|
|
11834
|
+
_EndpointFailure = class _EndpointFailure extends Error {
|
|
11835
|
+
constructor(code, data, options) {
|
|
11836
|
+
super(options.message);
|
|
11837
|
+
this.name = "EndpointFailure";
|
|
11838
|
+
this.code = code;
|
|
11839
|
+
this.data = data;
|
|
11840
|
+
this.status = options.status;
|
|
11841
|
+
}
|
|
11842
|
+
};
|
|
11843
|
+
__name(_EndpointFailure, "EndpointFailure");
|
|
11844
|
+
EndpointFailure = _EndpointFailure;
|
|
11845
|
+
__name(isEndpointFailure, "isEndpointFailure");
|
|
11846
|
+
EMPTY_ENDPOINT_MIDDLEWARE = Object.freeze([]);
|
|
11847
|
+
EMPTY_ENDPOINT_CONTEXT = Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
11848
|
+
}
|
|
11849
|
+
});
|
|
11850
|
+
|
|
11166
11851
|
// src/api/runtime.ts
|
|
11167
11852
|
function matchAPIRoute(routes, pathname) {
|
|
11168
11853
|
const exactRoute = routes.get(pathname);
|
|
@@ -11193,10 +11878,10 @@ async function invokeAPIRouteEndpoint(endpoint, request, params = {}) {
|
|
|
11193
11878
|
async function invokeAPIRouteEndpointInContext(endpoint, request, params) {
|
|
11194
11879
|
const farmHandler = endpoint.__handler || (isFarmContextHandler(endpoint) ? endpoint : null);
|
|
11195
11880
|
if (!farmHandler) {
|
|
11196
|
-
const
|
|
11881
|
+
const result = await endpoint(request, {
|
|
11197
11882
|
params: Promise.resolve(params)
|
|
11198
11883
|
});
|
|
11199
|
-
return normalizeRouteResponse(
|
|
11884
|
+
return normalizeRouteResponse(result);
|
|
11200
11885
|
}
|
|
11201
11886
|
const url = new URL(request.url);
|
|
11202
11887
|
const query = {};
|
|
@@ -11205,7 +11890,7 @@ async function invokeAPIRouteEndpointInContext(endpoint, request, params) {
|
|
|
11205
11890
|
});
|
|
11206
11891
|
let body = void 0;
|
|
11207
11892
|
if (request.method.toUpperCase() !== "GET" && request.method.toUpperCase() !== "HEAD") {
|
|
11208
|
-
body = await
|
|
11893
|
+
body = await readRequestBody2(request);
|
|
11209
11894
|
}
|
|
11210
11895
|
const headers = Object.fromEntries(request.headers.entries());
|
|
11211
11896
|
const types = endpoint.__types || {};
|
|
@@ -11221,15 +11906,30 @@ async function invokeAPIRouteEndpointInContext(endpoint, request, params) {
|
|
|
11221
11906
|
if (headersValidation instanceof Response) {
|
|
11222
11907
|
return headersValidation;
|
|
11223
11908
|
}
|
|
11224
|
-
const
|
|
11909
|
+
const handlerContext = {
|
|
11225
11910
|
query: queryValidation,
|
|
11226
11911
|
body: bodyValidation,
|
|
11227
11912
|
headers: headersValidation,
|
|
11228
11913
|
request,
|
|
11229
11914
|
context: {},
|
|
11230
11915
|
params
|
|
11231
|
-
}
|
|
11232
|
-
|
|
11916
|
+
};
|
|
11917
|
+
let execution;
|
|
11918
|
+
try {
|
|
11919
|
+
execution = typeof endpoint.__farmInvoke === "function" ? await endpoint.__farmInvoke(handlerContext) : {
|
|
11920
|
+
result: await farmHandler(handlerContext),
|
|
11921
|
+
context: handlerContext.context,
|
|
11922
|
+
handlerExecuted: true,
|
|
11923
|
+
invalidations: []
|
|
11924
|
+
};
|
|
11925
|
+
} catch (error) {
|
|
11926
|
+
if (isEndpointFailure(error)) {
|
|
11927
|
+
return createEndpointFailureResponse(error);
|
|
11928
|
+
}
|
|
11929
|
+
throw error;
|
|
11930
|
+
}
|
|
11931
|
+
const response = normalizeRouteResponse(execution.result);
|
|
11932
|
+
return attachEndpointInvalidations(response, execution.invalidations);
|
|
11233
11933
|
}
|
|
11234
11934
|
function normalizeRouteResponse(result) {
|
|
11235
11935
|
if (isWebResponse2(result)) {
|
|
@@ -11246,6 +11946,38 @@ function normalizeRouteResponse(result) {
|
|
|
11246
11946
|
function isWebResponse2(value) {
|
|
11247
11947
|
return value instanceof Response || typeof value === "object" && value !== null && "headers" in value && "status" in value && typeof value.arrayBuffer === "function";
|
|
11248
11948
|
}
|
|
11949
|
+
function attachEndpointInvalidations(response, keys) {
|
|
11950
|
+
const existing = decodeFarmCacheInvalidations(
|
|
11951
|
+
response.headers.get(FARM_CACHE_INVALIDATION_HEADER)
|
|
11952
|
+
);
|
|
11953
|
+
const encoded = encodeFarmCacheInvalidations([...existing, ...keys]);
|
|
11954
|
+
if (!encoded) return response;
|
|
11955
|
+
const headers = new Headers(response.headers);
|
|
11956
|
+
headers.set(FARM_CACHE_INVALIDATION_HEADER, encoded);
|
|
11957
|
+
return new Response(response.body, {
|
|
11958
|
+
status: response.status,
|
|
11959
|
+
statusText: response.statusText,
|
|
11960
|
+
headers
|
|
11961
|
+
});
|
|
11962
|
+
}
|
|
11963
|
+
function createEndpointFailureResponse(failure) {
|
|
11964
|
+
return new Response(
|
|
11965
|
+
JSON.stringify({
|
|
11966
|
+
error: {
|
|
11967
|
+
code: failure.code,
|
|
11968
|
+
message: failure.message,
|
|
11969
|
+
data: failure.data
|
|
11970
|
+
}
|
|
11971
|
+
}),
|
|
11972
|
+
{
|
|
11973
|
+
status: failure.status,
|
|
11974
|
+
headers: {
|
|
11975
|
+
"cache-control": "no-store",
|
|
11976
|
+
"content-type": "application/json"
|
|
11977
|
+
}
|
|
11978
|
+
}
|
|
11979
|
+
);
|
|
11980
|
+
}
|
|
11249
11981
|
function isFarmContextHandler(endpoint) {
|
|
11250
11982
|
if (typeof endpoint !== "function") {
|
|
11251
11983
|
return false;
|
|
@@ -11256,16 +11988,46 @@ function isFarmContextHandler(endpoint) {
|
|
|
11256
11988
|
const firstParameter = (arrowMatch?.[1] || arrowMatch?.[2] || functionMatch?.[1] || "").split(",")[0].trim();
|
|
11257
11989
|
return firstParameter === "ctx" || firstParameter === "context" || firstParameter.startsWith("{");
|
|
11258
11990
|
}
|
|
11259
|
-
async function
|
|
11991
|
+
async function readRequestBody2(request) {
|
|
11992
|
+
const contentType = request.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
|
|
11260
11993
|
try {
|
|
11994
|
+
if (contentType === "multipart/form-data") {
|
|
11995
|
+
return formDataToObject(await request.clone().formData());
|
|
11996
|
+
}
|
|
11261
11997
|
const text2 = await request.clone().text();
|
|
11262
|
-
if (text2)
|
|
11998
|
+
if (!text2) return void 0;
|
|
11999
|
+
if (contentType === "application/x-www-form-urlencoded") {
|
|
12000
|
+
return searchParamsToObject2(new URLSearchParams(text2));
|
|
12001
|
+
}
|
|
12002
|
+
if (contentType === "application/json" || contentType?.endsWith("+json")) {
|
|
11263
12003
|
return JSON.parse(text2);
|
|
11264
12004
|
}
|
|
12005
|
+
return JSON.parse(text2);
|
|
11265
12006
|
} catch {
|
|
11266
12007
|
}
|
|
11267
12008
|
return void 0;
|
|
11268
12009
|
}
|
|
12010
|
+
function formDataToObject(formData) {
|
|
12011
|
+
return entriesToObject(formData.entries());
|
|
12012
|
+
}
|
|
12013
|
+
function searchParamsToObject2(searchParams) {
|
|
12014
|
+
return entriesToObject(searchParams.entries());
|
|
12015
|
+
}
|
|
12016
|
+
function entriesToObject(entries) {
|
|
12017
|
+
const output = /* @__PURE__ */ Object.create(null);
|
|
12018
|
+
for (const [key, value] of entries) {
|
|
12019
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
|
|
12020
|
+
const current = output[key];
|
|
12021
|
+
if (current === void 0) {
|
|
12022
|
+
output[key] = value;
|
|
12023
|
+
} else if (Array.isArray(current)) {
|
|
12024
|
+
current.push(value);
|
|
12025
|
+
} else {
|
|
12026
|
+
output[key] = [current, value];
|
|
12027
|
+
}
|
|
12028
|
+
}
|
|
12029
|
+
return output;
|
|
12030
|
+
}
|
|
11269
12031
|
function validateInput(schema, value, error) {
|
|
11270
12032
|
if (!schema || typeof schema.parse !== "function") {
|
|
11271
12033
|
return value;
|
|
@@ -11354,13 +12116,20 @@ var init_runtime2 = __esm({
|
|
|
11354
12116
|
"src/api/runtime.ts"() {
|
|
11355
12117
|
"use strict";
|
|
11356
12118
|
init_request();
|
|
12119
|
+
init_cache_invalidation();
|
|
12120
|
+
init_endpoint();
|
|
11357
12121
|
__name(matchAPIRoute, "matchAPIRoute");
|
|
11358
12122
|
__name(invokeAPIRouteEndpoint, "invokeAPIRouteEndpoint");
|
|
11359
12123
|
__name(invokeAPIRouteEndpointInContext, "invokeAPIRouteEndpointInContext");
|
|
11360
12124
|
__name(normalizeRouteResponse, "normalizeRouteResponse");
|
|
11361
12125
|
__name(isWebResponse2, "isWebResponse");
|
|
12126
|
+
__name(attachEndpointInvalidations, "attachEndpointInvalidations");
|
|
12127
|
+
__name(createEndpointFailureResponse, "createEndpointFailureResponse");
|
|
11362
12128
|
__name(isFarmContextHandler, "isFarmContextHandler");
|
|
11363
|
-
__name(
|
|
12129
|
+
__name(readRequestBody2, "readRequestBody");
|
|
12130
|
+
__name(formDataToObject, "formDataToObject");
|
|
12131
|
+
__name(searchParamsToObject2, "searchParamsToObject");
|
|
12132
|
+
__name(entriesToObject, "entriesToObject");
|
|
11364
12133
|
__name(validateInput, "validateInput");
|
|
11365
12134
|
__name(matchRoutePath, "matchRoutePath");
|
|
11366
12135
|
__name(getPathSegments, "getPathSegments");
|
|
@@ -12329,7 +13098,9 @@ function readManifest(contentDir) {
|
|
|
12329
13098
|
const manifestPath = import_node_path4.default.join(contentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
|
|
12330
13099
|
if (!(0, import_node_fs2.existsSync)(manifestPath)) return null;
|
|
12331
13100
|
try {
|
|
12332
|
-
const parsed = JSON.parse(
|
|
13101
|
+
const parsed = JSON.parse(
|
|
13102
|
+
(0, import_node_fs2.readFileSync)(manifestPath, "utf8")
|
|
13103
|
+
);
|
|
12333
13104
|
if (parsed.version !== 1 || !parsed.pages || typeof parsed.pages !== "object") return null;
|
|
12334
13105
|
const pages = Object.fromEntries(
|
|
12335
13106
|
Object.entries(parsed.pages).filter(
|
|
@@ -13341,7 +14112,7 @@ var init_manager = __esm({
|
|
|
13341
14112
|
if (!nestedMatch.matched) {
|
|
13342
14113
|
return { matched: false };
|
|
13343
14114
|
}
|
|
13344
|
-
const params = { ...nestedMatch.params
|
|
14115
|
+
const params = { ...nestedMatch.params };
|
|
13345
14116
|
delete params.__farmRest;
|
|
13346
14117
|
return {
|
|
13347
14118
|
matched: true,
|
|
@@ -13715,6 +14486,7 @@ async function generateRouteTypes(options) {
|
|
|
13715
14486
|
absolute: false
|
|
13716
14487
|
});
|
|
13717
14488
|
for (const file of pageFiles) {
|
|
14489
|
+
if (parseRouteSlotFile(file)) continue;
|
|
13718
14490
|
const route = parseRoutePath(file);
|
|
13719
14491
|
if (route.type === "page") {
|
|
13720
14492
|
const pattern = createRoutePattern(route);
|
|
@@ -13780,6 +14552,7 @@ var init_generate_route_types = __esm({
|
|
|
13780
14552
|
path17 = __toESM(require("path"));
|
|
13781
14553
|
fs5 = __toESM(require("fs"));
|
|
13782
14554
|
init_utils();
|
|
14555
|
+
init_route_slots();
|
|
13783
14556
|
init_routes_server();
|
|
13784
14557
|
init_write_file_if_changed();
|
|
13785
14558
|
__name(routeSegmentsToTsTypeLiteral, "routeSegmentsToTsTypeLiteral");
|
|
@@ -14144,6 +14917,24 @@ var init_type_artifacts = __esm({
|
|
|
14144
14917
|
}
|
|
14145
14918
|
});
|
|
14146
14919
|
|
|
14920
|
+
// package.json
|
|
14921
|
+
var version;
|
|
14922
|
+
var init_package = __esm({
|
|
14923
|
+
"package.json"() {
|
|
14924
|
+
version = "0.1.0-beta.4";
|
|
14925
|
+
}
|
|
14926
|
+
});
|
|
14927
|
+
|
|
14928
|
+
// src/version.ts
|
|
14929
|
+
var FARM_VERSION;
|
|
14930
|
+
var init_version = __esm({
|
|
14931
|
+
"src/version.ts"() {
|
|
14932
|
+
"use strict";
|
|
14933
|
+
init_package();
|
|
14934
|
+
FARM_VERSION = version;
|
|
14935
|
+
}
|
|
14936
|
+
});
|
|
14937
|
+
|
|
14147
14938
|
// src/after.ts
|
|
14148
14939
|
function getAfterStorage() {
|
|
14149
14940
|
const runtime = globalThis;
|
|
@@ -20432,16 +21223,7 @@ __export(devtools_client_exports, {
|
|
|
20432
21223
|
function parseShortcut(shortcut) {
|
|
20433
21224
|
const tokens = shortcut.toLowerCase().split("+").map((token) => token.trim()).filter(Boolean);
|
|
20434
21225
|
const key = tokens.find(
|
|
20435
|
-
(token) => ![
|
|
20436
|
-
"alt",
|
|
20437
|
-
"ctrl",
|
|
20438
|
-
"control",
|
|
20439
|
-
"meta",
|
|
20440
|
-
"cmd",
|
|
20441
|
-
"command",
|
|
20442
|
-
"mod",
|
|
20443
|
-
"shift"
|
|
20444
|
-
].includes(token)
|
|
21226
|
+
(token) => !["alt", "ctrl", "control", "meta", "cmd", "command", "mod", "shift"].includes(token)
|
|
20445
21227
|
);
|
|
20446
21228
|
if (!key) {
|
|
20447
21229
|
return null;
|
|
@@ -20872,7 +21654,7 @@ function isResolvedEnvScope(value) {
|
|
|
20872
21654
|
);
|
|
20873
21655
|
}
|
|
20874
21656
|
function isPotentialProgrammaticRouteSourceFile(normalizedFile, srcDirSlug) {
|
|
20875
|
-
return normalizedFile.startsWith(`${srcDirSlug}/`) && /\.(ts|tsx|js|jsx)$/.test(normalizedFile) &&
|
|
21657
|
+
return normalizedFile.startsWith(`${srcDirSlug}/`) && /\.(ts|tsx|js|jsx)$/.test(normalizedFile) && !normalizedFile.endsWith(".d.ts") && !normalizedFile.endsWith("/farm-routes.d.ts") && !normalizedFile.endsWith("/farm-env.d.ts") && !normalizedFile.endsWith("/lib/api.generated.ts");
|
|
20876
21658
|
}
|
|
20877
21659
|
function fileContainsProgrammaticPageRoute(file) {
|
|
20878
21660
|
if (!fs7.existsSync(file)) {
|
|
@@ -21109,7 +21891,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
21109
21891
|
}, "isProgrammaticRouteSourceFile");
|
|
21110
21892
|
const isAppRuntimeFile = /* @__PURE__ */ __name((file) => {
|
|
21111
21893
|
const normalized = file.replace(/\\/g, "/");
|
|
21112
|
-
return appDirSlugs.some((appDir) => normalized.startsWith(`${appDir}/`)) && /\/(?:page|layout|loading|error|middleware|route)\.(?:ts|tsx|js|jsx|md|mdx)$|\/(?:opengraph-image|twitter-image)(?:\.(?:ts|tsx|js|jsx|png|jpg|jpeg|gif|webp)|\.alt\.txt)$/.test(
|
|
21894
|
+
return appDirSlugs.some((appDir) => normalized.startsWith(`${appDir}/`)) && /\/(?:page|default|layout|loading|error|middleware|route)\.(?:ts|tsx|js|jsx|md|mdx)$|\/(?:opengraph-image|twitter-image)(?:\.(?:ts|tsx|js|jsx|png|jpg|jpeg|gif|webp)|\.alt\.txt)$/.test(
|
|
21113
21895
|
normalized
|
|
21114
21896
|
);
|
|
21115
21897
|
}, "isAppRuntimeFile");
|
|
@@ -21800,7 +22582,10 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
21800
22582
|
method: req.method || "GET"
|
|
21801
22583
|
});
|
|
21802
22584
|
}
|
|
21803
|
-
const
|
|
22585
|
+
const interceptFromHeader = request.headers.get("x-farm-intercept-from") || void 0;
|
|
22586
|
+
const match = routeManager3.matchRoute(targetRequestUrl.pathname, {
|
|
22587
|
+
interceptFrom: interceptFromHeader
|
|
22588
|
+
});
|
|
21804
22589
|
if (pm) {
|
|
21805
22590
|
await pm.runHookParallel("afterRouteMatch", {
|
|
21806
22591
|
pathname: targetPath,
|
|
@@ -21816,7 +22601,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
21816
22601
|
res.end(JSON.stringify({ error: "Route not found" }));
|
|
21817
22602
|
return;
|
|
21818
22603
|
}
|
|
21819
|
-
const { route, params, layouts } = match;
|
|
22604
|
+
const { route, params, layouts, slots } = match;
|
|
21820
22605
|
if (!route) {
|
|
21821
22606
|
res.statusCode = 404;
|
|
21822
22607
|
res.setHeader("Content-Type", "application/json");
|
|
@@ -21871,6 +22656,54 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
21871
22656
|
search: searchParams,
|
|
21872
22657
|
routePath: route.pattern
|
|
21873
22658
|
});
|
|
22659
|
+
const routeSlots = await Promise.all(
|
|
22660
|
+
slots.map(async (slot) => {
|
|
22661
|
+
const slotModule = await routeManager3.loadRouteModule(slot.route.modulePath);
|
|
22662
|
+
const slotMetadata = getClientModuleMetadata(
|
|
22663
|
+
slot.route.modulePath,
|
|
22664
|
+
server.config.root
|
|
22665
|
+
);
|
|
22666
|
+
const slotContext = await resolveFarmRouteContext(farmApp.getConfig(), {
|
|
22667
|
+
request,
|
|
22668
|
+
params: slot.params,
|
|
22669
|
+
search: searchParams,
|
|
22670
|
+
path: targetUrl.pathname
|
|
22671
|
+
});
|
|
22672
|
+
const slotProps = await parseRouteModuleProps2(slotModule, {
|
|
22673
|
+
props: withFarmRouteContext(
|
|
22674
|
+
{
|
|
22675
|
+
params: slot.params,
|
|
22676
|
+
searchParams: Promise.resolve(searchParams),
|
|
22677
|
+
path: targetUrl.pathname
|
|
22678
|
+
},
|
|
22679
|
+
slotContext
|
|
22680
|
+
),
|
|
22681
|
+
search: searchParams,
|
|
22682
|
+
routePath: slot.route.pattern
|
|
22683
|
+
});
|
|
22684
|
+
return {
|
|
22685
|
+
name: slot.name,
|
|
22686
|
+
ownerPattern: slot.ownerPattern,
|
|
22687
|
+
containerId: slot.containerId,
|
|
22688
|
+
interception: slot.interception,
|
|
22689
|
+
fallback: slot.fallback,
|
|
22690
|
+
modulePath: slot.route.modulePath,
|
|
22691
|
+
isClientComponent: slotMetadata.isClientComponent,
|
|
22692
|
+
shouldHydrate: slotMetadata.shouldHydrate,
|
|
22693
|
+
props: {
|
|
22694
|
+
params: slotProps.params,
|
|
22695
|
+
search: slotProps.search,
|
|
22696
|
+
searchParams: slotProps.search,
|
|
22697
|
+
..."data" in slotProps ? { data: slotProps.data } : {},
|
|
22698
|
+
...slotProps.__farmCanonicalPath ? {
|
|
22699
|
+
__farmCanonicalPath: slotProps.__farmCanonicalPath
|
|
22700
|
+
} : {},
|
|
22701
|
+
...slotProps.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {},
|
|
22702
|
+
path: targetUrl.pathname
|
|
22703
|
+
}
|
|
22704
|
+
};
|
|
22705
|
+
})
|
|
22706
|
+
);
|
|
21874
22707
|
const projectRoot = server.config.root;
|
|
21875
22708
|
const toUrlPath = /* @__PURE__ */ __name((absolutePath) => {
|
|
21876
22709
|
if (absolutePath.startsWith(projectRoot)) {
|
|
@@ -21891,13 +22724,21 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
21891
22724
|
},
|
|
21892
22725
|
canonicalPath: routeProps.__farmCanonicalPath,
|
|
21893
22726
|
modulePath: toUrlPath(route.modulePath),
|
|
21894
|
-
isClientComponent,
|
|
21895
|
-
shouldHydrate,
|
|
22727
|
+
isClientComponent: routeSlots.length > 0 ? false : isClientComponent,
|
|
22728
|
+
shouldHydrate: shouldHydrate || routeSlots.some((slot) => slot.isClientComponent || slot.shouldHydrate),
|
|
21896
22729
|
metadata: {
|
|
21897
22730
|
title: mergedMetadata.title,
|
|
21898
22731
|
description: mergedMetadata.description
|
|
21899
22732
|
},
|
|
21900
22733
|
layoutModules: layouts.map((l) => toUrlPath(l.modulePath)),
|
|
22734
|
+
routeSlots: routeSlots.map((slot) => ({
|
|
22735
|
+
...slot,
|
|
22736
|
+
modulePath: toUrlPath(slot.modulePath)
|
|
22737
|
+
})),
|
|
22738
|
+
interception: routeSlots.some((slot) => slot.interception) ? {
|
|
22739
|
+
from: interceptFromHeader,
|
|
22740
|
+
slots: routeSlots.filter((slot) => slot.interception).map((slot) => slot.name)
|
|
22741
|
+
} : void 0,
|
|
21901
22742
|
i18n: getFarmI18nClientSnapshot()
|
|
21902
22743
|
};
|
|
21903
22744
|
await sendWebResponse(
|
|
@@ -22233,6 +23074,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
22233
23074
|
export const getManifest = () => ({
|
|
22234
23075
|
routes: {},
|
|
22235
23076
|
layouts: {},
|
|
23077
|
+
slots: [],
|
|
22236
23078
|
clientEntry: "/@farm/client.js",
|
|
22237
23079
|
sharedAssets: []
|
|
22238
23080
|
});
|
|
@@ -22243,6 +23085,7 @@ export const getManifest = () => ({
|
|
|
22243
23085
|
clientEntry: "/@farm/client.js",
|
|
22244
23086
|
routes: {},
|
|
22245
23087
|
layouts: {},
|
|
23088
|
+
slots: [],
|
|
22246
23089
|
sharedAssets: [
|
|
22247
23090
|
{
|
|
22248
23091
|
tag: "link",
|
|
@@ -22272,6 +23115,13 @@ export const getManifest = () => ({
|
|
|
22272
23115
|
assets: []
|
|
22273
23116
|
};
|
|
22274
23117
|
}
|
|
23118
|
+
for (const slot of manifest.slots) {
|
|
23119
|
+
fullManifest.slots.push({
|
|
23120
|
+
...slot,
|
|
23121
|
+
preloads: [slot.modulePath],
|
|
23122
|
+
assets: []
|
|
23123
|
+
});
|
|
23124
|
+
}
|
|
22275
23125
|
return `
|
|
22276
23126
|
// Auto-generated manifest for SPA navigation (TanStack Start pattern)
|
|
22277
23127
|
// This manifest is inlined in the server bundle - no file on disk
|
|
@@ -22908,7 +23758,7 @@ window.__FARM_WRAP_PROVIDERS__ = wrapWithIntegrationProviders;
|
|
|
22908
23758
|
|
|
22909
23759
|
// Get manifest from window (inlined by server in HTML)
|
|
22910
23760
|
// Fallback to empty manifest if not available yet
|
|
22911
|
-
const getManifest = () => window.__FARM_MANIFEST__ || { routes: {}, layouts: {}, clientEntry: '', sharedAssets: [] };
|
|
23761
|
+
const getManifest = () => window.__FARM_MANIFEST__ || { routes: {}, layouts: {}, slots: [], clientEntry: '', sharedAssets: [] };
|
|
22912
23762
|
|
|
22913
23763
|
// ====== CLIENT-SIDE ROUTE MATCHING ======
|
|
22914
23764
|
// Matches URL to route using manifest (no server request!)
|
|
@@ -23247,6 +24097,9 @@ let LayoutComponent = null;
|
|
|
23247
24097
|
|
|
23248
24098
|
// Track if we've taken over rendering from SSR
|
|
23249
24099
|
let hasClientTakenOver = false;
|
|
24100
|
+
const routeSlotRoots = new Map();
|
|
24101
|
+
const routeSlotDefinitions = new Map();
|
|
24102
|
+
let activeRouteInterception = null;
|
|
23250
24103
|
|
|
23251
24104
|
function normalizeServerProps(rawProps) {
|
|
23252
24105
|
const props = rawProps && typeof rawProps === 'object' ? { ...rawProps } : {};
|
|
@@ -23259,6 +24112,123 @@ function normalizeServerProps(rawProps) {
|
|
|
23259
24112
|
return props;
|
|
23260
24113
|
}
|
|
23261
24114
|
|
|
24115
|
+
function getRouteSlotKey(slot) {
|
|
24116
|
+
return slot.ownerPattern + ':' + slot.name;
|
|
24117
|
+
}
|
|
24118
|
+
|
|
24119
|
+
async function renderRouteSlot(slot, mode = 'render') {
|
|
24120
|
+
const container = document.getElementById(slot.containerId);
|
|
24121
|
+
if (!container || !slot.modulePath) return false;
|
|
24122
|
+
if (mode === 'intercept' && !slot.isClientComponent && !slot.shouldHydrate) {
|
|
24123
|
+
return false;
|
|
24124
|
+
}
|
|
24125
|
+
|
|
24126
|
+
let slotModule = pageModuleCache.get(slot.modulePath);
|
|
24127
|
+
if (!slotModule) {
|
|
24128
|
+
slotModule = await import(/* @vite-ignore */ slot.modulePath);
|
|
24129
|
+
pageModuleCache.set(slot.modulePath, slotModule);
|
|
24130
|
+
}
|
|
24131
|
+
const SlotComponent = slotModule?.default;
|
|
24132
|
+
if (!SlotComponent) return false;
|
|
24133
|
+
|
|
24134
|
+
const props = reviveDeferredData(
|
|
24135
|
+
normalizeServerProps(slot.props || {}),
|
|
24136
|
+
window.__FARM_DEFERRED_DATA__ || {},
|
|
24137
|
+
);
|
|
24138
|
+
const element = wrapWithIntegrationProviders(
|
|
24139
|
+
React.createElement(SlotComponent, props),
|
|
24140
|
+
);
|
|
24141
|
+
const key = getRouteSlotKey(slot);
|
|
24142
|
+
const existingRoot = routeSlotRoots.get(key);
|
|
24143
|
+
|
|
24144
|
+
if (mode === 'hydrate') {
|
|
24145
|
+
if (existingRoot) return true;
|
|
24146
|
+
const root = hydrateRoot(container, element);
|
|
24147
|
+
routeSlotRoots.set(key, root);
|
|
24148
|
+
} else {
|
|
24149
|
+
if (existingRoot) {
|
|
24150
|
+
try { existingRoot.unmount(); } catch (error) {}
|
|
24151
|
+
}
|
|
24152
|
+
const root = createRoot(container);
|
|
24153
|
+
root.render(element);
|
|
24154
|
+
routeSlotRoots.set(key, root);
|
|
24155
|
+
}
|
|
24156
|
+
|
|
24157
|
+
routeSlotDefinitions.set(key, slot);
|
|
24158
|
+
return true;
|
|
24159
|
+
}
|
|
24160
|
+
|
|
24161
|
+
async function hydrateInitialRouteSlots() {
|
|
24162
|
+
const slots = Array.isArray(window.__FARM_ROUTE_SLOTS__)
|
|
24163
|
+
? window.__FARM_ROUTE_SLOTS__
|
|
24164
|
+
: [];
|
|
24165
|
+
let hydrated = false;
|
|
24166
|
+
|
|
24167
|
+
for (const slot of slots) {
|
|
24168
|
+
routeSlotDefinitions.set(getRouteSlotKey(slot), slot);
|
|
24169
|
+
if (!slot.isClientComponent && !slot.shouldHydrate) continue;
|
|
24170
|
+
try {
|
|
24171
|
+
hydrated = (await renderRouteSlot(slot, 'hydrate')) || hydrated;
|
|
24172
|
+
} catch (error) {
|
|
24173
|
+
console.warn('[Farm.js] Could not hydrate route slot:', slot.name, error);
|
|
24174
|
+
}
|
|
24175
|
+
}
|
|
24176
|
+
|
|
24177
|
+
return hydrated;
|
|
24178
|
+
}
|
|
24179
|
+
|
|
24180
|
+
async function renderRouteInterception(pageData) {
|
|
24181
|
+
const slots = Array.isArray(pageData.routeSlots)
|
|
24182
|
+
? pageData.routeSlots.filter((slot) => slot.interception)
|
|
24183
|
+
: [];
|
|
24184
|
+
if (!pageData.interception || slots.length === 0) return false;
|
|
24185
|
+
|
|
24186
|
+
const previous = new Map();
|
|
24187
|
+
for (const slot of slots) {
|
|
24188
|
+
const key = getRouteSlotKey(slot);
|
|
24189
|
+
previous.set(key, routeSlotDefinitions.get(key) || null);
|
|
24190
|
+
if (!(await renderRouteSlot(slot, 'intercept'))) {
|
|
24191
|
+
return false;
|
|
24192
|
+
}
|
|
24193
|
+
}
|
|
24194
|
+
|
|
24195
|
+
activeRouteInterception = {
|
|
24196
|
+
from: pageData.interception.from,
|
|
24197
|
+
slots,
|
|
24198
|
+
previous,
|
|
24199
|
+
};
|
|
24200
|
+
return true;
|
|
24201
|
+
}
|
|
24202
|
+
|
|
24203
|
+
async function clearRouteInterception(destination) {
|
|
24204
|
+
if (!activeRouteInterception) return false;
|
|
24205
|
+
const active = activeRouteInterception;
|
|
24206
|
+
activeRouteInterception = null;
|
|
24207
|
+
|
|
24208
|
+
for (const slot of active.slots) {
|
|
24209
|
+
const key = getRouteSlotKey(slot);
|
|
24210
|
+
const root = routeSlotRoots.get(key);
|
|
24211
|
+
if (root) {
|
|
24212
|
+
try { root.unmount(); } catch (error) {}
|
|
24213
|
+
routeSlotRoots.delete(key);
|
|
24214
|
+
}
|
|
24215
|
+
|
|
24216
|
+
const previous = active.previous.get(key);
|
|
24217
|
+
if (previous && (previous.isClientComponent || previous.shouldHydrate)) {
|
|
24218
|
+
await renderRouteSlot(previous, 'render');
|
|
24219
|
+
} else {
|
|
24220
|
+
const container = document.getElementById(slot.containerId);
|
|
24221
|
+
if (container) container.replaceChildren();
|
|
24222
|
+
if (previous) routeSlotDefinitions.set(key, previous);
|
|
24223
|
+
else routeSlotDefinitions.delete(key);
|
|
24224
|
+
}
|
|
24225
|
+
}
|
|
24226
|
+
|
|
24227
|
+
if (!active.from) return false;
|
|
24228
|
+
const background = new URL(active.from, window.location.origin);
|
|
24229
|
+
return destination === background.pathname + background.search;
|
|
24230
|
+
}
|
|
24231
|
+
|
|
23262
24232
|
function applyCanonicalPathFromProps(props) {
|
|
23263
24233
|
const canonicalPath = props && typeof props.__farmCanonicalPath === 'string'
|
|
23264
24234
|
? props.__farmCanonicalPath
|
|
@@ -23493,6 +24463,17 @@ async function tryHydrateImportedPage(
|
|
|
23493
24463
|
async function renderPage(pageData) {
|
|
23494
24464
|
const container = document.getElementById('root');
|
|
23495
24465
|
if (!container) return;
|
|
24466
|
+
const destination = window.location.pathname + window.location.search;
|
|
24467
|
+
|
|
24468
|
+
if (pageData.interception) {
|
|
24469
|
+
if (await renderRouteInterception(pageData)) return;
|
|
24470
|
+
window.location.assign(destination);
|
|
24471
|
+
return;
|
|
24472
|
+
}
|
|
24473
|
+
|
|
24474
|
+
if (await clearRouteInterception(destination)) {
|
|
24475
|
+
return;
|
|
24476
|
+
}
|
|
23496
24477
|
|
|
23497
24478
|
const route = {
|
|
23498
24479
|
modulePath: pageData.modulePath,
|
|
@@ -23721,7 +24702,9 @@ async function hydrate() {
|
|
|
23721
24702
|
window.__FARM_SHOULD_HYDRATE__ === true ||
|
|
23722
24703
|
isClientComponent ||
|
|
23723
24704
|
await moduleLooksClient(modulePath);
|
|
24705
|
+
const hydratedSlots = await hydrateInitialRouteSlots();
|
|
23724
24706
|
if (!shouldHydrate) {
|
|
24707
|
+
if (hydratedSlots) replayPreHydrationClicks();
|
|
23725
24708
|
console.log('[Farm.js] Server component - SPA router ready')
|
|
23726
24709
|
return
|
|
23727
24710
|
}
|
|
@@ -23983,7 +24966,7 @@ async function defineConfig2(config = {}) {
|
|
|
23983
24966
|
const isExposed = hostConfig === true || hostConfig === "0.0.0.0";
|
|
23984
24967
|
console.log("");
|
|
23985
24968
|
console.log(
|
|
23986
|
-
` ${pc.bold(pc.green("Farm.js"))} ${pc.dim(
|
|
24969
|
+
` ${pc.bold(pc.green("Farm.js"))} ${pc.dim(`v${FARM_VERSION}`)} ${pc.dim(`ready in ${elapsed}ms`)}`
|
|
23987
24970
|
);
|
|
23988
24971
|
console.log("");
|
|
23989
24972
|
console.log(
|
|
@@ -24107,6 +25090,7 @@ var init_vite = __esm({
|
|
|
24107
25090
|
path23 = __toESM(require("path"));
|
|
24108
25091
|
init_layers();
|
|
24109
25092
|
init_environment_vite();
|
|
25093
|
+
init_version();
|
|
24110
25094
|
init_deferred();
|
|
24111
25095
|
init_after();
|
|
24112
25096
|
init_deployment();
|
|
@@ -25322,14 +26306,12 @@ export default defineEventHandler(async (event: H3Event) => {
|
|
|
25322
26306
|
...preset === "cloudflare-module" && cloudflareCronConfig ? {
|
|
25323
26307
|
cloudflare: cloudflareCronConfig
|
|
25324
26308
|
} : {},
|
|
25325
|
-
handlers: [
|
|
25326
|
-
|
|
25327
|
-
{
|
|
25328
|
-
|
|
25329
|
-
|
|
25330
|
-
|
|
25331
|
-
] : []
|
|
25332
|
-
],
|
|
26309
|
+
handlers: farmWorkflows.handlerPath ? [
|
|
26310
|
+
{
|
|
26311
|
+
route: `${config.workflows.route}/**`,
|
|
26312
|
+
handler: farmWorkflows.handlerPath
|
|
26313
|
+
}
|
|
26314
|
+
] : [],
|
|
25333
26315
|
// Route rules for Vercel
|
|
25334
26316
|
routeRules: {
|
|
25335
26317
|
"/api/**": {
|
|
@@ -25723,8 +26705,8 @@ function compareRuntimeRoutes(left, right) {
|
|
|
25723
26705
|
__name(compareRuntimeRoutes, "compareRuntimeRoutes");
|
|
25724
26706
|
function getPatternSpecificity(pattern) {
|
|
25725
26707
|
return normalizePattern(pattern).split("/").filter(Boolean).reduce((score, segment) => {
|
|
25726
|
-
if (segment === "**" ||
|
|
25727
|
-
if (segment === "*" ||
|
|
26708
|
+
if (segment === "**" || segment.startsWith("[[...")) return score + 1;
|
|
26709
|
+
if (segment === "*" || segment.startsWith("[...")) return score + 10;
|
|
25728
26710
|
if (/^\[.+\]$/.test(segment)) return score + 50;
|
|
25729
26711
|
return score + 100;
|
|
25730
26712
|
}, 0);
|
|
@@ -26235,6 +27217,18 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
|
|
|
26235
27217
|
...isFarmMarkdownPageFile(entry.modulePath) ? { source: (0, import_fs5.readFileSync)(entry.modulePath, "utf8") } : {}
|
|
26236
27218
|
});
|
|
26237
27219
|
}
|
|
27220
|
+
const routeSlots = Array.from(
|
|
27221
|
+
routeManager.getRouteSlots().values(),
|
|
27222
|
+
(entry) => ({
|
|
27223
|
+
name: entry.name,
|
|
27224
|
+
ownerPattern: entry.ownerPattern,
|
|
27225
|
+
pattern: entry.pattern,
|
|
27226
|
+
modulePath: entry.modulePath,
|
|
27227
|
+
containerId: entry.containerId,
|
|
27228
|
+
interception: entry.interception,
|
|
27229
|
+
fallback: entry.fallback
|
|
27230
|
+
})
|
|
27231
|
+
);
|
|
26238
27232
|
logger.info(`\u{1F4CB} Found ${pageRoutes.length} page routes`);
|
|
26239
27233
|
const fs8 = await import("fs/promises");
|
|
26240
27234
|
const layoutRoutes = [];
|
|
@@ -26278,7 +27272,16 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
|
|
|
26278
27272
|
logger.info("\u{1F4E6} Building client and SSR bundles in parallel...");
|
|
26279
27273
|
const [clientBuildResult, ssrBuildResult] = await Promise.allSettled([
|
|
26280
27274
|
// Client build (to disk)
|
|
26281
|
-
buildClient(
|
|
27275
|
+
buildClient(
|
|
27276
|
+
productionVite,
|
|
27277
|
+
config,
|
|
27278
|
+
root,
|
|
27279
|
+
srcDir,
|
|
27280
|
+
clientOutputDir,
|
|
27281
|
+
pageRoutes,
|
|
27282
|
+
layoutRoutes,
|
|
27283
|
+
routeSlots
|
|
27284
|
+
),
|
|
26282
27285
|
// SSR build (in memory)
|
|
26283
27286
|
buildSSRInMemory(
|
|
26284
27287
|
productionVite,
|
|
@@ -26289,7 +27292,8 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
|
|
|
26289
27292
|
serverRenderer,
|
|
26290
27293
|
preset,
|
|
26291
27294
|
pageRoutes,
|
|
26292
|
-
layoutRoutes
|
|
27295
|
+
layoutRoutes,
|
|
27296
|
+
routeSlots
|
|
26293
27297
|
)
|
|
26294
27298
|
]);
|
|
26295
27299
|
const [routeRuntimeManifestResult] = await routeRuntimeManifestResultPromise;
|
|
@@ -26309,7 +27313,8 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
|
|
|
26309
27313
|
srcDir,
|
|
26310
27314
|
clientOutputDir,
|
|
26311
27315
|
pageRoutes,
|
|
26312
|
-
layoutRoutes
|
|
27316
|
+
layoutRoutes,
|
|
27317
|
+
routeSlots
|
|
26313
27318
|
);
|
|
26314
27319
|
}
|
|
26315
27320
|
const ssrResult = ssrBuildResult.value;
|
|
@@ -26412,7 +27417,7 @@ async function validateClientBuildOutput(root, srcDir, outputDir) {
|
|
|
26412
27417
|
}
|
|
26413
27418
|
}
|
|
26414
27419
|
__name(validateClientBuildOutput, "validateClientBuildOutput");
|
|
26415
|
-
async function buildClient(productionVite, config, root, srcDir, outputDir, pageRoutes, layoutRoutes = []) {
|
|
27420
|
+
async function buildClient(productionVite, config, root, srcDir, outputDir, pageRoutes, layoutRoutes = [], routeSlots = []) {
|
|
26416
27421
|
const viteBuild = productionVite.build;
|
|
26417
27422
|
const { farmPlugin: farmPlugin2 } = await Promise.resolve().then(() => (init_vite(), vite_exports));
|
|
26418
27423
|
const { PluginManager: PluginManager2 } = await Promise.resolve().then(() => (init_plugin(), plugin_exports));
|
|
@@ -26439,8 +27444,16 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
|
|
|
26439
27444
|
logger.warn(`\u26A0\uFE0F Could not inspect route file ${route.modulePath}: ${error}`);
|
|
26440
27445
|
}
|
|
26441
27446
|
}
|
|
27447
|
+
const clientRouteSlots = routeSlots.filter((slot) => {
|
|
27448
|
+
try {
|
|
27449
|
+
return getClientModuleMetadata(slot.modulePath, root).shouldHydrate;
|
|
27450
|
+
} catch (error) {
|
|
27451
|
+
logger.warn(`\u26A0\uFE0F Could not inspect route slot ${slot.modulePath}: ${error}`);
|
|
27452
|
+
return false;
|
|
27453
|
+
}
|
|
27454
|
+
});
|
|
26442
27455
|
logger.info(
|
|
26443
|
-
`\u{1F4F1} Total hydratable routes detected: ${clientPages.length}
|
|
27456
|
+
`\u{1F4F1} Total hydratable routes detected: ${clientPages.length} pages and ${clientRouteSlots.length} slots`
|
|
26444
27457
|
);
|
|
26445
27458
|
const clientEntryRoot = import_path12.default.join(root, ".farm", "tmp");
|
|
26446
27459
|
await fs8.mkdir(clientEntryRoot, { recursive: true });
|
|
@@ -26449,6 +27462,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
|
|
|
26449
27462
|
const clientHydrationCode = generateClientHydrationEntry(
|
|
26450
27463
|
clientPages,
|
|
26451
27464
|
layoutRoutes,
|
|
27465
|
+
clientRouteSlots,
|
|
26452
27466
|
root,
|
|
26453
27467
|
srcDir,
|
|
26454
27468
|
isFarmDocsSearchEnabled(config.docs),
|
|
@@ -26781,7 +27795,7 @@ function generateUniversalRouterStateProperties() {
|
|
|
26781
27795
|
`.trim();
|
|
26782
27796
|
}
|
|
26783
27797
|
__name(generateUniversalRouterStateProperties, "generateUniversalRouterStateProperties");
|
|
26784
|
-
function generateClientHydrationEntry(clientPages, layoutRoutes, root, srcDir, docsSearchEnabled, docsSearchModuleId, i18nConfig = {
|
|
27798
|
+
function generateClientHydrationEntry(clientPages, layoutRoutes, clientRouteSlots, root, srcDir, docsSearchEnabled, docsSearchModuleId, i18nConfig = {
|
|
26785
27799
|
enabled: false,
|
|
26786
27800
|
locales: ["en"],
|
|
26787
27801
|
defaultLocale: "en",
|
|
@@ -26849,7 +27863,7 @@ function isFarmLocaleDocumentChange() {
|
|
|
26849
27863
|
return false;
|
|
26850
27864
|
}
|
|
26851
27865
|
`;
|
|
26852
|
-
if (clientPages.length === 0) {
|
|
27866
|
+
if (clientPages.length === 0 && clientRouteSlots.length === 0) {
|
|
26853
27867
|
return `
|
|
26854
27868
|
// Farm.js Client Runtime (no client components)
|
|
26855
27869
|
${cssImport}
|
|
@@ -27099,11 +28113,25 @@ document.addEventListener("click", function(e) {
|
|
|
27099
28113
|
}
|
|
27100
28114
|
const imports = [];
|
|
27101
28115
|
const routeEntries = [];
|
|
28116
|
+
const routeSlotEntries = [];
|
|
27102
28117
|
clientPages.forEach((page2, index) => {
|
|
27103
28118
|
const importPath = toImportPath(page2.modulePath);
|
|
27104
28119
|
imports.push(`import Page${index} from "${importPath}";`);
|
|
27105
28120
|
routeEntries.push(` { pattern: ${JSON.stringify(page2.pattern)}, Component: Page${index} }`);
|
|
27106
28121
|
});
|
|
28122
|
+
clientRouteSlots.forEach((slot, index) => {
|
|
28123
|
+
const importPath = toImportPath(slot.modulePath);
|
|
28124
|
+
imports.push(`import RouteSlot${index} from "${importPath}";`);
|
|
28125
|
+
routeSlotEntries.push(` {
|
|
28126
|
+
name: ${JSON.stringify(slot.name)},
|
|
28127
|
+
ownerPattern: ${JSON.stringify(slot.ownerPattern)},
|
|
28128
|
+
pattern: ${JSON.stringify(slot.pattern)},
|
|
28129
|
+
containerId: ${JSON.stringify(slot.containerId)},
|
|
28130
|
+
interception: ${JSON.stringify(slot.interception)},
|
|
28131
|
+
fallback: ${JSON.stringify(slot.fallback)},
|
|
28132
|
+
Component: RouteSlot${index},
|
|
28133
|
+
}`);
|
|
28134
|
+
});
|
|
27107
28135
|
return `
|
|
27108
28136
|
// Farm.js Client Runtime - SPA with Hydration
|
|
27109
28137
|
${cssImport}
|
|
@@ -27125,6 +28153,10 @@ const clientRoutes = [
|
|
|
27125
28153
|
${routeEntries.join(",\n")}
|
|
27126
28154
|
];
|
|
27127
28155
|
|
|
28156
|
+
const clientRouteSlots = [
|
|
28157
|
+
${routeSlotEntries.join(",\n")}
|
|
28158
|
+
];
|
|
28159
|
+
|
|
27128
28160
|
// Layout routes for wrapping client components
|
|
27129
28161
|
const layoutRoutes = [
|
|
27130
28162
|
${layoutRegistrations.join(",\n")}
|
|
@@ -27179,6 +28211,146 @@ function matchRoute(pathname) {
|
|
|
27179
28211
|
return null;
|
|
27180
28212
|
}
|
|
27181
28213
|
|
|
28214
|
+
function matchesRoutePrefix(pathname, pattern) {
|
|
28215
|
+
if (pattern === "/") return true;
|
|
28216
|
+
const pathSegments = getFarmRoutePathname(pathname).split("/").filter(Boolean);
|
|
28217
|
+
const patternSegments = pattern.split("/").filter(Boolean);
|
|
28218
|
+
if (patternSegments.length > pathSegments.length) return false;
|
|
28219
|
+
const candidate = "/" + pathSegments.slice(0, patternSegments.length).join("/");
|
|
28220
|
+
return matchFarmRoute(pattern, candidate) !== null;
|
|
28221
|
+
}
|
|
28222
|
+
|
|
28223
|
+
function matchInterceptedRouteSlot(pathname, from) {
|
|
28224
|
+
for (const slot of clientRouteSlots) {
|
|
28225
|
+
if (!slot.interception || !matchesRoutePrefix(from, slot.ownerPattern)) continue;
|
|
28226
|
+
const params = matchFarmRoute(slot.pattern, getFarmRoutePathname(pathname));
|
|
28227
|
+
if (params !== null) return { slot: slot, params: params };
|
|
28228
|
+
}
|
|
28229
|
+
return null;
|
|
28230
|
+
}
|
|
28231
|
+
|
|
28232
|
+
function routeSlotKey(slot) {
|
|
28233
|
+
return slot.ownerPattern + ":" + slot.name;
|
|
28234
|
+
}
|
|
28235
|
+
|
|
28236
|
+
function findClientRouteSlot(slot) {
|
|
28237
|
+
return clientRouteSlots.find(function(candidate) {
|
|
28238
|
+
return candidate.name === slot.name &&
|
|
28239
|
+
candidate.ownerPattern === slot.ownerPattern &&
|
|
28240
|
+
candidate.pattern === slot.pattern &&
|
|
28241
|
+
candidate.interception === slot.interception &&
|
|
28242
|
+
candidate.fallback === slot.fallback;
|
|
28243
|
+
});
|
|
28244
|
+
}
|
|
28245
|
+
|
|
28246
|
+
function readRouteSlotPayload(doc) {
|
|
28247
|
+
const script = doc.getElementById("__farm_route_slots_data__");
|
|
28248
|
+
if (!script?.textContent) return [];
|
|
28249
|
+
try {
|
|
28250
|
+
const parsed = JSON.parse(script.textContent);
|
|
28251
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
28252
|
+
} catch {
|
|
28253
|
+
return [];
|
|
28254
|
+
}
|
|
28255
|
+
}
|
|
28256
|
+
|
|
28257
|
+
const routeSlotRoots = new Map();
|
|
28258
|
+
let activeRouteInterception = null;
|
|
28259
|
+
|
|
28260
|
+
function resetRouteSlotRoots() {
|
|
28261
|
+
for (const root of routeSlotRoots.values()) {
|
|
28262
|
+
try { root.unmount(); } catch {}
|
|
28263
|
+
}
|
|
28264
|
+
routeSlotRoots.clear();
|
|
28265
|
+
activeRouteInterception = null;
|
|
28266
|
+
}
|
|
28267
|
+
|
|
28268
|
+
function renderClientRouteSlot(slot, registration, mode) {
|
|
28269
|
+
const container = document.getElementById(slot.containerId);
|
|
28270
|
+
if (!container || !registration?.Component) return false;
|
|
28271
|
+
const key = routeSlotKey(slot);
|
|
28272
|
+
const existingRoot = routeSlotRoots.get(key);
|
|
28273
|
+
const props = slot.props && typeof slot.props === "object" ? slot.props : {};
|
|
28274
|
+
const element = React.createElement(registration.Component, props);
|
|
28275
|
+
|
|
28276
|
+
if (mode === "hydrate") {
|
|
28277
|
+
if (existingRoot) return true;
|
|
28278
|
+
const root = hydrateRoot(container, element);
|
|
28279
|
+
routeSlotRoots.set(key, root);
|
|
28280
|
+
return true;
|
|
28281
|
+
}
|
|
28282
|
+
|
|
28283
|
+
if (existingRoot) {
|
|
28284
|
+
try { existingRoot.unmount(); } catch {}
|
|
28285
|
+
routeSlotRoots.delete(key);
|
|
28286
|
+
} else {
|
|
28287
|
+
container.replaceChildren();
|
|
28288
|
+
}
|
|
28289
|
+
const root = createRoot(container);
|
|
28290
|
+
root.render(element);
|
|
28291
|
+
routeSlotRoots.set(key, root);
|
|
28292
|
+
return true;
|
|
28293
|
+
}
|
|
28294
|
+
|
|
28295
|
+
function hydrateInitialRouteSlots() {
|
|
28296
|
+
const slots = Array.isArray(window.__FARM_ROUTE_SLOTS__)
|
|
28297
|
+
? window.__FARM_ROUTE_SLOTS__
|
|
28298
|
+
: [];
|
|
28299
|
+
for (const slot of slots) {
|
|
28300
|
+
const registration = findClientRouteSlot(slot);
|
|
28301
|
+
if (!registration) continue;
|
|
28302
|
+
try {
|
|
28303
|
+
renderClientRouteSlot(slot, registration, "hydrate");
|
|
28304
|
+
} catch (error) {
|
|
28305
|
+
console.warn("[Farm.js] Could not hydrate route slot:", slot.name, error);
|
|
28306
|
+
}
|
|
28307
|
+
}
|
|
28308
|
+
}
|
|
28309
|
+
|
|
28310
|
+
function renderRouteInterception(slot, registration, from) {
|
|
28311
|
+
const container = document.getElementById(slot.containerId);
|
|
28312
|
+
if (!container) return false;
|
|
28313
|
+
const key = routeSlotKey(slot);
|
|
28314
|
+
const previousSlot = (window.__FARM_ROUTE_SLOTS__ || []).find(function(candidate) {
|
|
28315
|
+
return routeSlotKey(candidate) === key;
|
|
28316
|
+
}) || null;
|
|
28317
|
+
const previousHtml = container.innerHTML;
|
|
28318
|
+
|
|
28319
|
+
if (!renderClientRouteSlot(slot, registration, "render")) return false;
|
|
28320
|
+
activeRouteInterception = {
|
|
28321
|
+
from: from,
|
|
28322
|
+
key: key,
|
|
28323
|
+
slot: slot,
|
|
28324
|
+
previousSlot: previousSlot,
|
|
28325
|
+
previousHtml: previousHtml,
|
|
28326
|
+
};
|
|
28327
|
+
return true;
|
|
28328
|
+
}
|
|
28329
|
+
|
|
28330
|
+
function clearRouteInterception(destination) {
|
|
28331
|
+
if (!activeRouteInterception) return false;
|
|
28332
|
+
const active = activeRouteInterception;
|
|
28333
|
+
activeRouteInterception = null;
|
|
28334
|
+
const root = routeSlotRoots.get(active.key);
|
|
28335
|
+
if (root) {
|
|
28336
|
+
try { root.unmount(); } catch {}
|
|
28337
|
+
routeSlotRoots.delete(active.key);
|
|
28338
|
+
}
|
|
28339
|
+
const container = document.getElementById(active.slot.containerId);
|
|
28340
|
+
if (container) {
|
|
28341
|
+
container.innerHTML = active.previousHtml;
|
|
28342
|
+
if (active.previousSlot) {
|
|
28343
|
+
const registration = findClientRouteSlot(active.previousSlot);
|
|
28344
|
+
if (registration) {
|
|
28345
|
+
try {
|
|
28346
|
+
renderClientRouteSlot(active.previousSlot, registration, "hydrate");
|
|
28347
|
+
} catch {}
|
|
28348
|
+
}
|
|
28349
|
+
}
|
|
28350
|
+
}
|
|
28351
|
+
return destination === active.from;
|
|
28352
|
+
}
|
|
28353
|
+
|
|
27182
28354
|
// State
|
|
27183
28355
|
let reactRoot = null;
|
|
27184
28356
|
let currentPathname = null;
|
|
@@ -27197,12 +28369,17 @@ function resetReactRoot() {
|
|
|
27197
28369
|
async function hydrate() {
|
|
27198
28370
|
const pathname = window.location.pathname;
|
|
27199
28371
|
const matched = matchRoute(pathname);
|
|
27200
|
-
|
|
28372
|
+
hydrateInitialRouteSlots();
|
|
28373
|
+
|
|
27201
28374
|
if (!matched) {
|
|
27202
28375
|
return;
|
|
27203
28376
|
}
|
|
27204
28377
|
|
|
27205
|
-
const
|
|
28378
|
+
const hasRouteSlots =
|
|
28379
|
+
Array.isArray(window.__FARM_ROUTE_SLOTS__) && window.__FARM_ROUTE_SLOTS__.length > 0;
|
|
28380
|
+
const container =
|
|
28381
|
+
(hasRouteSlots ? document.getElementById("__farm_page__") : null) ||
|
|
28382
|
+
document.getElementById("root");
|
|
27206
28383
|
if (!container) {
|
|
27207
28384
|
console.error("[Farm.js] No root element found");
|
|
27208
28385
|
return;
|
|
@@ -27216,7 +28393,9 @@ async function hydrate() {
|
|
|
27216
28393
|
|
|
27217
28394
|
// Create page element and wrap with layouts
|
|
27218
28395
|
const pageElement = React.createElement(Component, props);
|
|
27219
|
-
const wrappedElement =
|
|
28396
|
+
const wrappedElement = hasRouteSlots
|
|
28397
|
+
? pageElement
|
|
28398
|
+
: wrapWithLayouts(pageElement, pathname, params);
|
|
27220
28399
|
|
|
27221
28400
|
const shouldHydrate = !isHydrated && Boolean(container.innerHTML.trim());
|
|
27222
28401
|
const hydrationSession = await farmClientRuntime.beginHydration({
|
|
@@ -27281,6 +28460,57 @@ ${generateUniversalRouterStateProperties()}
|
|
|
27281
28460
|
: undefined,
|
|
27282
28461
|
});
|
|
27283
28462
|
|
|
28463
|
+
if (activeRouteInterception && clearRouteInterception(to)) {
|
|
28464
|
+
await farmClientRuntime.markNavigationLoaded(clientNavigation, {
|
|
28465
|
+
routeSlots: "restored",
|
|
28466
|
+
});
|
|
28467
|
+
await farmClientRuntime.resolveNavigation(clientNavigation);
|
|
28468
|
+
void farmClientRuntime.scheduleNavigationRendered(clientNavigation);
|
|
28469
|
+
this.currentPath = to;
|
|
28470
|
+
this.finishNavigation();
|
|
28471
|
+
return;
|
|
28472
|
+
}
|
|
28473
|
+
if (activeRouteInterception) {
|
|
28474
|
+
clearRouteInterception(to);
|
|
28475
|
+
}
|
|
28476
|
+
|
|
28477
|
+
const intercepted = matchInterceptedRouteSlot(pathname, from);
|
|
28478
|
+
if (intercepted) {
|
|
28479
|
+
const html = await this.fetchPage(to, from);
|
|
28480
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
28481
|
+
const slotPayload = readRouteSlotPayload(doc);
|
|
28482
|
+
const selectedSlot = slotPayload.find(function(slot) {
|
|
28483
|
+
return slot.interception &&
|
|
28484
|
+
slot.name === intercepted.slot.name &&
|
|
28485
|
+
slot.ownerPattern === intercepted.slot.ownerPattern;
|
|
28486
|
+
});
|
|
28487
|
+
|
|
28488
|
+
if (
|
|
28489
|
+
selectedSlot &&
|
|
28490
|
+
renderRouteInterception(selectedSlot, intercepted.slot, from)
|
|
28491
|
+
) {
|
|
28492
|
+
await farmClientRuntime.markNavigationLoaded(clientNavigation, {
|
|
28493
|
+
route: intercepted.slot.pattern,
|
|
28494
|
+
params: intercepted.params,
|
|
28495
|
+
});
|
|
28496
|
+
const historyState = createHistoryState(
|
|
28497
|
+
to,
|
|
28498
|
+
options.state,
|
|
28499
|
+
window.history.state,
|
|
28500
|
+
);
|
|
28501
|
+
if (action === "replace") {
|
|
28502
|
+
window.history.replaceState(historyState, "", url);
|
|
28503
|
+
} else if (action !== "pop") {
|
|
28504
|
+
window.history.pushState(historyState, "", url);
|
|
28505
|
+
}
|
|
28506
|
+
await farmClientRuntime.resolveNavigation(clientNavigation);
|
|
28507
|
+
void farmClientRuntime.scheduleNavigationRendered(clientNavigation);
|
|
28508
|
+
this.currentPath = to;
|
|
28509
|
+
this.finishNavigation();
|
|
28510
|
+
return;
|
|
28511
|
+
}
|
|
28512
|
+
}
|
|
28513
|
+
|
|
27284
28514
|
if (matched) {
|
|
27285
28515
|
const Component = matched.route.Component;
|
|
27286
28516
|
const params = matched.params;
|
|
@@ -27357,21 +28587,28 @@ ${generateUniversalRouterStateProperties()}
|
|
|
27357
28587
|
}
|
|
27358
28588
|
},
|
|
27359
28589
|
|
|
27360
|
-
fetchPage: async function(url) {
|
|
27361
|
-
const
|
|
28590
|
+
fetchPage: async function(url, interceptFrom) {
|
|
28591
|
+
const cacheKey = interceptFrom ? url + "\\nintercept:" + interceptFrom : url;
|
|
28592
|
+
const cached = this.prefetchCache.get(cacheKey);
|
|
27362
28593
|
if (cached) return cached;
|
|
27363
28594
|
|
|
27364
28595
|
const response = await fetch(url, {
|
|
27365
|
-
headers: {
|
|
28596
|
+
headers: {
|
|
28597
|
+
"Accept": "text/html",
|
|
28598
|
+
...(interceptFrom ? { "X-Farm-Intercept-From": interceptFrom } : {}),
|
|
28599
|
+
}
|
|
27366
28600
|
});
|
|
27367
28601
|
if (!response.ok) throw new Error("Failed to fetch page");
|
|
27368
|
-
|
|
28602
|
+
const html = await response.text();
|
|
28603
|
+
this.prefetchCache.set(cacheKey, html);
|
|
28604
|
+
return html;
|
|
27369
28605
|
},
|
|
27370
28606
|
|
|
27371
28607
|
swapContent: function(html, targetPath) {
|
|
27372
28608
|
const parser = new DOMParser();
|
|
27373
28609
|
const doc = parser.parseFromString(html, "text/html");
|
|
27374
28610
|
if (isFarmLocaleDocumentChange(doc)) return false;
|
|
28611
|
+
const nextRouteSlots = readRouteSlotPayload(doc);
|
|
27375
28612
|
|
|
27376
28613
|
// Update title
|
|
27377
28614
|
const newTitle = doc.querySelector("title");
|
|
@@ -27396,7 +28633,10 @@ ${generateUniversalRouterStateProperties()}
|
|
|
27396
28633
|
const currentRoot = document.getElementById("root");
|
|
27397
28634
|
if (!newRoot || !currentRoot) return this.swapDocument(doc);
|
|
27398
28635
|
resetReactRoot();
|
|
28636
|
+
resetRouteSlotRoots();
|
|
27399
28637
|
currentRoot.innerHTML = newRoot.innerHTML;
|
|
28638
|
+
window.__FARM_ROUTE_SLOTS__ = nextRouteSlots;
|
|
28639
|
+
hydrateInitialRouteSlots();
|
|
27400
28640
|
|
|
27401
28641
|
// Check if new page has a client component
|
|
27402
28642
|
const targetUrl = new URL(targetPath || window.location.href, window.location.origin);
|
|
@@ -27408,13 +28648,15 @@ ${generateUniversalRouterStateProperties()}
|
|
|
27408
28648
|
const params = matched.params;
|
|
27409
28649
|
const searchParams = Object.fromEntries(targetUrl.searchParams);
|
|
27410
28650
|
const props = { params: params, searchParams: Promise.resolve(searchParams) };
|
|
27411
|
-
|
|
27412
|
-
if (!reactRoot) {
|
|
27413
|
-
reactRoot = createRoot(currentRoot);
|
|
27414
|
-
}
|
|
27415
28651
|
const pageElement = React.createElement(Component, props);
|
|
27416
|
-
const
|
|
27417
|
-
|
|
28652
|
+
const hasRouteSlots = nextRouteSlots.length > 0;
|
|
28653
|
+
const pageContainer =
|
|
28654
|
+
(hasRouteSlots ? document.getElementById("__farm_page__") : null) || currentRoot;
|
|
28655
|
+
const wrappedElement = hasRouteSlots
|
|
28656
|
+
? pageElement
|
|
28657
|
+
: wrapWithLayouts(pageElement, newPathname, params);
|
|
28658
|
+
reactRoot = hydrateRoot(pageContainer, wrappedElement);
|
|
28659
|
+
isHydrated = true;
|
|
27418
28660
|
}
|
|
27419
28661
|
return true;
|
|
27420
28662
|
},
|
|
@@ -27423,6 +28665,7 @@ ${generateUniversalRouterStateProperties()}
|
|
|
27423
28665
|
if (!doc.documentElement || !doc.body) return false;
|
|
27424
28666
|
|
|
27425
28667
|
resetReactRoot();
|
|
28668
|
+
resetRouteSlotRoots();
|
|
27426
28669
|
|
|
27427
28670
|
Array.from(document.documentElement.attributes).forEach(function(attr) {
|
|
27428
28671
|
if (!doc.documentElement.hasAttribute(attr.name)) {
|
|
@@ -27456,10 +28699,12 @@ ${generateUniversalRouterStateProperties()}
|
|
|
27456
28699
|
if (url.origin !== window.location.origin) return;
|
|
27457
28700
|
|
|
27458
28701
|
const pathname = url.pathname + url.search;
|
|
27459
|
-
|
|
28702
|
+
const interceptFrom = this.currentPath;
|
|
28703
|
+
const cacheKey = pathname + "\\nintercept:" + interceptFrom;
|
|
28704
|
+
if (this.prefetchCache.has(cacheKey)) return;
|
|
27460
28705
|
|
|
27461
|
-
this.fetchPage(pathname)
|
|
27462
|
-
.then(function(html) { spaRouter.prefetchCache.set(
|
|
28706
|
+
this.fetchPage(pathname, interceptFrom)
|
|
28707
|
+
.then(function(html) { spaRouter.prefetchCache.set(cacheKey, html); })
|
|
27463
28708
|
.catch(function() {});
|
|
27464
28709
|
},
|
|
27465
28710
|
|
|
@@ -27550,7 +28795,7 @@ if (isFarmDocsSearchPage()) {
|
|
|
27550
28795
|
`.trim();
|
|
27551
28796
|
}
|
|
27552
28797
|
__name(generateClientHydrationEntry, "generateClientHydrationEntry");
|
|
27553
|
-
async function buildSSRInMemory(productionVite, config, root, routeManager, apiRouteManager, serverRenderer, preset, collectedPageRoutes, collectedLayoutRoutes) {
|
|
28798
|
+
async function buildSSRInMemory(productionVite, config, root, routeManager, apiRouteManager, serverRenderer, preset, collectedPageRoutes, collectedLayoutRoutes, collectedRouteSlots) {
|
|
27554
28799
|
const viteBuild = productionVite.build;
|
|
27555
28800
|
const { farmPlugin: farmPlugin2 } = await Promise.resolve().then(() => (init_vite(), vite_exports));
|
|
27556
28801
|
const { PluginManager: PluginManager2 } = await Promise.resolve().then(() => (init_plugin(), plugin_exports));
|
|
@@ -27583,6 +28828,7 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
|
|
|
27583
28828
|
let ssrEntryFile;
|
|
27584
28829
|
const pageRoutes = collectedPageRoutes.map((route) => ({ ...route }));
|
|
27585
28830
|
const layoutRoutes = collectedLayoutRoutes.map((route) => ({ ...route }));
|
|
28831
|
+
const routeSlots = collectedRouteSlots.map((slot) => ({ ...slot }));
|
|
27586
28832
|
const metadataImageRoutes = [];
|
|
27587
28833
|
for (const entry of routeManager.getMetadataImages().values()) {
|
|
27588
28834
|
if (entry.sourceType === "static") {
|
|
@@ -27683,6 +28929,7 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
|
|
|
27683
28929
|
apiRoutes,
|
|
27684
28930
|
pageRoutes,
|
|
27685
28931
|
layoutRoutes,
|
|
28932
|
+
routeSlots,
|
|
27686
28933
|
errorRoutes,
|
|
27687
28934
|
metadataImageRoutes,
|
|
27688
28935
|
middlewareRoutes,
|
|
@@ -27853,10 +29100,14 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
|
|
|
27853
29100
|
}
|
|
27854
29101
|
}
|
|
27855
29102
|
}
|
|
27856
|
-
return {
|
|
29103
|
+
return {
|
|
29104
|
+
bundle: ssrBundle,
|
|
29105
|
+
entryFile: ssrEntryFile,
|
|
29106
|
+
configuredHeaderRoutes
|
|
29107
|
+
};
|
|
27857
29108
|
}
|
|
27858
29109
|
__name(buildSSRInMemory, "buildSSRInMemory");
|
|
27859
|
-
function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, errorRoutes, metadataImageRoutes, middlewareRoutes, redirectRoutes, configuredRewriteRoutes, configuredHeaderRoutes, notFoundPath, config, configModulePath, hasServerRuntimeIntegrations, hasRuntimeIntegrationConfig, hasConfiguredRuntimePlugins, preset, i18nCatalogs) {
|
|
29110
|
+
function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, routeSlots, errorRoutes, metadataImageRoutes, middlewareRoutes, redirectRoutes, configuredRewriteRoutes, configuredHeaderRoutes, notFoundPath, config, configModulePath, hasServerRuntimeIntegrations, hasRuntimeIntegrationConfig, hasConfiguredRuntimePlugins, preset, i18nCatalogs) {
|
|
27860
29111
|
const hasPluginRuntime = hasRuntimeIntegrationConfig || hasConfiguredRuntimePlugins;
|
|
27861
29112
|
const hasMiddlewareRuntime = middlewareRoutes.length > 0 || hasFarmMiddlewareConfig(config.middleware);
|
|
27862
29113
|
const farmDocsBaseConfig = config.docs?.enabled ? { ...config.docs, config: void 0 } : void 0;
|
|
@@ -27900,10 +29151,12 @@ function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, errorRout
|
|
|
27900
29151
|
return;
|
|
27901
29152
|
}
|
|
27902
29153
|
pageImports.push(`import * as ${varName} from "${route.modulePath}";`);
|
|
29154
|
+
const shouldHydrate = getClientModuleMetadata(route.modulePath, config.root).shouldHydrate;
|
|
27903
29155
|
pageRegistrations.push(`
|
|
27904
29156
|
{
|
|
27905
29157
|
pattern: ${JSON.stringify(route.pattern)},
|
|
27906
29158
|
module: ${varName},
|
|
29159
|
+
shouldHydrate: ${JSON.stringify(shouldHydrate)},
|
|
27907
29160
|
}`);
|
|
27908
29161
|
});
|
|
27909
29162
|
const layoutImports = [];
|
|
@@ -27917,6 +29170,22 @@ function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, errorRout
|
|
|
27917
29170
|
module: ${varName},
|
|
27918
29171
|
}`);
|
|
27919
29172
|
});
|
|
29173
|
+
const routeSlotImports = [];
|
|
29174
|
+
const routeSlotRegistrations = [];
|
|
29175
|
+
routeSlots.forEach((slot, index) => {
|
|
29176
|
+
const varName = `routeSlot${index}`;
|
|
29177
|
+
routeSlotImports.push(`import * as ${varName} from "${slot.modulePath}";`);
|
|
29178
|
+
routeSlotRegistrations.push(`
|
|
29179
|
+
{
|
|
29180
|
+
name: ${JSON.stringify(slot.name)},
|
|
29181
|
+
ownerPattern: ${JSON.stringify(slot.ownerPattern)},
|
|
29182
|
+
pattern: ${JSON.stringify(slot.pattern)},
|
|
29183
|
+
containerId: ${JSON.stringify(slot.containerId)},
|
|
29184
|
+
interception: ${JSON.stringify(slot.interception)},
|
|
29185
|
+
fallback: ${JSON.stringify(slot.fallback)},
|
|
29186
|
+
module: ${varName},
|
|
29187
|
+
}`);
|
|
29188
|
+
});
|
|
27920
29189
|
const errorImports = [];
|
|
27921
29190
|
const errorRegistrations = [];
|
|
27922
29191
|
errorRoutes.forEach((errorRoute, index) => {
|
|
@@ -27967,6 +29236,7 @@ function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, errorRout
|
|
|
27967
29236
|
_runWithMiddlewareData,
|
|
27968
29237
|
addMetadataImageReference,
|
|
27969
29238
|
applyProductionMiddlewareHeaders,
|
|
29239
|
+
configureFarmCache,
|
|
27970
29240
|
configureFarmObservability,
|
|
27971
29241
|
createFarmCacheKey,
|
|
27972
29242
|
createFarmLocaleCookie,
|
|
@@ -28069,6 +29339,7 @@ async function handleAPIRequest(request) {
|
|
|
28069
29339
|
${apiImports.join("\n")}
|
|
28070
29340
|
${pageImports.join("\n")}
|
|
28071
29341
|
${layoutImports.join("\n")}
|
|
29342
|
+
${routeSlotImports.join("\n")}
|
|
28072
29343
|
${errorImports.join("\n")}
|
|
28073
29344
|
${metadataImageImports.join("\n")}
|
|
28074
29345
|
${middlewareImports.join("\n")}
|
|
@@ -28146,6 +29417,7 @@ const farmObservabilityConfig = farmUserConfig?.observability ?? ${JSON.stringif
|
|
|
28146
29417
|
config.observability ?? false
|
|
28147
29418
|
)};
|
|
28148
29419
|
configureFarmObservability(farmObservabilityConfig);
|
|
29420
|
+
configureFarmCache(farmResolvedRuntimeConfig.cache);
|
|
28149
29421
|
const farmI18nConfig = ${JSON.stringify(config.i18n)};
|
|
28150
29422
|
const farmI18nRuntime = ${config.i18n.enabled ? `createFarmI18nRuntime(farmI18nConfig, ${JSON.stringify(i18nCatalogs)})` : "null"};
|
|
28151
29423
|
${config.i18n.enabled ? "_setDefaultFarmI18nRuntime(farmI18nRuntime);" : ""}
|
|
@@ -28203,6 +29475,9 @@ for (const route of pageRoutes) {
|
|
|
28203
29475
|
const layoutRoutes = [${layoutRegistrations.join(",")}
|
|
28204
29476
|
];
|
|
28205
29477
|
|
|
29478
|
+
const routeSlots = [${routeSlotRegistrations.join(",")}
|
|
29479
|
+
];
|
|
29480
|
+
|
|
28206
29481
|
// Route-level error boundaries bundled at build time.
|
|
28207
29482
|
const errorRoutes = [${errorRegistrations.join(",")}
|
|
28208
29483
|
];
|
|
@@ -28237,18 +29512,21 @@ function serializeFarmInlineValue(value) {
|
|
|
28237
29512
|
.replace(/\\u2029/g, "\\\\u2029");
|
|
28238
29513
|
}
|
|
28239
29514
|
|
|
28240
|
-
function renderFarmClientBootstrapScript(canonicalPath) {
|
|
29515
|
+
function renderFarmClientBootstrapScript(canonicalPath, selectedRouteSlots) {
|
|
28241
29516
|
const integrationManifest = ${hasRuntimeIntegrationConfig ? "getRegisteredIntegrationAPIManifest()" : "{}"};
|
|
29517
|
+
const serializedRouteSlots = serializeFarmInlineValue(selectedRouteSlots || []);
|
|
28242
29518
|
let source = 'window.__FARM_INTEGRATION_API_MANIFEST__=' +
|
|
28243
29519
|
serializeFarmInlineValue(integrationManifest) +
|
|
28244
|
-
';';
|
|
29520
|
+
';window.__FARM_ROUTE_SLOTS__=' + serializedRouteSlots + ';';
|
|
28245
29521
|
if (typeof canonicalPath === "string" && canonicalPath.startsWith("/")) {
|
|
28246
29522
|
const serializedPath = serializeFarmInlineValue(canonicalPath);
|
|
28247
29523
|
source += 'if(location.pathname+location.search!==' + serializedPath + '){' +
|
|
28248
29524
|
'history.replaceState(Object.assign({},history.state||{},{path:' + serializedPath + '}),"",' +
|
|
28249
29525
|
serializedPath + ');}';
|
|
28250
29526
|
}
|
|
28251
|
-
return '<script>' +
|
|
29527
|
+
return '<script id="__farm_route_slots_data__" type="application/json">' +
|
|
29528
|
+
serializedRouteSlots +
|
|
29529
|
+
'</script><script>' + source + '</script>';
|
|
28252
29530
|
}
|
|
28253
29531
|
|
|
28254
29532
|
function escapeFarmHtmlAttribute(value) {
|
|
@@ -28998,6 +30276,79 @@ function matchPageRoute(pathname) {
|
|
|
28998
30276
|
return null;
|
|
28999
30277
|
}
|
|
29000
30278
|
|
|
30279
|
+
function matchesRoutePrefix(pathname, pattern) {
|
|
30280
|
+
if (pattern === "/") return true;
|
|
30281
|
+
const pathSegments = normalizeRuntimePath(pathname).split("/").filter(Boolean);
|
|
30282
|
+
const patternSegments = normalizeRuntimePath(pattern).split("/").filter(Boolean);
|
|
30283
|
+
if (patternSegments.length > pathSegments.length) return false;
|
|
30284
|
+
const candidate = "/" + pathSegments.slice(0, patternSegments.length).join("/");
|
|
30285
|
+
return matchRuntimePathPattern(pattern, candidate) !== null;
|
|
30286
|
+
}
|
|
30287
|
+
|
|
30288
|
+
function routeSlotSpecificity(slot) {
|
|
30289
|
+
return slot.pattern.split("/").reduce(function(score, segment) {
|
|
30290
|
+
if (!segment) return score;
|
|
30291
|
+
if (segment.startsWith("[[...")) return score + 1;
|
|
30292
|
+
if (segment.startsWith("[...")) return score + 2;
|
|
30293
|
+
if (segment.startsWith("[")) return score + 3;
|
|
30294
|
+
return score + 10;
|
|
30295
|
+
}, 0);
|
|
30296
|
+
}
|
|
30297
|
+
|
|
30298
|
+
function matchRouteSlots(pathname, interceptFrom) {
|
|
30299
|
+
const groups = new Map();
|
|
30300
|
+
for (const slot of routeSlots) {
|
|
30301
|
+
if (!matchesRoutePrefix(pathname, slot.ownerPattern)) continue;
|
|
30302
|
+
const key = slot.ownerPattern + ":" + slot.name;
|
|
30303
|
+
const entries = groups.get(key) || [];
|
|
30304
|
+
entries.push(slot);
|
|
30305
|
+
groups.set(key, entries);
|
|
30306
|
+
}
|
|
30307
|
+
|
|
30308
|
+
const normalizedFrom =
|
|
30309
|
+
typeof interceptFrom === "string" && interceptFrom.startsWith("/")
|
|
30310
|
+
? new URL(interceptFrom, "http://farm.local").pathname
|
|
30311
|
+
: null;
|
|
30312
|
+
const matches = [];
|
|
30313
|
+
|
|
30314
|
+
for (const entries of groups.values()) {
|
|
30315
|
+
const candidates = entries
|
|
30316
|
+
.filter(function(entry) { return !entry.fallback; })
|
|
30317
|
+
.filter(function(entry) {
|
|
30318
|
+
return !entry.interception ||
|
|
30319
|
+
(normalizedFrom && matchesRoutePrefix(normalizedFrom, entry.ownerPattern));
|
|
30320
|
+
})
|
|
30321
|
+
.map(function(entry) {
|
|
30322
|
+
return {
|
|
30323
|
+
entry: entry,
|
|
30324
|
+
params: matchRuntimePathPattern(entry.pattern, pathname),
|
|
30325
|
+
};
|
|
30326
|
+
})
|
|
30327
|
+
.filter(function(candidate) { return candidate.params !== null; })
|
|
30328
|
+
.sort(function(left, right) {
|
|
30329
|
+
if (left.entry.interception !== right.entry.interception) {
|
|
30330
|
+
return left.entry.interception ? -1 : 1;
|
|
30331
|
+
}
|
|
30332
|
+
return routeSlotSpecificity(right.entry) - routeSlotSpecificity(left.entry);
|
|
30333
|
+
});
|
|
30334
|
+
|
|
30335
|
+
if (candidates[0]) {
|
|
30336
|
+
matches.push({ ...candidates[0].entry, params: candidates[0].params });
|
|
30337
|
+
continue;
|
|
30338
|
+
}
|
|
30339
|
+
|
|
30340
|
+
const fallback = entries.find(function(entry) { return entry.fallback; });
|
|
30341
|
+
if (fallback) matches.push({ ...fallback, params: {} });
|
|
30342
|
+
}
|
|
30343
|
+
|
|
30344
|
+
return matches.sort(function(left, right) {
|
|
30345
|
+
const ownerDepth =
|
|
30346
|
+
left.ownerPattern.split("/").filter(Boolean).length -
|
|
30347
|
+
right.ownerPattern.split("/").filter(Boolean).length;
|
|
30348
|
+
return ownerDepth || left.name.localeCompare(right.name);
|
|
30349
|
+
});
|
|
30350
|
+
}
|
|
30351
|
+
|
|
29001
30352
|
function hasLocalRequestRoute(request, routePathname) {
|
|
29002
30353
|
const pathname = new URL(request.url).pathname;
|
|
29003
30354
|
if (matchLocalAPIRequest(request) || matchLocalIntegrationRequest(request)) {
|
|
@@ -29148,6 +30499,7 @@ function getPPRShellBypassReason(request, middlewareData, middlewareContext) {
|
|
|
29148
30499
|
if (method !== "GET" && method !== "HEAD") return "method";
|
|
29149
30500
|
if (request.headers.get("cookie")) return "cookie";
|
|
29150
30501
|
if (request.headers.get("authorization")) return "authorization";
|
|
30502
|
+
if (request.headers.get("x-farm-intercept-from")) return "route-interception";
|
|
29151
30503
|
if (request.headers.get("x-farm-ppr-refresh")) return "refresh";
|
|
29152
30504
|
if (hasConfiguredRouteContext) return "route-context";
|
|
29153
30505
|
if (middlewareData?.size) return "middleware-data";
|
|
@@ -29201,8 +30553,8 @@ function getRouteSharedCacheControl(routeModule, pprCanCache) {
|
|
|
29201
30553
|
return "public, s-maxage=" + revalidate + ", stale-while-revalidate=300";
|
|
29202
30554
|
}
|
|
29203
30555
|
|
|
29204
|
-
function getCachedPPRShell(cacheKey) {
|
|
29205
|
-
const entry = pprShellCache.
|
|
30556
|
+
async function getCachedPPRShell(cacheKey) {
|
|
30557
|
+
const entry = await pprShellCache.getEntryAsync(cacheKey);
|
|
29206
30558
|
if (!entry) {
|
|
29207
30559
|
return null;
|
|
29208
30560
|
}
|
|
@@ -29417,7 +30769,7 @@ async function handleFarmRequestInContext(
|
|
|
29417
30769
|
}
|
|
29418
30770
|
}
|
|
29419
30771
|
if (pprCacheKey) {
|
|
29420
|
-
const cachedPPRShell = getCachedPPRShell(pprCacheKey);
|
|
30772
|
+
const cachedPPRShell = await getCachedPPRShell(pprCacheKey);
|
|
29421
30773
|
if (cachedPPRShell) {
|
|
29422
30774
|
emitFarmEvent({ type: "ppr.shell.hit", route: pathname, key: pprCacheKey });
|
|
29423
30775
|
emitFarmEvent({
|
|
@@ -29445,6 +30797,10 @@ async function handleFarmRequestInContext(
|
|
|
29445
30797
|
|
|
29446
30798
|
// Get applicable layouts for this page
|
|
29447
30799
|
const applicableLayouts = getApplicableLayouts(routePathname);
|
|
30800
|
+
const selectedRouteSlots = matchRouteSlots(
|
|
30801
|
+
routePathname,
|
|
30802
|
+
request.headers.get("x-farm-intercept-from"),
|
|
30803
|
+
);
|
|
29448
30804
|
|
|
29449
30805
|
if (PageComponent) {
|
|
29450
30806
|
// Parse search params - make it a resolved Promise for async components
|
|
@@ -29532,6 +30888,82 @@ async function handleFarmRequestInContext(
|
|
|
29532
30888
|
throw routeStateError;
|
|
29533
30889
|
}
|
|
29534
30890
|
}
|
|
30891
|
+
|
|
30892
|
+
const renderedRouteSlots = await Promise.all(
|
|
30893
|
+
selectedRouteSlots.map(async function(slot) {
|
|
30894
|
+
const slotContext = hasConfiguredRouteContext
|
|
30895
|
+
? await resolveFarmRouteContext(farmResolvedRuntimeConfig, {
|
|
30896
|
+
request,
|
|
30897
|
+
params: slot.params,
|
|
30898
|
+
search: searchParamsObj,
|
|
30899
|
+
path: pathname,
|
|
30900
|
+
})
|
|
30901
|
+
: undefined;
|
|
30902
|
+
const rawSlotProps = withFarmRouteContext(
|
|
30903
|
+
{
|
|
30904
|
+
params: slot.params,
|
|
30905
|
+
searchParams: Promise.resolve(searchParamsObj),
|
|
30906
|
+
path: pathname,
|
|
30907
|
+
...(middlewareData?.size ? { middleware: { data: middlewareData } } : {}),
|
|
30908
|
+
},
|
|
30909
|
+
slotContext,
|
|
30910
|
+
);
|
|
30911
|
+
if (slot.module.__farmResolveRouteProps && slotContext !== undefined) {
|
|
30912
|
+
Object.defineProperty(rawSlotProps, "context", {
|
|
30913
|
+
value: slotContext,
|
|
30914
|
+
enumerable: true,
|
|
30915
|
+
configurable: true,
|
|
30916
|
+
});
|
|
30917
|
+
}
|
|
30918
|
+
|
|
30919
|
+
const slotSchemas = slot.module.__farmRouteParsesProps
|
|
30920
|
+
? {}
|
|
30921
|
+
: slot.module.__farmRouteSchemas || {};
|
|
30922
|
+
let slotProps = slot.module.__farmResolveRouteProps
|
|
30923
|
+
? await slot.module.__farmResolveRouteProps(rawSlotProps)
|
|
30924
|
+
: {
|
|
30925
|
+
...rawSlotProps,
|
|
30926
|
+
params: slotSchemas.params?.parse
|
|
30927
|
+
? slotSchemas.params.parse(slot.params)
|
|
30928
|
+
: slot.params,
|
|
30929
|
+
search: slotSchemas.search?.parse
|
|
30930
|
+
? slotSchemas.search.parse(searchParamsObj)
|
|
30931
|
+
: searchParamsObj,
|
|
30932
|
+
searchParams: Promise.resolve(
|
|
30933
|
+
slotSchemas.search?.parse
|
|
30934
|
+
? slotSchemas.search.parse(searchParamsObj)
|
|
30935
|
+
: searchParamsObj,
|
|
30936
|
+
),
|
|
30937
|
+
};
|
|
30938
|
+
if (
|
|
30939
|
+
slot.module.__farmResolveRouteProps &&
|
|
30940
|
+
slotContext !== undefined &&
|
|
30941
|
+
slotProps.context === slotContext
|
|
30942
|
+
) {
|
|
30943
|
+
const { context: _slotContext, ...renderSlotProps } = slotProps;
|
|
30944
|
+
slotProps = renderSlotProps;
|
|
30945
|
+
}
|
|
30946
|
+
|
|
30947
|
+
return { ...slot, props: slotProps };
|
|
30948
|
+
}),
|
|
30949
|
+
);
|
|
30950
|
+
const routeSlotPayload = renderedRouteSlots.map(function(slot) {
|
|
30951
|
+
return {
|
|
30952
|
+
name: slot.name,
|
|
30953
|
+
ownerPattern: slot.ownerPattern,
|
|
30954
|
+
pattern: slot.pattern,
|
|
30955
|
+
containerId: slot.containerId,
|
|
30956
|
+
interception: slot.interception,
|
|
30957
|
+
fallback: slot.fallback,
|
|
30958
|
+
props: {
|
|
30959
|
+
params: slot.props.params,
|
|
30960
|
+
search: slot.props.search || searchParamsObj,
|
|
30961
|
+
searchParams: slot.props.search || searchParamsObj,
|
|
30962
|
+
...("data" in slot.props ? { data: slot.props.data } : {}),
|
|
30963
|
+
path: pathname,
|
|
30964
|
+
},
|
|
30965
|
+
};
|
|
30966
|
+
});
|
|
29535
30967
|
|
|
29536
30968
|
const renderPageElement = async () => {
|
|
29537
30969
|
// First, render the page content
|
|
@@ -29559,6 +30991,14 @@ async function handleFarmRequestInContext(
|
|
|
29559
30991
|
pageElement = React.createElement(PageComponent, pageProps);
|
|
29560
30992
|
}
|
|
29561
30993
|
|
|
30994
|
+
if (route.shouldHydrate && renderedRouteSlots.length > 0) {
|
|
30995
|
+
pageElement = React.createElement(
|
|
30996
|
+
"div",
|
|
30997
|
+
{ id: "__farm_page__", "data-farm-client": "true" },
|
|
30998
|
+
pageElement,
|
|
30999
|
+
);
|
|
31000
|
+
}
|
|
31001
|
+
|
|
29562
31002
|
// Wrap with layouts (from innermost to outermost)
|
|
29563
31003
|
// Layouts are sorted by depth (root first), so we process in reverse
|
|
29564
31004
|
let wrappedElement = pageElement;
|
|
@@ -29566,9 +31006,23 @@ async function handleFarmRequestInContext(
|
|
|
29566
31006
|
const layout = applicableLayouts[i];
|
|
29567
31007
|
const LayoutComponent = layout.module.default;
|
|
29568
31008
|
if (LayoutComponent) {
|
|
31009
|
+
const slotProps = {};
|
|
31010
|
+
for (const slot of renderedRouteSlots) {
|
|
31011
|
+
if (slot.ownerPattern !== layout.pattern) continue;
|
|
31012
|
+
slotProps[slot.name] = React.createElement(
|
|
31013
|
+
"div",
|
|
31014
|
+
{
|
|
31015
|
+
id: slot.containerId,
|
|
31016
|
+
"data-farm-route-slot": slot.name,
|
|
31017
|
+
"data-farm-slot-owner": slot.ownerPattern,
|
|
31018
|
+
},
|
|
31019
|
+
React.createElement(slot.module.default, slot.props),
|
|
31020
|
+
);
|
|
31021
|
+
}
|
|
29569
31022
|
wrappedElement = React.createElement(LayoutComponent, {
|
|
29570
31023
|
children: wrappedElement,
|
|
29571
31024
|
params,
|
|
31025
|
+
...slotProps,
|
|
29572
31026
|
});
|
|
29573
31027
|
}
|
|
29574
31028
|
}
|
|
@@ -29620,6 +31074,7 @@ async function handleFarmRequestInContext(
|
|
|
29620
31074
|
);
|
|
29621
31075
|
const hasRequestScopedRender = Boolean(
|
|
29622
31076
|
pageStatus >= 400 ||
|
|
31077
|
+
request.headers.get("x-farm-intercept-from") ||
|
|
29623
31078
|
hasPrivateRequestHeaders ||
|
|
29624
31079
|
hasConfiguredRouteContext ||
|
|
29625
31080
|
middlewareData?.size ||
|
|
@@ -29659,7 +31114,10 @@ async function handleFarmRequestInContext(
|
|
|
29659
31114
|
' <link rel="modulepreload" href="/farm-client.js">\\n' +
|
|
29660
31115
|
'</head>\\n<body>\\n <div id="root">';
|
|
29661
31116
|
const streamSuffix = '</div>\\n' +
|
|
29662
|
-
' ' + renderFarmClientBootstrapScript(
|
|
31117
|
+
' ' + renderFarmClientBootstrapScript(
|
|
31118
|
+
pageProps.__farmCanonicalPath,
|
|
31119
|
+
routeSlotPayload
|
|
31120
|
+
) + '\\n' +
|
|
29663
31121
|
' <script type="module" src="/farm-client.js"></script>\\n' +
|
|
29664
31122
|
'</body>\\n</html>';
|
|
29665
31123
|
const streamedDocument = createFarmDocumentStream(
|
|
@@ -29716,7 +31174,10 @@ async function handleFarmRequestInContext(
|
|
|
29716
31174
|
// Inject client script before closing body tag
|
|
29717
31175
|
.replace(
|
|
29718
31176
|
/<\\/body>/i,
|
|
29719
|
-
' ' + renderFarmClientBootstrapScript(
|
|
31177
|
+
' ' + renderFarmClientBootstrapScript(
|
|
31178
|
+
pageProps.__farmCanonicalPath,
|
|
31179
|
+
routeSlotPayload
|
|
31180
|
+
) + '\\n' +
|
|
29720
31181
|
' <script type="module" src="/farm-client.js"></script>\\n</body>',
|
|
29721
31182
|
);
|
|
29722
31183
|
|
|
@@ -29737,7 +31198,7 @@ async function handleFarmRequestInContext(
|
|
|
29737
31198
|
</head>
|
|
29738
31199
|
<body>
|
|
29739
31200
|
<div id="root">\${html}</div>
|
|
29740
|
-
\${renderFarmClientBootstrapScript(pageProps.__farmCanonicalPath)}
|
|
31201
|
+
\${renderFarmClientBootstrapScript(pageProps.__farmCanonicalPath, routeSlotPayload)}
|
|
29741
31202
|
<script type="module" src="/farm-client.js"></script>
|
|
29742
31203
|
</body>
|
|
29743
31204
|
</html>\`;
|
|
@@ -29745,7 +31206,7 @@ async function handleFarmRequestInContext(
|
|
|
29745
31206
|
fullHtml = applyFarmI18nDocument(fullHtml, pathname, farmI18nSnapshot);
|
|
29746
31207
|
|
|
29747
31208
|
if (pageStatus === 200 && pprCacheKey && request.method.toUpperCase() !== "HEAD") {
|
|
29748
|
-
pprShellCache.
|
|
31209
|
+
await pprShellCache.setAsync(
|
|
29749
31210
|
pprCacheKey,
|
|
29750
31211
|
{ html: fullHtml },
|
|
29751
31212
|
{
|
|
@@ -30362,9 +31823,8 @@ async function buildNitroUniversal(config, routeManager, apiRouteManager, server
|
|
|
30362
31823
|
const nitroEntryPath = import_path12.default.join(ssrOutputDir, "nitro-entry.mjs");
|
|
30363
31824
|
const nitroEntryCode = `
|
|
30364
31825
|
// Farm.js Nitro Entry
|
|
30365
|
-
// This file
|
|
31826
|
+
// This file adapts Farm's Web fetch handler to Nitro's event handler contract.
|
|
30366
31827
|
|
|
30367
|
-
import { defineEventHandler } from 'h3'
|
|
30368
31828
|
import handler from './${ssrEntryFile}'
|
|
30369
31829
|
|
|
30370
31830
|
function mergeVaryHeaders(target, source) {
|
|
@@ -30402,8 +31862,8 @@ function createResponseFinishedHook(event) {
|
|
|
30402
31862
|
}
|
|
30403
31863
|
}
|
|
30404
31864
|
|
|
30405
|
-
// Export the
|
|
30406
|
-
export default
|
|
31865
|
+
// Export the event handler for Nitro
|
|
31866
|
+
export default async function farmNitroEventHandler(event) {
|
|
30407
31867
|
const response = await handler.fetch(event.req, {
|
|
30408
31868
|
waitUntil: (promise) => event.waitUntil(promise),
|
|
30409
31869
|
onResponseFinished: createResponseFinishedHook(event),
|
|
@@ -30414,7 +31874,7 @@ export default defineEventHandler(async (event) => {
|
|
|
30414
31874
|
const farmVary = response.headers.get('Vary')
|
|
30415
31875
|
if (farmVary) mergeVaryHeaders(event.res.headers, farmVary)
|
|
30416
31876
|
return response
|
|
30417
|
-
}
|
|
31877
|
+
}
|
|
30418
31878
|
`.trim();
|
|
30419
31879
|
await fs8.writeFile(nitroEntryPath, nitroEntryCode);
|
|
30420
31880
|
const prebuiltSSRPlugin = createExternalSSRBundlePlugin(
|
|
@@ -30832,8 +32292,8 @@ async function copySharpRuntime(config, root, nitroFuncDir, fs8) {
|
|
|
30832
32292
|
await fs8.mkdir(import_path12.default.dirname(targetDir), { recursive: true });
|
|
30833
32293
|
const packageRequire = (0, import_module2.createRequire)(packageJsonPath);
|
|
30834
32294
|
const dependencies = {
|
|
30835
|
-
...packageJson.dependencies
|
|
30836
|
-
...packageJson.optionalDependencies
|
|
32295
|
+
...packageJson.dependencies,
|
|
32296
|
+
...packageJson.optionalDependencies
|
|
30837
32297
|
};
|
|
30838
32298
|
await Promise.all([
|
|
30839
32299
|
fs8.cp(packageDir, targetDir, {
|
|
@@ -30926,7 +32386,7 @@ init_environment_vite();
|
|
|
30926
32386
|
// src/server/vite-config.ts
|
|
30927
32387
|
function mergeNoExternal(farmValue, userValue) {
|
|
30928
32388
|
if (farmValue === true || userValue === true) return true;
|
|
30929
|
-
const normalize = /* @__PURE__ */ __name((value) => value == null ? [] : Array.isArray(value) ? value : [value], "normalize");
|
|
32389
|
+
const normalize = /* @__PURE__ */ __name((value) => value == null || value === true ? [] : Array.isArray(value) ? value : [value], "normalize");
|
|
30930
32390
|
return Array.from(/* @__PURE__ */ new Set([...normalize(farmValue), ...normalize(userValue)]));
|
|
30931
32391
|
}
|
|
30932
32392
|
__name(mergeNoExternal, "mergeNoExternal");
|
|
@@ -30939,6 +32399,13 @@ function mergeFarmViteConfig(farmConfig, userConfig = {}) {
|
|
|
30939
32399
|
...farmConfig.server,
|
|
30940
32400
|
...userConfig.server
|
|
30941
32401
|
},
|
|
32402
|
+
resolve: {
|
|
32403
|
+
...farmConfig.resolve,
|
|
32404
|
+
...userConfig.resolve,
|
|
32405
|
+
dedupe: Array.from(
|
|
32406
|
+
/* @__PURE__ */ new Set([...farmConfig.resolve?.dedupe || [], ...userConfig.resolve?.dedupe || []])
|
|
32407
|
+
)
|
|
32408
|
+
},
|
|
30942
32409
|
optimizeDeps: {
|
|
30943
32410
|
...farmConfig.optimizeDeps,
|
|
30944
32411
|
...userConfig.optimizeDeps,
|