@farm.js/core 0.1.0-beta.95 → 0.1.0-beta.97
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/after.cjs +1 -1
- package/dist/after.mjs +1 -1
- package/dist/agent-runtime.d.mts +3 -2
- package/dist/agent-runtime.d.ts +3 -2
- package/dist/api/route-manager.cjs +43 -4
- package/dist/api/route-manager.d.mts +4 -3
- package/dist/api/route-manager.d.ts +4 -3
- package/dist/api/route-manager.mjs +7 -7
- package/dist/api/runtime.cjs +43 -4
- package/dist/api/runtime.d.mts +1 -1
- package/dist/api/runtime.d.ts +1 -1
- package/dist/api/runtime.mjs +5 -5
- package/dist/api.cjs +352 -109
- package/dist/api.d.mts +7 -6
- package/dist/api.d.ts +7 -6
- package/dist/api.mjs +19 -12
- package/dist/{app-CIIEvA4r.d.ts → app-CIOx3LvY.d.ts} +4 -4
- package/dist/{app-O4AEC1OH.d.mts → app-DBd6437H.d.mts} +4 -4
- package/dist/app-markdown.d.mts +4 -3
- package/dist/app-markdown.d.ts +4 -3
- package/dist/cache.cjs +42 -4
- package/dist/cache.d.mts +68 -1
- package/dist/cache.d.ts +68 -1
- package/dist/cache.mjs +3 -3
- package/dist/{chunk-AXVJCMVF.mjs → chunk-2HDOV47R.mjs} +3 -3
- package/dist/chunk-2HDOV47R.mjs.map +1 -0
- package/dist/{chunk-RBRLLZL5.mjs → chunk-34IAPZBG.mjs} +16 -3
- package/dist/chunk-34IAPZBG.mjs.map +1 -0
- package/dist/{chunk-VV24CC42.mjs → chunk-35NPLKQJ.mjs} +2 -2
- package/dist/{chunk-D7QH7MDU.mjs → chunk-3TWQERDE.mjs} +5 -4
- package/dist/chunk-3TWQERDE.mjs.map +1 -0
- package/dist/{chunk-RWYRFCLG.mjs → chunk-4X57GXQA.mjs} +2 -2
- package/dist/{chunk-KOTSX5JH.mjs → chunk-52BR7LTX.mjs} +30 -21
- package/dist/chunk-52BR7LTX.mjs.map +1 -0
- package/dist/{chunk-SALMKQXH.mjs → chunk-6EJHNHH4.mjs} +80 -27
- package/dist/chunk-6EJHNHH4.mjs.map +1 -0
- package/dist/{chunk-ZFNK77WN.mjs → chunk-6JNGOC37.mjs} +2 -2
- package/dist/{after.cjs.map → chunk-6JNGOC37.mjs.map} +1 -1
- package/dist/{chunk-MOW47IF5.mjs → chunk-6UYVU46O.mjs} +2 -2
- package/dist/{chunk-7MABZJIM.mjs → chunk-7PYVLJ4J.mjs} +1 -1
- package/dist/chunk-7PYVLJ4J.mjs.map +1 -0
- package/dist/{chunk-FLHLPB57.mjs → chunk-D7F7YZ7L.mjs} +93 -67
- package/dist/chunk-D7F7YZ7L.mjs.map +1 -0
- package/dist/chunk-DU3PKDVQ.mjs +35 -0
- package/dist/chunk-DU3PKDVQ.mjs.map +1 -0
- package/dist/{chunk-SCFX4UTD.mjs → chunk-EHTUKVSW.mjs} +1 -1
- package/dist/chunk-EHTUKVSW.mjs.map +1 -0
- package/dist/{chunk-KWCNQUH5.mjs → chunk-EPDIF432.mjs} +526 -50
- package/dist/chunk-EPDIF432.mjs.map +1 -0
- package/dist/{chunk-A3636IHN.mjs → chunk-FP5Q67FO.mjs} +167 -96
- package/dist/chunk-FP5Q67FO.mjs.map +1 -0
- package/dist/{chunk-HHZAOTQD.mjs → chunk-GJ7W6LNK.mjs} +7 -6
- package/dist/chunk-GJ7W6LNK.mjs.map +1 -0
- package/dist/{chunk-RLGUZ3HS.mjs → chunk-I3OOUWO5.mjs} +3 -3
- package/dist/{chunk-75CGAL6E.mjs → chunk-IZBX2TEU.mjs} +217 -105
- package/dist/chunk-IZBX2TEU.mjs.map +1 -0
- package/dist/{chunk-22VG4DFJ.mjs → chunk-J3MPQ4MQ.mjs} +2 -2
- package/dist/{chunk-22VG4DFJ.mjs.map → chunk-J3MPQ4MQ.mjs.map} +1 -1
- package/dist/{chunk-2LS3KKE7.mjs → chunk-JV7JUD7Q.mjs} +4 -4
- package/dist/{chunk-Q3OX763A.mjs → chunk-LXDASSTE.mjs} +2 -2
- package/dist/{chunk-ZRBCBOEX.mjs → chunk-N2FY2QZ7.mjs} +28 -3
- package/dist/chunk-N2FY2QZ7.mjs.map +1 -0
- package/dist/{chunk-MRVJCLYQ.mjs → chunk-PSQ7N4XP.mjs} +4 -2
- package/dist/chunk-PSQ7N4XP.mjs.map +1 -0
- package/dist/{chunk-HVG3HLQZ.mjs → chunk-Q7WGOOAI.mjs} +3 -3
- package/dist/{chunk-WTYAPO5I.mjs → chunk-RCNWMEBT.mjs} +3 -2
- package/dist/{chunk-WTYAPO5I.mjs.map → chunk-RCNWMEBT.mjs.map} +1 -1
- package/dist/{chunk-3INDBMUU.mjs → chunk-TGDIACZT.mjs} +2 -2
- package/dist/{chunk-WB75GIX2.mjs → chunk-TQTB33JS.mjs} +14 -3
- package/dist/chunk-TQTB33JS.mjs.map +1 -0
- package/dist/{chunk-MH27UH72.mjs → chunk-TT3E2JOF.mjs} +3 -3
- package/dist/{chunk-UWRGX3J3.mjs → chunk-UMUWR5XA.mjs} +2 -2
- package/dist/{chunk-XTLLHCWU.mjs → chunk-V4VRLVLW.mjs} +52 -31
- package/dist/chunk-V4VRLVLW.mjs.map +1 -0
- package/dist/{chunk-EXCGBERG.mjs → chunk-WD2EBM3I.mjs} +79 -17
- package/dist/chunk-WD2EBM3I.mjs.map +1 -0
- package/dist/{chunk-DLBUAJTK.mjs → chunk-WMJGA32P.mjs} +74 -5
- package/dist/chunk-WMJGA32P.mjs.map +1 -0
- package/dist/{chunk-TKQCJMY7.mjs → chunk-X4SFHKFH.mjs} +7 -4
- package/dist/{chunk-TKQCJMY7.mjs.map → chunk-X4SFHKFH.mjs.map} +1 -1
- package/dist/{chunk-Q7GPJZCO.mjs → chunk-YIBV77KZ.mjs} +26 -7
- package/dist/chunk-YIBV77KZ.mjs.map +1 -0
- package/dist/client/lifecycle.mjs +2 -2
- package/dist/{client-mcMC334J.d.mts → client-DWoLZ3QU.d.mts} +52 -5
- package/dist/{client-d5ONQ-Pd.d.ts → client-DuQuQC1h.d.ts} +52 -5
- package/dist/client-cache-BMxuFqwH.d.ts +18 -0
- package/dist/client-cache-CCK-fCe0.d.mts +18 -0
- package/dist/{client-plugins-BvClItiL.d.mts → client-plugins-B6-07YmP.d.mts} +52 -99
- package/dist/{client-plugins-B9Sq-iMg.d.ts → client-plugins-By6MVUX-.d.ts} +52 -99
- package/dist/client-plugins.cjs +1 -1
- package/dist/client-plugins.d.mts +3 -2
- package/dist/client-plugins.d.ts +3 -2
- package/dist/client-plugins.mjs +2 -2
- package/dist/client.cjs +1046 -211
- package/dist/client.d.mts +136 -18
- package/dist/client.d.ts +136 -18
- package/dist/client.mjs +32 -15
- package/dist/config.d.mts +3 -2
- package/dist/config.d.ts +3 -2
- package/dist/{devtools-S52RRRMN.mjs → devtools-XWZX6CCL.mjs} +5 -5
- package/dist/{devtools-client-3XRTBND5.mjs → devtools-client-Z7QQA3Q2.mjs} +56 -17
- package/dist/devtools-client-Z7QQA3Q2.mjs.map +1 -0
- package/dist/{devtools-ui-NJKFORTG.mjs → devtools-ui-2HG5M4EL.mjs} +3 -1
- package/dist/devtools-ui-2HG5M4EL.mjs.map +1 -0
- package/dist/docs.cjs +24 -5
- package/dist/docs.mjs +5 -5
- package/dist/i18n/server.cjs +13 -2
- package/dist/i18n/server.d.mts +2 -2
- package/dist/i18n/server.d.ts +2 -2
- package/dist/i18n/server.mjs +1 -1
- package/dist/index.cjs +1928 -894
- package/dist/index.d.mts +139 -21
- package/dist/index.d.ts +139 -21
- package/dist/index.mjs +57 -34
- package/dist/index.mjs.map +1 -1
- package/dist/integration-api-BT024nuJ.d.mts +97 -0
- package/dist/integration-api-BT024nuJ.d.ts +97 -0
- package/dist/integrations.d.mts +3 -2
- package/dist/integrations.d.ts +3 -2
- package/dist/internal/build-runtime.cjs +764 -547
- package/dist/internal/build-runtime.d.mts +5 -4
- package/dist/internal/build-runtime.d.ts +5 -4
- package/dist/internal/build-runtime.mjs +16 -16
- package/dist/internal/client-runtime.cjs +1 -1
- package/dist/internal/client-runtime.mjs +2 -2
- package/dist/internal/config-runtime.cjs +4 -1
- package/dist/internal/config-runtime.d.mts +4 -3
- package/dist/internal/config-runtime.d.ts +4 -3
- package/dist/internal/config-runtime.mjs +4 -4
- package/dist/internal/product-telemetry-runtime.cjs +1 -1
- package/dist/internal/product-telemetry-runtime.mjs +1 -1
- package/dist/internal/production-runtime.cjs +29 -3
- package/dist/internal/production-runtime.d.mts +8 -7
- package/dist/internal/production-runtime.d.ts +8 -7
- package/dist/internal/production-runtime.mjs +5 -5
- package/dist/{metadata-route-yV4U6X8h.d.ts → metadata-route-8_V3UonT.d.ts} +1 -1
- package/dist/{metadata-route-p4K1l92V.d.mts → metadata-route-CWP_HjGU.d.mts} +1 -1
- package/dist/middleware.cjs +28 -2
- package/dist/middleware.d.mts +5 -4
- package/dist/middleware.d.ts +5 -4
- package/dist/middleware.mjs +4 -4
- package/dist/navigation.cjs +3 -1
- package/dist/navigation.mjs +3 -3
- package/dist/observability.cjs +27 -2
- package/dist/observability.mjs +1 -1
- package/dist/plugin.cjs +528 -349
- package/dist/plugin.d.mts +3 -2
- package/dist/plugin.d.ts +3 -2
- package/dist/plugin.mjs +13 -13
- package/dist/{production-runtime-IkB0Qj4i.d.mts → production-runtime-BGRH1dKG.d.mts} +1 -1
- package/dist/{production-runtime-0JTch4_d.d.ts → production-runtime-CdmzsDax.d.ts} +1 -1
- package/dist/query/client.cjs +68 -29
- package/dist/query/client.mjs +69 -30
- package/dist/query/client.mjs.map +1 -1
- package/dist/{render-plan-Dc8CjNI7.d.ts → render-plan-0GeHiGVZ.d.ts} +1 -1
- package/dist/{render-plan-CU31j-Jk.d.mts → render-plan-DLxJYAA5.d.mts} +1 -1
- package/dist/renderer-client.cjs +169 -26
- package/dist/renderer-client.d.mts +7 -6
- package/dist/renderer-client.d.ts +7 -6
- package/dist/renderer-client.mjs +16 -19
- package/dist/renderer-client.mjs.map +1 -1
- package/dist/{request-BXa1KY8i.d.mts → request-BCNXSXLh.d.mts} +1 -1
- package/dist/{request-CUUBujZt.d.ts → request-BstWbZ6O.d.ts} +1 -1
- package/dist/request.d.mts +4 -3
- package/dist/request.d.ts +4 -3
- package/dist/{route-Y8lfz1wF.d.ts → route-4pd-EVtw.d.ts} +45 -50
- package/dist/{route-Cq3aObmj.d.mts → route-CvEr4Uc9.d.mts} +45 -50
- package/dist/routes.cjs +27 -2
- package/dist/routes.d.mts +3 -2
- package/dist/routes.d.ts +3 -2
- package/dist/routes.mjs +4 -4
- package/dist/{runtime-j1S3sDTh.d.ts → runtime-BgDQzBiu.d.ts} +1 -0
- package/dist/{runtime-DDwvDtS4.d.mts → runtime-CV2UCV-5.d.mts} +1 -0
- package/dist/server-action-security.mjs +2 -2
- package/dist/server-fn-client.cjs +102 -26
- package/dist/server-fn-client.d.mts +6 -0
- package/dist/server-fn-client.d.ts +6 -0
- package/dist/server-fn-client.mjs +2 -1
- package/dist/server-fn.cjs +42 -4
- package/dist/server-fn.mjs +5 -5
- package/dist/server-plugins.d.mts +4 -3
- package/dist/server-plugins.d.ts +4 -3
- package/dist/server-query-client.cjs +195 -34
- package/dist/server-query-client.d.mts +3 -3
- package/dist/server-query-client.d.ts +3 -3
- package/dist/server-query-client.mjs +7 -7
- package/dist/{server-query-runtime-3zAj77yv.d.ts → server-query-runtime-DXRNhX_3.d.ts} +2 -0
- package/dist/{server-query-runtime-B50KAcj5.d.mts → server-query-runtime-aP52iuL5.d.mts} +2 -0
- package/dist/server-query.cjs +44 -5
- package/dist/server-query.d.mts +4 -0
- package/dist/server-query.d.ts +4 -0
- package/dist/server-query.mjs +7 -7
- package/dist/server.cjs +553 -370
- package/dist/server.d.mts +11 -10
- package/dist/server.d.ts +11 -10
- package/dist/server.mjs +17 -17
- package/dist/{spa-router-CyLkwst6.d.mts → spa-router-BeyAVSc6.d.mts} +1 -1
- package/dist/{spa-router-BkqGXaV_.d.ts → spa-router-COgu4txb.d.ts} +1 -1
- package/dist/testing.cjs +27 -2
- package/dist/testing.d.mts +3 -2
- package/dist/testing.d.ts +3 -2
- package/dist/testing.mjs +9 -9
- package/dist/{utils-NKR6SoNv.d.mts → utils-DL2VwDQl.d.mts} +1 -1
- package/dist/{utils-B2OHrb9F.d.ts → utils-DkU2c_1B.d.ts} +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.mjs +1 -1
- package/dist/vite.cjs +536 -353
- package/dist/vite.d.mts +3 -2
- package/dist/vite.d.ts +3 -2
- package/dist/vite.mjs +17 -13
- package/package.json +17 -17
- package/types/client.d.ts +115 -10
- package/dist/agent-runtime.cjs.map +0 -1
- package/dist/api/route-manager.cjs.map +0 -1
- package/dist/api/runtime.cjs.map +0 -1
- package/dist/api.cjs.map +0 -1
- package/dist/app-markdown.cjs.map +0 -1
- package/dist/cache.cjs.map +0 -1
- package/dist/chunk-75CGAL6E.mjs.map +0 -1
- package/dist/chunk-7MABZJIM.mjs.map +0 -1
- package/dist/chunk-A3636IHN.mjs.map +0 -1
- package/dist/chunk-AXVJCMVF.mjs.map +0 -1
- package/dist/chunk-D7QH7MDU.mjs.map +0 -1
- package/dist/chunk-DLBUAJTK.mjs.map +0 -1
- package/dist/chunk-EXCGBERG.mjs.map +0 -1
- package/dist/chunk-FLHLPB57.mjs.map +0 -1
- package/dist/chunk-HHZAOTQD.mjs.map +0 -1
- package/dist/chunk-KOTSX5JH.mjs.map +0 -1
- package/dist/chunk-KWCNQUH5.mjs.map +0 -1
- package/dist/chunk-MRVJCLYQ.mjs.map +0 -1
- package/dist/chunk-Q7GPJZCO.mjs.map +0 -1
- package/dist/chunk-RBRLLZL5.mjs.map +0 -1
- package/dist/chunk-SALMKQXH.mjs.map +0 -1
- package/dist/chunk-SCFX4UTD.mjs.map +0 -1
- package/dist/chunk-WB75GIX2.mjs.map +0 -1
- package/dist/chunk-XTLLHCWU.mjs.map +0 -1
- package/dist/chunk-ZFNK77WN.mjs.map +0 -1
- package/dist/chunk-ZRBCBOEX.mjs.map +0 -1
- package/dist/client/lifecycle.cjs.map +0 -1
- package/dist/client-cache-CopR_MaI.d.mts +0 -6
- package/dist/client-cache-Djy_TlE8.d.ts +0 -6
- package/dist/client-plugins.cjs.map +0 -1
- package/dist/client.cjs.map +0 -1
- package/dist/config.cjs.map +0 -1
- package/dist/cron.cjs.map +0 -1
- package/dist/deferred.cjs.map +0 -1
- package/dist/deployment.cjs.map +0 -1
- package/dist/devtools-client-3XRTBND5.mjs.map +0 -1
- package/dist/devtools-ui-NJKFORTG.mjs.map +0 -1
- package/dist/docs.cjs.map +0 -1
- package/dist/env-types.cjs.map +0 -1
- package/dist/env.cjs.map +0 -1
- package/dist/environment/vite.cjs.map +0 -1
- package/dist/environment.cjs.map +0 -1
- package/dist/font.cjs.map +0 -1
- package/dist/headers.cjs.map +0 -1
- package/dist/i18n/client.cjs.map +0 -1
- package/dist/i18n/index.cjs.map +0 -1
- package/dist/i18n/server.cjs.map +0 -1
- package/dist/image/server.cjs.map +0 -1
- package/dist/image/sharp.cjs.map +0 -1
- package/dist/image.cjs.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/instrumentation.cjs.map +0 -1
- package/dist/integrations.cjs.map +0 -1
- package/dist/internal/build-runtime.cjs.map +0 -1
- package/dist/internal/client-runtime.cjs.map +0 -1
- package/dist/internal/config-runtime.cjs.map +0 -1
- package/dist/internal/isolated-boundary.cjs.map +0 -1
- package/dist/internal/metadata-image-runtime.cjs.map +0 -1
- package/dist/internal/product-telemetry-runtime.cjs.map +0 -1
- package/dist/internal/production-node-env.cjs.map +0 -1
- package/dist/internal/production-runtime.cjs.map +0 -1
- package/dist/markdown.cjs.map +0 -1
- package/dist/middleware.cjs.map +0 -1
- package/dist/navigation.cjs.map +0 -1
- package/dist/observability.cjs.map +0 -1
- package/dist/plugin.cjs.map +0 -1
- package/dist/query/client.cjs.map +0 -1
- package/dist/query/index.cjs.map +0 -1
- package/dist/query/parsers.cjs.map +0 -1
- package/dist/query/server.cjs.map +0 -1
- package/dist/renderer/react/client.cjs.map +0 -1
- package/dist/renderer/react/server.cjs.map +0 -1
- package/dist/renderer/react/vite.cjs.map +0 -1
- package/dist/renderer-client.cjs.map +0 -1
- package/dist/renderer.cjs.map +0 -1
- package/dist/request.cjs.map +0 -1
- package/dist/router.cjs.map +0 -1
- package/dist/routes.cjs.map +0 -1
- package/dist/server-action-security.cjs.map +0 -1
- package/dist/server-fn-client.cjs.map +0 -1
- package/dist/server-fn.cjs.map +0 -1
- package/dist/server-plugins.cjs.map +0 -1
- package/dist/server-query-client.cjs.map +0 -1
- package/dist/server-query.cjs.map +0 -1
- package/dist/server.cjs.map +0 -1
- package/dist/storage.cjs.map +0 -1
- package/dist/testing.cjs.map +0 -1
- package/dist/theme/client.cjs.map +0 -1
- package/dist/theme/index.cjs.map +0 -1
- package/dist/theme/runtime.cjs.map +0 -1
- package/dist/theme/server.cjs.map +0 -1
- package/dist/version.cjs.map +0 -1
- package/dist/vite.cjs.map +0 -1
- package/dist/workflows.cjs.map +0 -1
- /package/dist/{chunk-VV24CC42.mjs.map → chunk-35NPLKQJ.mjs.map} +0 -0
- /package/dist/{chunk-RWYRFCLG.mjs.map → chunk-4X57GXQA.mjs.map} +0 -0
- /package/dist/{chunk-MOW47IF5.mjs.map → chunk-6UYVU46O.mjs.map} +0 -0
- /package/dist/{chunk-RLGUZ3HS.mjs.map → chunk-I3OOUWO5.mjs.map} +0 -0
- /package/dist/{chunk-2LS3KKE7.mjs.map → chunk-JV7JUD7Q.mjs.map} +0 -0
- /package/dist/{chunk-Q3OX763A.mjs.map → chunk-LXDASSTE.mjs.map} +0 -0
- /package/dist/{chunk-HVG3HLQZ.mjs.map → chunk-Q7WGOOAI.mjs.map} +0 -0
- /package/dist/{chunk-3INDBMUU.mjs.map → chunk-TGDIACZT.mjs.map} +0 -0
- /package/dist/{chunk-MH27UH72.mjs.map → chunk-TT3E2JOF.mjs.map} +0 -0
- /package/dist/{chunk-UWRGX3J3.mjs.map → chunk-UMUWR5XA.mjs.map} +0 -0
- /package/dist/{devtools-S52RRRMN.mjs.map → devtools-XWZX6CCL.mjs.map} +0 -0
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
notifyClientObserver
|
|
3
|
+
} from "./chunk-DU3PKDVQ.mjs";
|
|
1
4
|
import {
|
|
2
5
|
__name
|
|
3
6
|
} from "./chunk-CGILA3WO.mjs";
|
|
@@ -10,10 +13,33 @@ import {
|
|
|
10
13
|
useRef,
|
|
11
14
|
useState
|
|
12
15
|
} from "react";
|
|
16
|
+
|
|
17
|
+
// src/mutation-retry.ts
|
|
18
|
+
async function invokeMutationWithRetry(invoke, retry, shouldContinue) {
|
|
19
|
+
const maxRetries = Math.max(0, retry?.count ?? 0);
|
|
20
|
+
let attempt = 0;
|
|
21
|
+
while (true) {
|
|
22
|
+
try {
|
|
23
|
+
return await invoke();
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (attempt >= maxRetries || !shouldContinue()) throw error;
|
|
26
|
+
attempt += 1;
|
|
27
|
+
const delay = typeof retry?.delay === "function" ? retry.delay(attempt) : retry?.delay ?? 0;
|
|
28
|
+
if (delay > 0) {
|
|
29
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
30
|
+
if (!shouldContinue()) throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
__name(invokeMutationWithRetry, "invokeMutationWithRetry");
|
|
36
|
+
|
|
37
|
+
// src/server-fn-client.ts
|
|
13
38
|
function useServerFn(serverFn, options = {}) {
|
|
14
39
|
const { initialResult = null, resetOnSubmit = true } = options;
|
|
15
40
|
const callbacksRef = useRef({});
|
|
16
41
|
const requestIdRef = useRef(0);
|
|
42
|
+
const lastResetIdRef = useRef(0);
|
|
17
43
|
const initialState = {
|
|
18
44
|
pendingCount: 0,
|
|
19
45
|
status: "idle",
|
|
@@ -24,11 +50,9 @@ function useServerFn(serverFn, options = {}) {
|
|
|
24
50
|
const [state, setState] = useState(initialState);
|
|
25
51
|
const setActionState = useCallback(
|
|
26
52
|
(value) => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return next;
|
|
31
|
-
});
|
|
53
|
+
const next = typeof value === "function" ? value(stateRef.current) : value;
|
|
54
|
+
stateRef.current = next;
|
|
55
|
+
setState(next);
|
|
32
56
|
},
|
|
33
57
|
[]
|
|
34
58
|
);
|
|
@@ -49,63 +73,88 @@ function useServerFn(serverFn, options = {}) {
|
|
|
49
73
|
current: previousResult
|
|
50
74
|
});
|
|
51
75
|
const hasOptimisticResult = optimisticResult !== void 0;
|
|
52
|
-
setActionState((current) =>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
76
|
+
setActionState((current) => {
|
|
77
|
+
if (requestId < lastResetIdRef.current) return current;
|
|
78
|
+
const pendingCount = current.pendingCount + 1;
|
|
79
|
+
if (requestId !== requestIdRef.current) return { ...current, pendingCount };
|
|
80
|
+
return {
|
|
81
|
+
pendingCount,
|
|
82
|
+
status: "pending",
|
|
83
|
+
result: hasOptimisticResult ? optimisticResult : resetOnSubmit ? null : current.result,
|
|
84
|
+
error: null
|
|
85
|
+
};
|
|
86
|
+
});
|
|
58
87
|
try {
|
|
59
|
-
const result = await
|
|
88
|
+
const result = await invokeMutationWithRetry(
|
|
89
|
+
() => serverFn(input),
|
|
90
|
+
options.retry,
|
|
91
|
+
// A reset disowns this submission; stop scheduling retries then.
|
|
92
|
+
() => requestId >= lastResetIdRef.current
|
|
93
|
+
);
|
|
60
94
|
const isLatestRequest = requestId === requestIdRef.current;
|
|
61
95
|
setActionState((current) => {
|
|
96
|
+
if (requestId < lastResetIdRef.current) return current;
|
|
62
97
|
const pendingCount = Math.max(0, current.pendingCount - 1);
|
|
63
98
|
if (!isLatestRequest) {
|
|
64
99
|
return {
|
|
65
100
|
...current,
|
|
66
|
-
pendingCount
|
|
67
|
-
status: pendingCount > 0 ? "pending" : current.status
|
|
101
|
+
pendingCount
|
|
68
102
|
};
|
|
69
103
|
}
|
|
70
104
|
return {
|
|
71
105
|
pendingCount,
|
|
72
|
-
status:
|
|
106
|
+
status: "success",
|
|
73
107
|
result,
|
|
74
108
|
error: null
|
|
75
109
|
};
|
|
76
110
|
});
|
|
77
111
|
if (isLatestRequest) {
|
|
78
|
-
callbacksRef.current.onSuccess
|
|
79
|
-
|
|
112
|
+
notifyClientObserver(callbacksRef.current.onSuccess, [result], "Action onSuccess");
|
|
113
|
+
if (requestId === requestIdRef.current) {
|
|
114
|
+
notifyClientObserver(
|
|
115
|
+
callbacksRef.current.onSettled,
|
|
116
|
+
[result, null],
|
|
117
|
+
"Action onSettled"
|
|
118
|
+
);
|
|
119
|
+
}
|
|
80
120
|
}
|
|
81
121
|
return result;
|
|
82
122
|
} catch (cause) {
|
|
83
123
|
const error = normalizeServerFnError(cause);
|
|
84
124
|
const isLatestRequest = requestId === requestIdRef.current;
|
|
85
125
|
setActionState((current) => {
|
|
126
|
+
if (requestId < lastResetIdRef.current) return current;
|
|
86
127
|
const pendingCount = Math.max(0, current.pendingCount - 1);
|
|
87
128
|
if (!isLatestRequest) {
|
|
88
129
|
return {
|
|
89
130
|
...current,
|
|
90
|
-
pendingCount
|
|
91
|
-
status: pendingCount > 0 ? "pending" : current.status
|
|
131
|
+
pendingCount
|
|
92
132
|
};
|
|
93
133
|
}
|
|
94
134
|
return {
|
|
95
135
|
pendingCount,
|
|
96
|
-
status:
|
|
136
|
+
status: "error",
|
|
97
137
|
result: hasOptimisticResult && options.rollbackOnError ? previousResult : resetOnSubmit ? null : current.result,
|
|
98
138
|
error
|
|
99
139
|
};
|
|
100
140
|
});
|
|
101
141
|
if (isLatestRequest) {
|
|
102
|
-
callbacksRef.current.onError
|
|
103
|
-
|
|
142
|
+
notifyClientObserver(callbacksRef.current.onError, [error], "Action onError");
|
|
143
|
+
if (requestId === requestIdRef.current) {
|
|
144
|
+
notifyClientObserver(callbacksRef.current.onSettled, [null, error], "Action onSettled");
|
|
145
|
+
}
|
|
104
146
|
}
|
|
105
147
|
throw error;
|
|
106
148
|
}
|
|
107
149
|
},
|
|
108
|
-
[
|
|
150
|
+
[
|
|
151
|
+
options.optimistic,
|
|
152
|
+
options.retry,
|
|
153
|
+
options.rollbackOnError,
|
|
154
|
+
resetOnSubmit,
|
|
155
|
+
serverFn,
|
|
156
|
+
setActionState
|
|
157
|
+
]
|
|
109
158
|
);
|
|
110
159
|
const formAction = useCallback(
|
|
111
160
|
async (formData) => {
|
|
@@ -120,7 +169,7 @@ function useServerFn(serverFn, options = {}) {
|
|
|
120
169
|
[submit]
|
|
121
170
|
);
|
|
122
171
|
const reset = useCallback(() => {
|
|
123
|
-
|
|
172
|
+
lastResetIdRef.current = ++requestIdRef.current;
|
|
124
173
|
setActionState({
|
|
125
174
|
pendingCount: 0,
|
|
126
175
|
status: "idle",
|
|
@@ -145,14 +194,17 @@ __name(useServerFn, "useServerFn");
|
|
|
145
194
|
function useAction(target, options = {}) {
|
|
146
195
|
const serverFn = resolveServerFnTarget(target);
|
|
147
196
|
const action = useServerFn(serverFn, options);
|
|
197
|
+
const formActionRef = useRef(action.formAction);
|
|
198
|
+
formActionRef.current = action.formAction;
|
|
148
199
|
const Form = useMemo(() => {
|
|
200
|
+
const submitForm = /* @__PURE__ */ __name((formData) => formActionRef.current(formData), "submitForm");
|
|
149
201
|
const ActionForm = /* @__PURE__ */ __name((props) => createElement("form", {
|
|
150
202
|
...props,
|
|
151
|
-
action:
|
|
203
|
+
action: submitForm
|
|
152
204
|
}), "ActionForm");
|
|
153
205
|
ActionForm.displayName = "FarmActionForm";
|
|
154
206
|
return ActionForm;
|
|
155
|
-
}, [
|
|
207
|
+
}, []);
|
|
156
208
|
return useMemo(() => {
|
|
157
209
|
const call = /* @__PURE__ */ __name(((input) => action.submit(input)), "call");
|
|
158
210
|
return Object.assign(call, {
|
|
@@ -202,7 +254,8 @@ function isFormData(value) {
|
|
|
202
254
|
__name(isFormData, "isFormData");
|
|
203
255
|
|
|
204
256
|
export {
|
|
257
|
+
invokeMutationWithRetry,
|
|
205
258
|
useServerFn,
|
|
206
259
|
useAction
|
|
207
260
|
};
|
|
208
|
-
//# sourceMappingURL=chunk-
|
|
261
|
+
//# sourceMappingURL=chunk-6EJHNHH4.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server-fn-client.ts","../src/mutation-retry.ts"],"sourcesContent":["\"use client\";\n\nimport {\n createElement,\n useCallback,\n useMemo,\n useRef,\n useState,\n type ComponentType,\n type FormHTMLAttributes,\n} from \"react\";\nimport type { ServerFn } from \"./server-fn\";\nimport type { RetryOptions } from \"./api/client\";\nimport { notifyClientObserver } from \"./client-observers\";\nimport { invokeMutationWithRetry } from \"./mutation-retry\";\n\nexport type ServerFnActionStatus = \"idle\" | \"pending\" | \"success\" | \"error\";\n\nexport type ServerFnSubmit<TInput, TResult> = [unknown] extends [TInput]\n ? (input?: TInput | FormData) => Promise<TResult>\n : (input: TInput | FormData) => Promise<TResult>;\n\nexport type ServerFnOptimisticContext<TInput, TResult> = {\n input: TInput | FormData | undefined;\n formData?: FormData;\n current: TResult | null;\n};\n\nexport type UseServerFnOptions<TResult, TError extends Error = Error, TInput = unknown> = {\n initialResult?: TResult | null;\n resetOnSubmit?: boolean;\n throwOnFormError?: boolean;\n optimistic?: (context: ServerFnOptimisticContext<TInput, TResult>) => TResult | null | undefined;\n rollbackOnError?: boolean;\n /** Retry failed submissions with the API client's retry shape. Defaults to no retries. */\n retry?: RetryOptions;\n onSuccess?: (result: TResult) => void;\n onError?: (error: TError) => void;\n onSettled?: (result: TResult | null, error: TError | null) => void;\n};\n\nexport type UseServerFnReturn<TInput, TResult, TError extends Error = Error> = {\n pending: boolean;\n status: ServerFnActionStatus;\n result: TResult | null;\n error: TError | null;\n submit: ServerFnSubmit<TInput, TResult>;\n formAction: (formData: FormData) => Promise<void>;\n reset: () => void;\n};\n\nexport type UseActionFormProps = Omit<FormHTMLAttributes<HTMLFormElement>, \"action\">;\n\nexport type RouteActionTarget<TServerFn extends ServerFn<any, any, any>> = {\n readonly action: TServerFn;\n};\n\nexport type UseActionReturn<TInput, TResult, TError extends Error = Error> = ServerFnSubmit<\n TInput,\n TResult\n> & {\n pending: boolean;\n status: ServerFnActionStatus;\n data: TResult | null;\n result: TResult | null;\n error: TError | null;\n formAction: (formData: FormData) => Promise<void>;\n Form: ComponentType<UseActionFormProps>;\n reset: () => void;\n};\n\ntype ServerFnActionState<TResult, TError extends Error> = {\n pendingCount: number;\n status: ServerFnActionStatus;\n result: TResult | null;\n error: TError | null;\n};\n\ntype ServerFnActionCallbacks<TResult, TError extends Error> = Pick<\n UseServerFnOptions<TResult, TError, unknown>,\n \"onError\" | \"onSettled\" | \"onSuccess\" | \"throwOnFormError\"\n>;\n\nexport function useServerFn<TInput, TResult, TError extends Error = Error>(\n serverFn: ServerFn<TInput, TResult, TError>,\n options: UseServerFnOptions<TResult, TError, TInput> = {},\n): UseServerFnReturn<TInput, TResult, TError> {\n const { initialResult = null, resetOnSubmit = true } = options;\n const callbacksRef = useRef<ServerFnActionCallbacks<TResult, TError>>({});\n const requestIdRef = useRef(0);\n const lastResetIdRef = useRef(0);\n const initialState: ServerFnActionState<TResult, TError> = {\n pendingCount: 0,\n status: \"idle\",\n result: initialResult,\n error: null,\n };\n const stateRef = useRef<ServerFnActionState<TResult, TError>>(initialState);\n const [state, setState] = useState<ServerFnActionState<TResult, TError>>(initialState);\n const setActionState = useCallback(\n (\n value:\n | ServerFnActionState<TResult, TError>\n | ((current: ServerFnActionState<TResult, TError>) => ServerFnActionState<TResult, TError>),\n ) => {\n // Later submissions in the same React batch must see this transition.\n const next = typeof value === \"function\" ? value(stateRef.current) : value;\n stateRef.current = next;\n setState(next);\n },\n [],\n );\n\n callbacksRef.current = {\n onError: options.onError,\n onSettled: options.onSettled,\n onSuccess: options.onSuccess,\n throwOnFormError: options.throwOnFormError,\n };\n\n const submit = useCallback(\n async (input?: TInput | FormData) => {\n const requestId = ++requestIdRef.current;\n const formData = isFormData(input) ? input : undefined;\n const previousResult = stateRef.current.result;\n const optimisticResult = options.optimistic?.({\n input,\n formData,\n current: previousResult,\n });\n const hasOptimisticResult = optimisticResult !== undefined;\n\n setActionState((current) => {\n // Optimistic callbacks are app code and may reset or submit again.\n if (requestId < lastResetIdRef.current) return current;\n const pendingCount = current.pendingCount + 1;\n if (requestId !== requestIdRef.current) return { ...current, pendingCount };\n return {\n pendingCount,\n status: \"pending\",\n result: hasOptimisticResult ? optimisticResult : resetOnSubmit ? null : current.result,\n error: null,\n };\n });\n\n try {\n const result = await invokeMutationWithRetry(\n () => serverFn(input as TInput | FormData),\n options.retry,\n // A reset disowns this submission; stop scheduling retries then.\n () => requestId >= lastResetIdRef.current,\n );\n const isLatestRequest = requestId === requestIdRef.current;\n\n setActionState((current) => {\n // Reset starts a new pending-count generation, not just a new result.\n if (requestId < lastResetIdRef.current) return current;\n const pendingCount = Math.max(0, current.pendingCount - 1);\n\n if (!isLatestRequest) {\n return {\n ...current,\n pendingCount,\n };\n }\n\n return {\n pendingCount,\n status: \"success\",\n result,\n error: null,\n };\n });\n\n if (isLatestRequest) {\n notifyClientObserver(callbacksRef.current.onSuccess, [result], \"Action onSuccess\");\n if (requestId === requestIdRef.current) {\n notifyClientObserver(\n callbacksRef.current.onSettled,\n [result, null],\n \"Action onSettled\",\n );\n }\n }\n\n return result;\n } catch (cause) {\n const error = normalizeServerFnError(cause) as TError;\n const isLatestRequest = requestId === requestIdRef.current;\n\n setActionState((current) => {\n if (requestId < lastResetIdRef.current) return current;\n const pendingCount = Math.max(0, current.pendingCount - 1);\n\n if (!isLatestRequest) {\n return {\n ...current,\n pendingCount,\n };\n }\n\n return {\n pendingCount,\n status: \"error\",\n result:\n hasOptimisticResult && options.rollbackOnError\n ? previousResult\n : resetOnSubmit\n ? null\n : current.result,\n error,\n };\n });\n\n if (isLatestRequest) {\n notifyClientObserver(callbacksRef.current.onError, [error], \"Action onError\");\n if (requestId === requestIdRef.current) {\n notifyClientObserver(callbacksRef.current.onSettled, [null, error], \"Action onSettled\");\n }\n }\n\n throw error;\n }\n },\n [\n options.optimistic,\n options.retry,\n options.rollbackOnError,\n resetOnSubmit,\n serverFn,\n setActionState,\n ],\n ) as ServerFnSubmit<TInput, TResult>;\n\n const formAction = useCallback(\n async (formData: FormData) => {\n try {\n await submit(formData as TInput | FormData);\n } catch (error) {\n if (callbacksRef.current.throwOnFormError) {\n throw error;\n }\n }\n },\n [submit],\n );\n\n const reset = useCallback(() => {\n lastResetIdRef.current = ++requestIdRef.current;\n setActionState({\n pendingCount: 0,\n status: \"idle\",\n result: initialResult,\n error: null,\n });\n }, [initialResult, setActionState]);\n\n return useMemo(\n () => ({\n pending: state.pendingCount > 0,\n status: state.status,\n result: state.result,\n error: state.error,\n submit,\n formAction,\n reset,\n }),\n [formAction, reset, state.error, state.pendingCount, state.result, state.status, submit],\n );\n}\n\n/**\n * Wrap a server function, or a route's default server function, as a callable\n * RPC with React mutation state.\n */\nexport function useAction<TInput, TResult, TError extends Error = Error>(\n route: RouteActionTarget<ServerFn<TInput, TResult, TError>>,\n options?: UseServerFnOptions<TResult, TError, TInput>,\n): UseActionReturn<TInput, TResult, TError>;\nexport function useAction<TInput, TResult, TError extends Error = Error>(\n serverFn: ServerFn<TInput, TResult, TError>,\n options?: UseServerFnOptions<TResult, TError, TInput>,\n): UseActionReturn<TInput, TResult, TError>;\nexport function useAction<TInput, TResult, TError extends Error = Error>(\n target: ServerFn<TInput, TResult, TError> | RouteActionTarget<ServerFn<TInput, TResult, TError>>,\n options: UseServerFnOptions<TResult, TError, TInput> = {},\n): UseActionReturn<TInput, TResult, TError> {\n const serverFn = resolveServerFnTarget(target);\n const action = useServerFn(serverFn, options);\n const formActionRef = useRef(action.formAction);\n formActionRef.current = action.formAction;\n\n const Form = useMemo(() => {\n // Keep both the component and its action stable, even when a parent caches\n // the form element. Resolve the latest target/options at submission time.\n const submitForm = (formData: FormData) => formActionRef.current(formData);\n const ActionForm = (props: UseActionFormProps) =>\n createElement(\"form\", {\n ...props,\n action: submitForm,\n });\n\n ActionForm.displayName = \"FarmActionForm\";\n return ActionForm;\n }, []);\n\n return useMemo(() => {\n const call = ((input?: TInput | FormData) =>\n action.submit(input as TInput | FormData)) as ServerFnSubmit<TInput, TResult>;\n\n return Object.assign(call, {\n pending: action.pending,\n status: action.status,\n data: action.result,\n result: action.result,\n error: action.error,\n formAction: action.formAction,\n Form,\n reset: action.reset,\n });\n }, [\n Form,\n action.error,\n action.formAction,\n action.pending,\n action.reset,\n action.result,\n action.status,\n action.submit,\n ]);\n}\n\nfunction resolveServerFnTarget<TInput, TResult, TError extends Error>(\n target: ServerFn<TInput, TResult, TError> | RouteActionTarget<ServerFn<TInput, TResult, TError>>,\n): ServerFn<TInput, TResult, TError> {\n if (typeof target === \"function\") return target;\n if (target && typeof target.action === \"function\") return target.action;\n\n throw new TypeError(\n \"useAction requires a server function or a route with at least one declared action\",\n );\n}\n\nfunction normalizeServerFnError(error: unknown) {\n if (error instanceof Error) return error;\n\n const normalized = new Error(typeof error === \"string\" ? error : \"Server function failed\");\n (normalized as Error & { cause?: unknown }).cause = error;\n return normalized;\n}\n\nfunction isFormData(value: unknown): value is FormData {\n if (!value || typeof value !== \"object\") return false;\n\n if (typeof FormData !== \"undefined\" && value instanceof FormData) {\n return true;\n }\n\n return (\n Object.prototype.toString.call(value) === \"[object FormData]\" &&\n typeof (value as { entries?: unknown }).entries === \"function\"\n );\n}\n","import type { RetryOptions } from \"./api/client\";\n\n/**\n * Retry a server-function mutation with the API client's retry shape.\n *\n * Attempts run until success, until `count` retries are exhausted, or until\n * `shouldContinue` reports that the owning lifecycle was reset. The delay\n * callback receives the upcoming attempt number starting at 1, matching the\n * API client. Defaults to zero retries so existing behavior is unchanged.\n */\nexport async function invokeMutationWithRetry<T>(\n invoke: () => Promise<T>,\n retry: RetryOptions | undefined,\n shouldContinue: () => boolean,\n): Promise<T> {\n const maxRetries = Math.max(0, retry?.count ?? 0);\n let attempt = 0;\n\n while (true) {\n try {\n return await invoke();\n } catch (error) {\n if (attempt >= maxRetries || !shouldContinue()) throw error;\n\n attempt += 1;\n const delay = typeof retry?.delay === \"function\" ? retry.delay(attempt) : (retry?.delay ?? 0);\n if (delay > 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, delay));\n // The lifecycle may have been reset while this attempt waited.\n if (!shouldContinue()) throw error;\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -162,7 +162,7 @@ async function _runWithAfterRequest(request, handler, context) {
|
|
|
162
162
|
const response = await afterStorage.run(state, handler);
|
|
163
163
|
return hasResponseHook ? response : wrapResponseBody(response, request, state);
|
|
164
164
|
} catch (error) {
|
|
165
|
-
|
|
165
|
+
finishSoon(state);
|
|
166
166
|
throw error;
|
|
167
167
|
}
|
|
168
168
|
}
|
|
@@ -200,4 +200,4 @@ export {
|
|
|
200
200
|
_runWithAfterNodeResponse,
|
|
201
201
|
_withAfterNodeMiddleware
|
|
202
202
|
};
|
|
203
|
-
//# sourceMappingURL=chunk-
|
|
203
|
+
//# sourceMappingURL=chunk-6JNGOC37.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/after.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nexport type AfterCallback = () => void | Promise<void>;\n\n/** Runtime hooks supplied by a deployment adapter. */\nexport interface FarmAfterPlatformContext {\n /** Keep a serverless invocation alive until the scheduled work settles. */\n waitUntil?: (promise: Promise<void>) => void;\n /** Register a callback that runs once the response has finished. */\n onResponseFinished?: (callback: () => void) => void;\n}\n\ninterface AfterTask {\n result: Promise<void>;\n start: () => void;\n}\n\ninterface AfterRequestState {\n completion: Promise<void>;\n finishResponse: () => void;\n phase: \"open\" | \"running\" | \"closed\";\n reportError: (error: unknown) => void;\n tasks: AfterTask[];\n}\n\nconst AFTER_STORAGE = Symbol.for(\"@farm.js/core/after-storage\");\n\nfunction getAfterStorage(): AsyncLocalStorage<AfterRequestState> {\n const runtime = globalThis as typeof globalThis & Record<PropertyKey, unknown>;\n const existing = runtime[AFTER_STORAGE];\n if (existing instanceof AsyncLocalStorage) {\n return existing as AsyncLocalStorage<AfterRequestState>;\n }\n\n const storage = new AsyncLocalStorage<AfterRequestState>();\n runtime[AFTER_STORAGE] = storage;\n return storage;\n}\n\nconst afterStorage = getAfterStorage();\n\nfunction defaultAfterErrorReporter(error: unknown): void {\n console.error(\"[Farm.js] after() callback failed:\", error);\n}\n\nfunction reportAfterError(state: AfterRequestState, error: unknown): void {\n try {\n state.reportError(error);\n } catch {\n // Error reporting must never interrupt the remaining post-response work.\n }\n}\n\nfunction createAfterRequestState(\n reportError: (error: unknown) => void = defaultAfterErrorReporter,\n): AfterRequestState {\n let resolveResponseFinished!: () => void;\n let responseFinished = false;\n const responseFinishedPromise = new Promise<void>((resolve) => {\n resolveResponseFinished = resolve;\n });\n\n const state: AfterRequestState = {\n completion: Promise.resolve(),\n finishResponse: () => {\n if (responseFinished) return;\n responseFinished = true;\n resolveResponseFinished();\n },\n phase: \"open\",\n reportError,\n tasks: [],\n };\n\n state.completion = responseFinishedPromise.then(() =>\n afterStorage.run(state, async () => {\n state.phase = \"running\";\n\n for (let index = 0; index < state.tasks.length; index++) {\n const task = state.tasks[index];\n task.start();\n try {\n await task.result;\n } catch (error) {\n reportAfterError(state, error);\n }\n }\n\n state.phase = \"closed\";\n }),\n );\n\n return state;\n}\n\nfunction registerPlatformLifetime(\n state: AfterRequestState,\n context: FarmAfterPlatformContext | undefined,\n): void {\n if (!context?.waitUntil) return;\n\n try {\n context.waitUntil(state.completion);\n } catch (error) {\n reportAfterError(state, error);\n }\n}\n\nfunction registerResponseFinishedHook(\n state: AfterRequestState,\n context: FarmAfterPlatformContext | undefined,\n): boolean {\n if (!context?.onResponseFinished) return false;\n\n try {\n context.onResponseFinished(state.finishResponse);\n return true;\n } catch (error) {\n reportAfterError(state, error);\n return false;\n }\n}\n\nfunction finishSoon(state: AfterRequestState): void {\n setTimeout(state.finishResponse, 0);\n}\n\nfunction wrapResponseBody(\n response: Response,\n request: Request,\n state: AfterRequestState,\n): Response {\n if (\n request.method === \"HEAD\" ||\n response.status < 200 ||\n response.status > 599 ||\n !response.body ||\n response.bodyUsed ||\n response.body.locked\n ) {\n finishSoon(state);\n return response;\n }\n\n const reader = response.body.getReader();\n let released = false;\n const releaseReader = () => {\n if (released) return;\n released = true;\n reader.releaseLock();\n };\n\n const body = new ReadableStream<Uint8Array>({\n async pull(controller) {\n try {\n const chunk = await reader.read();\n if (chunk.done) {\n releaseReader();\n controller.close();\n finishSoon(state);\n return;\n }\n controller.enqueue(chunk.value);\n } catch (error) {\n releaseReader();\n controller.error(error);\n finishSoon(state);\n }\n },\n cancel(reason) {\n try {\n // Preserve the caller's cleanup promise, but response completion must\n // not depend on whether producer-owned cancellation ever settles.\n return reader.cancel(reason);\n } finally {\n releaseReader();\n finishSoon(state);\n }\n },\n });\n\n return new Response(body, {\n headers: response.headers,\n status: response.status,\n statusText: response.statusText,\n });\n}\n\n/**\n * Schedule non-blocking work for after the current response finishes.\n *\n * Callbacks run in registration order. A callback failure is reported without\n * changing the response or preventing later callbacks from running.\n */\nexport function after(callback: AfterCallback): void {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"after() expects a callback function.\");\n }\n\n const state = afterStorage.getStore();\n if (!state) {\n throw new Error(\"after() can only be used while Farm is handling a server request.\");\n }\n if (state.phase === \"closed\") {\n throw new Error(\"after() cannot schedule work after the request lifecycle has completed.\");\n }\n\n let start!: () => void;\n const ready = new Promise<void>((resolve) => {\n start = resolve;\n });\n\n // Registering the continuation here preserves every request AsyncLocalStorage\n // context that is active at the after() call site.\n const result = ready.then(callback);\n state.tasks.push({ result, start });\n}\n\n/** @internal Run a Web Request handler inside Farm's post-response lifecycle. */\nexport async function _runWithAfterRequest(\n request: Request,\n handler: () => Response | Promise<Response>,\n context?: FarmAfterPlatformContext,\n): Promise<Response> {\n if (afterStorage.getStore()) {\n return await handler();\n }\n\n const state = createAfterRequestState();\n registerPlatformLifetime(state, context);\n const hasResponseHook = registerResponseFinishedHook(state, context);\n\n try {\n const response = await afterStorage.run(state, handler);\n return hasResponseHook ? response : wrapResponseBody(response, request, state);\n } catch (error) {\n if (!hasResponseHook) finishSoon(state);\n throw error;\n }\n}\n\n/** @internal Run a Node response handler inside Farm's post-response lifecycle. */\nexport async function _runWithAfterNodeResponse<T>(\n response: ServerResponse,\n handler: () => T | Promise<T>,\n context?: Pick<FarmAfterPlatformContext, \"waitUntil\">,\n): Promise<T> {\n if (afterStorage.getStore()) {\n return await handler();\n }\n\n const state = createAfterRequestState();\n let finished = false;\n const finish = () => {\n if (finished) return;\n finished = true;\n response.off(\"finish\", finish);\n response.off(\"close\", finish);\n state.finishResponse();\n };\n\n response.once(\"finish\", finish);\n response.once(\"close\", finish);\n if (response.writableEnded) finishSoon(state);\n registerPlatformLifetime(state, context);\n\n return await afterStorage.run(state, handler);\n}\n\n/** @internal Add Farm's post-response lifecycle to a Node middleware. */\nexport function _withAfterNodeMiddleware(\n handler: (\n request: IncomingMessage,\n response: ServerResponse,\n next: (error?: unknown) => void,\n ) => void | Promise<void>,\n): (\n request: IncomingMessage,\n response: ServerResponse,\n next: (error?: unknown) => void,\n) => Promise<void> {\n return async (request, response, next) => {\n await _runWithAfterNodeResponse(response, () => handler(request, response, next));\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/after.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nexport type AfterCallback = () => void | Promise<void>;\n\n/** Runtime hooks supplied by a deployment adapter. */\nexport interface FarmAfterPlatformContext {\n /** Keep a serverless invocation alive until the scheduled work settles. */\n waitUntil?: (promise: Promise<void>) => void;\n /** Register a callback that runs once the response has finished. */\n onResponseFinished?: (callback: () => void) => void;\n}\n\ninterface AfterTask {\n result: Promise<void>;\n start: () => void;\n}\n\ninterface AfterRequestState {\n completion: Promise<void>;\n finishResponse: () => void;\n phase: \"open\" | \"running\" | \"closed\";\n reportError: (error: unknown) => void;\n tasks: AfterTask[];\n}\n\nconst AFTER_STORAGE = Symbol.for(\"@farm.js/core/after-storage\");\n\nfunction getAfterStorage(): AsyncLocalStorage<AfterRequestState> {\n const runtime = globalThis as typeof globalThis & Record<PropertyKey, unknown>;\n const existing = runtime[AFTER_STORAGE];\n if (existing instanceof AsyncLocalStorage) {\n return existing as AsyncLocalStorage<AfterRequestState>;\n }\n\n const storage = new AsyncLocalStorage<AfterRequestState>();\n runtime[AFTER_STORAGE] = storage;\n return storage;\n}\n\nconst afterStorage = getAfterStorage();\n\nfunction defaultAfterErrorReporter(error: unknown): void {\n console.error(\"[Farm.js] after() callback failed:\", error);\n}\n\nfunction reportAfterError(state: AfterRequestState, error: unknown): void {\n try {\n state.reportError(error);\n } catch {\n // Error reporting must never interrupt the remaining post-response work.\n }\n}\n\nfunction createAfterRequestState(\n reportError: (error: unknown) => void = defaultAfterErrorReporter,\n): AfterRequestState {\n let resolveResponseFinished!: () => void;\n let responseFinished = false;\n const responseFinishedPromise = new Promise<void>((resolve) => {\n resolveResponseFinished = resolve;\n });\n\n const state: AfterRequestState = {\n completion: Promise.resolve(),\n finishResponse: () => {\n if (responseFinished) return;\n responseFinished = true;\n resolveResponseFinished();\n },\n phase: \"open\",\n reportError,\n tasks: [],\n };\n\n state.completion = responseFinishedPromise.then(() =>\n afterStorage.run(state, async () => {\n state.phase = \"running\";\n\n for (let index = 0; index < state.tasks.length; index++) {\n const task = state.tasks[index];\n task.start();\n try {\n await task.result;\n } catch (error) {\n reportAfterError(state, error);\n }\n }\n\n state.phase = \"closed\";\n }),\n );\n\n return state;\n}\n\nfunction registerPlatformLifetime(\n state: AfterRequestState,\n context: FarmAfterPlatformContext | undefined,\n): void {\n if (!context?.waitUntil) return;\n\n try {\n context.waitUntil(state.completion);\n } catch (error) {\n reportAfterError(state, error);\n }\n}\n\nfunction registerResponseFinishedHook(\n state: AfterRequestState,\n context: FarmAfterPlatformContext | undefined,\n): boolean {\n if (!context?.onResponseFinished) return false;\n\n try {\n context.onResponseFinished(state.finishResponse);\n return true;\n } catch (error) {\n reportAfterError(state, error);\n return false;\n }\n}\n\nfunction finishSoon(state: AfterRequestState): void {\n setTimeout(state.finishResponse, 0);\n}\n\nfunction wrapResponseBody(\n response: Response,\n request: Request,\n state: AfterRequestState,\n): Response {\n if (\n request.method === \"HEAD\" ||\n response.status < 200 ||\n response.status > 599 ||\n !response.body ||\n response.bodyUsed ||\n response.body.locked\n ) {\n finishSoon(state);\n return response;\n }\n\n const reader = response.body.getReader();\n let released = false;\n const releaseReader = () => {\n if (released) return;\n released = true;\n reader.releaseLock();\n };\n\n const body = new ReadableStream<Uint8Array>({\n async pull(controller) {\n try {\n const chunk = await reader.read();\n if (chunk.done) {\n releaseReader();\n controller.close();\n finishSoon(state);\n return;\n }\n controller.enqueue(chunk.value);\n } catch (error) {\n releaseReader();\n controller.error(error);\n finishSoon(state);\n }\n },\n cancel(reason) {\n try {\n // Preserve the caller's cleanup promise, but response completion must\n // not depend on whether producer-owned cancellation ever settles.\n return reader.cancel(reason);\n } finally {\n releaseReader();\n finishSoon(state);\n }\n },\n });\n\n return new Response(body, {\n headers: response.headers,\n status: response.status,\n statusText: response.statusText,\n });\n}\n\n/**\n * Schedule non-blocking work for after the current response finishes.\n *\n * Callbacks run in registration order. A callback failure is reported without\n * changing the response or preventing later callbacks from running.\n */\nexport function after(callback: AfterCallback): void {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"after() expects a callback function.\");\n }\n\n const state = afterStorage.getStore();\n if (!state) {\n throw new Error(\"after() can only be used while Farm is handling a server request.\");\n }\n if (state.phase === \"closed\") {\n throw new Error(\"after() cannot schedule work after the request lifecycle has completed.\");\n }\n\n let start!: () => void;\n const ready = new Promise<void>((resolve) => {\n start = resolve;\n });\n\n // Registering the continuation here preserves every request AsyncLocalStorage\n // context that is active at the after() call site.\n const result = ready.then(callback);\n state.tasks.push({ result, start });\n}\n\n/** @internal Run a Web Request handler inside Farm's post-response lifecycle. */\nexport async function _runWithAfterRequest(\n request: Request,\n handler: () => Response | Promise<Response>,\n context?: FarmAfterPlatformContext,\n): Promise<Response> {\n if (afterStorage.getStore()) {\n return await handler();\n }\n\n const state = createAfterRequestState();\n registerPlatformLifetime(state, context);\n const hasResponseHook = registerResponseFinishedHook(state, context);\n\n try {\n const response = await afterStorage.run(state, handler);\n return hasResponseHook ? response : wrapResponseBody(response, request, state);\n } catch (error) {\n // The handler threw, so there is no successful response for a\n // response-finished hook to fire on. Run the after-lifecycle now regardless\n // of the hook; otherwise a spec-compliant adapter (whose hook only fires on\n // a real response) never runs the registered after() callbacks and\n // waitUntil(state.completion) hangs forever. finishResponse is idempotent,\n // so a later hook firing (e.g. a Node error response's close) is a no-op.\n finishSoon(state);\n throw error;\n }\n}\n\n/** @internal Run a Node response handler inside Farm's post-response lifecycle. */\nexport async function _runWithAfterNodeResponse<T>(\n response: ServerResponse,\n handler: () => T | Promise<T>,\n context?: Pick<FarmAfterPlatformContext, \"waitUntil\">,\n): Promise<T> {\n if (afterStorage.getStore()) {\n return await handler();\n }\n\n const state = createAfterRequestState();\n let finished = false;\n const finish = () => {\n if (finished) return;\n finished = true;\n response.off(\"finish\", finish);\n response.off(\"close\", finish);\n state.finishResponse();\n };\n\n response.once(\"finish\", finish);\n response.once(\"close\", finish);\n if (response.writableEnded) finishSoon(state);\n registerPlatformLifetime(state, context);\n\n return await afterStorage.run(state, handler);\n}\n\n/** @internal Add Farm's post-response lifecycle to a Node middleware. */\nexport function _withAfterNodeMiddleware(\n handler: (\n request: IncomingMessage,\n response: ServerResponse,\n next: (error?: unknown) => void,\n ) => void | Promise<void>,\n): (\n request: IncomingMessage,\n response: ServerResponse,\n next: (error?: unknown) => void,\n) => Promise<void> {\n return async (request, response, next) => {\n await _runWithAfterNodeResponse(response, () => handler(request, response, next));\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
notifyHistoryChange,
|
|
8
8
|
readPageState,
|
|
9
9
|
subscribeHistoryChange
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-PSQ7N4XP.mjs";
|
|
11
11
|
import {
|
|
12
12
|
getFarmI18nClientState
|
|
13
13
|
} from "./chunk-ULD4ENAH.mjs";
|
|
@@ -236,4 +236,4 @@ export {
|
|
|
236
236
|
useBlocker,
|
|
237
237
|
useScrollRestoration
|
|
238
238
|
};
|
|
239
|
-
//# sourceMappingURL=chunk-
|
|
239
|
+
//# sourceMappingURL=chunk-6UYVU46O.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/devtools-config.ts"],"sourcesContent":["export const DEFAULT_FARM_DEVTOOLS_SHORTCUT = \"mod+shift+.\";\nexport const FARM_DEVTOOLS_PATH = \"/__farm/devtools\";\nexport const FARM_DEVTOOLS_LAUNCH_PARAM = \"__farm_devtools\";\n\n/**\n * Configuration for the built-in DevTools dashboard. The dashboard is deprecated in favor\n * of the `@farm.js/devtools` plugin, which reuses this configuration for enablement and\n * the keyboard shortcut. Both options keep working while the built-in UI remains available.\n */\nexport interface FarmDevtoolsConfig {\n /** Enable the development-only DevTools UI and runtime endpoints. */\n enabled?: boolean;\n /** Keyboard shortcut used to toggle DevTools, or false to disable the shortcut. */\n shortcut?: string | false;\n}\n\nexport type FarmDevtoolsUserConfig = boolean | FarmDevtoolsConfig;\n\nexport interface ResolvedFarmDevtoolsConfig {\n enabled: boolean;\n shortcut: string | false;\n}\n\nexport function resolveFarmDevtoolsConfig(\n config: FarmDevtoolsUserConfig | ResolvedFarmDevtoolsConfig | undefined,\n mode: \"development\" | \"production\" = \"development\",\n): ResolvedFarmDevtoolsConfig {\n if (mode !== \"development\" || config === false) {\n return { enabled: false, shortcut: false };\n }\n\n const options = config === true || config === undefined ? {} : config;\n const enabled = options.enabled ?? true;\n\n if (!enabled) {\n return { enabled: false, shortcut: false };\n }\n\n const shortcut =\n typeof options.shortcut === \"string\" && options.shortcut.trim()\n ? options.shortcut\n .toLowerCase()\n .split(\"+\")\n .map((part) => part.trim())\n .filter(Boolean)\n .join(\"+\")\n : options.shortcut === false\n ? false\n : DEFAULT_FARM_DEVTOOLS_SHORTCUT;\n\n return { enabled: true, shortcut };\n}\n"],"mappings":";;;;;AAAO,IAAM,iCAAiC;AACvC,IAAM,qBAAqB;AAC3B,IAAM,6BAA6B;AAqBnC,SAAS,0BACd,QACA,OAAqC,eACT;AAC5B,MAAI,SAAS,iBAAiB,WAAW,OAAO;AAC9C,WAAO,EAAE,SAAS,OAAO,UAAU,MAAM;AAAA,EAC3C;AAEA,QAAM,UAAU,WAAW,QAAQ,WAAW,SAAY,CAAC,IAAI;AAC/D,QAAM,UAAU,QAAQ,WAAW;AAEnC,MAAI,CAAC,SAAS;AACZ,WAAO,EAAE,SAAS,OAAO,UAAU,MAAM;AAAA,EAC3C;AAEA,QAAM,WACJ,OAAO,QAAQ,aAAa,YAAY,QAAQ,SAAS,KAAK,IAC1D,QAAQ,SACL,YAAY,EACZ,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EACzB,OAAO,OAAO,EACd,KAAK,GAAG,IACX,QAAQ,aAAa,QACnB,QACA;AAER,SAAO,EAAE,SAAS,MAAM,SAAS;AACnC;AA5BgB;","names":[]}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
FARM_DOCS_LAST_MODIFIED_MANIFEST,
|
|
10
10
|
createFarmDocsLastModifiedManifest,
|
|
11
11
|
getFarmDocsRouteTypeEntries
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-YIBV77KZ.mjs";
|
|
13
13
|
import {
|
|
14
14
|
generateFarmDocsSearchClientRuntime,
|
|
15
15
|
isFarmDocsSearchEnabled,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
getDeployTargetForPreset,
|
|
21
21
|
hasCustomFarmRouteContext,
|
|
22
22
|
resolveDeployOutputPath
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-X4SFHKFH.mjs";
|
|
24
24
|
import {
|
|
25
25
|
resolveFarmInstrumentationFile
|
|
26
26
|
} from "./chunk-5NAM3OTS.mjs";
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
createFarmThemeCssPlugin,
|
|
33
33
|
enforceFarmIsolatedHydrationRouteBudget,
|
|
34
34
|
farmFontImportsPlugin,
|
|
35
|
+
generateClientCachePersistenceCode,
|
|
35
36
|
generateFarmClientPluginEntryCode,
|
|
36
37
|
generateFarmIntegrationProviderClientCode,
|
|
37
38
|
generateFarmIntegrationProviderServerModules,
|
|
@@ -40,10 +41,11 @@ import {
|
|
|
40
41
|
getClientModuleMetadata,
|
|
41
42
|
mergeFarmFontCss,
|
|
42
43
|
mergeFarmViteConfig,
|
|
44
|
+
resolveFarmClientCacheAdapterEntry,
|
|
43
45
|
resolveFarmIsolatedClientHydrationMode,
|
|
44
46
|
resolveFarmNotFoundComponentPath,
|
|
45
47
|
resolveRouteRenderingConfigFromFile
|
|
46
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-FP5Q67FO.mjs";
|
|
47
49
|
import {
|
|
48
50
|
farmEnvironmentFunctionsPlugin
|
|
49
51
|
} from "./chunk-V6WE6JSZ.mjs";
|
|
@@ -82,13 +84,13 @@ import {
|
|
|
82
84
|
} from "./chunk-AAC66ILR.mjs";
|
|
83
85
|
import {
|
|
84
86
|
appendMiddlewareRoutePath
|
|
85
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-4X57GXQA.mjs";
|
|
86
88
|
import {
|
|
87
89
|
APIRouteManager
|
|
88
|
-
} from "./chunk-
|
|
90
|
+
} from "./chunk-TT3E2JOF.mjs";
|
|
89
91
|
import {
|
|
90
92
|
readFarmI18nCatalogs
|
|
91
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-TQTB33JS.mjs";
|
|
92
94
|
import {
|
|
93
95
|
createFarmRouteRuntimeKey,
|
|
94
96
|
getFarmRouteRuntimeConfig,
|
|
@@ -435,6 +437,34 @@ function createFarmVercelImmutableAssetRoute() {
|
|
|
435
437
|
};
|
|
436
438
|
}
|
|
437
439
|
__name(createFarmVercelImmutableAssetRoute, "createFarmVercelImmutableAssetRoute");
|
|
440
|
+
function buildFarmVercelRoutes(options) {
|
|
441
|
+
const { presetRoutes, runtimeRoutes, apiBasePath } = options;
|
|
442
|
+
const filesystemIndex = presetRoutes.findIndex((route) => route.handle === "filesystem");
|
|
443
|
+
const sourceRoutes = filesystemIndex >= 0 ? presetRoutes.slice(0, filesystemIndex) : [];
|
|
444
|
+
const preservedSourceRoutes = sourceRoutes.filter((route) => route.continue !== true);
|
|
445
|
+
return [
|
|
446
|
+
...preservedSourceRoutes,
|
|
447
|
+
createFarmVercelImmutableAssetRoute(),
|
|
448
|
+
{ handle: "filesystem" },
|
|
449
|
+
...runtimeRoutes,
|
|
450
|
+
...apiBasePath === "/" ? [] : [
|
|
451
|
+
{
|
|
452
|
+
src: `${apiBasePath}/(.*)`,
|
|
453
|
+
dest: "/__nitro",
|
|
454
|
+
headers: {
|
|
455
|
+
"Access-Control-Allow-Origin": "*",
|
|
456
|
+
"Access-Control-Allow-Methods": "*",
|
|
457
|
+
"Access-Control-Allow-Headers": "*"
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
],
|
|
461
|
+
{
|
|
462
|
+
src: "/(.*)",
|
|
463
|
+
dest: "/__nitro"
|
|
464
|
+
}
|
|
465
|
+
];
|
|
466
|
+
}
|
|
467
|
+
__name(buildFarmVercelRoutes, "buildFarmVercelRoutes");
|
|
438
468
|
|
|
439
469
|
// src/nitro/node-server-entry.ts
|
|
440
470
|
function createFarmNodeServerEntry(options) {
|
|
@@ -1598,7 +1628,8 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
|
|
|
1598
1628
|
config.publicRuntimeConfig,
|
|
1599
1629
|
config.trailingSlash,
|
|
1600
1630
|
getIntegrationProviders(config.integrations),
|
|
1601
|
-
config.basePath
|
|
1631
|
+
config.basePath,
|
|
1632
|
+
generateClientCachePersistenceCode(resolveFarmClientCacheAdapterEntry(root, config.cache))
|
|
1602
1633
|
);
|
|
1603
1634
|
await fs.writeFile(clientEntryPath, clientHydrationCode);
|
|
1604
1635
|
const hasScopedPostcssConfig = hasProjectPostcssConfig(root);
|
|
@@ -1909,6 +1940,46 @@ function matchRuntimePathPattern(pattern, pathname) {
|
|
|
1909
1940
|
`.trim();
|
|
1910
1941
|
}
|
|
1911
1942
|
__name(generateRuntimePathMatcherSource, "generateRuntimePathMatcherSource");
|
|
1943
|
+
function generateRedirectInterpolationSource() {
|
|
1944
|
+
return `
|
|
1945
|
+
function encodeRuntimePathSegment(value) {
|
|
1946
|
+
return encodeURIComponent(String(value)).replace(
|
|
1947
|
+
/[!'()*]/g,
|
|
1948
|
+
function(character) {
|
|
1949
|
+
return "%" + character.charCodeAt(0).toString(16).toUpperCase();
|
|
1950
|
+
},
|
|
1951
|
+
);
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
function interpolateRedirectDestination(destination, params) {
|
|
1955
|
+
let result = destination;
|
|
1956
|
+
const catchAllParamSegments = params[farmCatchAllParamSegments] || {};
|
|
1957
|
+
const orderedCaptures = [];
|
|
1958
|
+
for (const [key, value] of Object.entries(params)) {
|
|
1959
|
+
const segments = catchAllParamSegments[key];
|
|
1960
|
+
const encodedValue = Array.isArray(segments)
|
|
1961
|
+
? segments.map(encodeRuntimePathSegment).join("/")
|
|
1962
|
+
: encodeRuntimePathSegment(value);
|
|
1963
|
+
orderedCaptures.push(encodedValue);
|
|
1964
|
+
result = result.split("[[..." + key + "]]").join(encodedValue);
|
|
1965
|
+
result = result.split("[..." + key + "]").join(encodedValue);
|
|
1966
|
+
result = result.split("[" + key + "]").join(encodedValue);
|
|
1967
|
+
result = result.split(":" + key + "*").join(encodedValue);
|
|
1968
|
+
result = result.split(":" + key).join(encodedValue);
|
|
1969
|
+
if (key === "wildcard") result = result.split("*").join(encodedValue);
|
|
1970
|
+
}
|
|
1971
|
+
// Numbered captures resolve after the named substitutions. Encoded values
|
|
1972
|
+
// never contain "$", so this cannot rewrite an already-injected value. An
|
|
1973
|
+
// out-of-range index resolves to "", matching the development path.
|
|
1974
|
+
result = result.replace(/\\$(\\d+)/g, function(_whole, group) {
|
|
1975
|
+
const captured = orderedCaptures[Number(group) - 1];
|
|
1976
|
+
return captured === undefined ? "" : captured;
|
|
1977
|
+
});
|
|
1978
|
+
return result;
|
|
1979
|
+
}
|
|
1980
|
+
`.trim();
|
|
1981
|
+
}
|
|
1982
|
+
__name(generateRedirectInterpolationSource, "generateRedirectInterpolationSource");
|
|
1912
1983
|
function generateUniversalRouterStateProperties() {
|
|
1913
1984
|
return `
|
|
1914
1985
|
blockers: new Set(),
|
|
@@ -2200,7 +2271,7 @@ function generateClientHydrationEntry(clientPages, layoutRoutes, clientRouteSlot
|
|
|
2200
2271
|
secure: false
|
|
2201
2272
|
},
|
|
2202
2273
|
direction: {}
|
|
2203
|
-
}, plugins = [], renderer = REACT_RENDERER, publicRuntimeConfig = void 0, trailingSlash = false, integrationProviders = [], basePath = "/") {
|
|
2274
|
+
}, plugins = [], renderer = REACT_RENDERER, publicRuntimeConfig = void 0, trailingSlash = false, integrationProviders = [], basePath = "/", clientCachePersistence = { imports: "", init: "" }) {
|
|
2204
2275
|
const toImportPath = /* @__PURE__ */ __name((targetPath) => targetPath.replace(/\\/g, "/"), "toImportPath");
|
|
2205
2276
|
const clientPluginEntry = generateFarmClientPluginEntryCode(
|
|
2206
2277
|
plugins,
|
|
@@ -2212,8 +2283,7 @@ function generateClientHydrationEntry(clientPages, layoutRoutes, clientRouteSlot
|
|
|
2212
2283
|
import { createRoot, hydrateRoot } from "react-dom/client";` : `import React, { createRoot, hydrateRoot } from ${JSON.stringify(renderer.client)};`;
|
|
2213
2284
|
const providerClientCode = generateFarmIntegrationProviderClientCode(integrationProviders, root);
|
|
2214
2285
|
const globalsCssPath = path4.join(root, srcDir, "app", "globals.css");
|
|
2215
|
-
const
|
|
2216
|
-
const cssImport = `import ${JSON.stringify(cssImportPath)};`;
|
|
2286
|
+
const cssImport = existsSync(globalsCssPath) ? `import ${JSON.stringify(toImportPath(globalsCssPath))};` : "";
|
|
2217
2287
|
const layoutImportStatements = [];
|
|
2218
2288
|
const layoutRegistrations = [];
|
|
2219
2289
|
layoutRoutes.forEach((layout, index) => {
|
|
@@ -2298,6 +2368,7 @@ ${layoutImports}
|
|
|
2298
2368
|
import { createClientPluginManager, getHashTargetElement, installChunkErrorRecovery, isFarmExternalNavigationURL, reconcileFarmDocumentHead, setFarmBasePath, setFarmTrailingSlashPreference, stripFarmBasePath } from "@farm.js/core/internal/client-runtime";
|
|
2299
2369
|
import { createFarmDeploymentMismatchError, createFarmDeploymentRequestHeaders, isFarmDeploymentMismatchResponse } from "@farm.js/core/deployment";
|
|
2300
2370
|
${clientPluginEntry.imports}
|
|
2371
|
+
${clientCachePersistence.imports}
|
|
2301
2372
|
${i18nClientRuntime}
|
|
2302
2373
|
${docsNavigationRuntime}
|
|
2303
2374
|
${docsAdapterRuntime}
|
|
@@ -2306,6 +2377,7 @@ ${generateFarmDocsSearchClientRuntime(docsSearchEnabled, docsSearchModuleId)}
|
|
|
2306
2377
|
setFarmBasePath(${JSON.stringify(basePath)});
|
|
2307
2378
|
setFarmTrailingSlashPreference(${JSON.stringify(trailingSlash)});
|
|
2308
2379
|
installChunkErrorRecovery();
|
|
2380
|
+
${clientCachePersistence.init}
|
|
2309
2381
|
mountFarmDocsSearch();
|
|
2310
2382
|
|
|
2311
2383
|
${generateUniversalRouterStateRuntime()}
|
|
@@ -2660,6 +2732,7 @@ import { createClientPluginManager, getHashTargetElement, installChunkErrorRecov
|
|
|
2660
2732
|
import { createFarmDeploymentMismatchError, createFarmDeploymentRequestHeaders, isFarmDeploymentMismatchResponse } from "@farm.js/core/deployment";
|
|
2661
2733
|
import { isFarmRouteActive, matchFarmRoute } from "@farm.js/core/router";
|
|
2662
2734
|
${clientPluginEntry.imports}
|
|
2735
|
+
${clientCachePersistence.imports}
|
|
2663
2736
|
${i18nClientRuntime}
|
|
2664
2737
|
${docsNavigationRuntime}
|
|
2665
2738
|
${docsAdapterRuntime}
|
|
@@ -2672,6 +2745,7 @@ ${providerClientCode.runtime}
|
|
|
2672
2745
|
setFarmBasePath(${JSON.stringify(basePath)});
|
|
2673
2746
|
setFarmTrailingSlashPreference(${JSON.stringify(trailingSlash)});
|
|
2674
2747
|
installChunkErrorRecovery();
|
|
2748
|
+
${clientCachePersistence.init}
|
|
2675
2749
|
|
|
2676
2750
|
// Client component routes
|
|
2677
2751
|
const clientRoutes = [
|
|
@@ -5416,32 +5490,7 @@ async function handleApplicationMetadataRouteRequest(request, routePathname) {
|
|
|
5416
5490
|
}
|
|
5417
5491
|
}
|
|
5418
5492
|
|
|
5419
|
-
|
|
5420
|
-
return encodeURIComponent(String(value)).replace(
|
|
5421
|
-
/[!'()*]/g,
|
|
5422
|
-
function(character) {
|
|
5423
|
-
return "%" + character.charCodeAt(0).toString(16).toUpperCase();
|
|
5424
|
-
},
|
|
5425
|
-
);
|
|
5426
|
-
}
|
|
5427
|
-
|
|
5428
|
-
function interpolateRedirectDestination(destination, params) {
|
|
5429
|
-
let result = destination;
|
|
5430
|
-
const catchAllParamSegments = params[farmCatchAllParamSegments] || {};
|
|
5431
|
-
for (const [key, value] of Object.entries(params)) {
|
|
5432
|
-
const segments = catchAllParamSegments[key];
|
|
5433
|
-
const encodedValue = Array.isArray(segments)
|
|
5434
|
-
? segments.map(encodeRuntimePathSegment).join("/")
|
|
5435
|
-
: encodeRuntimePathSegment(value);
|
|
5436
|
-
result = result.split("[[..." + key + "]]").join(encodedValue);
|
|
5437
|
-
result = result.split("[..." + key + "]").join(encodedValue);
|
|
5438
|
-
result = result.split("[" + key + "]").join(encodedValue);
|
|
5439
|
-
result = result.split(":" + key + "*").join(encodedValue);
|
|
5440
|
-
result = result.split(":" + key).join(encodedValue);
|
|
5441
|
-
if (key === "wildcard") result = result.split("*").join(encodedValue);
|
|
5442
|
-
}
|
|
5443
|
-
return result;
|
|
5444
|
-
}
|
|
5493
|
+
${generateRedirectInterpolationSource()}
|
|
5445
5494
|
|
|
5446
5495
|
function matchRedirectRoute(pathname, locale, search) {
|
|
5447
5496
|
for (const redirect of redirectRoutes) {
|
|
@@ -5864,9 +5913,10 @@ ${config.docs?.enabled ? `async function wrapFarmDocsResponseWithLayouts(request
|
|
|
5864
5913
|
}` : ""}
|
|
5865
5914
|
|
|
5866
5915
|
const pprShellCache = getFarmDataCache();
|
|
5916
|
+
const experimentalPPREnabled = ${JSON.stringify(config.experimental?.ppr === true)};
|
|
5867
5917
|
|
|
5868
5918
|
function resolvePPRConfig(routeModule) {
|
|
5869
|
-
if (!routeModule || routeModule.dynamic === "force-dynamic") {
|
|
5919
|
+
if (!experimentalPPREnabled || !routeModule || routeModule.dynamic === "force-dynamic") {
|
|
5870
5920
|
return { enabled: false };
|
|
5871
5921
|
}
|
|
5872
5922
|
|
|
@@ -7955,35 +8005,11 @@ async function postProcessVercelOutput(root, outputDir, fs, config, farmWorkflow
|
|
|
7955
8005
|
routeRuntimeManifest,
|
|
7956
8006
|
fs
|
|
7957
8007
|
);
|
|
7958
|
-
vercelConfig.routes =
|
|
7959
|
-
|
|
7960
|
-
|
|
7961
|
-
|
|
7962
|
-
|
|
7963
|
-
createFarmVercelImmutableAssetRoute(),
|
|
7964
|
-
// Serve static files first
|
|
7965
|
-
{
|
|
7966
|
-
handle: "filesystem"
|
|
7967
|
-
},
|
|
7968
|
-
...runtimeRoutes,
|
|
7969
|
-
// API routes
|
|
7970
|
-
...resolveFarmAPIServerBasePath(config.api) === "/" ? [] : [
|
|
7971
|
-
{
|
|
7972
|
-
src: `${resolveFarmAPIServerBasePath(config.api)}/(.*)`,
|
|
7973
|
-
dest: "/__nitro",
|
|
7974
|
-
headers: {
|
|
7975
|
-
"Access-Control-Allow-Origin": "*",
|
|
7976
|
-
"Access-Control-Allow-Methods": "*",
|
|
7977
|
-
"Access-Control-Allow-Headers": "*"
|
|
7978
|
-
}
|
|
7979
|
-
}
|
|
7980
|
-
],
|
|
7981
|
-
// All other routes go to the serverless function
|
|
7982
|
-
{
|
|
7983
|
-
src: "/(.*)",
|
|
7984
|
-
dest: "/__nitro"
|
|
7985
|
-
}
|
|
7986
|
-
];
|
|
8008
|
+
vercelConfig.routes = buildFarmVercelRoutes({
|
|
8009
|
+
presetRoutes: Array.isArray(vercelConfig.routes) ? vercelConfig.routes : [],
|
|
8010
|
+
runtimeRoutes,
|
|
8011
|
+
apiBasePath: resolveFarmAPIServerBasePath(config.api)
|
|
8012
|
+
});
|
|
7987
8013
|
const vercelConfigWithWorkflowCrons = applyFarmWorkflowVercelCrons(
|
|
7988
8014
|
vercelConfig,
|
|
7989
8015
|
farmWorkflows.workflows
|
|
@@ -8582,4 +8608,4 @@ __name(buildNitro, "buildNitro");
|
|
|
8582
8608
|
export {
|
|
8583
8609
|
build
|
|
8584
8610
|
};
|
|
8585
|
-
//# sourceMappingURL=chunk-
|
|
8611
|
+
//# sourceMappingURL=chunk-D7F7YZ7L.mjs.map
|