@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
package/dist/server.cjs
CHANGED
|
@@ -118,7 +118,7 @@ function createFarmMarkdownRouteModule(input) {
|
|
|
118
118
|
...props,
|
|
119
119
|
components: {
|
|
120
120
|
...components,
|
|
121
|
-
...props?.components
|
|
121
|
+
...props?.components
|
|
122
122
|
}
|
|
123
123
|
})
|
|
124
124
|
);
|
|
@@ -635,7 +635,11 @@ async function prepareFarmWorkflowsForNitro(config) {
|
|
|
635
635
|
};
|
|
636
636
|
}
|
|
637
637
|
const handlerPath = path23.join(generatedDir, "http-handler.mjs");
|
|
638
|
-
await fs9.writeFile(
|
|
638
|
+
await fs9.writeFile(
|
|
639
|
+
handlerPath,
|
|
640
|
+
createNitroWorkflowHTTPHandler(workflowConfig, workflows),
|
|
641
|
+
"utf8"
|
|
642
|
+
);
|
|
639
643
|
const manifestPath = path23.join(generatedDir, "manifest.json");
|
|
640
644
|
await fs9.writeFile(
|
|
641
645
|
manifestPath,
|
|
@@ -709,13 +713,7 @@ function normalizeSchedule(schedule) {
|
|
|
709
713
|
return (Array.isArray(schedule) ? schedule : [schedule]).map((value) => value.trim()).filter(Boolean);
|
|
710
714
|
}
|
|
711
715
|
function resolveWorkflowDefinition(module2) {
|
|
712
|
-
const candidates = [
|
|
713
|
-
module2.default,
|
|
714
|
-
module2.workflow,
|
|
715
|
-
module2.cron,
|
|
716
|
-
module2.task,
|
|
717
|
-
module2.job
|
|
718
|
-
];
|
|
716
|
+
const candidates = [module2.default, module2.workflow, module2.cron, module2.task, module2.job];
|
|
719
717
|
for (const candidate of candidates) {
|
|
720
718
|
if (candidate && typeof candidate === "object" && typeof candidate.run === "function") {
|
|
721
719
|
return candidate;
|
|
@@ -1708,8 +1706,8 @@ function compareFarmRouteRuleSpecificity(left, right) {
|
|
|
1708
1706
|
}
|
|
1709
1707
|
function getFarmRouteRuleSpecificity(pattern) {
|
|
1710
1708
|
return normalizeRoutePattern(pattern).split("/").filter(Boolean).reduce((score, segment) => {
|
|
1711
|
-
if (segment === "**" ||
|
|
1712
|
-
if (segment === "*" ||
|
|
1709
|
+
if (segment === "**" || segment.startsWith("[[...")) return score + 1;
|
|
1710
|
+
if (segment === "*" || segment.startsWith("[...")) return score + 10;
|
|
1713
1711
|
if (/^\[.+\]$/.test(segment) || /^:.+$/.test(segment)) return score + 50;
|
|
1714
1712
|
return score + 100;
|
|
1715
1713
|
}, 0);
|
|
@@ -1770,7 +1768,7 @@ function routeRulesToHeaders(routeRules) {
|
|
|
1770
1768
|
for (const [source, rule] of Object.entries(routeRules)) {
|
|
1771
1769
|
const headers = {
|
|
1772
1770
|
...normalizeCorsHeaders(rule.cors),
|
|
1773
|
-
...rule.headers
|
|
1771
|
+
...rule.headers
|
|
1774
1772
|
};
|
|
1775
1773
|
const entries = Object.entries(headers);
|
|
1776
1774
|
if (entries.length === 0) continue;
|
|
@@ -1821,7 +1819,8 @@ var init_route_rules = __esm({
|
|
|
1821
1819
|
// src/cache-invalidation.ts
|
|
1822
1820
|
function getFarmCacheInvalidationState() {
|
|
1823
1821
|
return globalState[FARM_CACHE_INVALIDATION_STATE] ?? (globalState[FARM_CACHE_INVALIDATION_STATE] = {
|
|
1824
|
-
listeners: /* @__PURE__ */ new Set()
|
|
1822
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
1823
|
+
taskListeners: /* @__PURE__ */ new Set()
|
|
1825
1824
|
});
|
|
1826
1825
|
}
|
|
1827
1826
|
function notifyFarmCacheInvalidation(key) {
|
|
@@ -1830,6 +1829,11 @@ function notifyFarmCacheInvalidation(key) {
|
|
|
1830
1829
|
listener(key);
|
|
1831
1830
|
}
|
|
1832
1831
|
}
|
|
1832
|
+
function notifyFarmCacheTask(task) {
|
|
1833
|
+
for (const listener of getFarmCacheInvalidationState().taskListeners) {
|
|
1834
|
+
listener(task);
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1833
1837
|
function applyFarmCacheInvalidations(keys) {
|
|
1834
1838
|
if (!Array.isArray(keys)) return;
|
|
1835
1839
|
for (const key of keys) {
|
|
@@ -1838,21 +1842,49 @@ function applyFarmCacheInvalidations(keys) {
|
|
|
1838
1842
|
}
|
|
1839
1843
|
}
|
|
1840
1844
|
}
|
|
1845
|
+
function encodeFarmCacheInvalidations(keys) {
|
|
1846
|
+
const normalized = Array.from(
|
|
1847
|
+
new Set(keys.filter((key) => typeof key === "string" && key.length > 0))
|
|
1848
|
+
);
|
|
1849
|
+
if (normalized.length === 0) return null;
|
|
1850
|
+
return encodeURIComponent(JSON.stringify(normalized));
|
|
1851
|
+
}
|
|
1852
|
+
function decodeFarmCacheInvalidations(value) {
|
|
1853
|
+
if (!value) return [];
|
|
1854
|
+
try {
|
|
1855
|
+
const parsed = JSON.parse(decodeURIComponent(value));
|
|
1856
|
+
return Array.isArray(parsed) ? Array.from(
|
|
1857
|
+
new Set(parsed.filter((key) => typeof key === "string" && key.length > 0))
|
|
1858
|
+
) : [];
|
|
1859
|
+
} catch {
|
|
1860
|
+
return [];
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1841
1863
|
function subscribeFarmCacheInvalidation(listener) {
|
|
1842
1864
|
const state = getFarmCacheInvalidationState();
|
|
1843
1865
|
state.listeners.add(listener);
|
|
1844
1866
|
return () => state.listeners.delete(listener);
|
|
1845
1867
|
}
|
|
1846
|
-
|
|
1868
|
+
function subscribeFarmCacheTask(listener) {
|
|
1869
|
+
const state = getFarmCacheInvalidationState();
|
|
1870
|
+
state.taskListeners.add(listener);
|
|
1871
|
+
return () => state.taskListeners.delete(listener);
|
|
1872
|
+
}
|
|
1873
|
+
var FARM_CACHE_INVALIDATION_HEADER, FARM_CACHE_INVALIDATION_STATE, globalState;
|
|
1847
1874
|
var init_cache_invalidation = __esm({
|
|
1848
1875
|
"src/cache-invalidation.ts"() {
|
|
1849
1876
|
"use strict";
|
|
1877
|
+
FARM_CACHE_INVALIDATION_HEADER = "x-farm-cache-invalidations";
|
|
1850
1878
|
FARM_CACHE_INVALIDATION_STATE = /* @__PURE__ */ Symbol.for("farm.cacheInvalidationState");
|
|
1851
1879
|
globalState = globalThis;
|
|
1852
1880
|
__name(getFarmCacheInvalidationState, "getFarmCacheInvalidationState");
|
|
1853
1881
|
__name(notifyFarmCacheInvalidation, "notifyFarmCacheInvalidation");
|
|
1882
|
+
__name(notifyFarmCacheTask, "notifyFarmCacheTask");
|
|
1854
1883
|
__name(applyFarmCacheInvalidations, "applyFarmCacheInvalidations");
|
|
1884
|
+
__name(encodeFarmCacheInvalidations, "encodeFarmCacheInvalidations");
|
|
1885
|
+
__name(decodeFarmCacheInvalidations, "decodeFarmCacheInvalidations");
|
|
1855
1886
|
__name(subscribeFarmCacheInvalidation, "subscribeFarmCacheInvalidation");
|
|
1887
|
+
__name(subscribeFarmCacheTask, "subscribeFarmCacheTask");
|
|
1856
1888
|
}
|
|
1857
1889
|
});
|
|
1858
1890
|
|
|
@@ -1948,16 +1980,24 @@ function sanitizeServerActionError(_error) {
|
|
|
1948
1980
|
message: "Server function failed"
|
|
1949
1981
|
};
|
|
1950
1982
|
}
|
|
1951
|
-
function runWithServerActionRequest(request, callback) {
|
|
1983
|
+
async function runWithServerActionRequest(request, callback) {
|
|
1952
1984
|
throwIfAborted(request.signal);
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1985
|
+
const context = {
|
|
1986
|
+
request,
|
|
1987
|
+
signal: request.signal,
|
|
1988
|
+
invalidations: /* @__PURE__ */ new Set(),
|
|
1989
|
+
cacheTasks: /* @__PURE__ */ new Set()
|
|
1990
|
+
};
|
|
1991
|
+
return getServerActionStorage().run(context, async () => {
|
|
1992
|
+
try {
|
|
1993
|
+
const result = await callback();
|
|
1994
|
+
await Promise.all(context.cacheTasks);
|
|
1995
|
+
return result;
|
|
1996
|
+
} catch (error) {
|
|
1997
|
+
await Promise.allSettled(context.cacheTasks);
|
|
1998
|
+
throw error;
|
|
1999
|
+
}
|
|
2000
|
+
});
|
|
1961
2001
|
}
|
|
1962
2002
|
function getServerActionExecutionContext() {
|
|
1963
2003
|
return getServerActionStorage().getStore();
|
|
@@ -2268,6 +2308,9 @@ var init_server_action_security = __esm({
|
|
|
2268
2308
|
subscribeFarmCacheInvalidation((key) => {
|
|
2269
2309
|
getServerActionExecutionContext()?.invalidations.add(key);
|
|
2270
2310
|
});
|
|
2311
|
+
subscribeFarmCacheTask((task) => {
|
|
2312
|
+
getServerActionExecutionContext()?.cacheTasks.add(task);
|
|
2313
|
+
});
|
|
2271
2314
|
__name(getServerActionStorage, "getServerActionStorage");
|
|
2272
2315
|
__name(getFallbackAbortController, "getFallbackAbortController");
|
|
2273
2316
|
__name(parseBodySizeLimit, "parseBodySizeLimit");
|
|
@@ -5898,7 +5941,9 @@ function readManifest(contentDir) {
|
|
|
5898
5941
|
const manifestPath = import_node_path7.default.join(contentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
|
|
5899
5942
|
if (!(0, import_node_fs5.existsSync)(manifestPath)) return null;
|
|
5900
5943
|
try {
|
|
5901
|
-
const parsed = JSON.parse(
|
|
5944
|
+
const parsed = JSON.parse(
|
|
5945
|
+
(0, import_node_fs5.readFileSync)(manifestPath, "utf8")
|
|
5946
|
+
);
|
|
5902
5947
|
if (parsed.version !== 1 || !parsed.pages || typeof parsed.pages !== "object") return null;
|
|
5903
5948
|
const pages = Object.fromEntries(
|
|
5904
5949
|
Object.entries(parsed.pages).filter(
|
|
@@ -9446,6 +9491,7 @@ async function resolveConfig(userConfig, mode) {
|
|
|
9446
9491
|
observability: userConfig.observability ?? false,
|
|
9447
9492
|
devtools: resolveFarmDevtoolsConfig(userConfig.devtools, mode),
|
|
9448
9493
|
storage: userConfig.storage || {},
|
|
9494
|
+
cache: userConfig.cache || {},
|
|
9449
9495
|
suppressLintOnLink: userConfig.suppressLintOnLink ?? false,
|
|
9450
9496
|
experimental: {
|
|
9451
9497
|
serverComponents: false,
|
|
@@ -12417,16 +12463,7 @@ __export(devtools_client_exports, {
|
|
|
12417
12463
|
function parseShortcut(shortcut) {
|
|
12418
12464
|
const tokens = shortcut.toLowerCase().split("+").map((token) => token.trim()).filter(Boolean);
|
|
12419
12465
|
const key = tokens.find(
|
|
12420
|
-
(token) => ![
|
|
12421
|
-
"alt",
|
|
12422
|
-
"ctrl",
|
|
12423
|
-
"control",
|
|
12424
|
-
"meta",
|
|
12425
|
-
"cmd",
|
|
12426
|
-
"command",
|
|
12427
|
-
"mod",
|
|
12428
|
-
"shift"
|
|
12429
|
-
].includes(token)
|
|
12466
|
+
(token) => !["alt", "ctrl", "control", "meta", "cmd", "command", "mod", "shift"].includes(token)
|
|
12430
12467
|
);
|
|
12431
12468
|
if (!key) {
|
|
12432
12469
|
return null;
|
|
@@ -12709,6 +12746,7 @@ var init_image_sharp = __esm({
|
|
|
12709
12746
|
// src/server.ts
|
|
12710
12747
|
var server_exports = {};
|
|
12711
12748
|
__export(server_exports, {
|
|
12749
|
+
DEFAULT_FARM_DEV_SERVER_PORT: () => DEFAULT_FARM_DEV_SERVER_PORT,
|
|
12712
12750
|
DEFAULT_SERVER_ACTION_BODY_SIZE_LIMIT: () => DEFAULT_SERVER_ACTION_BODY_SIZE_LIMIT,
|
|
12713
12751
|
FARM_SERVER_QUERY_SYMBOL: () => FARM_SERVER_QUERY_SYMBOL,
|
|
12714
12752
|
FarmApp: () => FarmApp,
|
|
@@ -12721,7 +12759,9 @@ __export(server_exports, {
|
|
|
12721
12759
|
_runWithAfterRequest: () => _runWithAfterRequest,
|
|
12722
12760
|
_withAfterNodeMiddleware: () => _withAfterNodeMiddleware,
|
|
12723
12761
|
after: () => after,
|
|
12762
|
+
applyFarmCacheInvalidationTargets: () => applyFarmCacheInvalidationTargets,
|
|
12724
12763
|
applyFarmCacheInvalidations: () => applyFarmCacheInvalidations,
|
|
12764
|
+
configureFarmCache: () => configureFarmCache,
|
|
12725
12765
|
createClientOnlyFn: () => createClientOnlyFn,
|
|
12726
12766
|
createFarmApp: () => createFarmApp,
|
|
12727
12767
|
createFarmCacheKey: () => createFarmCacheKey,
|
|
@@ -12736,6 +12776,7 @@ __export(server_exports, {
|
|
|
12736
12776
|
createServerQuery: () => createServerQuery,
|
|
12737
12777
|
createStorageClient: () => createStorageClient,
|
|
12738
12778
|
databaseStorage: () => databaseStorage,
|
|
12779
|
+
defineCacheKey: () => defineCacheKey,
|
|
12739
12780
|
defineConfig: () => defineConfig2,
|
|
12740
12781
|
defineStorageClient: () => defineStorageClient,
|
|
12741
12782
|
disposeStorage: () => disposeStorage,
|
|
@@ -12786,6 +12827,7 @@ __export(server_exports, {
|
|
|
12786
12827
|
segmentsToPattern: () => segmentsToPattern,
|
|
12787
12828
|
sqliteStorage: () => sqliteStorage,
|
|
12788
12829
|
startDevServer: () => startDevServer,
|
|
12830
|
+
storageCacheAdapter: () => storageCacheAdapter,
|
|
12789
12831
|
toViteModuleId: () => toViteModuleId,
|
|
12790
12832
|
unstable_cache: () => unstable_cache,
|
|
12791
12833
|
updateTag: () => updateTag,
|
|
@@ -13472,12 +13514,109 @@ __name(getActiveFarmI18nSnapshot, "getActiveFarmI18nSnapshot");
|
|
|
13472
13514
|
|
|
13473
13515
|
// src/cache.ts
|
|
13474
13516
|
init_cache_invalidation();
|
|
13517
|
+
function defineCacheKey() {
|
|
13518
|
+
return (factory) => {
|
|
13519
|
+
if (typeof factory !== "function") {
|
|
13520
|
+
throw new TypeError("defineCacheKey expects a key factory function.");
|
|
13521
|
+
}
|
|
13522
|
+
return ((...args) => {
|
|
13523
|
+
const key = factory(...args);
|
|
13524
|
+
if (typeof key !== "string" && !Array.isArray(key)) {
|
|
13525
|
+
throw new TypeError(
|
|
13526
|
+
"A defined cache key factory must return a string or structured array."
|
|
13527
|
+
);
|
|
13528
|
+
}
|
|
13529
|
+
return key;
|
|
13530
|
+
});
|
|
13531
|
+
};
|
|
13532
|
+
}
|
|
13533
|
+
__name(defineCacheKey, "defineCacheKey");
|
|
13534
|
+
function storageCacheAdapter(storage, options = {}) {
|
|
13535
|
+
if (!storage || typeof storage.getItem !== "function" || typeof storage.setItem !== "function") {
|
|
13536
|
+
throw new TypeError("storageCacheAdapter expects a compatible storage client.");
|
|
13537
|
+
}
|
|
13538
|
+
const base = normalizeCacheNamespace(options.base || "farm-cache");
|
|
13539
|
+
const entryKey = /* @__PURE__ */ __name((key) => `${base}:entry:${key}`, "entryKey");
|
|
13540
|
+
const tagKey = /* @__PURE__ */ __name((tag) => `${base}:tag:${tag}`, "tagKey");
|
|
13541
|
+
return {
|
|
13542
|
+
name: "storage",
|
|
13543
|
+
get: /* @__PURE__ */ __name((key) => storage.getItem(entryKey(key)), "get"),
|
|
13544
|
+
set: /* @__PURE__ */ __name(async (key, entry) => {
|
|
13545
|
+
await storage.setItem(entryKey(key), entry);
|
|
13546
|
+
}, "set"),
|
|
13547
|
+
delete: /* @__PURE__ */ __name(async (key) => {
|
|
13548
|
+
await storage.removeItem(entryKey(key));
|
|
13549
|
+
}, "delete"),
|
|
13550
|
+
clear: storage.clear ? async () => {
|
|
13551
|
+
await storage.clear(base);
|
|
13552
|
+
} : void 0,
|
|
13553
|
+
getTagVersions: /* @__PURE__ */ __name(async (tags) => {
|
|
13554
|
+
const versions = await Promise.all(
|
|
13555
|
+
tags.map(async (tag) => {
|
|
13556
|
+
const value = await storage.getItem(tagKey(tag));
|
|
13557
|
+
return [tag, normalizeAdapterVersion(value)];
|
|
13558
|
+
})
|
|
13559
|
+
);
|
|
13560
|
+
return Object.fromEntries(versions);
|
|
13561
|
+
}, "getTagVersions"),
|
|
13562
|
+
invalidateTags: /* @__PURE__ */ __name(async (tags) => {
|
|
13563
|
+
await Promise.all(
|
|
13564
|
+
tags.map(async (tag) => {
|
|
13565
|
+
const key = tagKey(tag);
|
|
13566
|
+
const current = normalizeAdapterVersion(await storage.getItem(key));
|
|
13567
|
+
await storage.setItem(key, Math.max(Date.now(), current + 1));
|
|
13568
|
+
})
|
|
13569
|
+
);
|
|
13570
|
+
}, "invalidateTags")
|
|
13571
|
+
};
|
|
13572
|
+
}
|
|
13573
|
+
__name(storageCacheAdapter, "storageCacheAdapter");
|
|
13475
13574
|
var _FarmDataCache = class _FarmDataCache {
|
|
13476
|
-
constructor() {
|
|
13575
|
+
constructor(config = {}) {
|
|
13477
13576
|
this.entries = /* @__PURE__ */ new Map();
|
|
13478
13577
|
this.inflight = /* @__PURE__ */ new Map();
|
|
13479
13578
|
this.invalidatedTagVersions = /* @__PURE__ */ new Map();
|
|
13480
13579
|
this.version = 0;
|
|
13580
|
+
this.namespace = "farm";
|
|
13581
|
+
this.local = true;
|
|
13582
|
+
this.lease = {
|
|
13583
|
+
enabled: true,
|
|
13584
|
+
ttlMs: 1e4,
|
|
13585
|
+
waitTimeoutMs: 1e4,
|
|
13586
|
+
pollIntervalMs: 25
|
|
13587
|
+
};
|
|
13588
|
+
this.configure(config);
|
|
13589
|
+
}
|
|
13590
|
+
configure(config = {}) {
|
|
13591
|
+
this.adapter = config.adapter;
|
|
13592
|
+
this.namespace = normalizeCacheNamespace(config.namespace || "farm");
|
|
13593
|
+
this.local = !config.adapter;
|
|
13594
|
+
this.lease = config.lease === false ? { ...this.lease, enabled: false } : {
|
|
13595
|
+
enabled: true,
|
|
13596
|
+
ttlMs: normalizePositiveDuration(config.lease?.ttlMs, 1e4, "cache.lease.ttlMs"),
|
|
13597
|
+
waitTimeoutMs: normalizePositiveDuration(
|
|
13598
|
+
config.lease?.waitTimeoutMs,
|
|
13599
|
+
1e4,
|
|
13600
|
+
"cache.lease.waitTimeoutMs"
|
|
13601
|
+
),
|
|
13602
|
+
pollIntervalMs: normalizePositiveDuration(
|
|
13603
|
+
config.lease?.pollIntervalMs,
|
|
13604
|
+
25,
|
|
13605
|
+
"cache.lease.pollIntervalMs"
|
|
13606
|
+
)
|
|
13607
|
+
};
|
|
13608
|
+
if (!this.local) {
|
|
13609
|
+
this.entries.clear();
|
|
13610
|
+
this.inflight.clear();
|
|
13611
|
+
this.invalidatedTagVersions.clear();
|
|
13612
|
+
this.version = 0;
|
|
13613
|
+
}
|
|
13614
|
+
}
|
|
13615
|
+
get adapterName() {
|
|
13616
|
+
return this.adapter?.name || (this.adapter ? "custom" : "memory");
|
|
13617
|
+
}
|
|
13618
|
+
get hasAdapter() {
|
|
13619
|
+
return this.adapter !== void 0;
|
|
13481
13620
|
}
|
|
13482
13621
|
get size() {
|
|
13483
13622
|
return this.entries.size;
|
|
@@ -13513,6 +13652,45 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
13513
13652
|
});
|
|
13514
13653
|
return this.toPublicEntry(entry);
|
|
13515
13654
|
}
|
|
13655
|
+
async getEntryAsync(key, options = {}) {
|
|
13656
|
+
if (this.local) {
|
|
13657
|
+
const localEntry = this.getEntry(key, options);
|
|
13658
|
+
if (localEntry) return localEntry;
|
|
13659
|
+
}
|
|
13660
|
+
if (!this.adapter) {
|
|
13661
|
+
return this.local ? void 0 : this.getEntry(key, options);
|
|
13662
|
+
}
|
|
13663
|
+
const entry = await this.adapter.get(this.createAdapterKey(key));
|
|
13664
|
+
if (!entry) {
|
|
13665
|
+
emitFarmEvent({ type: "cache.miss", key });
|
|
13666
|
+
return void 0;
|
|
13667
|
+
}
|
|
13668
|
+
assertFarmCacheEntry(entry, key);
|
|
13669
|
+
const stale = await this.isAdapterEntryStale(entry, options.now);
|
|
13670
|
+
if (stale) {
|
|
13671
|
+
emitFarmEvent({
|
|
13672
|
+
type: "cache.stale",
|
|
13673
|
+
key,
|
|
13674
|
+
tags: [...entry.tags],
|
|
13675
|
+
revalidate: entry.revalidate
|
|
13676
|
+
});
|
|
13677
|
+
if (!options.allowStale) {
|
|
13678
|
+
emitFarmEvent({ type: "cache.miss", key, reason: "stale" });
|
|
13679
|
+
return void 0;
|
|
13680
|
+
}
|
|
13681
|
+
}
|
|
13682
|
+
emitFarmEvent({
|
|
13683
|
+
type: "cache.hit",
|
|
13684
|
+
key,
|
|
13685
|
+
tags: [...entry.tags],
|
|
13686
|
+
revalidate: entry.revalidate,
|
|
13687
|
+
stale
|
|
13688
|
+
});
|
|
13689
|
+
if (this.local && !stale) {
|
|
13690
|
+
this.hydrateLocalEntry(entry);
|
|
13691
|
+
}
|
|
13692
|
+
return { ...entry, key };
|
|
13693
|
+
}
|
|
13516
13694
|
set(key, value, options = {}) {
|
|
13517
13695
|
const tags = /* @__PURE__ */ new Set();
|
|
13518
13696
|
for (const tag of options.tags ?? []) {
|
|
@@ -13525,6 +13703,7 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
13525
13703
|
key,
|
|
13526
13704
|
value,
|
|
13527
13705
|
tags,
|
|
13706
|
+
tagVersions: void 0,
|
|
13528
13707
|
createdAt: options.createdAt ?? Date.now(),
|
|
13529
13708
|
createdVersion: ++this.version,
|
|
13530
13709
|
revalidate: normalizeRevalidate(options.revalidate)
|
|
@@ -13538,11 +13717,45 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
13538
13717
|
});
|
|
13539
13718
|
return this.toPublicEntry(entry);
|
|
13540
13719
|
}
|
|
13720
|
+
async setAsync(key, value, options = {}, tagVersions) {
|
|
13721
|
+
const tags = normalizeCacheOptionsTags(options);
|
|
13722
|
+
const capturedVersions = tagVersions ?? await this.getAdapterTagVersions(Array.from(tags.values()));
|
|
13723
|
+
const entry = {
|
|
13724
|
+
key,
|
|
13725
|
+
value,
|
|
13726
|
+
tags: Array.from(tags),
|
|
13727
|
+
tagVersions: capturedVersions,
|
|
13728
|
+
createdAt: options.createdAt ?? Date.now(),
|
|
13729
|
+
createdVersion: ++this.version,
|
|
13730
|
+
revalidate: normalizeRevalidate(options.revalidate)
|
|
13731
|
+
};
|
|
13732
|
+
if (this.local) {
|
|
13733
|
+
this.hydrateLocalEntry(entry);
|
|
13734
|
+
}
|
|
13735
|
+
if (this.adapter) {
|
|
13736
|
+
await this.adapter.set(this.createAdapterKey(key), entry);
|
|
13737
|
+
}
|
|
13738
|
+
emitFarmEvent({
|
|
13739
|
+
type: "cache.set",
|
|
13740
|
+
key,
|
|
13741
|
+
tags: [...entry.tags],
|
|
13742
|
+
revalidate: entry.revalidate
|
|
13743
|
+
});
|
|
13744
|
+
return entry;
|
|
13745
|
+
}
|
|
13541
13746
|
delete(key) {
|
|
13542
13747
|
const deleted = this.entries.delete(key);
|
|
13543
13748
|
emitFarmEvent({ type: "cache.delete", key, deleted });
|
|
13544
13749
|
return deleted;
|
|
13545
13750
|
}
|
|
13751
|
+
async deleteAsync(key) {
|
|
13752
|
+
const deleted = this.entries.delete(key);
|
|
13753
|
+
if (this.adapter) {
|
|
13754
|
+
await this.adapter.delete(this.createAdapterKey(key));
|
|
13755
|
+
}
|
|
13756
|
+
emitFarmEvent({ type: "cache.delete", key, deleted: this.adapter ? true : deleted });
|
|
13757
|
+
return this.adapter ? true : deleted;
|
|
13758
|
+
}
|
|
13546
13759
|
clear() {
|
|
13547
13760
|
const count = this.entries.size;
|
|
13548
13761
|
this.entries.clear();
|
|
@@ -13551,6 +13764,10 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
13551
13764
|
this.version = 0;
|
|
13552
13765
|
emitFarmEvent({ type: "cache.clear", count });
|
|
13553
13766
|
}
|
|
13767
|
+
async clearAsync() {
|
|
13768
|
+
this.clear();
|
|
13769
|
+
await this.adapter?.clear?.();
|
|
13770
|
+
}
|
|
13554
13771
|
isStale(entry, now = Date.now()) {
|
|
13555
13772
|
if (typeof entry.revalidate === "number" && entry.revalidate > 0 && now - entry.createdAt >= entry.revalidate * 1e3) {
|
|
13556
13773
|
return true;
|
|
@@ -13563,6 +13780,12 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
13563
13780
|
}
|
|
13564
13781
|
return false;
|
|
13565
13782
|
}
|
|
13783
|
+
async isStaleAsync(entry, now = Date.now()) {
|
|
13784
|
+
if (this.adapter) {
|
|
13785
|
+
return this.isAdapterEntryStale(entry, now);
|
|
13786
|
+
}
|
|
13787
|
+
return this.isStale(entry, now);
|
|
13788
|
+
}
|
|
13566
13789
|
revalidateTag(tag, options = {}) {
|
|
13567
13790
|
const normalized = normalizeCacheTag(tag);
|
|
13568
13791
|
const count = this.invalidateTag(normalized);
|
|
@@ -13571,6 +13794,15 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
13571
13794
|
);
|
|
13572
13795
|
return count;
|
|
13573
13796
|
}
|
|
13797
|
+
async revalidateTagAsync(tag, options = {}) {
|
|
13798
|
+
const normalized = normalizeCacheTag(tag);
|
|
13799
|
+
const count = this.invalidateTag(normalized);
|
|
13800
|
+
await this.adapter?.invalidateTags?.([this.createAdapterTag(normalized)]);
|
|
13801
|
+
emitFarmEvent(
|
|
13802
|
+
options.source === "updateTag" ? { type: "cache.updateTag", tag: normalized, count } : { type: "cache.revalidateTag", tag: normalized, profile: options.profile, count }
|
|
13803
|
+
);
|
|
13804
|
+
return count;
|
|
13805
|
+
}
|
|
13574
13806
|
revalidatePath(routePath) {
|
|
13575
13807
|
const normalizedPath = normalizeRevalidatePath(routePath);
|
|
13576
13808
|
const pathTag = createPathCacheTag(normalizedPath);
|
|
@@ -13587,8 +13819,25 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
13587
13819
|
}
|
|
13588
13820
|
return count;
|
|
13589
13821
|
}
|
|
13822
|
+
async revalidatePathAsync(routePath) {
|
|
13823
|
+
const normalizedPath = normalizeRevalidatePath(routePath);
|
|
13824
|
+
const pathTag = createPathCacheTag(normalizedPath);
|
|
13825
|
+
const pprCount = this.countEntriesForTags([pathTag, "ppr"]);
|
|
13826
|
+
const count = this.invalidateTag(pathTag);
|
|
13827
|
+
await this.adapter?.invalidateTags?.([this.createAdapterTag(pathTag)]);
|
|
13828
|
+
emitFarmEvent({ type: "cache.revalidatePath", path: normalizedPath, count });
|
|
13829
|
+
if (pprCount > 0) {
|
|
13830
|
+
emitFarmEvent({
|
|
13831
|
+
type: "ppr.shell.invalidated",
|
|
13832
|
+
route: normalizedPath,
|
|
13833
|
+
reason: "revalidatePath",
|
|
13834
|
+
count: pprCount
|
|
13835
|
+
});
|
|
13836
|
+
}
|
|
13837
|
+
return count;
|
|
13838
|
+
}
|
|
13590
13839
|
async getOrSet(key, producer, options = {}) {
|
|
13591
|
-
const cached = this.
|
|
13840
|
+
const cached = await this.getEntryAsync(key);
|
|
13592
13841
|
if (cached) {
|
|
13593
13842
|
return cached.value;
|
|
13594
13843
|
}
|
|
@@ -13597,10 +13846,8 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
13597
13846
|
emitFarmEvent({ type: "cache.dedupe", key });
|
|
13598
13847
|
return inflight;
|
|
13599
13848
|
}
|
|
13600
|
-
const
|
|
13601
|
-
|
|
13602
|
-
return value;
|
|
13603
|
-
}).catch((error) => {
|
|
13849
|
+
const tags = Array.from(normalizeCacheOptionsTags(options));
|
|
13850
|
+
const promise = this.fillCacheEntry(key, producer, options, tags).catch((error) => {
|
|
13604
13851
|
emitFarmEvent({ type: "cache.error", key, operation: "set", error });
|
|
13605
13852
|
throw error;
|
|
13606
13853
|
}).finally(() => {
|
|
@@ -13609,6 +13856,40 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
13609
13856
|
this.inflight.set(key, promise);
|
|
13610
13857
|
return promise;
|
|
13611
13858
|
}
|
|
13859
|
+
async fillCacheEntry(key, producer, options, tags) {
|
|
13860
|
+
const leaseKey = `${this.namespace}:lease:${key}`;
|
|
13861
|
+
let leaseToken;
|
|
13862
|
+
if (this.adapter?.acquireLease && this.adapter.releaseLease && this.lease.enabled) {
|
|
13863
|
+
leaseToken = await this.adapter.acquireLease(leaseKey, this.lease.ttlMs);
|
|
13864
|
+
if (!leaseToken) {
|
|
13865
|
+
const shared = await this.waitForAdapterEntry(key);
|
|
13866
|
+
if (shared) {
|
|
13867
|
+
emitFarmEvent({ type: "cache.dedupe", key });
|
|
13868
|
+
return shared.value;
|
|
13869
|
+
}
|
|
13870
|
+
leaseToken = await this.adapter.acquireLease(leaseKey, this.lease.ttlMs);
|
|
13871
|
+
}
|
|
13872
|
+
}
|
|
13873
|
+
try {
|
|
13874
|
+
const initialTagVersions = await this.getAdapterTagVersions(tags);
|
|
13875
|
+
const value = await producer();
|
|
13876
|
+
await this.setAsync(key, value, options, initialTagVersions);
|
|
13877
|
+
return value;
|
|
13878
|
+
} finally {
|
|
13879
|
+
if (leaseToken && this.adapter?.releaseLease) {
|
|
13880
|
+
await this.adapter.releaseLease(leaseKey, leaseToken);
|
|
13881
|
+
}
|
|
13882
|
+
}
|
|
13883
|
+
}
|
|
13884
|
+
async waitForAdapterEntry(key) {
|
|
13885
|
+
const deadline = Date.now() + this.lease.waitTimeoutMs;
|
|
13886
|
+
while (Date.now() < deadline) {
|
|
13887
|
+
await delay(this.lease.pollIntervalMs);
|
|
13888
|
+
const entry = await this.getEntryAsync(key);
|
|
13889
|
+
if (entry) return entry;
|
|
13890
|
+
}
|
|
13891
|
+
return void 0;
|
|
13892
|
+
}
|
|
13612
13893
|
countEntriesForTag(tag) {
|
|
13613
13894
|
let count = 0;
|
|
13614
13895
|
for (const entry of this.entries.values()) {
|
|
@@ -13636,11 +13917,53 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
13636
13917
|
key: entry.key,
|
|
13637
13918
|
value: entry.value,
|
|
13638
13919
|
tags: Array.from(entry.tags),
|
|
13920
|
+
tagVersions: entry.tagVersions,
|
|
13639
13921
|
createdAt: entry.createdAt,
|
|
13640
13922
|
createdVersion: entry.createdVersion,
|
|
13641
13923
|
revalidate: entry.revalidate
|
|
13642
13924
|
};
|
|
13643
13925
|
}
|
|
13926
|
+
hydrateLocalEntry(entry) {
|
|
13927
|
+
this.entries.set(entry.key, {
|
|
13928
|
+
key: entry.key,
|
|
13929
|
+
value: entry.value,
|
|
13930
|
+
tags: new Set(entry.tags.map(normalizeCacheTag)),
|
|
13931
|
+
tagVersions: entry.tagVersions,
|
|
13932
|
+
createdAt: entry.createdAt,
|
|
13933
|
+
createdVersion: entry.createdVersion ?? ++this.version,
|
|
13934
|
+
revalidate: normalizeRevalidate(entry.revalidate)
|
|
13935
|
+
});
|
|
13936
|
+
}
|
|
13937
|
+
createAdapterKey(key) {
|
|
13938
|
+
return `${this.namespace}:entry:${key}`;
|
|
13939
|
+
}
|
|
13940
|
+
createAdapterTag(tag) {
|
|
13941
|
+
return `${this.namespace}:tag:${tag}`;
|
|
13942
|
+
}
|
|
13943
|
+
async getAdapterTagVersions(tags) {
|
|
13944
|
+
if (!this.adapter?.getTagVersions || tags.length === 0) return {};
|
|
13945
|
+
const normalized = tags.map(normalizeCacheTag);
|
|
13946
|
+
const physicalTags = normalized.map((tag) => this.createAdapterTag(tag));
|
|
13947
|
+
const versions = await this.adapter.getTagVersions(physicalTags);
|
|
13948
|
+
return Object.fromEntries(
|
|
13949
|
+
normalized.map((tag, index) => [
|
|
13950
|
+
tag,
|
|
13951
|
+
normalizeAdapterVersion(versions[physicalTags[index]])
|
|
13952
|
+
])
|
|
13953
|
+
);
|
|
13954
|
+
}
|
|
13955
|
+
async isAdapterEntryStale(entry, now = Date.now()) {
|
|
13956
|
+
if (typeof entry.revalidate === "number" && entry.revalidate > 0 && now - entry.createdAt >= entry.revalidate * 1e3) {
|
|
13957
|
+
return true;
|
|
13958
|
+
}
|
|
13959
|
+
const currentVersions = await this.getAdapterTagVersions(entry.tags);
|
|
13960
|
+
for (const tag of entry.tags) {
|
|
13961
|
+
if (normalizeAdapterVersion(currentVersions[tag]) > normalizeAdapterVersion(entry.tagVersions?.[tag])) {
|
|
13962
|
+
return true;
|
|
13963
|
+
}
|
|
13964
|
+
}
|
|
13965
|
+
return false;
|
|
13966
|
+
}
|
|
13644
13967
|
};
|
|
13645
13968
|
__name(_FarmDataCache, "FarmDataCache");
|
|
13646
13969
|
var FarmDataCache = _FarmDataCache;
|
|
@@ -13653,6 +13976,10 @@ function getFarmDataCache() {
|
|
|
13653
13976
|
return sharedFarmDataCache;
|
|
13654
13977
|
}
|
|
13655
13978
|
__name(getFarmDataCache, "getFarmDataCache");
|
|
13979
|
+
function configureFarmCache(config) {
|
|
13980
|
+
sharedFarmDataCache.configure(config);
|
|
13981
|
+
}
|
|
13982
|
+
__name(configureFarmCache, "configureFarmCache");
|
|
13656
13983
|
function unstable_cache(fn, keyParts = [], options = {}) {
|
|
13657
13984
|
return async (...args) => {
|
|
13658
13985
|
const locale = getActiveFarmI18nSnapshot()?.locale;
|
|
@@ -13668,30 +13995,71 @@ function unstable_cache(fn, keyParts = [], options = {}) {
|
|
|
13668
13995
|
}
|
|
13669
13996
|
__name(unstable_cache, "unstable_cache");
|
|
13670
13997
|
function revalidateTag(_tag, _profile) {
|
|
13671
|
-
getFarmDataCache()
|
|
13998
|
+
const cache = getFarmDataCache();
|
|
13999
|
+
if (cache.hasAdapter) {
|
|
14000
|
+
const task = cache.revalidateTagAsync(_tag, {
|
|
14001
|
+
source: "revalidateTag",
|
|
14002
|
+
profile: _profile
|
|
14003
|
+
}).then(() => void 0);
|
|
14004
|
+
notifyFarmCacheTask(task);
|
|
14005
|
+
return task;
|
|
14006
|
+
}
|
|
14007
|
+
cache.revalidateTag(_tag, {
|
|
13672
14008
|
source: "revalidateTag",
|
|
13673
14009
|
profile: _profile
|
|
13674
14010
|
});
|
|
13675
14011
|
}
|
|
13676
14012
|
__name(revalidateTag, "revalidateTag");
|
|
13677
14013
|
function updateTag(tag) {
|
|
13678
|
-
|
|
14014
|
+
const cache = getFarmDataCache();
|
|
14015
|
+
if (cache.hasAdapter) {
|
|
14016
|
+
const task = cache.revalidateTagAsync(tag, { source: "updateTag" }).then(() => void 0);
|
|
14017
|
+
notifyFarmCacheTask(task);
|
|
14018
|
+
return task;
|
|
14019
|
+
}
|
|
14020
|
+
cache.revalidateTag(tag, { source: "updateTag" });
|
|
13679
14021
|
}
|
|
13680
14022
|
__name(updateTag, "updateTag");
|
|
13681
14023
|
function revalidatePath(routePath) {
|
|
13682
|
-
getFarmDataCache()
|
|
14024
|
+
const cache = getFarmDataCache();
|
|
14025
|
+
if (cache.hasAdapter) {
|
|
14026
|
+
const task = cache.revalidatePathAsync(routePath).then(() => void 0);
|
|
14027
|
+
notifyFarmCacheTask(task);
|
|
14028
|
+
return task;
|
|
14029
|
+
}
|
|
14030
|
+
cache.revalidatePath(routePath);
|
|
13683
14031
|
}
|
|
13684
14032
|
__name(revalidatePath, "revalidatePath");
|
|
13685
14033
|
function invalidate(key) {
|
|
13686
14034
|
const clientKey = createRouteDataCacheKey(key);
|
|
13687
|
-
|
|
14035
|
+
const task = updateTag(createRouteDataCacheTag(key));
|
|
13688
14036
|
notifyFarmCacheInvalidation(clientKey);
|
|
14037
|
+
return task;
|
|
13689
14038
|
}
|
|
13690
14039
|
__name(invalidate, "invalidate");
|
|
13691
14040
|
function invalidateRouteData(key) {
|
|
13692
|
-
invalidate(key);
|
|
14041
|
+
return invalidate(key);
|
|
13693
14042
|
}
|
|
13694
14043
|
__name(invalidateRouteData, "invalidateRouteData");
|
|
14044
|
+
async function applyFarmCacheInvalidationTargets(targets) {
|
|
14045
|
+
if (!Array.isArray(targets)) {
|
|
14046
|
+
throw new TypeError("Cache invalidations must resolve to an array of targets.");
|
|
14047
|
+
}
|
|
14048
|
+
const clientKeys = [];
|
|
14049
|
+
for (const target of targets) {
|
|
14050
|
+
assertFarmCacheInvalidationTarget(target);
|
|
14051
|
+
if ("key" in target) {
|
|
14052
|
+
await invalidate(target.key);
|
|
14053
|
+
clientKeys.push(createRouteDataCacheKey(target.key));
|
|
14054
|
+
} else if ("path" in target) {
|
|
14055
|
+
await revalidatePath(target.path);
|
|
14056
|
+
} else {
|
|
14057
|
+
await updateTag(target.tag);
|
|
14058
|
+
}
|
|
14059
|
+
}
|
|
14060
|
+
return Array.from(new Set(clientKeys));
|
|
14061
|
+
}
|
|
14062
|
+
__name(applyFarmCacheInvalidationTargets, "applyFarmCacheInvalidationTargets");
|
|
13695
14063
|
function createPathCacheTag(routePath) {
|
|
13696
14064
|
return `path:${normalizeRevalidatePath(routePath)}`;
|
|
13697
14065
|
}
|
|
@@ -13752,6 +14120,67 @@ function normalizeCacheTag(tag) {
|
|
|
13752
14120
|
return normalized;
|
|
13753
14121
|
}
|
|
13754
14122
|
__name(normalizeCacheTag, "normalizeCacheTag");
|
|
14123
|
+
function normalizeCacheNamespace(namespace) {
|
|
14124
|
+
if (typeof namespace !== "string") {
|
|
14125
|
+
throw new TypeError("Cache namespace must be a string.");
|
|
14126
|
+
}
|
|
14127
|
+
const normalized = namespace.trim().replace(/:+$/g, "");
|
|
14128
|
+
if (!normalized) {
|
|
14129
|
+
throw new Error("Cache namespace cannot be empty.");
|
|
14130
|
+
}
|
|
14131
|
+
return normalized;
|
|
14132
|
+
}
|
|
14133
|
+
__name(normalizeCacheNamespace, "normalizeCacheNamespace");
|
|
14134
|
+
function normalizeAdapterVersion(value) {
|
|
14135
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
|
|
14136
|
+
}
|
|
14137
|
+
__name(normalizeAdapterVersion, "normalizeAdapterVersion");
|
|
14138
|
+
function normalizePositiveDuration(value, fallback, name) {
|
|
14139
|
+
if (value === void 0) return fallback;
|
|
14140
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
14141
|
+
throw new TypeError(`${name} must be a positive number of milliseconds.`);
|
|
14142
|
+
}
|
|
14143
|
+
return Math.floor(value);
|
|
14144
|
+
}
|
|
14145
|
+
__name(normalizePositiveDuration, "normalizePositiveDuration");
|
|
14146
|
+
function delay(ms) {
|
|
14147
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
14148
|
+
}
|
|
14149
|
+
__name(delay, "delay");
|
|
14150
|
+
function normalizeCacheOptionsTags(options) {
|
|
14151
|
+
const tags = /* @__PURE__ */ new Set();
|
|
14152
|
+
for (const tag of options.tags ?? []) {
|
|
14153
|
+
tags.add(normalizeCacheTag(tag));
|
|
14154
|
+
}
|
|
14155
|
+
for (const routePath of options.paths ?? []) {
|
|
14156
|
+
tags.add(createPathCacheTag(routePath));
|
|
14157
|
+
}
|
|
14158
|
+
return tags;
|
|
14159
|
+
}
|
|
14160
|
+
__name(normalizeCacheOptionsTags, "normalizeCacheOptionsTags");
|
|
14161
|
+
function assertFarmCacheEntry(entry, expectedKey) {
|
|
14162
|
+
if (!entry || typeof entry !== "object" || entry.key !== expectedKey || !Array.isArray(entry.tags) || typeof entry.createdAt !== "number") {
|
|
14163
|
+
throw new TypeError(
|
|
14164
|
+
`Cache adapter returned an invalid entry for ${JSON.stringify(expectedKey)}.`
|
|
14165
|
+
);
|
|
14166
|
+
}
|
|
14167
|
+
}
|
|
14168
|
+
__name(assertFarmCacheEntry, "assertFarmCacheEntry");
|
|
14169
|
+
function assertFarmCacheInvalidationTarget(target) {
|
|
14170
|
+
if (!target || typeof target !== "object") {
|
|
14171
|
+
throw new TypeError("Cache invalidation targets must be { key }, { path }, or { tag }.");
|
|
14172
|
+
}
|
|
14173
|
+
if ("key" in target) {
|
|
14174
|
+
const key = target.key;
|
|
14175
|
+
if (typeof key === "string" || Array.isArray(key)) return;
|
|
14176
|
+
} else if ("path" in target && typeof target.path === "string") {
|
|
14177
|
+
return;
|
|
14178
|
+
} else if ("tag" in target && typeof target.tag === "string") {
|
|
14179
|
+
return;
|
|
14180
|
+
}
|
|
14181
|
+
throw new TypeError("Cache invalidation targets must contain a string/array key, path, or tag.");
|
|
14182
|
+
}
|
|
14183
|
+
__name(assertFarmCacheInvalidationTarget, "assertFarmCacheInvalidationTarget");
|
|
13755
14184
|
function getFunctionCacheIdentity(fn) {
|
|
13756
14185
|
if (fn.name) {
|
|
13757
14186
|
return `name:${fn.name}`;
|
|
@@ -14892,6 +15321,76 @@ function normalizePathname(pathname) {
|
|
|
14892
15321
|
}
|
|
14893
15322
|
__name(normalizePathname, "normalizePathname");
|
|
14894
15323
|
|
|
15324
|
+
// src/routing/route-slots.ts
|
|
15325
|
+
var SLOT_SEGMENT = /^@([A-Za-z][A-Za-z0-9_-]*)$/;
|
|
15326
|
+
function parseRouteSlotFile(filePath) {
|
|
15327
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
15328
|
+
const parts = normalized.split("/").filter(Boolean);
|
|
15329
|
+
const fileName = parts.at(-1) ?? "";
|
|
15330
|
+
const baseName = fileName.replace(/\.(tsx?|jsx?)$/, "");
|
|
15331
|
+
if (baseName !== "page" && baseName !== "default") return null;
|
|
15332
|
+
const slotIndex = parts.findIndex((part) => SLOT_SEGMENT.test(part));
|
|
15333
|
+
if (slotIndex < 0) return null;
|
|
15334
|
+
if (parts.slice(slotIndex + 1, -1).some((part) => SLOT_SEGMENT.test(part))) {
|
|
15335
|
+
throw new Error(`Nested route slots are not supported in "${filePath}"`);
|
|
15336
|
+
}
|
|
15337
|
+
const slotMatch = parts[slotIndex].match(SLOT_SEGMENT);
|
|
15338
|
+
const name = slotMatch?.[1];
|
|
15339
|
+
if (!name) return null;
|
|
15340
|
+
const ownerParts = parts.slice(0, slotIndex);
|
|
15341
|
+
const contentParts = parts.slice(slotIndex + 1, -1);
|
|
15342
|
+
const marker = parseInterceptionMarker(contentParts[0]);
|
|
15343
|
+
let targetBase = ownerParts;
|
|
15344
|
+
let targetParts = contentParts;
|
|
15345
|
+
if (marker) {
|
|
15346
|
+
targetBase = marker.root === true ? [] : ownerParts.slice(0, Math.max(0, ownerParts.length - marker.up));
|
|
15347
|
+
targetParts = [...marker.remainder ? [marker.remainder] : [], ...contentParts.slice(1)];
|
|
15348
|
+
}
|
|
15349
|
+
const ownerFile = [...ownerParts, "layout.tsx"].join("/");
|
|
15350
|
+
const routeFile = [
|
|
15351
|
+
...baseName === "default" ? ownerParts : targetBase,
|
|
15352
|
+
...baseName === "default" ? [] : targetParts,
|
|
15353
|
+
"page.tsx"
|
|
15354
|
+
].join("/");
|
|
15355
|
+
return {
|
|
15356
|
+
name,
|
|
15357
|
+
ownerRoute: parseRoutePath(ownerFile || "layout.tsx"),
|
|
15358
|
+
route: parseRoutePath(routeFile || "page.tsx"),
|
|
15359
|
+
interception: marker !== null,
|
|
15360
|
+
fallback: baseName === "default"
|
|
15361
|
+
};
|
|
15362
|
+
}
|
|
15363
|
+
__name(parseRouteSlotFile, "parseRouteSlotFile");
|
|
15364
|
+
function createRouteSlotContainerId(name, ownerPattern) {
|
|
15365
|
+
const owner = ownerPattern === "/" ? "root" : ownerPattern.replace(/^\//, "").replace(/[^A-Za-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
15366
|
+
return `__farm_slot_${name}_${owner || "root"}__`;
|
|
15367
|
+
}
|
|
15368
|
+
__name(createRouteSlotContainerId, "createRouteSlotContainerId");
|
|
15369
|
+
function parseInterceptionMarker(segment) {
|
|
15370
|
+
if (!segment) return null;
|
|
15371
|
+
if (segment.startsWith("(...)")) {
|
|
15372
|
+
return {
|
|
15373
|
+
up: 0,
|
|
15374
|
+
root: true,
|
|
15375
|
+
remainder: segment.slice(5)
|
|
15376
|
+
};
|
|
15377
|
+
}
|
|
15378
|
+
if (segment.startsWith("(.)")) {
|
|
15379
|
+
return {
|
|
15380
|
+
up: 0,
|
|
15381
|
+
remainder: segment.slice(3)
|
|
15382
|
+
};
|
|
15383
|
+
}
|
|
15384
|
+
let remainder = segment;
|
|
15385
|
+
let up = 0;
|
|
15386
|
+
while (remainder.startsWith("(..)")) {
|
|
15387
|
+
up += 1;
|
|
15388
|
+
remainder = remainder.slice(4);
|
|
15389
|
+
}
|
|
15390
|
+
return up > 0 ? { up, remainder } : null;
|
|
15391
|
+
}
|
|
15392
|
+
__name(parseInterceptionMarker, "parseInterceptionMarker");
|
|
15393
|
+
|
|
14895
15394
|
// src/routing/route-manager.ts
|
|
14896
15395
|
function routeSpecificity(entry) {
|
|
14897
15396
|
return entry.route.segments.reduce((score, segment) => {
|
|
@@ -14905,6 +15404,7 @@ var _RouteManager = class _RouteManager {
|
|
|
14905
15404
|
constructor(config, viteServer) {
|
|
14906
15405
|
this.routes = /* @__PURE__ */ new Map();
|
|
14907
15406
|
this.layouts = /* @__PURE__ */ new Map();
|
|
15407
|
+
this.routeSlots = /* @__PURE__ */ new Map();
|
|
14908
15408
|
this.loadings = /* @__PURE__ */ new Map();
|
|
14909
15409
|
this.errors = /* @__PURE__ */ new Map();
|
|
14910
15410
|
this.metadataImages = /* @__PURE__ */ new Map();
|
|
@@ -14920,6 +15420,7 @@ var _RouteManager = class _RouteManager {
|
|
|
14920
15420
|
async discoverRoutes() {
|
|
14921
15421
|
this.routes.clear();
|
|
14922
15422
|
this.layouts.clear();
|
|
15423
|
+
this.routeSlots.clear();
|
|
14923
15424
|
this.loadings.clear();
|
|
14924
15425
|
this.errors.clear();
|
|
14925
15426
|
this.metadataImages.clear();
|
|
@@ -14930,6 +15431,13 @@ var _RouteManager = class _RouteManager {
|
|
|
14930
15431
|
await this.discoverFileRoutes(source);
|
|
14931
15432
|
await this.discoverProgrammaticRoutes(source);
|
|
14932
15433
|
}
|
|
15434
|
+
for (const slot of this.routeSlots.values()) {
|
|
15435
|
+
if (slot.interception && !this.routes.has(slot.pattern)) {
|
|
15436
|
+
throw new Error(
|
|
15437
|
+
`Intercepting route slot "${slot.name}" targets "${slot.pattern}", but no canonical page exists for that URL`
|
|
15438
|
+
);
|
|
15439
|
+
}
|
|
15440
|
+
}
|
|
14933
15441
|
this.routes = new Map(
|
|
14934
15442
|
Array.from(this.routes.entries()).sort(
|
|
14935
15443
|
([, left], [, right]) => routeSpecificity(right) - routeSpecificity(left)
|
|
@@ -14945,7 +15453,7 @@ var _RouteManager = class _RouteManager {
|
|
|
14945
15453
|
/**
|
|
14946
15454
|
* Find matching route for a given URL path
|
|
14947
15455
|
*/
|
|
14948
|
-
matchRoute(pathname) {
|
|
15456
|
+
matchRoute(pathname, options = {}) {
|
|
14949
15457
|
const routePathname = this.toRoutePathname(pathname);
|
|
14950
15458
|
const normalizedPath = routePathname === "/" ? "/" : routePathname.replace(/\/$/, "");
|
|
14951
15459
|
let matchedRoute = null;
|
|
@@ -14959,10 +15467,12 @@ var _RouteManager = class _RouteManager {
|
|
|
14959
15467
|
}
|
|
14960
15468
|
}
|
|
14961
15469
|
const layouts = this.findMatchingLayouts(normalizedPath);
|
|
15470
|
+
const slots = this.findMatchingRouteSlots(normalizedPath, options.interceptFrom);
|
|
14962
15471
|
return {
|
|
14963
15472
|
route: matchedRoute,
|
|
14964
15473
|
params,
|
|
14965
|
-
layouts
|
|
15474
|
+
layouts,
|
|
15475
|
+
slots
|
|
14966
15476
|
};
|
|
14967
15477
|
}
|
|
14968
15478
|
/**
|
|
@@ -14977,6 +15487,9 @@ var _RouteManager = class _RouteManager {
|
|
|
14977
15487
|
getLayouts() {
|
|
14978
15488
|
return new Map(this.layouts);
|
|
14979
15489
|
}
|
|
15490
|
+
getRouteSlots() {
|
|
15491
|
+
return new Map(this.routeSlots);
|
|
15492
|
+
}
|
|
14980
15493
|
/** Resolve route rules, inherited layouts, and the page export in precedence order. */
|
|
14981
15494
|
async resolveRouteRuntimeConfig(pattern) {
|
|
14982
15495
|
const routeEntry = this.routes.get(pattern);
|
|
@@ -15135,7 +15648,22 @@ var _RouteManager = class _RouteManager {
|
|
|
15135
15648
|
pattern: entry.pattern,
|
|
15136
15649
|
modulePath: toUrlPath(entry.modulePath)
|
|
15137
15650
|
}));
|
|
15138
|
-
|
|
15651
|
+
const slots = Array.from(this.routeSlots.values()).map((entry) => {
|
|
15652
|
+
const metadata = getClientModuleMetadata(entry.modulePath, projectRoot);
|
|
15653
|
+
return {
|
|
15654
|
+
name: entry.name,
|
|
15655
|
+
ownerPattern: entry.ownerPattern,
|
|
15656
|
+
pattern: entry.pattern,
|
|
15657
|
+
modulePath: toUrlPath(entry.modulePath),
|
|
15658
|
+
containerId: entry.containerId,
|
|
15659
|
+
interception: entry.interception,
|
|
15660
|
+
fallback: entry.fallback,
|
|
15661
|
+
shouldHydrate: metadata.shouldHydrate,
|
|
15662
|
+
isClientComponent: metadata.isClientComponent,
|
|
15663
|
+
segments: entry.route.segments
|
|
15664
|
+
};
|
|
15665
|
+
});
|
|
15666
|
+
return { routes, layouts, slots };
|
|
15139
15667
|
}
|
|
15140
15668
|
/**
|
|
15141
15669
|
* Load a route module dynamically
|
|
@@ -15212,6 +15740,7 @@ var _RouteManager = class _RouteManager {
|
|
|
15212
15740
|
async discoverFileRoutes(source) {
|
|
15213
15741
|
const appDir = resolveAppPath(source.root, source.srcDir, "app");
|
|
15214
15742
|
const pageFiles = await safeGlobFiles("**/page.{ts,tsx,js,jsx,md,mdx}", appDir);
|
|
15743
|
+
const slotDefaultFiles = await safeGlobFiles("**/@*/**/default.{ts,tsx,js,jsx}", appDir);
|
|
15215
15744
|
const layoutFiles = await safeGlobFiles("**/layout.{ts,tsx,js,jsx}", appDir);
|
|
15216
15745
|
const loadingFiles = await safeGlobFiles("**/loading.{ts,tsx,js,jsx}", appDir);
|
|
15217
15746
|
const errorFiles = await safeGlobFiles("**/error.{ts,tsx,js,jsx}", appDir);
|
|
@@ -15220,7 +15749,7 @@ var _RouteManager = class _RouteManager {
|
|
|
15220
15749
|
appDir
|
|
15221
15750
|
);
|
|
15222
15751
|
for (const [kind, files, target] of [
|
|
15223
|
-
["page", pageFiles, this.routes],
|
|
15752
|
+
["page", pageFiles.filter((file) => parseRouteSlotFile(file) === null), this.routes],
|
|
15224
15753
|
["layout", layoutFiles, this.layouts],
|
|
15225
15754
|
["loading", loadingFiles, this.loadings],
|
|
15226
15755
|
["error", errorFiles, this.errors]
|
|
@@ -15244,6 +15773,32 @@ var _RouteManager = class _RouteManager {
|
|
|
15244
15773
|
});
|
|
15245
15774
|
}
|
|
15246
15775
|
}
|
|
15776
|
+
for (const file of [...pageFiles, ...slotDefaultFiles]) {
|
|
15777
|
+
const slot = parseRouteSlotFile(file);
|
|
15778
|
+
if (!slot) continue;
|
|
15779
|
+
const modulePath = import_path5.default.join(appDir, file);
|
|
15780
|
+
const pattern = this.createRoutePattern(slot.route);
|
|
15781
|
+
const ownerPattern = this.createRoutePattern(slot.ownerRoute);
|
|
15782
|
+
const key = `${ownerPattern}:${slot.name}:${slot.interception ? "intercept" : "slot"}:${slot.fallback ? "default" : pattern}`;
|
|
15783
|
+
const existing = this.routeSlots.get(key);
|
|
15784
|
+
if (existing?.sourceRoot === source.root) {
|
|
15785
|
+
throw new Error(
|
|
15786
|
+
`Duplicate route slot "${slot.name}" for "${pattern}". Found both ${existing.modulePath} and ${modulePath}.`
|
|
15787
|
+
);
|
|
15788
|
+
}
|
|
15789
|
+
this.routeSlots.set(key, {
|
|
15790
|
+
route: slot.route,
|
|
15791
|
+
modulePath,
|
|
15792
|
+
pattern,
|
|
15793
|
+
source: "file",
|
|
15794
|
+
sourceRoot: source.root,
|
|
15795
|
+
name: slot.name,
|
|
15796
|
+
ownerPattern,
|
|
15797
|
+
interception: slot.interception,
|
|
15798
|
+
fallback: slot.fallback,
|
|
15799
|
+
containerId: createRouteSlotContainerId(slot.name, ownerPattern)
|
|
15800
|
+
});
|
|
15801
|
+
}
|
|
15247
15802
|
for (const file of metadataImageFiles) {
|
|
15248
15803
|
const fileBase = import_path5.default.basename(file, import_path5.default.extname(file));
|
|
15249
15804
|
const kind = fileBase === "twitter-image" ? "twitter" : "opengraph";
|
|
@@ -15369,6 +15924,71 @@ var _RouteManager = class _RouteManager {
|
|
|
15369
15924
|
}
|
|
15370
15925
|
return matchingLayouts;
|
|
15371
15926
|
}
|
|
15927
|
+
findMatchingRouteSlots(pathname, interceptFrom) {
|
|
15928
|
+
const groups = /* @__PURE__ */ new Map();
|
|
15929
|
+
for (const entry of this.routeSlots.values()) {
|
|
15930
|
+
if (!this.matchesRoutePrefix(pathname, entry.ownerPattern)) continue;
|
|
15931
|
+
const key = `${entry.ownerPattern}:${entry.name}`;
|
|
15932
|
+
const entries = groups.get(key) ?? [];
|
|
15933
|
+
entries.push(entry);
|
|
15934
|
+
groups.set(key, entries);
|
|
15935
|
+
}
|
|
15936
|
+
const normalizedFrom = interceptFrom ? this.toRoutePathname(new URL(interceptFrom, "http://farm.local").pathname) : void 0;
|
|
15937
|
+
const matches = [];
|
|
15938
|
+
for (const entries of groups.values()) {
|
|
15939
|
+
const candidates = entries.filter((entry) => !entry.fallback).filter(
|
|
15940
|
+
(entry) => !entry.interception || normalizedFrom !== void 0 && this.matchesRoutePrefix(normalizedFrom, entry.ownerPattern)
|
|
15941
|
+
).map((entry) => ({
|
|
15942
|
+
entry,
|
|
15943
|
+
match: matchRoute(pathname, entry.route.segments)
|
|
15944
|
+
})).filter((candidate) => candidate.match.matches).sort((left, right) => {
|
|
15945
|
+
if (left.entry.interception !== right.entry.interception) {
|
|
15946
|
+
return left.entry.interception ? -1 : 1;
|
|
15947
|
+
}
|
|
15948
|
+
return routeSpecificity(right.entry) - routeSpecificity(left.entry);
|
|
15949
|
+
});
|
|
15950
|
+
const selected = candidates[0];
|
|
15951
|
+
if (selected) {
|
|
15952
|
+
matches.push({
|
|
15953
|
+
name: selected.entry.name,
|
|
15954
|
+
ownerPattern: selected.entry.ownerPattern,
|
|
15955
|
+
containerId: selected.entry.containerId,
|
|
15956
|
+
interception: selected.entry.interception,
|
|
15957
|
+
fallback: false,
|
|
15958
|
+
route: selected.entry,
|
|
15959
|
+
params: selected.match.params
|
|
15960
|
+
});
|
|
15961
|
+
continue;
|
|
15962
|
+
}
|
|
15963
|
+
const fallback = entries.find((entry) => entry.fallback);
|
|
15964
|
+
if (fallback) {
|
|
15965
|
+
matches.push({
|
|
15966
|
+
name: fallback.name,
|
|
15967
|
+
ownerPattern: fallback.ownerPattern,
|
|
15968
|
+
containerId: fallback.containerId,
|
|
15969
|
+
interception: false,
|
|
15970
|
+
fallback: true,
|
|
15971
|
+
route: fallback,
|
|
15972
|
+
params: {}
|
|
15973
|
+
});
|
|
15974
|
+
}
|
|
15975
|
+
}
|
|
15976
|
+
return matches.sort((left, right) => {
|
|
15977
|
+
const ownerDifference = left.route.route.segments.length - right.route.route.segments.length;
|
|
15978
|
+
return ownerDifference || left.name.localeCompare(right.name);
|
|
15979
|
+
});
|
|
15980
|
+
}
|
|
15981
|
+
matchesRoutePrefix(pathname, pattern) {
|
|
15982
|
+
if (pattern === "/") return true;
|
|
15983
|
+
const patternSegments = parseRoutePath(`${pattern}/page.tsx`).segments;
|
|
15984
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
15985
|
+
if (patternSegments.length > pathSegments.length) return false;
|
|
15986
|
+
for (let index = 0; index < patternSegments.length; index++) {
|
|
15987
|
+
const segment = patternSegments[index];
|
|
15988
|
+
if (!segment.isDynamic && segment.segment !== pathSegments[index]) return false;
|
|
15989
|
+
}
|
|
15990
|
+
return true;
|
|
15991
|
+
}
|
|
15372
15992
|
findNearestBoundary(pathname, boundaries) {
|
|
15373
15993
|
const normalizedPath = pathname === "/" ? "/" : pathname.replace(/\/$/, "");
|
|
15374
15994
|
const pathSegments = normalizedPath.split("/").filter(Boolean);
|
|
@@ -15985,7 +16605,7 @@ function mergeMetadata(base, next) {
|
|
|
15985
16605
|
__name(mergeMetadata, "mergeMetadata");
|
|
15986
16606
|
function addMetadataImageReference(metadata, reference) {
|
|
15987
16607
|
if (reference.kind === "opengraph") {
|
|
15988
|
-
const openGraph = { ...metadata.openGraph
|
|
16608
|
+
const openGraph = { ...metadata.openGraph };
|
|
15989
16609
|
if (!hasMetadataImages(openGraph.images) && !hasMetadataImages(openGraph.image)) {
|
|
15990
16610
|
openGraph.images = [
|
|
15991
16611
|
{
|
|
@@ -16002,7 +16622,7 @@ function addMetadataImageReference(metadata, reference) {
|
|
|
16002
16622
|
openGraph
|
|
16003
16623
|
};
|
|
16004
16624
|
}
|
|
16005
|
-
const twitter = { ...metadata.twitter
|
|
16625
|
+
const twitter = { ...metadata.twitter };
|
|
16006
16626
|
if (!hasMetadataImages(twitter.images)) {
|
|
16007
16627
|
twitter.images = [reference.href];
|
|
16008
16628
|
twitter.card = twitter.card || "summary_large_image";
|
|
@@ -16608,8 +17228,8 @@ var _FarmI18nRuntime = class _FarmI18nRuntime {
|
|
|
16608
17228
|
cookie: this.config.cookie,
|
|
16609
17229
|
direction: getFarmLocaleDirection(resolution.locale, this.config.direction),
|
|
16610
17230
|
messages: {
|
|
16611
|
-
...this.catalogs[this.config.fallbackLocale]
|
|
16612
|
-
...this.catalogs[resolution.locale]
|
|
17231
|
+
...this.catalogs[this.config.fallbackLocale],
|
|
17232
|
+
...this.catalogs[resolution.locale]
|
|
16613
17233
|
}
|
|
16614
17234
|
};
|
|
16615
17235
|
}
|
|
@@ -16911,7 +17531,9 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
16911
17531
|
async runWithRequestContext(request, fn) {
|
|
16912
17532
|
return _runWithCurrentRequest(
|
|
16913
17533
|
request,
|
|
16914
|
-
() => this.i18nRuntime?.config.enabled ? _runWithFarmI18nRequest(this.i18nRuntime, request, fn, {
|
|
17534
|
+
() => this.i18nRuntime?.config.enabled ? _runWithFarmI18nRequest(this.i18nRuntime, request, fn, {
|
|
17535
|
+
redirect: false
|
|
17536
|
+
}) : fn()
|
|
16915
17537
|
);
|
|
16916
17538
|
}
|
|
16917
17539
|
async resolveRouteContext(input) {
|
|
@@ -16934,11 +17556,11 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
16934
17556
|
/**
|
|
16935
17557
|
* Check if a path should be served from SSG cache
|
|
16936
17558
|
*/
|
|
16937
|
-
shouldServeSSG(pathname) {
|
|
17559
|
+
async shouldServeSSG(pathname) {
|
|
16938
17560
|
const ssgPage = matchSSGPage(pathname, this.ssgManifest);
|
|
16939
17561
|
if (!ssgPage) return null;
|
|
16940
|
-
const cached = this.getCachedSSGPage(pathname);
|
|
16941
|
-
if (cached && this.dataCache.
|
|
17562
|
+
const cached = await this.getCachedSSGPage(pathname);
|
|
17563
|
+
if (cached && await this.dataCache.isStaleAsync(cached)) {
|
|
16942
17564
|
this.regenerateSSGPage(ssgPage);
|
|
16943
17565
|
}
|
|
16944
17566
|
return ssgPage;
|
|
@@ -16950,12 +17572,12 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
16950
17572
|
return createFarmCacheKey(["ppr", normalizeRevalidatePath(pathname), search]);
|
|
16951
17573
|
}
|
|
16952
17574
|
getCachedSSGPage(urlPath) {
|
|
16953
|
-
return this.dataCache.
|
|
17575
|
+
return this.dataCache.getEntryAsync(this.getSSGCacheKey(urlPath), {
|
|
16954
17576
|
allowStale: true
|
|
16955
17577
|
});
|
|
16956
17578
|
}
|
|
16957
|
-
cacheSSGPage(page2, html, options) {
|
|
16958
|
-
this.dataCache.
|
|
17579
|
+
async cacheSSGPage(page2, html, options) {
|
|
17580
|
+
await this.dataCache.setAsync(
|
|
16959
17581
|
this.getSSGCacheKey(page2.urlPath),
|
|
16960
17582
|
{ html, document: options.document },
|
|
16961
17583
|
{
|
|
@@ -16967,11 +17589,11 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
16967
17589
|
);
|
|
16968
17590
|
}
|
|
16969
17591
|
getCachedPPRShell(pathname, search) {
|
|
16970
|
-
return this.dataCache.
|
|
17592
|
+
return this.dataCache.getEntryAsync(this.getPPRCacheKey(pathname, search));
|
|
16971
17593
|
}
|
|
16972
|
-
cachePPRShell(options, html) {
|
|
17594
|
+
async cachePPRShell(options, html) {
|
|
16973
17595
|
const key = this.getPPRCacheKey(options.pathname, options.search);
|
|
16974
|
-
this.dataCache.
|
|
17596
|
+
await this.dataCache.setAsync(
|
|
16975
17597
|
key,
|
|
16976
17598
|
{ html },
|
|
16977
17599
|
{
|
|
@@ -17069,7 +17691,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17069
17691
|
}
|
|
17070
17692
|
const { renderToString } = await import("react-dom/server");
|
|
17071
17693
|
const html = renderToString(await this.wrapWithIntegrationProviders(pageElement));
|
|
17072
|
-
this.cacheSSGPage(page2, html, { document: false });
|
|
17694
|
+
await this.cacheSSGPage(page2, html, { document: false });
|
|
17073
17695
|
logger.info(`ISR: Regenerated ${page2.urlPath}`);
|
|
17074
17696
|
} catch (error) {
|
|
17075
17697
|
logger.error(`ISR regeneration failed for ${page2.urlPath}: ${error}`);
|
|
@@ -17083,7 +17705,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17083
17705
|
* Serve a pre-rendered SSG page
|
|
17084
17706
|
*/
|
|
17085
17707
|
async serveSSGPage(req, res, page2) {
|
|
17086
|
-
const cached = this.getCachedSSGPage(page2.urlPath);
|
|
17708
|
+
const cached = await this.getCachedSSGPage(page2.urlPath);
|
|
17087
17709
|
if (cached) {
|
|
17088
17710
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
17089
17711
|
res.setHeader("X-Farm-SSG", "cached");
|
|
@@ -17101,9 +17723,12 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17101
17723
|
if (fs2.existsSync(htmlPath)) {
|
|
17102
17724
|
const stat = fs2.statSync(htmlPath);
|
|
17103
17725
|
const html = fs2.readFileSync(htmlPath, "utf-8");
|
|
17104
|
-
this.cacheSSGPage(page2, html, {
|
|
17105
|
-
|
|
17106
|
-
|
|
17726
|
+
await this.cacheSSGPage(page2, html, {
|
|
17727
|
+
document: true,
|
|
17728
|
+
createdAt: stat.mtimeMs
|
|
17729
|
+
});
|
|
17730
|
+
const fileCacheEntry = await this.getCachedSSGPage(page2.urlPath);
|
|
17731
|
+
if (fileCacheEntry && await this.dataCache.isStaleAsync(fileCacheEntry)) {
|
|
17107
17732
|
this.regenerateSSGPage(page2);
|
|
17108
17733
|
}
|
|
17109
17734
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
@@ -17149,6 +17774,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17149
17774
|
let pathname = "/";
|
|
17150
17775
|
let params = {};
|
|
17151
17776
|
let layouts = [];
|
|
17777
|
+
let routeSlots = [];
|
|
17152
17778
|
let searchParamsObject = {};
|
|
17153
17779
|
let middlewareMap = /* @__PURE__ */ new Map();
|
|
17154
17780
|
let middlewareContext = /* @__PURE__ */ new Map();
|
|
@@ -17181,7 +17807,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17181
17807
|
}
|
|
17182
17808
|
this.applyDeploymentHeaders(req, res);
|
|
17183
17809
|
if (process.env.NODE_ENV === "production") {
|
|
17184
|
-
const ssgPage = this.shouldServeSSG(pathname);
|
|
17810
|
+
const ssgPage = await this.shouldServeSSG(pathname);
|
|
17185
17811
|
if (ssgPage) {
|
|
17186
17812
|
const served = await this.serveSSGPage(req, res, ssgPage);
|
|
17187
17813
|
if (served) {
|
|
@@ -17194,6 +17820,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17194
17820
|
const route = match.route;
|
|
17195
17821
|
params = match.params;
|
|
17196
17822
|
layouts = match.layouts;
|
|
17823
|
+
routeSlots = match.slots ?? [];
|
|
17197
17824
|
if (!route) {
|
|
17198
17825
|
emitFarmEvent({ type: "route.notFound", pathname });
|
|
17199
17826
|
await this.render404(req, res);
|
|
@@ -17210,7 +17837,9 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17210
17837
|
errorBoundaryEntry = this.routeManager.getMatchingError(pathname);
|
|
17211
17838
|
middlewareMap = toMiddlewareMap2(req.__FARM_MIDDLEWARE_DATA__);
|
|
17212
17839
|
middlewareContext = toMiddlewareMap2(req.__FARM_MIDDLEWARE_CONTEXT__);
|
|
17213
|
-
pluginExposedContext = getRequestContextSnapshot(req, {
|
|
17840
|
+
pluginExposedContext = getRequestContextSnapshot(req, {
|
|
17841
|
+
exposedOnly: true
|
|
17842
|
+
});
|
|
17214
17843
|
const currentRequest = createWebRequestFromFarmRequest(req);
|
|
17215
17844
|
const routeContext = await this.resolveRouteContext({
|
|
17216
17845
|
request: currentRequest,
|
|
@@ -17274,8 +17903,16 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17274
17903
|
revalidate: renderingConfig.revalidate
|
|
17275
17904
|
} : void 0;
|
|
17276
17905
|
if (renderingConfig.ppr && pprBypassReason) {
|
|
17277
|
-
emitFarmEvent({
|
|
17278
|
-
|
|
17906
|
+
emitFarmEvent({
|
|
17907
|
+
type: "ppr.shell.bypass",
|
|
17908
|
+
route: pathname,
|
|
17909
|
+
reason: pprBypassReason
|
|
17910
|
+
});
|
|
17911
|
+
emitFarmEvent({
|
|
17912
|
+
type: "cache.bypass",
|
|
17913
|
+
route: pathname,
|
|
17914
|
+
reason: pprBypassReason
|
|
17915
|
+
});
|
|
17279
17916
|
if (pprBypassReason === "refresh") {
|
|
17280
17917
|
pprRefreshRoute = pathname;
|
|
17281
17918
|
emitFarmEvent({ type: "ppr.refresh.start", route: pathname });
|
|
@@ -17283,14 +17920,22 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17283
17920
|
}
|
|
17284
17921
|
if (pprShellOptions) {
|
|
17285
17922
|
const pprCacheKey = this.getPPRCacheKey(pathname, url.search);
|
|
17286
|
-
const cachedPPRShell = this.getCachedPPRShell(pathname, url.search);
|
|
17923
|
+
const cachedPPRShell = await this.getCachedPPRShell(pathname, url.search);
|
|
17287
17924
|
if (cachedPPRShell) {
|
|
17288
|
-
emitFarmEvent({
|
|
17925
|
+
emitFarmEvent({
|
|
17926
|
+
type: "ppr.shell.hit",
|
|
17927
|
+
route: pathname,
|
|
17928
|
+
key: pprCacheKey
|
|
17929
|
+
});
|
|
17289
17930
|
this.serveCachedPPRShell(res, cachedPPRShell.value, renderingConfig.revalidate);
|
|
17290
17931
|
completeRender(res.statusCode || 200, pathname);
|
|
17291
17932
|
return;
|
|
17292
17933
|
}
|
|
17293
|
-
emitFarmEvent({
|
|
17934
|
+
emitFarmEvent({
|
|
17935
|
+
type: "ppr.shell.miss",
|
|
17936
|
+
route: pathname,
|
|
17937
|
+
key: pprCacheKey
|
|
17938
|
+
});
|
|
17294
17939
|
}
|
|
17295
17940
|
let LoadingFallbackComponent = null;
|
|
17296
17941
|
if (loadingBoundaryEntry) {
|
|
@@ -17314,14 +17959,77 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17314
17959
|
);
|
|
17315
17960
|
const moduleMetadata = routeManifestEntry || getClientModuleMetadata(route.modulePath, this.config.root);
|
|
17316
17961
|
const isClientComponent = moduleMetadata.isClientComponent;
|
|
17962
|
+
const renderedRouteSlots = await Promise.all(
|
|
17963
|
+
routeSlots.map(async (slot) => {
|
|
17964
|
+
const slotModule = await this.routeManager.loadRouteModule(slot.route.modulePath);
|
|
17965
|
+
if (!slotModule.default) {
|
|
17966
|
+
throw new Error(
|
|
17967
|
+
`Route slot "${slot.name}" module ${slot.route.modulePath} does not export a default component`
|
|
17968
|
+
);
|
|
17969
|
+
}
|
|
17970
|
+
const slotContext = await this.resolveRouteContext({
|
|
17971
|
+
request: currentRequest,
|
|
17972
|
+
rawRequest: req,
|
|
17973
|
+
params: slot.params,
|
|
17974
|
+
search: searchParamsObject,
|
|
17975
|
+
path: pathname
|
|
17976
|
+
});
|
|
17977
|
+
const rawSlotProps = withFarmRouteContext(
|
|
17978
|
+
{
|
|
17979
|
+
params: slot.params,
|
|
17980
|
+
searchParams: Promise.resolve(searchParamsObject),
|
|
17981
|
+
path: pathname,
|
|
17982
|
+
middleware: middlewareMap.size > 0 ? { data: middlewareMap } : void 0,
|
|
17983
|
+
context: pluginExposedContext.size > 0 ? { data: pluginExposedContext } : void 0
|
|
17984
|
+
},
|
|
17985
|
+
slotContext
|
|
17986
|
+
);
|
|
17987
|
+
const slotProps = await parseRouteModuleProps(slotModule, {
|
|
17988
|
+
props: rawSlotProps,
|
|
17989
|
+
search: searchParamsObject,
|
|
17990
|
+
routePath: slot.route.pattern
|
|
17991
|
+
});
|
|
17992
|
+
const metadata = getClientModuleMetadata(slot.route.modulePath, this.config.root);
|
|
17993
|
+
return {
|
|
17994
|
+
...slot,
|
|
17995
|
+
module: slotModule,
|
|
17996
|
+
props: slotProps,
|
|
17997
|
+
isClientComponent: metadata.isClientComponent,
|
|
17998
|
+
shouldHydrate: metadata.shouldHydrate
|
|
17999
|
+
};
|
|
18000
|
+
})
|
|
18001
|
+
);
|
|
17317
18002
|
const shouldHydrate = moduleMetadata.shouldHydrate;
|
|
18003
|
+
const hasHydratableRouteSlots = renderedRouteSlots.some(
|
|
18004
|
+
(slot) => slot.isClientComponent || slot.shouldHydrate
|
|
18005
|
+
);
|
|
17318
18006
|
req.__FARM_PAGE_PATH__ = route.modulePath;
|
|
17319
18007
|
req.__FARM_ROUTE__ = pathname;
|
|
17320
18008
|
req.__FARM_IS_CLIENT_COMPONENT__ = isClientComponent;
|
|
17321
18009
|
req.__FARM_SHOULD_HYDRATE__ = shouldHydrate;
|
|
18010
|
+
req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ = hasHydratableRouteSlots;
|
|
17322
18011
|
req.__FARM_LOADING_MODULE_PATH__ = loadingBoundaryEntry?.modulePath ? loadingBoundaryEntry.modulePath.substring(
|
|
17323
18012
|
loadingBoundaryEntry.modulePath.indexOf("/src/app/")
|
|
17324
18013
|
) : null;
|
|
18014
|
+
req.__FARM_ROUTE_SLOTS__ = renderedRouteSlots.map((slot) => ({
|
|
18015
|
+
name: slot.name,
|
|
18016
|
+
ownerPattern: slot.ownerPattern,
|
|
18017
|
+
containerId: slot.containerId,
|
|
18018
|
+
interception: slot.interception,
|
|
18019
|
+
fallback: slot.fallback,
|
|
18020
|
+
modulePath: slot.route.modulePath,
|
|
18021
|
+
isClientComponent: slot.isClientComponent,
|
|
18022
|
+
shouldHydrate: slot.shouldHydrate,
|
|
18023
|
+
props: {
|
|
18024
|
+
params: slot.props.params,
|
|
18025
|
+
search: slot.props.search,
|
|
18026
|
+
searchParams: slot.props.search,
|
|
18027
|
+
..."data" in slot.props ? { data: slot.props.data } : {},
|
|
18028
|
+
...slot.props.__farmCanonicalPath ? { __farmCanonicalPath: slot.props.__farmCanonicalPath } : {},
|
|
18029
|
+
...slot.props.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {},
|
|
18030
|
+
path: pathname
|
|
18031
|
+
}
|
|
18032
|
+
}));
|
|
17325
18033
|
req.__FARM_PROPS__ = {
|
|
17326
18034
|
params: pageProps.params,
|
|
17327
18035
|
search: pageProps.search,
|
|
@@ -17381,12 +18089,32 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17381
18089
|
let wrappedElement = pageElement;
|
|
17382
18090
|
for (let i = layoutModules.length - 1; i >= 0; i--) {
|
|
17383
18091
|
const layoutModule = layoutModules[i];
|
|
18092
|
+
const layoutEntry = layouts[i];
|
|
17384
18093
|
const LayoutComponent = layoutModule.default;
|
|
18094
|
+
const slotProps = {};
|
|
18095
|
+
for (const slot of renderedRouteSlots) {
|
|
18096
|
+
if (slot.ownerPattern !== layoutEntry.pattern) continue;
|
|
18097
|
+
let slotElement = import_react4.default.createElement(
|
|
18098
|
+
slot.module.default,
|
|
18099
|
+
slot.props
|
|
18100
|
+
);
|
|
18101
|
+
slotElement = import_react4.default.createElement(
|
|
18102
|
+
"div",
|
|
18103
|
+
{
|
|
18104
|
+
id: slot.containerId,
|
|
18105
|
+
"data-farm-route-slot": slot.name,
|
|
18106
|
+
"data-farm-slot-owner": slot.ownerPattern
|
|
18107
|
+
},
|
|
18108
|
+
slotElement
|
|
18109
|
+
);
|
|
18110
|
+
slotProps[slot.name] = slotElement;
|
|
18111
|
+
}
|
|
17385
18112
|
wrappedElement = import_react4.default.createElement(
|
|
17386
18113
|
LayoutComponent,
|
|
17387
18114
|
{
|
|
17388
18115
|
children: wrappedElement,
|
|
17389
|
-
params
|
|
18116
|
+
params,
|
|
18117
|
+
...slotProps
|
|
17390
18118
|
}
|
|
17391
18119
|
);
|
|
17392
18120
|
}
|
|
@@ -17423,7 +18151,10 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17423
18151
|
routeManifest,
|
|
17424
18152
|
captureStaticShell: Boolean(pprShellOptions),
|
|
17425
18153
|
observabilityRoute: pathname,
|
|
17426
|
-
onSuspenseHoleDetected: pprShellOptions ? () => emitFarmEvent({
|
|
18154
|
+
onSuspenseHoleDetected: pprShellOptions ? () => emitFarmEvent({
|
|
18155
|
+
type: "ppr.suspense.holeDetected",
|
|
18156
|
+
route: pathname
|
|
18157
|
+
}) : void 0,
|
|
17427
18158
|
onComplete: pprShellOptions && req.method !== "HEAD" ? (html) => this.cachePPRShell(pprShellOptions, html) : void 0
|
|
17428
18159
|
}
|
|
17429
18160
|
);
|
|
@@ -17471,7 +18202,11 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17471
18202
|
}
|
|
17472
18203
|
emitFarmEvent({ type: "render.error", route: pathname, error });
|
|
17473
18204
|
if (pprRefreshRoute) {
|
|
17474
|
-
emitFarmEvent({
|
|
18205
|
+
emitFarmEvent({
|
|
18206
|
+
type: "ppr.refresh.error",
|
|
18207
|
+
route: pprRefreshRoute,
|
|
18208
|
+
error
|
|
18209
|
+
});
|
|
17475
18210
|
}
|
|
17476
18211
|
logger.error(`Error rendering page: ${error}`);
|
|
17477
18212
|
if (res.headersSent || res.writableEnded) {
|
|
@@ -17524,7 +18259,9 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17524
18259
|
if (typeof layoutModule.generateMetadata === "function") {
|
|
17525
18260
|
metadata = mergeMetadata(
|
|
17526
18261
|
metadata,
|
|
17527
|
-
await layoutModule.generateMetadata({
|
|
18262
|
+
await layoutModule.generateMetadata({
|
|
18263
|
+
params: options.pageProps.params
|
|
18264
|
+
})
|
|
17528
18265
|
);
|
|
17529
18266
|
}
|
|
17530
18267
|
}
|
|
@@ -17755,7 +18492,13 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17755
18492
|
clientEntry: "/@farm/client.js",
|
|
17756
18493
|
routes: {},
|
|
17757
18494
|
layouts: {},
|
|
17758
|
-
|
|
18495
|
+
slots: [],
|
|
18496
|
+
sharedAssets: [
|
|
18497
|
+
{
|
|
18498
|
+
tag: "link",
|
|
18499
|
+
attrs: { rel: "stylesheet", href: "/src/app/globals.css" }
|
|
18500
|
+
}
|
|
18501
|
+
]
|
|
17759
18502
|
};
|
|
17760
18503
|
for (const routeEntry of manifest.routes) {
|
|
17761
18504
|
clientManifest.routes[routeEntry.pattern] = {
|
|
@@ -17777,9 +18520,26 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17777
18520
|
assets: []
|
|
17778
18521
|
};
|
|
17779
18522
|
}
|
|
17780
|
-
const
|
|
18523
|
+
for (const slotEntry of manifest.slots ?? []) {
|
|
18524
|
+
clientManifest.slots.push({
|
|
18525
|
+
...slotEntry,
|
|
18526
|
+
preloads: [slotEntry.modulePath],
|
|
18527
|
+
assets: []
|
|
18528
|
+
});
|
|
18529
|
+
}
|
|
18530
|
+
const routeSlotPayload = (req.__FARM_ROUTE_SLOTS__ || []).map(
|
|
18531
|
+
(slot) => ({
|
|
18532
|
+
...slot,
|
|
18533
|
+
modulePath: typeof slot.modulePath === "string" && slot.modulePath.startsWith(this.config.root) ? slot.modulePath.slice(this.config.root.length) : slot.modulePath
|
|
18534
|
+
})
|
|
18535
|
+
);
|
|
18536
|
+
const deferredProps = prepareDeferredData({
|
|
18537
|
+
page: req.__FARM_PROPS__ || {},
|
|
18538
|
+
slots: routeSlotPayload
|
|
18539
|
+
});
|
|
17781
18540
|
const propsScript = `<script>
|
|
17782
|
-
window.__FARM_PROPS__ = ${serializeInlineValue(deferredProps.data)};
|
|
18541
|
+
window.__FARM_PROPS__ = ${serializeInlineValue(deferredProps.data.page)};
|
|
18542
|
+
window.__FARM_ROUTE_SLOTS__ = ${serializeInlineValue(deferredProps.data.slots)};
|
|
17783
18543
|
window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue(deploymentId)};
|
|
17784
18544
|
window.__FARM_PATH__ = ${JSON.stringify(req.__FARM_ROUTE__ || req.url || "/")};
|
|
17785
18545
|
window.__FARM_IS_CLIENT__ = ${JSON.stringify(isClientComponent)};
|
|
@@ -17792,7 +18552,7 @@ window.__FARM_MANIFEST__ = ${JSON.stringify(clientManifest)};
|
|
|
17792
18552
|
window.__FARM_INTEGRATION_API_MANIFEST__ = ${JSON.stringify(getRegisteredIntegrationAPIManifest())};
|
|
17793
18553
|
${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(getFarmI18nClientSnapshot())};` : ""}
|
|
17794
18554
|
</script>`;
|
|
17795
|
-
const hydrationClickQueueScript = isClientComponent || req.__FARM_SHOULD_HYDRATE__ === true ? createPreHydrationClickQueueScript() : "";
|
|
18555
|
+
const hydrationClickQueueScript = isClientComponent || req.__FARM_SHOULD_HYDRATE__ === true || req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ === true ? createPreHydrationClickQueueScript() : "";
|
|
17796
18556
|
const {
|
|
17797
18557
|
title,
|
|
17798
18558
|
tags: metaTags,
|
|
@@ -17903,7 +18663,11 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
|
|
|
17903
18663
|
didError = true;
|
|
17904
18664
|
if (!isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
|
|
17905
18665
|
logger.error(`SSR shell error: ${error}`);
|
|
17906
|
-
emitFarmEvent({
|
|
18666
|
+
emitFarmEvent({
|
|
18667
|
+
type: "render.error",
|
|
18668
|
+
route: observabilityRoute,
|
|
18669
|
+
error
|
|
18670
|
+
});
|
|
17907
18671
|
}
|
|
17908
18672
|
if (clearMiddlewareData) {
|
|
17909
18673
|
clearMiddlewareData();
|
|
@@ -17914,7 +18678,11 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
|
|
|
17914
18678
|
didError = true;
|
|
17915
18679
|
if (!isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
|
|
17916
18680
|
logger.error(`SSR streaming error: ${error}`);
|
|
17917
|
-
emitFarmEvent({
|
|
18681
|
+
emitFarmEvent({
|
|
18682
|
+
type: "render.error",
|
|
18683
|
+
route: observabilityRoute,
|
|
18684
|
+
error
|
|
18685
|
+
});
|
|
17918
18686
|
}
|
|
17919
18687
|
}
|
|
17920
18688
|
});
|
|
@@ -18083,17 +18851,14 @@ var _FarmApp = class _FarmApp {
|
|
|
18083
18851
|
_setDefaultFarmI18nRuntime(this.i18nRuntime);
|
|
18084
18852
|
this.viteServer = viteServer;
|
|
18085
18853
|
this.routeManager = new RouteManager(this.config, viteServer);
|
|
18086
|
-
this.serverRenderer = new ServerRenderer(
|
|
18087
|
-
this.config,
|
|
18088
|
-
this.routeManager,
|
|
18089
|
-
this.i18nRuntime
|
|
18090
|
-
);
|
|
18854
|
+
this.serverRenderer = new ServerRenderer(this.config, this.routeManager, this.i18nRuntime);
|
|
18091
18855
|
}
|
|
18092
18856
|
async initialize() {
|
|
18093
18857
|
if (process.env.FARM_VERBOSE) {
|
|
18094
18858
|
logger.info("Initializing Farm.js application...");
|
|
18095
18859
|
}
|
|
18096
18860
|
await initStorage(this.config.storage);
|
|
18861
|
+
await configureFarmCache(this.config.cache);
|
|
18097
18862
|
await this.i18nRuntime.initialize();
|
|
18098
18863
|
await this.verifyAppStructure();
|
|
18099
18864
|
await this.routeManager.discoverRoutes();
|
|
@@ -18125,6 +18890,7 @@ var _FarmApp = class _FarmApp {
|
|
|
18125
18890
|
preset: config.preset ?? "node-server",
|
|
18126
18891
|
deploy: config.deploy || {},
|
|
18127
18892
|
storage: config.storage || {},
|
|
18893
|
+
cache: config.cache || {},
|
|
18128
18894
|
integrations: config.integrations || {},
|
|
18129
18895
|
plugins: config.plugins || [],
|
|
18130
18896
|
migrations: config.migrations || { commands: [] },
|
|
@@ -18536,6 +19302,29 @@ var fs3 = __toESM(require("fs"));
|
|
|
18536
19302
|
var path10 = __toESM(require("path"));
|
|
18537
19303
|
init_route_runtime();
|
|
18538
19304
|
|
|
19305
|
+
// src/api/runtime.ts
|
|
19306
|
+
init_cache_invalidation();
|
|
19307
|
+
|
|
19308
|
+
// src/api/endpoint.ts
|
|
19309
|
+
var import_better_call = require("better-call");
|
|
19310
|
+
var _EndpointFailure = class _EndpointFailure extends Error {
|
|
19311
|
+
constructor(code, data, options) {
|
|
19312
|
+
super(options.message);
|
|
19313
|
+
this.name = "EndpointFailure";
|
|
19314
|
+
this.code = code;
|
|
19315
|
+
this.data = data;
|
|
19316
|
+
this.status = options.status;
|
|
19317
|
+
}
|
|
19318
|
+
};
|
|
19319
|
+
__name(_EndpointFailure, "EndpointFailure");
|
|
19320
|
+
var EndpointFailure = _EndpointFailure;
|
|
19321
|
+
function isEndpointFailure(value) {
|
|
19322
|
+
return value instanceof EndpointFailure;
|
|
19323
|
+
}
|
|
19324
|
+
__name(isEndpointFailure, "isEndpointFailure");
|
|
19325
|
+
var EMPTY_ENDPOINT_MIDDLEWARE = Object.freeze([]);
|
|
19326
|
+
var EMPTY_ENDPOINT_CONTEXT = Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
19327
|
+
|
|
18539
19328
|
// src/api/runtime.ts
|
|
18540
19329
|
function matchAPIRoute(routes, pathname) {
|
|
18541
19330
|
const exactRoute = routes.get(pathname);
|
|
@@ -18568,10 +19357,10 @@ __name(invokeAPIRouteEndpoint, "invokeAPIRouteEndpoint");
|
|
|
18568
19357
|
async function invokeAPIRouteEndpointInContext(endpoint, request, params) {
|
|
18569
19358
|
const farmHandler = endpoint.__handler || (isFarmContextHandler(endpoint) ? endpoint : null);
|
|
18570
19359
|
if (!farmHandler) {
|
|
18571
|
-
const
|
|
19360
|
+
const result = await endpoint(request, {
|
|
18572
19361
|
params: Promise.resolve(params)
|
|
18573
19362
|
});
|
|
18574
|
-
return normalizeRouteResponse(
|
|
19363
|
+
return normalizeRouteResponse(result);
|
|
18575
19364
|
}
|
|
18576
19365
|
const url = new URL(request.url);
|
|
18577
19366
|
const query = {};
|
|
@@ -18580,7 +19369,7 @@ async function invokeAPIRouteEndpointInContext(endpoint, request, params) {
|
|
|
18580
19369
|
});
|
|
18581
19370
|
let body = void 0;
|
|
18582
19371
|
if (request.method.toUpperCase() !== "GET" && request.method.toUpperCase() !== "HEAD") {
|
|
18583
|
-
body = await
|
|
19372
|
+
body = await readRequestBody2(request);
|
|
18584
19373
|
}
|
|
18585
19374
|
const headers = Object.fromEntries(request.headers.entries());
|
|
18586
19375
|
const types = endpoint.__types || {};
|
|
@@ -18596,15 +19385,30 @@ async function invokeAPIRouteEndpointInContext(endpoint, request, params) {
|
|
|
18596
19385
|
if (headersValidation instanceof Response) {
|
|
18597
19386
|
return headersValidation;
|
|
18598
19387
|
}
|
|
18599
|
-
const
|
|
19388
|
+
const handlerContext = {
|
|
18600
19389
|
query: queryValidation,
|
|
18601
19390
|
body: bodyValidation,
|
|
18602
19391
|
headers: headersValidation,
|
|
18603
19392
|
request,
|
|
18604
19393
|
context: {},
|
|
18605
19394
|
params
|
|
18606
|
-
}
|
|
18607
|
-
|
|
19395
|
+
};
|
|
19396
|
+
let execution;
|
|
19397
|
+
try {
|
|
19398
|
+
execution = typeof endpoint.__farmInvoke === "function" ? await endpoint.__farmInvoke(handlerContext) : {
|
|
19399
|
+
result: await farmHandler(handlerContext),
|
|
19400
|
+
context: handlerContext.context,
|
|
19401
|
+
handlerExecuted: true,
|
|
19402
|
+
invalidations: []
|
|
19403
|
+
};
|
|
19404
|
+
} catch (error) {
|
|
19405
|
+
if (isEndpointFailure(error)) {
|
|
19406
|
+
return createEndpointFailureResponse(error);
|
|
19407
|
+
}
|
|
19408
|
+
throw error;
|
|
19409
|
+
}
|
|
19410
|
+
const response = normalizeRouteResponse(execution.result);
|
|
19411
|
+
return attachEndpointInvalidations(response, execution.invalidations);
|
|
18608
19412
|
}
|
|
18609
19413
|
__name(invokeAPIRouteEndpointInContext, "invokeAPIRouteEndpointInContext");
|
|
18610
19414
|
function normalizeRouteResponse(result) {
|
|
@@ -18624,6 +19428,40 @@ function isWebResponse2(value) {
|
|
|
18624
19428
|
return value instanceof Response || typeof value === "object" && value !== null && "headers" in value && "status" in value && typeof value.arrayBuffer === "function";
|
|
18625
19429
|
}
|
|
18626
19430
|
__name(isWebResponse2, "isWebResponse");
|
|
19431
|
+
function attachEndpointInvalidations(response, keys) {
|
|
19432
|
+
const existing = decodeFarmCacheInvalidations(
|
|
19433
|
+
response.headers.get(FARM_CACHE_INVALIDATION_HEADER)
|
|
19434
|
+
);
|
|
19435
|
+
const encoded = encodeFarmCacheInvalidations([...existing, ...keys]);
|
|
19436
|
+
if (!encoded) return response;
|
|
19437
|
+
const headers = new Headers(response.headers);
|
|
19438
|
+
headers.set(FARM_CACHE_INVALIDATION_HEADER, encoded);
|
|
19439
|
+
return new Response(response.body, {
|
|
19440
|
+
status: response.status,
|
|
19441
|
+
statusText: response.statusText,
|
|
19442
|
+
headers
|
|
19443
|
+
});
|
|
19444
|
+
}
|
|
19445
|
+
__name(attachEndpointInvalidations, "attachEndpointInvalidations");
|
|
19446
|
+
function createEndpointFailureResponse(failure) {
|
|
19447
|
+
return new Response(
|
|
19448
|
+
JSON.stringify({
|
|
19449
|
+
error: {
|
|
19450
|
+
code: failure.code,
|
|
19451
|
+
message: failure.message,
|
|
19452
|
+
data: failure.data
|
|
19453
|
+
}
|
|
19454
|
+
}),
|
|
19455
|
+
{
|
|
19456
|
+
status: failure.status,
|
|
19457
|
+
headers: {
|
|
19458
|
+
"cache-control": "no-store",
|
|
19459
|
+
"content-type": "application/json"
|
|
19460
|
+
}
|
|
19461
|
+
}
|
|
19462
|
+
);
|
|
19463
|
+
}
|
|
19464
|
+
__name(createEndpointFailureResponse, "createEndpointFailureResponse");
|
|
18627
19465
|
function isFarmContextHandler(endpoint) {
|
|
18628
19466
|
if (typeof endpoint !== "function") {
|
|
18629
19467
|
return false;
|
|
@@ -18635,17 +19473,50 @@ function isFarmContextHandler(endpoint) {
|
|
|
18635
19473
|
return firstParameter === "ctx" || firstParameter === "context" || firstParameter.startsWith("{");
|
|
18636
19474
|
}
|
|
18637
19475
|
__name(isFarmContextHandler, "isFarmContextHandler");
|
|
18638
|
-
async function
|
|
19476
|
+
async function readRequestBody2(request) {
|
|
19477
|
+
const contentType = request.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
|
|
18639
19478
|
try {
|
|
19479
|
+
if (contentType === "multipart/form-data") {
|
|
19480
|
+
return formDataToObject(await request.clone().formData());
|
|
19481
|
+
}
|
|
18640
19482
|
const text2 = await request.clone().text();
|
|
18641
|
-
if (text2)
|
|
19483
|
+
if (!text2) return void 0;
|
|
19484
|
+
if (contentType === "application/x-www-form-urlencoded") {
|
|
19485
|
+
return searchParamsToObject2(new URLSearchParams(text2));
|
|
19486
|
+
}
|
|
19487
|
+
if (contentType === "application/json" || contentType?.endsWith("+json")) {
|
|
18642
19488
|
return JSON.parse(text2);
|
|
18643
19489
|
}
|
|
19490
|
+
return JSON.parse(text2);
|
|
18644
19491
|
} catch {
|
|
18645
19492
|
}
|
|
18646
19493
|
return void 0;
|
|
18647
19494
|
}
|
|
18648
|
-
__name(
|
|
19495
|
+
__name(readRequestBody2, "readRequestBody");
|
|
19496
|
+
function formDataToObject(formData) {
|
|
19497
|
+
return entriesToObject(formData.entries());
|
|
19498
|
+
}
|
|
19499
|
+
__name(formDataToObject, "formDataToObject");
|
|
19500
|
+
function searchParamsToObject2(searchParams) {
|
|
19501
|
+
return entriesToObject(searchParams.entries());
|
|
19502
|
+
}
|
|
19503
|
+
__name(searchParamsToObject2, "searchParamsToObject");
|
|
19504
|
+
function entriesToObject(entries) {
|
|
19505
|
+
const output = /* @__PURE__ */ Object.create(null);
|
|
19506
|
+
for (const [key, value] of entries) {
|
|
19507
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
|
|
19508
|
+
const current = output[key];
|
|
19509
|
+
if (current === void 0) {
|
|
19510
|
+
output[key] = value;
|
|
19511
|
+
} else if (Array.isArray(current)) {
|
|
19512
|
+
current.push(value);
|
|
19513
|
+
} else {
|
|
19514
|
+
output[key] = [current, value];
|
|
19515
|
+
}
|
|
19516
|
+
}
|
|
19517
|
+
return output;
|
|
19518
|
+
}
|
|
19519
|
+
__name(entriesToObject, "entriesToObject");
|
|
18649
19520
|
function validateInput(schema, value, error) {
|
|
18650
19521
|
if (!schema || typeof schema.parse !== "function") {
|
|
18651
19522
|
return value;
|
|
@@ -19652,7 +20523,7 @@ var _MiddlewareManager = class _MiddlewareManager {
|
|
|
19652
20523
|
if (!nestedMatch.matched) {
|
|
19653
20524
|
return { matched: false };
|
|
19654
20525
|
}
|
|
19655
|
-
const params = { ...nestedMatch.params
|
|
20526
|
+
const params = { ...nestedMatch.params };
|
|
19656
20527
|
delete params.__farmRest;
|
|
19657
20528
|
return {
|
|
19658
20529
|
matched: true,
|
|
@@ -19800,6 +20671,7 @@ async function generateRouteTypes(options) {
|
|
|
19800
20671
|
absolute: false
|
|
19801
20672
|
});
|
|
19802
20673
|
for (const file of pageFiles) {
|
|
20674
|
+
if (parseRouteSlotFile(file)) continue;
|
|
19803
20675
|
const route = parseRoutePath(file);
|
|
19804
20676
|
if (route.type === "page") {
|
|
19805
20677
|
const pattern = createRoutePattern(route);
|
|
@@ -20534,6 +21406,12 @@ function transformError(id, message) {
|
|
|
20534
21406
|
}
|
|
20535
21407
|
__name(transformError, "transformError");
|
|
20536
21408
|
|
|
21409
|
+
// package.json
|
|
21410
|
+
var version = "0.1.0-beta.4";
|
|
21411
|
+
|
|
21412
|
+
// src/version.ts
|
|
21413
|
+
var FARM_VERSION = version;
|
|
21414
|
+
|
|
20537
21415
|
// src/after.ts
|
|
20538
21416
|
var import_node_async_hooks4 = require("async_hooks");
|
|
20539
21417
|
var AFTER_STORAGE = /* @__PURE__ */ Symbol.for("@farm.js/core/after-storage");
|
|
@@ -21005,7 +21883,7 @@ function isResolvedEnvScope(value) {
|
|
|
21005
21883
|
}
|
|
21006
21884
|
__name(isResolvedEnvScope, "isResolvedEnvScope");
|
|
21007
21885
|
function isPotentialProgrammaticRouteSourceFile(normalizedFile, srcDirSlug) {
|
|
21008
|
-
return normalizedFile.startsWith(`${srcDirSlug}/`) && /\.(ts|tsx|js|jsx)$/.test(normalizedFile) &&
|
|
21886
|
+
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");
|
|
21009
21887
|
}
|
|
21010
21888
|
__name(isPotentialProgrammaticRouteSourceFile, "isPotentialProgrammaticRouteSourceFile");
|
|
21011
21889
|
function fileContainsProgrammaticPageRoute(file) {
|
|
@@ -21248,7 +22126,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
21248
22126
|
}, "isProgrammaticRouteSourceFile");
|
|
21249
22127
|
const isAppRuntimeFile = /* @__PURE__ */ __name((file) => {
|
|
21250
22128
|
const normalized = file.replace(/\\/g, "/");
|
|
21251
|
-
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(
|
|
22129
|
+
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(
|
|
21252
22130
|
normalized
|
|
21253
22131
|
);
|
|
21254
22132
|
}, "isAppRuntimeFile");
|
|
@@ -21939,7 +22817,10 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
21939
22817
|
method: req.method || "GET"
|
|
21940
22818
|
});
|
|
21941
22819
|
}
|
|
21942
|
-
const
|
|
22820
|
+
const interceptFromHeader = request.headers.get("x-farm-intercept-from") || void 0;
|
|
22821
|
+
const match = routeManager3.matchRoute(targetRequestUrl.pathname, {
|
|
22822
|
+
interceptFrom: interceptFromHeader
|
|
22823
|
+
});
|
|
21943
22824
|
if (pm) {
|
|
21944
22825
|
await pm.runHookParallel("afterRouteMatch", {
|
|
21945
22826
|
pathname: targetPath,
|
|
@@ -21955,7 +22836,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
21955
22836
|
res.end(JSON.stringify({ error: "Route not found" }));
|
|
21956
22837
|
return;
|
|
21957
22838
|
}
|
|
21958
|
-
const { route, params, layouts } = match;
|
|
22839
|
+
const { route, params, layouts, slots } = match;
|
|
21959
22840
|
if (!route) {
|
|
21960
22841
|
res.statusCode = 404;
|
|
21961
22842
|
res.setHeader("Content-Type", "application/json");
|
|
@@ -22010,6 +22891,54 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
22010
22891
|
search: searchParams,
|
|
22011
22892
|
routePath: route.pattern
|
|
22012
22893
|
});
|
|
22894
|
+
const routeSlots = await Promise.all(
|
|
22895
|
+
slots.map(async (slot) => {
|
|
22896
|
+
const slotModule = await routeManager3.loadRouteModule(slot.route.modulePath);
|
|
22897
|
+
const slotMetadata = getClientModuleMetadata(
|
|
22898
|
+
slot.route.modulePath,
|
|
22899
|
+
server.config.root
|
|
22900
|
+
);
|
|
22901
|
+
const slotContext = await resolveFarmRouteContext(farmApp.getConfig(), {
|
|
22902
|
+
request,
|
|
22903
|
+
params: slot.params,
|
|
22904
|
+
search: searchParams,
|
|
22905
|
+
path: targetUrl.pathname
|
|
22906
|
+
});
|
|
22907
|
+
const slotProps = await parseRouteModuleProps2(slotModule, {
|
|
22908
|
+
props: withFarmRouteContext(
|
|
22909
|
+
{
|
|
22910
|
+
params: slot.params,
|
|
22911
|
+
searchParams: Promise.resolve(searchParams),
|
|
22912
|
+
path: targetUrl.pathname
|
|
22913
|
+
},
|
|
22914
|
+
slotContext
|
|
22915
|
+
),
|
|
22916
|
+
search: searchParams,
|
|
22917
|
+
routePath: slot.route.pattern
|
|
22918
|
+
});
|
|
22919
|
+
return {
|
|
22920
|
+
name: slot.name,
|
|
22921
|
+
ownerPattern: slot.ownerPattern,
|
|
22922
|
+
containerId: slot.containerId,
|
|
22923
|
+
interception: slot.interception,
|
|
22924
|
+
fallback: slot.fallback,
|
|
22925
|
+
modulePath: slot.route.modulePath,
|
|
22926
|
+
isClientComponent: slotMetadata.isClientComponent,
|
|
22927
|
+
shouldHydrate: slotMetadata.shouldHydrate,
|
|
22928
|
+
props: {
|
|
22929
|
+
params: slotProps.params,
|
|
22930
|
+
search: slotProps.search,
|
|
22931
|
+
searchParams: slotProps.search,
|
|
22932
|
+
..."data" in slotProps ? { data: slotProps.data } : {},
|
|
22933
|
+
...slotProps.__farmCanonicalPath ? {
|
|
22934
|
+
__farmCanonicalPath: slotProps.__farmCanonicalPath
|
|
22935
|
+
} : {},
|
|
22936
|
+
...slotProps.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {},
|
|
22937
|
+
path: targetUrl.pathname
|
|
22938
|
+
}
|
|
22939
|
+
};
|
|
22940
|
+
})
|
|
22941
|
+
);
|
|
22013
22942
|
const projectRoot = server.config.root;
|
|
22014
22943
|
const toUrlPath = /* @__PURE__ */ __name((absolutePath) => {
|
|
22015
22944
|
if (absolutePath.startsWith(projectRoot)) {
|
|
@@ -22030,13 +22959,21 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
22030
22959
|
},
|
|
22031
22960
|
canonicalPath: routeProps.__farmCanonicalPath,
|
|
22032
22961
|
modulePath: toUrlPath(route.modulePath),
|
|
22033
|
-
isClientComponent,
|
|
22034
|
-
shouldHydrate,
|
|
22962
|
+
isClientComponent: routeSlots.length > 0 ? false : isClientComponent,
|
|
22963
|
+
shouldHydrate: shouldHydrate || routeSlots.some((slot) => slot.isClientComponent || slot.shouldHydrate),
|
|
22035
22964
|
metadata: {
|
|
22036
22965
|
title: mergedMetadata.title,
|
|
22037
22966
|
description: mergedMetadata.description
|
|
22038
22967
|
},
|
|
22039
22968
|
layoutModules: layouts.map((l) => toUrlPath(l.modulePath)),
|
|
22969
|
+
routeSlots: routeSlots.map((slot) => ({
|
|
22970
|
+
...slot,
|
|
22971
|
+
modulePath: toUrlPath(slot.modulePath)
|
|
22972
|
+
})),
|
|
22973
|
+
interception: routeSlots.some((slot) => slot.interception) ? {
|
|
22974
|
+
from: interceptFromHeader,
|
|
22975
|
+
slots: routeSlots.filter((slot) => slot.interception).map((slot) => slot.name)
|
|
22976
|
+
} : void 0,
|
|
22040
22977
|
i18n: getFarmI18nClientSnapshot()
|
|
22041
22978
|
};
|
|
22042
22979
|
await sendWebResponse(
|
|
@@ -22372,6 +23309,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
22372
23309
|
export const getManifest = () => ({
|
|
22373
23310
|
routes: {},
|
|
22374
23311
|
layouts: {},
|
|
23312
|
+
slots: [],
|
|
22375
23313
|
clientEntry: "/@farm/client.js",
|
|
22376
23314
|
sharedAssets: []
|
|
22377
23315
|
});
|
|
@@ -22382,6 +23320,7 @@ export const getManifest = () => ({
|
|
|
22382
23320
|
clientEntry: "/@farm/client.js",
|
|
22383
23321
|
routes: {},
|
|
22384
23322
|
layouts: {},
|
|
23323
|
+
slots: [],
|
|
22385
23324
|
sharedAssets: [
|
|
22386
23325
|
{
|
|
22387
23326
|
tag: "link",
|
|
@@ -22411,6 +23350,13 @@ export const getManifest = () => ({
|
|
|
22411
23350
|
assets: []
|
|
22412
23351
|
};
|
|
22413
23352
|
}
|
|
23353
|
+
for (const slot of manifest.slots) {
|
|
23354
|
+
fullManifest.slots.push({
|
|
23355
|
+
...slot,
|
|
23356
|
+
preloads: [slot.modulePath],
|
|
23357
|
+
assets: []
|
|
23358
|
+
});
|
|
23359
|
+
}
|
|
22414
23360
|
return `
|
|
22415
23361
|
// Auto-generated manifest for SPA navigation (TanStack Start pattern)
|
|
22416
23362
|
// This manifest is inlined in the server bundle - no file on disk
|
|
@@ -23053,7 +23999,7 @@ window.__FARM_WRAP_PROVIDERS__ = wrapWithIntegrationProviders;
|
|
|
23053
23999
|
|
|
23054
24000
|
// Get manifest from window (inlined by server in HTML)
|
|
23055
24001
|
// Fallback to empty manifest if not available yet
|
|
23056
|
-
const getManifest = () => window.__FARM_MANIFEST__ || { routes: {}, layouts: {}, clientEntry: '', sharedAssets: [] };
|
|
24002
|
+
const getManifest = () => window.__FARM_MANIFEST__ || { routes: {}, layouts: {}, slots: [], clientEntry: '', sharedAssets: [] };
|
|
23057
24003
|
|
|
23058
24004
|
// ====== CLIENT-SIDE ROUTE MATCHING ======
|
|
23059
24005
|
// Matches URL to route using manifest (no server request!)
|
|
@@ -23392,6 +24338,9 @@ let LayoutComponent = null;
|
|
|
23392
24338
|
|
|
23393
24339
|
// Track if we've taken over rendering from SSR
|
|
23394
24340
|
let hasClientTakenOver = false;
|
|
24341
|
+
const routeSlotRoots = new Map();
|
|
24342
|
+
const routeSlotDefinitions = new Map();
|
|
24343
|
+
let activeRouteInterception = null;
|
|
23395
24344
|
|
|
23396
24345
|
function normalizeServerProps(rawProps) {
|
|
23397
24346
|
const props = rawProps && typeof rawProps === 'object' ? { ...rawProps } : {};
|
|
@@ -23404,6 +24353,123 @@ function normalizeServerProps(rawProps) {
|
|
|
23404
24353
|
return props;
|
|
23405
24354
|
}
|
|
23406
24355
|
|
|
24356
|
+
function getRouteSlotKey(slot) {
|
|
24357
|
+
return slot.ownerPattern + ':' + slot.name;
|
|
24358
|
+
}
|
|
24359
|
+
|
|
24360
|
+
async function renderRouteSlot(slot, mode = 'render') {
|
|
24361
|
+
const container = document.getElementById(slot.containerId);
|
|
24362
|
+
if (!container || !slot.modulePath) return false;
|
|
24363
|
+
if (mode === 'intercept' && !slot.isClientComponent && !slot.shouldHydrate) {
|
|
24364
|
+
return false;
|
|
24365
|
+
}
|
|
24366
|
+
|
|
24367
|
+
let slotModule = pageModuleCache.get(slot.modulePath);
|
|
24368
|
+
if (!slotModule) {
|
|
24369
|
+
slotModule = await import(/* @vite-ignore */ slot.modulePath);
|
|
24370
|
+
pageModuleCache.set(slot.modulePath, slotModule);
|
|
24371
|
+
}
|
|
24372
|
+
const SlotComponent = slotModule?.default;
|
|
24373
|
+
if (!SlotComponent) return false;
|
|
24374
|
+
|
|
24375
|
+
const props = reviveDeferredData(
|
|
24376
|
+
normalizeServerProps(slot.props || {}),
|
|
24377
|
+
window.__FARM_DEFERRED_DATA__ || {},
|
|
24378
|
+
);
|
|
24379
|
+
const element = wrapWithIntegrationProviders(
|
|
24380
|
+
React.createElement(SlotComponent, props),
|
|
24381
|
+
);
|
|
24382
|
+
const key = getRouteSlotKey(slot);
|
|
24383
|
+
const existingRoot = routeSlotRoots.get(key);
|
|
24384
|
+
|
|
24385
|
+
if (mode === 'hydrate') {
|
|
24386
|
+
if (existingRoot) return true;
|
|
24387
|
+
const root = hydrateRoot(container, element);
|
|
24388
|
+
routeSlotRoots.set(key, root);
|
|
24389
|
+
} else {
|
|
24390
|
+
if (existingRoot) {
|
|
24391
|
+
try { existingRoot.unmount(); } catch (error) {}
|
|
24392
|
+
}
|
|
24393
|
+
const root = createRoot(container);
|
|
24394
|
+
root.render(element);
|
|
24395
|
+
routeSlotRoots.set(key, root);
|
|
24396
|
+
}
|
|
24397
|
+
|
|
24398
|
+
routeSlotDefinitions.set(key, slot);
|
|
24399
|
+
return true;
|
|
24400
|
+
}
|
|
24401
|
+
|
|
24402
|
+
async function hydrateInitialRouteSlots() {
|
|
24403
|
+
const slots = Array.isArray(window.__FARM_ROUTE_SLOTS__)
|
|
24404
|
+
? window.__FARM_ROUTE_SLOTS__
|
|
24405
|
+
: [];
|
|
24406
|
+
let hydrated = false;
|
|
24407
|
+
|
|
24408
|
+
for (const slot of slots) {
|
|
24409
|
+
routeSlotDefinitions.set(getRouteSlotKey(slot), slot);
|
|
24410
|
+
if (!slot.isClientComponent && !slot.shouldHydrate) continue;
|
|
24411
|
+
try {
|
|
24412
|
+
hydrated = (await renderRouteSlot(slot, 'hydrate')) || hydrated;
|
|
24413
|
+
} catch (error) {
|
|
24414
|
+
console.warn('[Farm.js] Could not hydrate route slot:', slot.name, error);
|
|
24415
|
+
}
|
|
24416
|
+
}
|
|
24417
|
+
|
|
24418
|
+
return hydrated;
|
|
24419
|
+
}
|
|
24420
|
+
|
|
24421
|
+
async function renderRouteInterception(pageData) {
|
|
24422
|
+
const slots = Array.isArray(pageData.routeSlots)
|
|
24423
|
+
? pageData.routeSlots.filter((slot) => slot.interception)
|
|
24424
|
+
: [];
|
|
24425
|
+
if (!pageData.interception || slots.length === 0) return false;
|
|
24426
|
+
|
|
24427
|
+
const previous = new Map();
|
|
24428
|
+
for (const slot of slots) {
|
|
24429
|
+
const key = getRouteSlotKey(slot);
|
|
24430
|
+
previous.set(key, routeSlotDefinitions.get(key) || null);
|
|
24431
|
+
if (!(await renderRouteSlot(slot, 'intercept'))) {
|
|
24432
|
+
return false;
|
|
24433
|
+
}
|
|
24434
|
+
}
|
|
24435
|
+
|
|
24436
|
+
activeRouteInterception = {
|
|
24437
|
+
from: pageData.interception.from,
|
|
24438
|
+
slots,
|
|
24439
|
+
previous,
|
|
24440
|
+
};
|
|
24441
|
+
return true;
|
|
24442
|
+
}
|
|
24443
|
+
|
|
24444
|
+
async function clearRouteInterception(destination) {
|
|
24445
|
+
if (!activeRouteInterception) return false;
|
|
24446
|
+
const active = activeRouteInterception;
|
|
24447
|
+
activeRouteInterception = null;
|
|
24448
|
+
|
|
24449
|
+
for (const slot of active.slots) {
|
|
24450
|
+
const key = getRouteSlotKey(slot);
|
|
24451
|
+
const root = routeSlotRoots.get(key);
|
|
24452
|
+
if (root) {
|
|
24453
|
+
try { root.unmount(); } catch (error) {}
|
|
24454
|
+
routeSlotRoots.delete(key);
|
|
24455
|
+
}
|
|
24456
|
+
|
|
24457
|
+
const previous = active.previous.get(key);
|
|
24458
|
+
if (previous && (previous.isClientComponent || previous.shouldHydrate)) {
|
|
24459
|
+
await renderRouteSlot(previous, 'render');
|
|
24460
|
+
} else {
|
|
24461
|
+
const container = document.getElementById(slot.containerId);
|
|
24462
|
+
if (container) container.replaceChildren();
|
|
24463
|
+
if (previous) routeSlotDefinitions.set(key, previous);
|
|
24464
|
+
else routeSlotDefinitions.delete(key);
|
|
24465
|
+
}
|
|
24466
|
+
}
|
|
24467
|
+
|
|
24468
|
+
if (!active.from) return false;
|
|
24469
|
+
const background = new URL(active.from, window.location.origin);
|
|
24470
|
+
return destination === background.pathname + background.search;
|
|
24471
|
+
}
|
|
24472
|
+
|
|
23407
24473
|
function applyCanonicalPathFromProps(props) {
|
|
23408
24474
|
const canonicalPath = props && typeof props.__farmCanonicalPath === 'string'
|
|
23409
24475
|
? props.__farmCanonicalPath
|
|
@@ -23638,6 +24704,17 @@ async function tryHydrateImportedPage(
|
|
|
23638
24704
|
async function renderPage(pageData) {
|
|
23639
24705
|
const container = document.getElementById('root');
|
|
23640
24706
|
if (!container) return;
|
|
24707
|
+
const destination = window.location.pathname + window.location.search;
|
|
24708
|
+
|
|
24709
|
+
if (pageData.interception) {
|
|
24710
|
+
if (await renderRouteInterception(pageData)) return;
|
|
24711
|
+
window.location.assign(destination);
|
|
24712
|
+
return;
|
|
24713
|
+
}
|
|
24714
|
+
|
|
24715
|
+
if (await clearRouteInterception(destination)) {
|
|
24716
|
+
return;
|
|
24717
|
+
}
|
|
23641
24718
|
|
|
23642
24719
|
const route = {
|
|
23643
24720
|
modulePath: pageData.modulePath,
|
|
@@ -23866,7 +24943,9 @@ async function hydrate() {
|
|
|
23866
24943
|
window.__FARM_SHOULD_HYDRATE__ === true ||
|
|
23867
24944
|
isClientComponent ||
|
|
23868
24945
|
await moduleLooksClient(modulePath);
|
|
24946
|
+
const hydratedSlots = await hydrateInitialRouteSlots();
|
|
23869
24947
|
if (!shouldHydrate) {
|
|
24948
|
+
if (hydratedSlots) replayPreHydrationClicks();
|
|
23870
24949
|
console.log('[Farm.js] Server component - SPA router ready')
|
|
23871
24950
|
return
|
|
23872
24951
|
}
|
|
@@ -24131,7 +25210,7 @@ async function defineConfig2(config = {}) {
|
|
|
24131
25210
|
const isExposed = hostConfig === true || hostConfig === "0.0.0.0";
|
|
24132
25211
|
console.log("");
|
|
24133
25212
|
console.log(
|
|
24134
|
-
` ${pc.bold(pc.green("Farm.js"))} ${pc.dim(
|
|
25213
|
+
` ${pc.bold(pc.green("Farm.js"))} ${pc.dim(`v${FARM_VERSION}`)} ${pc.dim(`ready in ${elapsed}ms`)}`
|
|
24135
25214
|
);
|
|
24136
25215
|
console.log("");
|
|
24137
25216
|
console.log(
|
|
@@ -24250,7 +25329,7 @@ function createServerFn(options) {
|
|
|
24250
25329
|
const middleware = resolveServerFnMiddleware(options.middleware);
|
|
24251
25330
|
const serverFn = /* @__PURE__ */ __name(async (value) => {
|
|
24252
25331
|
const formData = isFormData(value) ? value : void 0;
|
|
24253
|
-
const rawInput = formData ?
|
|
25332
|
+
const rawInput = formData ? formDataToObject2(formData) : value;
|
|
24254
25333
|
const input = await _parseServerFnSchema(options.input, rawInput, "input");
|
|
24255
25334
|
const executionContext = getServerActionExecutionContext();
|
|
24256
25335
|
const request = executionContext?.request ?? _resolveCurrentRequest();
|
|
@@ -24262,8 +25341,21 @@ function createServerFn(options) {
|
|
|
24262
25341
|
request,
|
|
24263
25342
|
signal
|
|
24264
25343
|
};
|
|
24265
|
-
|
|
24266
|
-
|
|
25344
|
+
let resolvedContext = Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
25345
|
+
const result = await runServerFnMiddleware(middleware, handlerContext, async (context) => {
|
|
25346
|
+
resolvedContext = context.context;
|
|
25347
|
+
return options.handler(context);
|
|
25348
|
+
});
|
|
25349
|
+
const parsedResult = await _parseServerFnSchema(options.output, result, "output");
|
|
25350
|
+
if (options.invalidates) {
|
|
25351
|
+
const declaration = typeof options.invalidates === "function" ? await options.invalidates({
|
|
25352
|
+
...handlerContext,
|
|
25353
|
+
context: resolvedContext,
|
|
25354
|
+
result: parsedResult
|
|
25355
|
+
}) : options.invalidates;
|
|
25356
|
+
await applyFarmCacheInvalidationTargets(declaration);
|
|
25357
|
+
}
|
|
25358
|
+
return parsedResult;
|
|
24267
25359
|
}, "serverFn");
|
|
24268
25360
|
Object.defineProperties(serverFn, {
|
|
24269
25361
|
[FARM_SERVER_FN_SYMBOL]: {
|
|
@@ -24285,6 +25377,10 @@ function createServerFn(options) {
|
|
|
24285
25377
|
__farmServerFnMiddleware: {
|
|
24286
25378
|
value: middleware,
|
|
24287
25379
|
enumerable: false
|
|
25380
|
+
},
|
|
25381
|
+
__farmServerFnInvalidates: {
|
|
25382
|
+
value: options.invalidates,
|
|
25383
|
+
enumerable: false
|
|
24288
25384
|
}
|
|
24289
25385
|
});
|
|
24290
25386
|
return serverFn;
|
|
@@ -24382,7 +25478,7 @@ function unwrapSafeParseResult(result) {
|
|
|
24382
25478
|
return result;
|
|
24383
25479
|
}
|
|
24384
25480
|
__name(unwrapSafeParseResult, "unwrapSafeParseResult");
|
|
24385
|
-
function
|
|
25481
|
+
function formDataToObject2(formData) {
|
|
24386
25482
|
const output = /* @__PURE__ */ Object.create(null);
|
|
24387
25483
|
for (const [key, value] of formData.entries()) {
|
|
24388
25484
|
if (!isSafeFormKey(key)) continue;
|
|
@@ -24397,7 +25493,7 @@ function formDataToObject(formData) {
|
|
|
24397
25493
|
}
|
|
24398
25494
|
return output;
|
|
24399
25495
|
}
|
|
24400
|
-
__name(
|
|
25496
|
+
__name(formDataToObject2, "formDataToObject");
|
|
24401
25497
|
function isSafeFormKey(key) {
|
|
24402
25498
|
return !key.startsWith("$ACTION_") && !UNSAFE_FORM_KEYS.has(key);
|
|
24403
25499
|
}
|
|
@@ -24459,7 +25555,7 @@ function createServerQuery(options) {
|
|
|
24459
25555
|
tags: [createRouteDataCacheTag(routeKey)],
|
|
24460
25556
|
revalidate: staleTime === false ? false : Math.max(1, Math.ceil(staleTime / 1e3))
|
|
24461
25557
|
});
|
|
24462
|
-
updatedAt = cache.
|
|
25558
|
+
updatedAt = (await cache.getEntryAsync(cacheKey, { allowStale: true }))?.createdAt ?? Date.now();
|
|
24463
25559
|
}
|
|
24464
25560
|
return createFarmServerQueryResult(data, {
|
|
24465
25561
|
key: clientKey,
|
|
@@ -25295,7 +26391,7 @@ __name(createLoggerPlugin, "createLoggerPlugin");
|
|
|
25295
26391
|
// src/server/vite-config.ts
|
|
25296
26392
|
function mergeNoExternal(farmValue, userValue) {
|
|
25297
26393
|
if (farmValue === true || userValue === true) return true;
|
|
25298
|
-
const normalize = /* @__PURE__ */ __name((value) => value == null ? [] : Array.isArray(value) ? value : [value], "normalize");
|
|
26394
|
+
const normalize = /* @__PURE__ */ __name((value) => value == null || value === true ? [] : Array.isArray(value) ? value : [value], "normalize");
|
|
25299
26395
|
return Array.from(/* @__PURE__ */ new Set([...normalize(farmValue), ...normalize(userValue)]));
|
|
25300
26396
|
}
|
|
25301
26397
|
__name(mergeNoExternal, "mergeNoExternal");
|
|
@@ -25308,6 +26404,13 @@ function mergeFarmViteConfig(farmConfig, userConfig = {}) {
|
|
|
25308
26404
|
...farmConfig.server,
|
|
25309
26405
|
...userConfig.server
|
|
25310
26406
|
},
|
|
26407
|
+
resolve: {
|
|
26408
|
+
...farmConfig.resolve,
|
|
26409
|
+
...userConfig.resolve,
|
|
26410
|
+
dedupe: Array.from(
|
|
26411
|
+
/* @__PURE__ */ new Set([...farmConfig.resolve?.dedupe || [], ...userConfig.resolve?.dedupe || []])
|
|
26412
|
+
)
|
|
26413
|
+
},
|
|
25311
26414
|
optimizeDeps: {
|
|
25312
26415
|
...farmConfig.optimizeDeps,
|
|
25313
26416
|
...userConfig.optimizeDeps,
|
|
@@ -25334,6 +26437,7 @@ function mergeFarmViteConfig(farmConfig, userConfig = {}) {
|
|
|
25334
26437
|
__name(mergeFarmViteConfig, "mergeFarmViteConfig");
|
|
25335
26438
|
|
|
25336
26439
|
// src/server/create-server.ts
|
|
26440
|
+
var DEFAULT_FARM_DEV_SERVER_PORT = 3e3;
|
|
25337
26441
|
function createBrandingPlugin() {
|
|
25338
26442
|
let serverStarted = false;
|
|
25339
26443
|
let startTime = Date.now();
|
|
@@ -25369,7 +26473,7 @@ function createBrandingPlugin() {
|
|
|
25369
26473
|
const pc = getColors();
|
|
25370
26474
|
console.log("");
|
|
25371
26475
|
console.log(
|
|
25372
|
-
` ${pc.bold(pc.green("Farm.js"))} ${pc.dim(
|
|
26476
|
+
` ${pc.bold(pc.green("Farm.js"))} ${pc.dim(`v${FARM_VERSION}`)} ${pc.dim(`ready in ${elapsed}ms`)}`
|
|
25373
26477
|
);
|
|
25374
26478
|
console.log("");
|
|
25375
26479
|
console.log(
|
|
@@ -25495,7 +26599,13 @@ async function createServer(config = {}) {
|
|
|
25495
26599
|
createBrandingPlugin()
|
|
25496
26600
|
],
|
|
25497
26601
|
server: {
|
|
25498
|
-
middlewareMode: false
|
|
26602
|
+
middlewareMode: false,
|
|
26603
|
+
port: DEFAULT_FARM_DEV_SERVER_PORT,
|
|
26604
|
+
strictPort: true
|
|
26605
|
+
},
|
|
26606
|
+
resolve: {
|
|
26607
|
+
// Keep framework and application modules on one React runtime.
|
|
26608
|
+
dedupe: ["react", "react-dom"]
|
|
25499
26609
|
},
|
|
25500
26610
|
optimizeDeps: {
|
|
25501
26611
|
// Avoid Vite scanning server/native-only deps from framework internals.
|
|
@@ -25570,7 +26680,7 @@ async function createServer(config = {}) {
|
|
|
25570
26680
|
}
|
|
25571
26681
|
}
|
|
25572
26682
|
__name(createServer, "createServer");
|
|
25573
|
-
async function startDevServer(config = {}, port
|
|
26683
|
+
async function startDevServer(config = {}, port) {
|
|
25574
26684
|
const server = await createServer(config);
|
|
25575
26685
|
await server.listen(port);
|
|
25576
26686
|
const pluginManager = server.__farmPluginManager;
|
|
@@ -25651,6 +26761,7 @@ function assertFunction(value, label) {
|
|
|
25651
26761
|
__name(assertFunction, "assertFunction");
|
|
25652
26762
|
// Annotate the CommonJS export names for ESM import in node:
|
|
25653
26763
|
0 && (module.exports = {
|
|
26764
|
+
DEFAULT_FARM_DEV_SERVER_PORT,
|
|
25654
26765
|
DEFAULT_SERVER_ACTION_BODY_SIZE_LIMIT,
|
|
25655
26766
|
FARM_SERVER_QUERY_SYMBOL,
|
|
25656
26767
|
FarmApp,
|
|
@@ -25663,7 +26774,9 @@ __name(assertFunction, "assertFunction");
|
|
|
25663
26774
|
_runWithAfterRequest,
|
|
25664
26775
|
_withAfterNodeMiddleware,
|
|
25665
26776
|
after,
|
|
26777
|
+
applyFarmCacheInvalidationTargets,
|
|
25666
26778
|
applyFarmCacheInvalidations,
|
|
26779
|
+
configureFarmCache,
|
|
25667
26780
|
createClientOnlyFn,
|
|
25668
26781
|
createFarmApp,
|
|
25669
26782
|
createFarmCacheKey,
|
|
@@ -25678,6 +26791,7 @@ __name(assertFunction, "assertFunction");
|
|
|
25678
26791
|
createServerQuery,
|
|
25679
26792
|
createStorageClient,
|
|
25680
26793
|
databaseStorage,
|
|
26794
|
+
defineCacheKey,
|
|
25681
26795
|
defineConfig,
|
|
25682
26796
|
defineStorageClient,
|
|
25683
26797
|
disposeStorage,
|
|
@@ -25728,6 +26842,7 @@ __name(assertFunction, "assertFunction");
|
|
|
25728
26842
|
segmentsToPattern,
|
|
25729
26843
|
sqliteStorage,
|
|
25730
26844
|
startDevServer,
|
|
26845
|
+
storageCacheAdapter,
|
|
25731
26846
|
toViteModuleId,
|
|
25732
26847
|
unstable_cache,
|
|
25733
26848
|
updateTag,
|