@farm.js/core 0.1.0-beta.97 → 0.1.0-beta.99
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.map +1 -0
- package/dist/agent-runtime.cjs +7 -3
- package/dist/agent-runtime.cjs.map +1 -0
- package/dist/agent-runtime.d.mts +2 -2
- package/dist/agent-runtime.d.ts +2 -2
- package/dist/agent-runtime.mjs +2 -1
- package/dist/agent-runtime.mjs.map +1 -1
- package/dist/api/route-manager.cjs.map +1 -0
- package/dist/api/route-manager.d.mts +2 -2
- package/dist/api/route-manager.d.ts +2 -2
- package/dist/api/runtime.cjs.map +1 -0
- package/dist/api.cjs +26 -1
- package/dist/api.cjs.map +1 -0
- package/dist/api.d.mts +3 -3
- package/dist/api.d.ts +3 -3
- package/dist/api.mjs +2 -2
- package/dist/{app-CIOx3LvY.d.ts → app-CGjrKNoN.d.ts} +4 -4
- package/dist/{app-DBd6437H.d.mts → app-DOcLs_iq.d.mts} +4 -4
- package/dist/app-markdown.cjs +21 -0
- package/dist/app-markdown.cjs.map +1 -0
- package/dist/app-markdown.d.mts +19 -4
- package/dist/app-markdown.d.ts +19 -4
- package/dist/app-markdown.mjs +7 -1
- package/dist/cache.cjs.map +1 -0
- package/dist/{chunk-VMCHLH3Y.mjs → chunk-26BCDVJS.mjs} +19 -1
- package/dist/chunk-26BCDVJS.mjs.map +1 -0
- package/dist/{chunk-FP5Q67FO.mjs → chunk-2HYYZCCI.mjs} +308 -19
- package/dist/chunk-2HYYZCCI.mjs.map +1 -0
- package/dist/{chunk-WKDAA6V2.mjs → chunk-3BTAMIQE.mjs} +100 -41
- package/dist/chunk-3BTAMIQE.mjs.map +1 -0
- package/dist/{chunk-WD2EBM3I.mjs → chunk-3CQJV3NC.mjs} +2 -2
- package/dist/{chunk-I3OOUWO5.mjs → chunk-3GDRV7SG.mjs} +2 -2
- package/dist/{chunk-YIBV77KZ.mjs → chunk-4WLAVHCY.mjs} +2 -2
- package/dist/{chunk-KDP5ZSWP.mjs → chunk-7PS5NKOM.mjs} +26 -11
- package/dist/chunk-7PS5NKOM.mjs.map +1 -0
- package/dist/{chunk-X4SFHKFH.mjs → chunk-BU65A3LZ.mjs} +10 -6
- package/dist/chunk-BU65A3LZ.mjs.map +1 -0
- package/dist/{chunk-WMJGA32P.mjs → chunk-BXVOHG6B.mjs} +27 -2
- package/dist/{chunk-WMJGA32P.mjs.map → chunk-BXVOHG6B.mjs.map} +1 -1
- package/dist/{chunk-BZAIS65C.mjs → chunk-DIHNOVZZ.mjs} +40 -13
- package/dist/chunk-DIHNOVZZ.mjs.map +1 -0
- package/dist/{chunk-ISSFLGJ5.mjs → chunk-FDWECN3W.mjs} +8 -4
- package/dist/chunk-FDWECN3W.mjs.map +1 -0
- package/dist/chunk-FDWXXTWR.mjs +114 -0
- package/dist/chunk-FDWXXTWR.mjs.map +1 -0
- package/dist/{chunk-FSIXEIOB.mjs → chunk-L7FSTPGS.mjs} +2 -2
- package/dist/{chunk-J3MPQ4MQ.mjs → chunk-LG4XB6RN.mjs} +2 -2
- package/dist/{chunk-J3MPQ4MQ.mjs.map → chunk-LG4XB6RN.mjs.map} +1 -1
- package/dist/{chunk-AAC66ILR.mjs → chunk-LXXG3K2Y.mjs} +61 -2
- package/dist/chunk-LXXG3K2Y.mjs.map +1 -0
- package/dist/{chunk-GJ7W6LNK.mjs → chunk-N5RK4LK6.mjs} +3 -3
- package/dist/{chunk-D7F7YZ7L.mjs → chunk-NCVFPT67.mjs} +100 -40
- package/dist/{chunk-D7F7YZ7L.mjs.map → chunk-NCVFPT67.mjs.map} +1 -1
- package/dist/{chunk-UMUWR5XA.mjs → chunk-PURU7FXR.mjs} +2 -2
- package/dist/{chunk-2SKCXYLB.mjs → chunk-QQCCBMTH.mjs} +60 -6
- package/dist/chunk-QQCCBMTH.mjs.map +1 -0
- package/dist/chunk-RKUPOYQV.mjs +28 -0
- package/dist/chunk-RKUPOYQV.mjs.map +1 -0
- package/dist/{chunk-52BR7LTX.mjs → chunk-STSPSJUI.mjs} +3 -3
- package/dist/{chunk-EPDIF432.mjs → chunk-UOGX6UNO.mjs} +37 -17
- package/dist/chunk-UOGX6UNO.mjs.map +1 -0
- package/dist/{chunk-IZBX2TEU.mjs → chunk-VQG3QWWK.mjs} +2 -2
- package/dist/{chunk-35NPLKQJ.mjs → chunk-XWM2C267.mjs} +21 -105
- package/dist/chunk-XWM2C267.mjs.map +1 -0
- package/dist/{chunk-7ZVN3YZI.mjs → chunk-Z5ARESQG.mjs} +43 -1
- package/dist/chunk-Z5ARESQG.mjs.map +1 -0
- package/dist/client/lifecycle.cjs.map +1 -0
- package/dist/client/lifecycle.mjs +2 -2
- package/dist/{client-plugins-B6-07YmP.d.mts → client-plugins-BqtHoJ9C.d.mts} +91 -3
- package/dist/{client-plugins-By6MVUX-.d.ts → client-plugins-DYprkCKN.d.ts} +91 -3
- package/dist/client-plugins.cjs +1 -1
- package/dist/client-plugins.cjs.map +1 -0
- package/dist/client-plugins.d.mts +2 -2
- package/dist/client-plugins.d.ts +2 -2
- package/dist/client-plugins.mjs +2 -2
- package/dist/client.cjs +61 -16
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.mts +5 -5
- package/dist/client.d.ts +5 -5
- package/dist/client.mjs +7 -7
- package/dist/config.cjs.map +1 -0
- package/dist/config.d.mts +2 -2
- package/dist/config.d.ts +2 -2
- package/dist/cron.cjs +48 -12
- package/dist/cron.cjs.map +1 -0
- package/dist/cron.mjs +2 -1
- package/dist/deferred.cjs.map +1 -0
- package/dist/deployment.cjs.map +1 -0
- package/dist/{devtools-XWZX6CCL.mjs → devtools-24N3U5IG.mjs} +9 -7
- package/dist/{devtools-XWZX6CCL.mjs.map → devtools-24N3U5IG.mjs.map} +1 -1
- package/dist/docs.cjs +7 -3
- package/dist/docs.cjs.map +1 -0
- package/dist/docs.mjs +9 -7
- package/dist/env-types.cjs.map +1 -0
- package/dist/env.cjs.map +1 -0
- package/dist/environment/vite.cjs.map +1 -0
- package/dist/environment.cjs.map +1 -0
- package/dist/font.cjs.map +1 -0
- package/dist/headers.cjs.map +1 -0
- package/dist/i18n/client.cjs.map +1 -0
- package/dist/i18n/index.cjs.map +1 -0
- package/dist/i18n/server.cjs.map +1 -0
- package/dist/image/server.cjs +99 -40
- package/dist/image/server.cjs.map +1 -0
- package/dist/image/server.d.mts +6 -0
- package/dist/image/server.d.ts +6 -0
- package/dist/image/server.mjs +1 -1
- package/dist/image/sharp.cjs +1 -0
- package/dist/image/sharp.cjs.map +1 -0
- package/dist/image/sharp.d.mts +1 -1
- package/dist/image/sharp.d.ts +1 -1
- package/dist/image/sharp.mjs +1 -1
- package/dist/image/sharp.mjs.map +1 -1
- package/dist/image.cjs.map +1 -0
- package/dist/index.cjs +943 -231
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.mts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.mjs +38 -24
- package/dist/index.mjs.map +1 -1
- package/dist/instrumentation.cjs.map +1 -0
- package/dist/{integration-orm-LLW6WZNK.mjs → integration-orm-G5BPBT5X.mjs} +3 -3
- package/dist/integrations.cjs +168 -5
- package/dist/integrations.cjs.map +1 -0
- package/dist/integrations.d.mts +2 -2
- package/dist/integrations.d.ts +2 -2
- package/dist/integrations.mjs +10 -3
- package/dist/internal/build-runtime.cjs +745 -139
- package/dist/internal/build-runtime.cjs.map +1 -0
- package/dist/internal/build-runtime.d.mts +4 -4
- package/dist/internal/build-runtime.d.ts +4 -4
- package/dist/internal/build-runtime.mjs +16 -14
- package/dist/internal/client-runtime.cjs +7 -2
- package/dist/internal/client-runtime.cjs.map +1 -0
- package/dist/internal/client-runtime.mjs +8 -3
- package/dist/internal/client-runtime.mjs.map +1 -1
- package/dist/internal/config-runtime.cjs +59 -42
- package/dist/internal/config-runtime.cjs.map +1 -0
- package/dist/internal/config-runtime.d.mts +3 -3
- package/dist/internal/config-runtime.d.ts +3 -3
- package/dist/internal/config-runtime.mjs +8 -6
- package/dist/internal/isolated-boundary.cjs.map +1 -0
- package/dist/internal/metadata-image-runtime.cjs.map +1 -0
- package/dist/internal/product-telemetry-runtime.cjs +52 -5
- package/dist/internal/product-telemetry-runtime.cjs.map +1 -0
- package/dist/internal/product-telemetry-runtime.d.mts +12 -1
- package/dist/internal/product-telemetry-runtime.d.ts +12 -1
- package/dist/internal/product-telemetry-runtime.mjs +50 -5
- package/dist/internal/product-telemetry-runtime.mjs.map +1 -1
- package/dist/internal/production-node-env.cjs.map +1 -0
- package/dist/internal/production-runtime.cjs +56 -10
- package/dist/internal/production-runtime.cjs.map +1 -0
- package/dist/internal/production-runtime.d.mts +8 -8
- package/dist/internal/production-runtime.d.ts +8 -8
- package/dist/internal/production-runtime.mjs +2 -2
- package/dist/markdown.cjs.map +1 -0
- package/dist/{metadata-route-8_V3UonT.d.ts → metadata-route-D2be_0kC.d.ts} +17 -2
- package/dist/{metadata-route-CWP_HjGU.d.mts → metadata-route-Dw5CrDIZ.d.mts} +17 -2
- package/dist/middleware.cjs.map +1 -0
- package/dist/middleware.d.mts +4 -4
- package/dist/middleware.d.ts +4 -4
- package/dist/navigation.cjs.map +1 -0
- package/dist/{nitro-EGRNOB5P.mjs → nitro-YJEP3FWM.mjs} +4 -3
- package/dist/{nitro-EGRNOB5P.mjs.map → nitro-YJEP3FWM.mjs.map} +1 -1
- package/dist/observability.cjs.map +1 -0
- package/dist/plugin.cjs +599 -104
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.mts +2 -2
- package/dist/plugin.d.ts +2 -2
- package/dist/plugin.mjs +13 -11
- package/dist/{production-runtime-CdmzsDax.d.ts → production-runtime-CTqpD1C8.d.ts} +2 -2
- package/dist/{production-runtime-BGRH1dKG.d.mts → production-runtime-HNqNZd4D.d.mts} +2 -2
- package/dist/query/client.cjs.map +1 -0
- package/dist/query/index.cjs.map +1 -0
- package/dist/query/parsers.cjs.map +1 -0
- package/dist/query/server.cjs.map +1 -0
- package/dist/{render-plan-DLxJYAA5.d.mts → render-plan-COscpW-i.d.mts} +1 -1
- package/dist/{render-plan-0GeHiGVZ.d.ts → render-plan-Z4kSxaT_.d.ts} +1 -1
- package/dist/renderer/react/client.cjs.map +1 -0
- package/dist/renderer/react/server.cjs.map +1 -0
- package/dist/renderer/react/vite.cjs.map +1 -0
- package/dist/renderer-client.cjs +26 -1
- package/dist/renderer-client.cjs.map +1 -0
- package/dist/renderer-client.d.mts +4 -4
- package/dist/renderer-client.d.ts +4 -4
- package/dist/renderer-client.mjs +2 -2
- package/dist/renderer.cjs.map +1 -0
- package/dist/{request-BstWbZ6O.d.ts → request-BEDb2jE9.d.ts} +1 -1
- package/dist/{request-BCNXSXLh.d.mts → request-CbIAqJY9.d.mts} +1 -1
- package/dist/request.cjs.map +1 -0
- package/dist/request.d.mts +3 -3
- package/dist/request.d.ts +3 -3
- package/dist/router.cjs.map +1 -0
- package/dist/routes.cjs.map +1 -0
- package/dist/routes.d.mts +2 -2
- package/dist/routes.d.ts +2 -2
- package/dist/server-action-security.cjs +117 -104
- package/dist/server-action-security.cjs.map +1 -0
- package/dist/server-action-security.mjs +2 -1
- package/dist/server-fn-client.cjs.map +1 -0
- package/dist/server-fn.cjs.map +1 -0
- package/dist/server-fn.mjs +3 -2
- package/dist/server-plugins.cjs.map +1 -0
- package/dist/server-plugins.d.mts +3 -3
- package/dist/server-plugins.d.ts +3 -3
- package/dist/server-query-client.cjs +26 -1
- package/dist/server-query-client.cjs.map +1 -0
- package/dist/server-query-client.mjs +3 -3
- package/dist/server-query.cjs.map +1 -0
- package/dist/server-query.mjs +4 -3
- package/dist/server.cjs +686 -170
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.mts +8 -8
- package/dist/server.d.ts +8 -8
- package/dist/server.mjs +16 -14
- package/dist/server.mjs.map +1 -1
- package/dist/{spa-router-COgu4txb.d.ts → spa-router-CjeQites.d.ts} +1 -1
- package/dist/{spa-router-BeyAVSc6.d.mts → spa-router-FJbNou1a.d.mts} +1 -1
- package/dist/storage.cjs +7 -3
- package/dist/storage.cjs.map +1 -0
- package/dist/storage.mjs +1 -1
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.mts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/testing.mjs +2 -1
- package/dist/testing.mjs.map +1 -1
- package/dist/theme/client.cjs.map +1 -0
- package/dist/theme/index.cjs.map +1 -0
- package/dist/theme/runtime.cjs.map +1 -0
- package/dist/theme/server.cjs.map +1 -0
- package/dist/{utils-DL2VwDQl.d.mts → utils-BiMJv9Ys.d.mts} +1 -1
- package/dist/{utils-DkU2c_1B.d.ts → utils-BpnKRFv9.d.ts} +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -0
- package/dist/version.mjs +1 -1
- package/dist/vite.cjs +599 -104
- package/dist/vite.cjs.map +1 -0
- package/dist/vite.d.mts +2 -2
- package/dist/vite.d.ts +2 -2
- package/dist/vite.mjs +13 -11
- package/dist/{workflows-ChyK_oTu.d.mts → workflows-BantWytQ.d.mts} +7 -0
- package/dist/{workflows-ChyK_oTu.d.ts → workflows-BantWytQ.d.ts} +7 -0
- package/dist/workflows.cjs +73 -5
- package/dist/workflows.cjs.map +1 -0
- package/dist/workflows.d.mts +1 -1
- package/dist/workflows.d.ts +1 -1
- package/dist/workflows.mjs +2 -1
- package/package.json +17 -17
- package/dist/chunk-2SKCXYLB.mjs.map +0 -1
- package/dist/chunk-35NPLKQJ.mjs.map +0 -1
- package/dist/chunk-7ZVN3YZI.mjs.map +0 -1
- package/dist/chunk-AAC66ILR.mjs.map +0 -1
- package/dist/chunk-BZAIS65C.mjs.map +0 -1
- package/dist/chunk-EPDIF432.mjs.map +0 -1
- package/dist/chunk-FP5Q67FO.mjs.map +0 -1
- package/dist/chunk-ISSFLGJ5.mjs.map +0 -1
- package/dist/chunk-KDP5ZSWP.mjs.map +0 -1
- package/dist/chunk-VMCHLH3Y.mjs.map +0 -1
- package/dist/chunk-WKDAA6V2.mjs.map +0 -1
- package/dist/chunk-X4SFHKFH.mjs.map +0 -1
- /package/dist/{chunk-WD2EBM3I.mjs.map → chunk-3CQJV3NC.mjs.map} +0 -0
- /package/dist/{chunk-I3OOUWO5.mjs.map → chunk-3GDRV7SG.mjs.map} +0 -0
- /package/dist/{chunk-YIBV77KZ.mjs.map → chunk-4WLAVHCY.mjs.map} +0 -0
- /package/dist/{chunk-FSIXEIOB.mjs.map → chunk-L7FSTPGS.mjs.map} +0 -0
- /package/dist/{chunk-GJ7W6LNK.mjs.map → chunk-N5RK4LK6.mjs.map} +0 -0
- /package/dist/{chunk-UMUWR5XA.mjs.map → chunk-PURU7FXR.mjs.map} +0 -0
- /package/dist/{chunk-52BR7LTX.mjs.map → chunk-STSPSJUI.mjs.map} +0 -0
- /package/dist/{chunk-IZBX2TEU.mjs.map → chunk-VQG3QWWK.mjs.map} +0 -0
- /package/dist/{integration-orm-LLW6WZNK.mjs.map → integration-orm-G5BPBT5X.mjs.map} +0 -0
package/dist/plugin.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Z as PluginRoutes, P as PluginRoutesFactory, W as RouteDefinition } from './route-CvEr4Uc9.mjs';
|
|
2
|
-
export {
|
|
2
|
+
export { bs as APIHandlerLifecyclePayload, bo as APIRouteDiscoveredPayload, bv as BundleLifecyclePayload, B as BundleResultPayload, bt as ErrorLifecyclePayload, ec as FARM_NODE_RESPONSE_END_PENDING, a as FarmPlugin, bi as FarmPluginBuildHooks, bk as FarmPluginClientConfig, aX as FarmPluginContext, bj as FarmPluginDevHooks, bf as FarmPluginDiscoveredRoute, aY as FarmPluginIntegrationContext, aZ as FarmPluginLifecycle, bh as FarmPluginRenderHooks, b1 as FarmPluginRouteRuntimePayload, bg as FarmPluginRouterHooks, b7 as FarmPluginRuntimeAfterEvent, b4 as FarmPluginRuntimeBaseEvent, b6 as FarmPluginRuntimeBeforeEvent, ba as FarmPluginRuntimeCloseEvent, b5 as FarmPluginRuntimeContextEvent, b8 as FarmPluginRuntimeErrorEvent, bb as FarmPluginRuntimeHooks, b0 as FarmPluginRuntimeKind, bd as FarmPluginRuntimeRequestHandler, bc as FarmPluginRuntimeRequestOptions, be as FarmPluginRuntimeSession, b9 as FarmPluginRuntimeStartEvent, b2 as FarmPluginSetupContext, b3 as FarmPluginStateContext, a_ as FarmRequestPluginContext, a$ as FarmRequestStore, aw as FarmRuntimeShutdownError, bu as HMRUpdatePayload, bn as MiddlewareDiscoveredPayload, bw as NitroBuildLifecyclePayload, ax as PluginManager, aW as PluginRequestContext, br as RenderLifecyclePayload, bl as RouteDiscoveredPayload, bp as RouteMatchPayload, bq as RouteMatchResultPayload, bm as RoutesGeneratedPayload, bx as ShutdownPayload, av as definePlugin, s as farmPlugin } from './client-plugins-BqtHoJ9C.mjs';
|
|
3
3
|
import 'vite';
|
|
4
4
|
import './lifecycle-De0vQG45.mjs';
|
|
5
5
|
import './env.mjs';
|
|
@@ -17,7 +17,7 @@ import '@farming-labs/docs';
|
|
|
17
17
|
import './markdown.mjs';
|
|
18
18
|
import './observability.mjs';
|
|
19
19
|
import '@opentelemetry/api';
|
|
20
|
-
import './workflows-
|
|
20
|
+
import './workflows-BantWytQ.mjs';
|
|
21
21
|
import './cron.mjs';
|
|
22
22
|
import './navigation-errors-Dvwpzaer.mjs';
|
|
23
23
|
import './server-action-security.mjs';
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Z as PluginRoutes, P as PluginRoutesFactory, W as RouteDefinition } from './route-4pd-EVtw.js';
|
|
2
|
-
export {
|
|
2
|
+
export { bs as APIHandlerLifecyclePayload, bo as APIRouteDiscoveredPayload, bv as BundleLifecyclePayload, B as BundleResultPayload, bt as ErrorLifecyclePayload, ec as FARM_NODE_RESPONSE_END_PENDING, a as FarmPlugin, bi as FarmPluginBuildHooks, bk as FarmPluginClientConfig, aX as FarmPluginContext, bj as FarmPluginDevHooks, bf as FarmPluginDiscoveredRoute, aY as FarmPluginIntegrationContext, aZ as FarmPluginLifecycle, bh as FarmPluginRenderHooks, b1 as FarmPluginRouteRuntimePayload, bg as FarmPluginRouterHooks, b7 as FarmPluginRuntimeAfterEvent, b4 as FarmPluginRuntimeBaseEvent, b6 as FarmPluginRuntimeBeforeEvent, ba as FarmPluginRuntimeCloseEvent, b5 as FarmPluginRuntimeContextEvent, b8 as FarmPluginRuntimeErrorEvent, bb as FarmPluginRuntimeHooks, b0 as FarmPluginRuntimeKind, bd as FarmPluginRuntimeRequestHandler, bc as FarmPluginRuntimeRequestOptions, be as FarmPluginRuntimeSession, b9 as FarmPluginRuntimeStartEvent, b2 as FarmPluginSetupContext, b3 as FarmPluginStateContext, a_ as FarmRequestPluginContext, a$ as FarmRequestStore, aw as FarmRuntimeShutdownError, bu as HMRUpdatePayload, bn as MiddlewareDiscoveredPayload, bw as NitroBuildLifecyclePayload, ax as PluginManager, aW as PluginRequestContext, br as RenderLifecyclePayload, bl as RouteDiscoveredPayload, bp as RouteMatchPayload, bq as RouteMatchResultPayload, bm as RoutesGeneratedPayload, bx as ShutdownPayload, av as definePlugin, s as farmPlugin } from './client-plugins-DYprkCKN.js';
|
|
3
3
|
import 'vite';
|
|
4
4
|
import './lifecycle-De0vQG45.js';
|
|
5
5
|
import './env.js';
|
|
@@ -17,7 +17,7 @@ import '@farming-labs/docs';
|
|
|
17
17
|
import './markdown.js';
|
|
18
18
|
import './observability.js';
|
|
19
19
|
import '@opentelemetry/api';
|
|
20
|
-
import './workflows-
|
|
20
|
+
import './workflows-BantWytQ.js';
|
|
21
21
|
import './cron.js';
|
|
22
22
|
import './navigation-errors-Dvwpzaer.js';
|
|
23
23
|
import './server-action-security.js';
|
package/dist/plugin.mjs
CHANGED
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
PluginManager,
|
|
5
5
|
definePlugin,
|
|
6
6
|
farmPlugin
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2HYYZCCI.mjs";
|
|
8
8
|
import "./chunk-YVPFZ2TK.mjs";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-7PS5NKOM.mjs";
|
|
10
10
|
import "./chunk-WQDQCTC5.mjs";
|
|
11
11
|
import "./chunk-6ZXIQSXE.mjs";
|
|
12
12
|
import "./chunk-V6WE6JSZ.mjs";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-3BTAMIQE.mjs";
|
|
14
14
|
import "./chunk-CGIXMLSY.mjs";
|
|
15
15
|
import "./chunk-USWZZUEH.mjs";
|
|
16
16
|
import "./chunk-USLFXFFH.mjs";
|
|
@@ -19,20 +19,22 @@ import "./chunk-YKAUAZA4.mjs";
|
|
|
19
19
|
import "./chunk-7PYVLJ4J.mjs";
|
|
20
20
|
import "./chunk-7T2QYWDH.mjs";
|
|
21
21
|
import "./chunk-5EZRXIFH.mjs";
|
|
22
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-Z5ARESQG.mjs";
|
|
23
23
|
import "./chunk-235AKA6S.mjs";
|
|
24
24
|
import "./chunk-RQ633A5I.mjs";
|
|
25
|
-
import "./chunk-
|
|
25
|
+
import "./chunk-26BCDVJS.mjs";
|
|
26
26
|
import "./chunk-A5VG2BDG.mjs";
|
|
27
27
|
import "./chunk-EUYRVVXL.mjs";
|
|
28
|
-
import "./chunk-
|
|
29
|
-
import "./chunk-
|
|
30
|
-
import "./chunk-
|
|
28
|
+
import "./chunk-QQCCBMTH.mjs";
|
|
29
|
+
import "./chunk-DIHNOVZZ.mjs";
|
|
30
|
+
import "./chunk-RKUPOYQV.mjs";
|
|
31
|
+
import "./chunk-XWM2C267.mjs";
|
|
31
32
|
import "./chunk-N2KC75H7.mjs";
|
|
32
33
|
import "./chunk-H53KVQUU.mjs";
|
|
33
34
|
import "./chunk-QKVUNGAH.mjs";
|
|
34
|
-
import "./chunk-
|
|
35
|
-
import "./chunk-
|
|
35
|
+
import "./chunk-LXXG3K2Y.mjs";
|
|
36
|
+
import "./chunk-FDWXXTWR.mjs";
|
|
37
|
+
import "./chunk-FDWECN3W.mjs";
|
|
36
38
|
import "./chunk-4X57GXQA.mjs";
|
|
37
39
|
import "./chunk-IGOLMCE3.mjs";
|
|
38
40
|
import "./chunk-YUE4CJNB.mjs";
|
|
@@ -67,7 +69,7 @@ import "./chunk-34IAPZBG.mjs";
|
|
|
67
69
|
import "./chunk-WZ5QFROO.mjs";
|
|
68
70
|
import "./chunk-N2FY2QZ7.mjs";
|
|
69
71
|
import "./chunk-FXG2PS27.mjs";
|
|
70
|
-
import "./chunk-
|
|
72
|
+
import "./chunk-LG4XB6RN.mjs";
|
|
71
73
|
import "./chunk-PHN22XB2.mjs";
|
|
72
74
|
import "./chunk-XYTDSPBD.mjs";
|
|
73
75
|
import "./chunk-OMQWEX4N.mjs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ad as ReadonlyMiddlewareStore, ae as FarmMiddlewareConfig, af as MiddlewareModule } from './client-plugins-
|
|
1
|
+
import { ad as ReadonlyMiddlewareStore, ae as FarmMiddlewareConfig, af as MiddlewareModule } from './client-plugins-DYprkCKN.js';
|
|
2
2
|
import { R as ResolvedFarmI18nConfig } from './types-CnH8DOqo.js';
|
|
3
|
-
import { R as ResolvedFarmServerConfig } from './workflows-
|
|
3
|
+
import { R as ResolvedFarmServerConfig } from './workflows-BantWytQ.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Server-side middleware utilities for accessing middleware data in pages
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ad as ReadonlyMiddlewareStore, ae as FarmMiddlewareConfig, af as MiddlewareModule } from './client-plugins-
|
|
1
|
+
import { ad as ReadonlyMiddlewareStore, ae as FarmMiddlewareConfig, af as MiddlewareModule } from './client-plugins-BqtHoJ9C.mjs';
|
|
2
2
|
import { R as ResolvedFarmI18nConfig } from './types-CnH8DOqo.mjs';
|
|
3
|
-
import { R as ResolvedFarmServerConfig } from './workflows-
|
|
3
|
+
import { R as ResolvedFarmServerConfig } from './workflows-BantWytQ.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Server-side middleware utilities for accessing middleware data in pages
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/query/client.ts","../../src/i18n/client-runtime.ts","../../src/i18n/bridge.ts","../../src/client/spa-router.ts","../../src/client/history-sync.ts","../../src/server/request-bridge.ts","../../src/query/sync.ts","../../src/query/params.ts","../../src/query/parsers.ts"],"sourcesContent":["/**\n * Farm.js Client-Side Query State Management\n *\n * Type-safe URL search parameter state management - Like useState, but stored in the URL query string.\n * Client-only hooks for managing query parameters in the browser.\n * Inspired by nuqs implementation patterns.\n */\n\nimport { useState, useEffect, useCallback, useRef } from \"react\";\nimport {\n notifyHistoryChange,\n subscribeHistoryChange,\n writeFarmURLSearchHistory,\n} from \"../client/history-sync\";\nimport { _resolveCurrentRequest } from \"../server/request-bridge\";\nimport { emitter, type KeyUpdate } from \"./sync\";\nexport { parseRouteParams, loadRouteParams, type RouteParamsInput } from \"./params\";\n\nimport { asString as asStringClient, asInteger as asIntegerClient, type Parser } from \"./parsers\";\n\nexport {\n asString,\n asInteger,\n asFloat,\n asBoolean,\n asArrayOf,\n asJson,\n asIsoDate,\n asIsoDateTime,\n createParser,\n type ArrayParserOptions,\n type Parser,\n type inferParserType,\n} from \"./parsers\";\n\nexport type UrlUpdateType = \"push\" | \"replace\";\nexport type HistoryMethod = \"pushState\" | \"replaceState\";\n\nexport interface Options {\n history?: HistoryMethod;\n shallow?: boolean;\n scroll?: boolean;\n throttleMs?: number;\n}\n\nconst getCurrentSearchParams = (): URLSearchParams => {\n if (typeof window !== \"undefined\") {\n discardDepartedURLUpdates();\n let params = new URLSearchParams(window.location.search);\n // Draft values belong to the existing throttle queue, not to a parser's\n // identity. Inline parsers and newly mounted consumers see the same draft.\n for (const pending of throttleTimers.values()) {\n if (pending.href === window.location.href) params = applyChange(params, pending.updates);\n }\n return params;\n }\n\n // Server rendering used to see an empty query string here, so a hook read one\n // value on the server and another in the browser. React reports that as a\n // hydration mismatch and discards the server rendered markup for the branch.\n const request = _resolveCurrentRequest();\n if (!request) return new URLSearchParams();\n try {\n return new URL(request.url).searchParams;\n } catch {\n return new URLSearchParams();\n }\n};\n\nconst readSearchParam = (searchParams: URLSearchParams, key: string): string => {\n const values = searchParams.getAll(key);\n return values.length > 1 ? values.join(\",\") : (values[0] ?? \"\");\n};\n\nconst throttleTimers = new Map<\n string,\n {\n timer: ReturnType<typeof setTimeout>;\n updates: Record<string, string | null>;\n href: string;\n }\n>();\n\nfunction discardDepartedURLUpdates(): void {\n for (const [key, pending] of throttleTimers) {\n if (pending.href === window.location.href) continue;\n clearTimeout(pending.timer);\n throttleTimers.delete(key);\n }\n}\n\nfunction getUpdateKey(updates: Record<string, unknown>): string {\n return JSON.stringify(Object.keys(updates).sort());\n}\n\nfunction supersedeQueuedKeys(updates: Record<string, string | null>): void {\n const keys = Object.keys(updates);\n for (const [queueKey, pending] of throttleTimers) {\n for (const key of keys) delete pending.updates[key];\n if (Object.keys(pending.updates).length > 0) continue;\n clearTimeout(pending.timer);\n throttleTimers.delete(queueKey);\n }\n}\n\nconst compareStructuredValues = (\n current: unknown,\n next: unknown,\n seen = new WeakMap<object, object>(),\n): boolean | undefined => {\n if (Object.is(current, next)) return true;\n if (current === null || next === null || typeof current !== typeof next) return false;\n if (typeof current !== \"object\" || typeof next !== \"object\") return false;\n if (current instanceof Date || next instanceof Date) {\n return current instanceof Date && next instanceof Date && current.getTime() === next.getTime();\n }\n if (Array.isArray(current) || Array.isArray(next)) {\n if (!Array.isArray(current) || !Array.isArray(next) || current.length !== next.length) {\n return false;\n }\n const knownNext = seen.get(current);\n if (knownNext) return knownNext === next;\n seen.set(current, next);\n for (let index = 0; index < current.length; index++) {\n const equal = compareStructuredValues(current[index], next[index], seen);\n if (equal !== true) return equal;\n }\n return true;\n }\n\n const currentPrototype = Object.getPrototypeOf(current);\n const nextPrototype = Object.getPrototypeOf(next);\n if (currentPrototype !== nextPrototype) return false;\n if (currentPrototype !== Object.prototype && currentPrototype !== null) return undefined;\n\n const knownNext = seen.get(current);\n if (knownNext) return knownNext === next;\n seen.set(current, next);\n\n const currentKeys = Object.keys(current);\n const nextKeys = Object.keys(next);\n if (\n currentKeys.length !== nextKeys.length ||\n currentKeys.some((key) => !Object.prototype.hasOwnProperty.call(next, key))\n ) {\n return false;\n }\n for (const key of currentKeys) {\n const equal = compareStructuredValues(\n (current as Record<string, unknown>)[key],\n (next as Record<string, unknown>)[key],\n seen,\n );\n if (equal !== true) return equal;\n }\n return true;\n};\n\nconst areParsedValuesEqual = <T>(parser: Parser<T>, current: T | null, next: T | null) => {\n if (Object.is(current, next)) return true;\n const structuredResult = compareStructuredValues(current, next);\n if (structuredResult === false) return false;\n if (current === null || next === null) return false;\n\n try {\n return parser.serialize(current) === parser.serialize(next);\n } catch {\n return structuredResult === true;\n }\n};\n\nconst applyChange = (\n searchParams: URLSearchParams,\n updates: Record<string, string | null>,\n keepExisting = true,\n): URLSearchParams => {\n const newParams = keepExisting ? new URLSearchParams(searchParams) : new URLSearchParams();\n\n Object.entries(updates).forEach(([key, value]) => {\n if (value === null || value === undefined || value === \"\") {\n newParams.delete(key);\n } else {\n newParams.set(key, value);\n }\n });\n\n return newParams;\n};\n\nconst commitURLUpdate = (\n updates: Record<string, string | null>,\n options: Options,\n emitUpdate: boolean,\n) => {\n const { history = \"pushState\", shallow = true, scroll = false } = options;\n const url = new URL(window.location.href);\n const newSearchParams = applyChange(url.searchParams, updates);\n const newSearch = newSearchParams.toString();\n const newUrl = url.pathname + (newSearch ? `?${newSearch}` : \"\") + url.hash;\n const currentUrl = url.pathname + url.search + url.hash;\n\n if (newUrl === currentUrl) return;\n\n const historyAction = history === \"replaceState\" ? \"replace\" : \"push\";\n if (!writeFarmURLSearchHistory(historyAction, newUrl)) {\n const historyState = window.history.state;\n const nextHistoryState =\n historyState && typeof historyState === \"object\" && \"path\" in historyState\n ? { ...historyState, path: newUrl }\n : historyState;\n window.history[history](nextHistoryState, \"\", newUrl);\n }\n\n if (emitUpdate) {\n // Composing one queued key must not discard drafts for other keys. Only\n // carry drafts forward across this write, never across unrelated navigation.\n for (const pending of throttleTimers.values()) {\n if (pending.href === url.href) pending.href = window.location.href;\n }\n emitter.emitUpdate(getCurrentSearchParams());\n }\n\n if (shallow) notifyHistoryChange(\"url-search\");\n\n if (scroll) {\n window.scrollTo(0, 0);\n }\n};\n\nconst updateURL = (\n updates: Record<string, string | null>,\n options: Options = {},\n emitUpdate = true,\n): (() => boolean) | undefined => {\n if (typeof window === \"undefined\") return;\n\n discardDepartedURLUpdates();\n\n const { throttleMs } = options;\n // Latest intent owns each key, including immediate writes and URL no-ops.\n // Keep unrelated keys in an older batch scheduled with their original owner.\n supersedeQueuedKeys(updates);\n if (!throttleMs || throttleMs <= 0) {\n commitURLUpdate(updates, options, emitUpdate);\n return;\n }\n\n const throttleKey = getUpdateKey(updates);\n\n const currentUrl = new URL(window.location.href);\n const nextSearch = applyChange(currentUrl.searchParams, updates).toString();\n if (nextSearch === currentUrl.searchParams.toString()) return;\n\n const timeout = setTimeout(() => {\n const pending = throttleTimers.get(throttleKey);\n if (pending?.timer !== timeout) return;\n throttleTimers.delete(throttleKey);\n if (pending.href !== window.location.href) return;\n commitURLUpdate(updates, options, emitUpdate);\n }, throttleMs);\n\n throttleTimers.set(throttleKey, { timer: timeout, updates, href: currentUrl.href });\n return () => {\n if (throttleTimers.get(throttleKey)?.timer !== timeout) return false;\n clearTimeout(timeout);\n throttleTimers.delete(throttleKey);\n return true;\n };\n};\n\nexport function useQueryState<TParser extends Parser<any>>(\n key: string,\n parser: TParser,\n options?: Options,\n): [\n NonNullable<ReturnType<TParser[\"parse\"]>> | null,\n (value: NonNullable<ReturnType<TParser[\"parse\"]>> | null) => void,\n];\nexport function useQueryState<T>(\n key: string,\n parser: Parser<T>,\n options?: Options,\n): [T | null, (value: T | null) => void];\nexport function useQueryState<TParser extends Parser<any>>(\n key: string,\n parser: TParser,\n options?: Options,\n): [\n NonNullable<ReturnType<TParser[\"parse\"]>> | null,\n (value: NonNullable<ReturnType<TParser[\"parse\"]>> | null) => void,\n] {\n type T = NonNullable<ReturnType<TParser[\"parse\"]>>;\n const [state, setState] = useState<T | null>(() => {\n const searchParams = getCurrentSearchParams();\n const parsed = parser.parse(readSearchParam(searchParams, key));\n return parsed;\n });\n\n const stateRef = useRef(state);\n const stateKeyRef = useRef(key);\n const cancelPendingUpdateRef = useRef<(() => boolean) | undefined>(undefined);\n stateRef.current = state;\n\n const setValue = useCallback(\n (value: T | null) => {\n setState(value);\n stateRef.current = value;\n\n const serialized = value === null ? null : parser.serialize(value);\n\n emitter.emitKey(key, { state: value, query: serialized, source: stateRef });\n\n cancelPendingUpdateRef.current?.();\n cancelPendingUpdateRef.current = updateURL({ [key]: serialized }, options, true);\n },\n [key, parser, options],\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n const onPopState = () => {\n const searchParams = getCurrentSearchParams();\n const parsed = parser.parse(readSearchParam(searchParams, key));\n const sourceChanged = stateKeyRef.current !== key;\n stateKeyRef.current = key;\n if (sourceChanged || !areParsedValuesEqual(parser, stateRef.current, parsed)) {\n setState(parsed);\n stateRef.current = parsed;\n }\n };\n\n const onEmitterUpdate = (searchParams: URLSearchParams) => {\n const parsed = parser.parse(readSearchParam(searchParams, key));\n if (!areParsedValuesEqual(parser, stateRef.current, parsed)) {\n setState(parsed);\n stateRef.current = parsed;\n }\n };\n\n const onKeyUpdate = (payload: KeyUpdate) => {\n // Skip only this hook's synchronous echo, never a peer's newer edit.\n // The ref identity is stable across renders and is not serialized.\n if (payload.source === stateRef) {\n return;\n }\n\n // Consumers may use different parsers for the same URL key.\n const parsed = parser.parse(payload.query ?? \"\");\n if (!areParsedValuesEqual(parser, stateRef.current, parsed)) {\n setState(parsed);\n stateRef.current = parsed;\n }\n };\n\n // Page-state writes with an href can change the query string without a\n // popstate, so listen through the shared history channel (real\n // back/forward events included). Self-updates no-op via the Object.is\n // comparison above.\n onPopState();\n const unsubscribeHistory = subscribeHistoryChange(onPopState);\n emitter.on(\"update\", onEmitterUpdate);\n emitter.onKey(key, onKeyUpdate);\n\n return () => {\n unsubscribeHistory();\n emitter.off(\"update\", onEmitterUpdate);\n emitter.offKey(key, onKeyUpdate);\n };\n }, [key, parser]);\n\n useEffect(\n () => () => {\n const canceledPendingWrite = cancelPendingUpdateRef.current?.() ?? false;\n cancelPendingUpdateRef.current = undefined;\n // A throttled write is discarded on unmount, but its value was already\n // broadcast to peers via emitKey. Peers that adopted the optimistic draft\n // get no other reconciliation signal (unmount fires no history event), so\n // tell them to re-read the URL, which no longer carries this draft.\n if (canceledPendingWrite && typeof window !== \"undefined\") {\n emitter.emitUpdate(getCurrentSearchParams());\n }\n },\n [key],\n );\n\n return [state, setValue];\n}\n\nexport function useQueryStates<T extends Record<string, Parser<any>>>(\n parsers: T,\n options: Options = {},\n): [\n { [K in keyof T]: ReturnType<T[K][\"parse\"]> },\n (updates: Partial<{ [K in keyof T]: ReturnType<T[K][\"parse\"]> | null }>) => void,\n] {\n const keys = Object.keys(parsers);\n const watchKeys = JSON.stringify(keys);\n\n const [state, setState] = useState<{ [K in keyof T]: ReturnType<T[K][\"parse\"]> }>(() => {\n const searchParams = getCurrentSearchParams();\n const result = {} as { [K in keyof T]: ReturnType<T[K][\"parse\"]> };\n\n Object.entries(parsers).forEach(([key, parser]) => {\n result[key as keyof T] = parser.parse(readSearchParam(searchParams, key));\n });\n\n return result;\n });\n\n const stateRef = useRef(state);\n const pendingUpdatesRef = useRef(new Map<string, () => boolean>());\n stateRef.current = state;\n\n const setValues = useCallback(\n (updates: Partial<{ [K in keyof T]: ReturnType<T[K][\"parse\"]> | null }>) => {\n const newState = { ...stateRef.current, ...updates };\n setState(newState);\n stateRef.current = newState;\n\n Object.entries(updates).forEach(([key, value]) => {\n const parser = parsers[key];\n if (parser) {\n const serialized = value === null ? null : parser.serialize(value);\n emitter.emitKey(key, { state: value, query: serialized, source: stateRef });\n }\n });\n\n const urlUpdates: Record<string, string | null> = {};\n Object.entries(updates).forEach(([key, value]) => {\n const parser = parsers[key];\n if (parser) {\n const serialized = value === null ? null : parser.serialize(value);\n urlUpdates[key] = serialized;\n }\n });\n\n const updateKey = getUpdateKey(urlUpdates);\n pendingUpdatesRef.current.get(updateKey)?.();\n const cancelPendingUpdate = updateURL(urlUpdates, options, true);\n if (cancelPendingUpdate) {\n pendingUpdatesRef.current.set(updateKey, cancelPendingUpdate);\n } else {\n pendingUpdatesRef.current.delete(updateKey);\n }\n },\n [parsers, options],\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n const applyChange = (searchParams: URLSearchParams) => {\n const result = {} as { [K in keyof T]: ReturnType<T[K][\"parse\"]> };\n const currentKeys = Object.keys(stateRef.current);\n let hasChanged =\n currentKeys.length !== keys.length ||\n currentKeys.some((key) => !Object.prototype.hasOwnProperty.call(parsers, key));\n\n Object.entries(parsers).forEach(([key, parser]) => {\n const parsed = parser.parse(readSearchParam(searchParams, key));\n const currentValue = stateRef.current[key as keyof T];\n\n if (!areParsedValuesEqual(parser, currentValue, parsed)) {\n hasChanged = true;\n }\n result[key as keyof T] = parsed;\n });\n\n if (hasChanged) {\n setState(result);\n stateRef.current = result;\n }\n };\n\n const onPopState = () => {\n const searchParams = getCurrentSearchParams();\n applyChange(searchParams);\n };\n\n const onEmitterUpdate = (searchParams: URLSearchParams) => {\n applyChange(searchParams);\n };\n\n applyChange(getCurrentSearchParams());\n const unsubscribeHistory = subscribeHistoryChange(onPopState);\n emitter.on(\"update\", onEmitterUpdate);\n const unsubscribeKeys = Object.entries(parsers).map(([key, parser]) => {\n const onKeyUpdate = (payload: KeyUpdate) => {\n if (payload.source === stateRef) return;\n const parsed = parser.parse(payload.query ?? \"\");\n if (areParsedValuesEqual(parser, stateRef.current[key as keyof T], parsed)) return;\n\n // Update only this key, preserving local drafts for the other fields.\n const next = { ...stateRef.current, [key]: parsed };\n stateRef.current = next;\n setState(next);\n };\n emitter.onKey(key, onKeyUpdate);\n return () => emitter.offKey(key, onKeyUpdate);\n });\n\n return () => {\n unsubscribeHistory();\n emitter.off(\"update\", onEmitterUpdate);\n for (const unsubscribe of unsubscribeKeys) unsubscribe();\n };\n }, [watchKeys, parsers]);\n\n useEffect(\n () => () => {\n let canceledPendingWrite = false;\n for (const cancelPendingUpdate of pendingUpdatesRef.current.values()) {\n if (cancelPendingUpdate()) canceledPendingWrite = true;\n }\n pendingUpdatesRef.current.clear();\n // Discarded throttled writes were already broadcast to peers via emitKey;\n // reconcile any peer that adopted a now-cancelled draft (see useQueryState).\n if (canceledPendingWrite && typeof window !== \"undefined\") {\n emitter.emitUpdate(getCurrentSearchParams());\n }\n },\n [watchKeys],\n );\n\n return [state, setValues];\n}\n\nexport function usePagination(options?: {\n defaultPage?: number;\n defaultLimit?: number;\n pageKey?: string;\n limitKey?: string;\n}) {\n const {\n defaultPage = 1,\n defaultLimit = 10,\n pageKey = \"page\",\n limitKey = \"limit\",\n } = options || {};\n\n const [page, setPage] = useQueryState(pageKey, asIntegerClient.withDefault!(defaultPage));\n const [limit, setLimit] = useQueryState(limitKey, asIntegerClient.withDefault!(defaultLimit));\n\n const currentPage = page ?? defaultPage;\n const currentLimit = limit ?? defaultLimit;\n const offset = ((currentPage as number) - 1) * (currentLimit as number);\n\n return {\n page: currentPage,\n setPage,\n limit: currentLimit,\n setLimit,\n offset,\n resetPagination: () => {\n setPage(defaultPage);\n setLimit(defaultLimit);\n },\n };\n}\n\nexport function useSearchFilters<T extends Record<string, any>>(options?: {\n searchKey?: string;\n defaultFilters?: T;\n filterKeys?: (keyof T)[];\n}) {\n const {\n searchKey = \"search\",\n defaultFilters = {} as T,\n filterKeys = Object.keys(defaultFilters) as (keyof T)[],\n } = options || {};\n\n const [search, setSearch] = useQueryState(searchKey, asStringClient);\n\n const filterParsers = filterKeys.reduce(\n (acc, key) => {\n acc[key as string] = asStringClient;\n return acc;\n },\n {} as Record<string, Parser<string>>,\n );\n\n const [filters, setFilters] = useQueryStates(filterParsers);\n\n const clearFilters = () => {\n setSearch(null);\n const clearedFilters = filterKeys.reduce(\n (acc, key) => {\n acc[key as string] = null;\n return acc;\n },\n {} as Record<string, null>,\n );\n setFilters(clearedFilters);\n };\n\n return {\n search,\n setSearch,\n filters: filters as T,\n setFilters,\n clearFilters,\n };\n}\n","import IntlMessageFormat from \"intl-messageformat\";\nimport { getActiveFarmI18nSnapshot } from \"./bridge\";\nimport { localizeFarmHref, resolveFarmLocalePath } from \"./routing\";\nimport type {\n FarmI18nClientSnapshot,\n FarmI18nLocale,\n FarmI18nMessageArgs,\n FarmI18nMessageKey,\n FarmTranslator,\n} from \"./types\";\n\ntype Listener = () => void;\n\nconst listeners = new Set<Listener>();\nconst compiled = new Map<string, IntlMessageFormat>();\nlet currentSnapshot: FarmI18nClientSnapshot | undefined;\n\nexport function getFarmI18nClientState(): FarmI18nClientSnapshot | undefined {\n return currentSnapshot || getActiveFarmI18nSnapshot();\n}\n\nexport function subscribeFarmI18n(listener: Listener): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\nexport function _hydrateFarmI18n(snapshot: FarmI18nClientSnapshot | undefined): void {\n if (!snapshot) return;\n const changed = currentSnapshot?.locale !== snapshot.locale;\n currentSnapshot = snapshot;\n if (typeof window !== \"undefined\") window.__FARM_I18N__ = snapshot;\n if (typeof document !== \"undefined\") {\n document.documentElement.lang = snapshot.locale;\n document.documentElement.dir = snapshot.direction;\n }\n if (changed) compiled.clear();\n for (const listener of listeners) listener();\n}\n\nconst translate = (key: string, values?: Record<string, unknown>, rich = false): unknown => {\n const snapshot = requireSnapshot();\n const message = snapshot.messages[key];\n if (message === undefined) return key;\n const cacheKey = `${snapshot.locale}\\u0000${key}\\u0000${message}`;\n let formatter = compiled.get(cacheKey);\n if (!formatter) {\n formatter = new IntlMessageFormat(message, snapshot.locale);\n compiled.set(cacheKey, formatter);\n }\n const result = formatter.format(values as any);\n if (rich) return Array.isArray(result) && result.length === 1 ? result[0] : result;\n if (Array.isArray(result) && result.some((part) => typeof part !== \"string\")) {\n throw new Error(`Farm i18n message \"${key}\" contains rich content. Render it with t.rich().`);\n }\n return Array.isArray(result) ? result.join(\"\") : String(result);\n};\n\nexport const t = ((key: string, values?: Record<string, unknown>) =>\n translate(key, values)) as FarmTranslator;\nt.rich = (key: string, values?: Record<string, unknown>) => translate(key, values, true);\nt.raw = (key: string) => requireSnapshot().messages[key] ?? key;\nt.has = (key: string) => key in requireSnapshot().messages;\n\nexport function localizeActiveFarmHref(href: string, locale?: FarmI18nLocale): string {\n const snapshot = getFarmI18nClientState();\n if (!snapshot) return href;\n return localizeFarmHref(href, locale || snapshot.locale, snapshot);\n}\n\nexport function isFarmLocaleChangeHref(href: string): boolean {\n const snapshot = getFarmI18nClientState();\n if (!snapshot || typeof window === \"undefined\") return false;\n if (snapshot.routing === \"none\") return false;\n const target = new URL(href, window.location.origin);\n const match = resolveFarmLocalePath(target.pathname, snapshot);\n const targetLocale = match.locale || snapshot.defaultLocale;\n return targetLocale !== snapshot.locale;\n}\n\nexport function createFarmClientTranslator(): FarmTranslator {\n return (<TKey extends FarmI18nMessageKey>(key: TKey, ...args: FarmI18nMessageArgs<TKey>) =>\n t(key, ...args)) as FarmTranslator;\n}\n\nfunction requireSnapshot(): FarmI18nClientSnapshot {\n const snapshot = getFarmI18nClientState();\n if (!snapshot) {\n throw new Error(\"Farm i18n is not configured or has not been hydrated.\");\n }\n return snapshot;\n}\n","import type { FarmI18nClientSnapshot } from \"./types\";\n\ntype SnapshotResolver = () => FarmI18nClientSnapshot | undefined;\n\nconst FARM_I18N_SNAPSHOT_RESOLVER = Symbol.for(\"farm.i18n.snapshotResolver\");\ntype GlobalWithI18nResolver = typeof globalThis & {\n [FARM_I18N_SNAPSHOT_RESOLVER]?: SnapshotResolver;\n};\n\nexport function _setFarmI18nSnapshotResolver(resolver: SnapshotResolver | undefined): void {\n (globalThis as GlobalWithI18nResolver)[FARM_I18N_SNAPSHOT_RESOLVER] = resolver;\n}\n\nexport function getActiveFarmI18nSnapshot(): FarmI18nClientSnapshot | undefined {\n if (typeof window !== \"undefined\" && window.__FARM_I18N__) {\n return window.__FARM_I18N__;\n }\n return (globalThis as GlobalWithI18nResolver)[FARM_I18N_SNAPSHOT_RESOLVER]?.();\n}\n","\"use client\";\n\nimport { readDeferredDataResponse } from \"../deferred\";\nimport { notifyHistoryChange, notifyRouterHistoryChange } from \"./history-sync\";\nimport {\n createFarmDeploymentMismatchError,\n createFarmDeploymentRequestHeaders,\n isFarmDeploymentMismatchResponse,\n} from \"../deployment\";\nimport { getHashTargetElement } from \"./hash-target\";\nimport { isFarmExternalNavigationURL } from \"./navigation-url\";\nimport type { FarmClientNavigationSession, FarmClientPluginManager } from \"./plugin\";\nimport { _hydrateFarmI18n, isFarmLocaleChangeHref } from \"../i18n/client-runtime\";\nimport type { FarmI18nClientSnapshot } from \"../i18n/types\";\nimport type { FarmIslandStrategy } from \"../island\";\nimport type { FarmRouteRenderPlan } from \"../navigation/render-plan\";\n\nexport { getHashTargetElement } from \"./hash-target\";\nexport { isFarmExternalNavigationURL } from \"./navigation-url\";\n\n/**\n * Farm.js SPA Router\n *\n * Provides client-side navigation without full page reloads.\n * Features:\n * - Prefetch on viewport intersection\n * - Prefetch on hover\n * - Page caching\n * - History API integration\n * - Scroll restoration\n */\n\ninterface PageData {\n props: Record<string, any>;\n modulePath: string;\n loadingModulePath?: string | null;\n canonicalPath?: string;\n isClientComponent?: boolean;\n shouldHydrate?: boolean;\n islandStrategy?: FarmIslandStrategy | null;\n renderPlan?: FarmRouteRenderPlan;\n fragment?: {\n html: string;\n layoutPatterns: string[];\n };\n metadata?: {\n title?: string;\n description?: string;\n };\n layoutModules?: string[];\n routeSlots?: RouteSlotPageData[];\n interception?: {\n from?: string;\n slots: string[];\n };\n i18n?: FarmI18nClientSnapshot;\n}\n\ninterface RouteSlotPageData {\n name: string;\n ownerPattern: string;\n containerId: string;\n interception: boolean;\n fallback: boolean;\n modulePath: string;\n isClientComponent: boolean;\n shouldHydrate: boolean;\n props: Record<string, any>;\n}\n\nexport interface RouterOptions {\n prefetchTimeout?: number;\n cacheMaxAge?: number;\n scrollRestoration?: boolean;\n shouldUseDocumentNavigation?: (pathname: string) => boolean;\n deploymentId?: string;\n}\n\ninterface CacheEntry {\n data: PageData;\n timestamp: number;\n}\n\nexport interface FarmNavigationBlockerContext {\n from: string;\n to: string;\n action: \"push\" | \"replace\" | \"pop\";\n}\n\nexport type FarmNavigationBlocker = (\n context: FarmNavigationBlockerContext,\n) => boolean | void | Promise<boolean | void>;\n\nexport type FarmViewTransitionMode = boolean | \"auto\";\n\nexport interface FarmNavigateOptions {\n replace?: boolean;\n scroll?: boolean;\n state?: unknown;\n viewTransition?: FarmViewTransitionMode;\n /** Re-fetch the current route even when its URL has not changed. */\n refresh?: boolean;\n}\n\nexport interface FarmNavigationLocation {\n href: string;\n pathname: string;\n search: string;\n hash: string;\n}\n\nexport interface FarmNavigationState {\n state: \"idle\" | \"loading\";\n pending: boolean;\n from: string | null;\n to: FarmNavigationLocation | null;\n action: FarmNavigationBlockerContext[\"action\"] | null;\n startedAt: number | null;\n}\n\nexport type FarmNavigationListener = (state: FarmNavigationState) => void;\n\nconst FARM_PAGE_STATE_KEY = \"__farmPageState\";\nconst FARM_INTERCEPT_FROM_KEY = \"__farmInterceptFrom\";\nconst FARM_HISTORY_INDEX_KEY = \"__farmHistoryIndex\";\n\nfunction readHistoryIndex(state: unknown): number | null {\n if (!state || typeof state !== \"object\") return null;\n const value = (state as Record<string, unknown>)[FARM_HISTORY_INDEX_KEY];\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\nconst IDLE_NAVIGATION_STATE: FarmNavigationState = {\n state: \"idle\",\n pending: false,\n from: null,\n to: null,\n action: null,\n startedAt: null,\n};\n\nfunction getActiveLayoutChainHeader(): string | undefined {\n if (typeof document === \"undefined\") return undefined;\n const patterns = Array.from(\n document.querySelectorAll<HTMLElement>('[data-farm-layout-boundary=\"true\"]'),\n )\n .map((element) => element.dataset.farmLayoutPattern)\n .filter((pattern): pattern is string => Boolean(pattern));\n return patterns.length > 0 ? JSON.stringify(patterns) : undefined;\n}\n\n// Global router instance\nlet routerInstance: SPARouter | null = null;\n\nexport class SPARouter {\n private cache: Map<string, CacheEntry> = new Map();\n private prefetchingUrls: Set<string> = new Set();\n private observers: Map<Element, IntersectionObserver> = new Map();\n private prefetchTimers: Map<Element, ReturnType<typeof setTimeout>> = new Map();\n private blockers: Set<FarmNavigationBlocker> = new Set();\n private unloadBlockers: Map<FarmNavigationBlocker, () => boolean> = new Map();\n private navigationListeners: Set<FarmNavigationListener> = new Set();\n private navigationState: FarmNavigationState = IDLE_NAVIGATION_STATE;\n private currentHistoryPath: string | null = null;\n private currentHistoryIndex: number | null = null;\n private suppressNextPopState = false;\n private navigationSequence = 0;\n private activeNavigation?: {\n id: number;\n controller: AbortController;\n };\n private scrollElements: Map<string, HTMLElement> = new Map();\n private options: Required<Omit<RouterOptions, \"deploymentId\">> &\n Pick<RouterOptions, \"deploymentId\">;\n private onNavigate?: (data: PageData) => Promise<void>;\n private clientPlugins?: Pick<\n FarmClientPluginManager,\n | \"beginNavigation\"\n | \"markNavigationLoaded\"\n | \"resolveNavigation\"\n | \"scheduleNavigationRendered\"\n | \"failNavigation\"\n >;\n\n private readonly onPopState = (event: PopStateEvent) => {\n void this.handlePopState(event);\n };\n\n private readonly onBeforeUnload = (event: BeforeUnloadEvent) => {\n if (this.shouldBlockUnload()) {\n event.preventDefault();\n event.returnValue = \"\";\n }\n this.saveScrollPosition(window.location.pathname + window.location.search);\n };\n\n constructor(options: RouterOptions = {}) {\n this.options = {\n prefetchTimeout: options.prefetchTimeout ?? 100,\n cacheMaxAge: options.cacheMaxAge ?? 30000, // 30 seconds\n scrollRestoration: options.scrollRestoration ?? true,\n shouldUseDocumentNavigation: options.shouldUseDocumentNavigation ?? (() => false),\n deploymentId: options.deploymentId ?? readBrowserDeploymentId(),\n };\n\n if (typeof window !== \"undefined\") {\n // Listen for popstate (back/forward navigation)\n window.addEventListener(\"popstate\", this.onPopState);\n\n // Save scroll position before unload\n window.addEventListener(\"beforeunload\", this.onBeforeUnload);\n\n // Track the rendered location and its position in the history stack so\n // popstate can report a real `from` and revert blocked traversals.\n this.currentHistoryPath = window.location.pathname + window.location.search;\n const existingIndex = readHistoryIndex(window.history.state);\n if (existingIndex == null) {\n try {\n window.history.replaceState(\n {\n ...((window.history.state as object | null) ?? {}),\n [FARM_HISTORY_INDEX_KEY]: 0,\n },\n \"\",\n window.location.href,\n );\n this.currentHistoryIndex = 0;\n } catch {\n this.currentHistoryIndex = null;\n }\n } else {\n this.currentHistoryIndex = existingIndex;\n }\n }\n }\n\n /** Remove global listeners. Intended for tests and teardown. */\n destroy(): void {\n if (typeof window === \"undefined\") return;\n this.cancelActiveNavigation();\n for (const observer of this.observers.values()) observer.disconnect();\n for (const timer of this.prefetchTimers.values()) clearTimeout(timer);\n this.observers.clear();\n this.prefetchTimers.clear();\n window.removeEventListener(\"popstate\", this.onPopState);\n window.removeEventListener(\"beforeunload\", this.onBeforeUnload);\n }\n\n /**\n * Set the navigation handler that updates React\n */\n setNavigationHandler(handler: (data: PageData) => Promise<void>) {\n this.onNavigate = handler;\n }\n\n /**\n * Connect Farm's browser plugin lifecycle to SPA navigation.\n */\n setClientPluginManager(manager: FarmClientPluginManager) {\n this.clientPlugins = manager;\n }\n\n /**\n * Navigate to a new URL\n */\n async navigate(href: string, options: FarmNavigateOptions = {}): Promise<void> {\n const {\n replace = false,\n scroll = true,\n state,\n viewTransition = false,\n refresh = false,\n } = options;\n\n // Parse the URL\n const url = new URL(href, window.location.origin);\n const pathname = url.pathname;\n const search = url.search;\n const fullPath = pathname + search;\n\n if (\n isFarmExternalNavigationURL(url, window.location.origin) ||\n isFarmLocaleChangeHref(url.toString()) ||\n this.options.shouldUseDocumentNavigation(pathname)\n ) {\n this.cancelActiveNavigation();\n if (replace) window.location.replace(url.toString());\n else window.location.assign(url.toString());\n return;\n }\n\n // Same page navigation - update fragment history without fetching route data.\n if (!refresh && pathname === window.location.pathname && search === window.location.search) {\n this.cancelActiveNavigation();\n if (url.hash === window.location.hash) return;\n\n this.writePageState(\n replace ? \"replace\" : \"push\",\n state === undefined ? readPageState() : state,\n url.toString(),\n );\n if (scroll) {\n if (url.hash) {\n getHashTargetElement(url.hash)?.scrollIntoView();\n } else {\n window.scrollTo(0, 0);\n }\n }\n return;\n }\n\n const from = window.location.pathname + window.location.search;\n if (\n await this.shouldBlockNavigation({\n from,\n to: fullPath,\n action: replace ? \"replace\" : \"push\",\n })\n ) {\n return;\n }\n\n // Save current scroll position\n if (this.options.scrollRestoration) {\n this.saveScrollPosition(window.location.pathname + window.location.search);\n }\n\n const navigation = this.startNavigation({\n from,\n to: createNavigationLocation(url),\n action: replace ? \"replace\" : \"push\",\n });\n\n let clientNavigation: FarmClientNavigationSession | undefined;\n try {\n clientNavigation = await this.clientPlugins?.beginNavigation({\n from,\n to: url,\n action: replace ? \"replace\" : \"push\",\n });\n if (!this.isCurrentNavigation(navigation, clientNavigation)) return;\n\n // Fetch page data (from cache or server)\n const pageData = await this.fetchPageData(\n fullPath,\n true,\n from,\n refresh,\n navigation.controller.signal,\n );\n if (!this.isCurrentNavigation(navigation, clientNavigation)) return;\n if (clientNavigation) {\n await this.clientPlugins?.markNavigationLoaded(clientNavigation, pageData);\n }\n if (!this.isCurrentNavigation(navigation, clientNavigation)) return;\n\n await this.runViewTransition(viewTransition, () =>\n this.isCurrentNavigation(navigation, clientNavigation)\n ? this.commitNavigation({\n fullPath,\n pageData,\n pathname,\n replace,\n scroll,\n state,\n url,\n })\n : Promise.resolve(),\n );\n if (!this.isCurrentNavigation(navigation, clientNavigation)) return;\n\n if (clientNavigation) {\n await this.clientPlugins?.resolveNavigation(clientNavigation);\n void this.clientPlugins?.scheduleNavigationRendered(clientNavigation);\n }\n this.finishNavigation(navigation);\n } catch (error) {\n if (!this.isCurrentNavigation(navigation, clientNavigation)) return;\n if (clientNavigation) {\n await this.clientPlugins?.failNavigation(clientNavigation, error);\n }\n this.finishNavigation(navigation);\n console.error(\"[Farm.js] Navigation error:\", error);\n // Fall back to full page navigation\n window.location.href = href;\n }\n }\n\n /**\n * Re-render the active route from the server while preserving the document,\n * shared layouts, client runtime, and browser history entry.\n */\n refresh(options: Omit<FarmNavigateOptions, \"replace\" | \"refresh\"> = {}): Promise<void> {\n return this.navigate(window.location.href, {\n ...options,\n replace: true,\n refresh: true,\n scroll: options.scroll ?? false,\n });\n }\n\n /**\n * Prefetch a URL\n */\n async prefetch(href: string): Promise<void> {\n if (isFarmLocaleChangeHref(href)) return;\n const url = new URL(href, window.location.origin);\n if (isFarmExternalNavigationURL(url, window.location.origin)) return;\n if (this.options.shouldUseDocumentNavigation(url.pathname)) return;\n const fullPath = url.pathname + url.search;\n const interceptFrom = window.location.pathname + window.location.search;\n\n // Skip if already prefetching or cached\n if (this.prefetchingUrls.has(fullPath)) return;\n if (this.isCached(fullPath, interceptFrom)) return;\n\n this.prefetchingUrls.add(fullPath);\n\n try {\n await this.fetchPageData(fullPath, false, interceptFrom);\n } catch (error) {\n console.warn(\"[Farm.js] Prefetch failed:\", href, error);\n } finally {\n this.prefetchingUrls.delete(fullPath);\n }\n }\n\n /**\n * Observe an element for viewport intersection (prefetch when visible)\n */\n observeForPrefetch(element: HTMLAnchorElement): void {\n if (typeof IntersectionObserver === \"undefined\") return;\n\n const href = element.getAttribute(\"href\");\n if (!href || this.isExternalUrl(href)) return;\n this.unobserveForPrefetch(element);\n\n const observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting) {\n if (this.observers.get(element) !== observer) continue;\n // Delay prefetch slightly to avoid prefetching during scroll\n const timer = setTimeout(() => {\n if (this.prefetchTimers.get(element) !== timer) return;\n this.prefetchTimers.delete(element);\n void this.prefetch(href);\n }, this.options.prefetchTimeout);\n this.prefetchTimers.set(element, timer);\n\n // Stop observing after first intersection\n observer.unobserve(element);\n this.observers.delete(element);\n }\n }\n },\n { rootMargin: \"200px\" }, // Start prefetching when 200px from viewport\n );\n\n observer.observe(element);\n this.observers.set(element, observer);\n }\n\n /**\n * Stop observing an element\n */\n unobserveForPrefetch(element: HTMLAnchorElement): void {\n const observer = this.observers.get(element);\n if (observer) {\n observer.unobserve(element);\n this.observers.delete(element);\n }\n const timer = this.prefetchTimers.get(element);\n if (timer !== undefined) {\n clearTimeout(timer);\n this.prefetchTimers.delete(element);\n }\n }\n\n addBlocker(blocker: FarmNavigationBlocker, shouldBlockUnload?: () => boolean): () => void {\n this.blockers.add(blocker);\n this.unloadBlockers.set(\n blocker,\n shouldBlockUnload ?? (() => this.evaluateBlockerForUnload(blocker)),\n );\n return () => {\n this.blockers.delete(blocker);\n this.unloadBlockers.delete(blocker);\n };\n }\n\n getNavigationState(): FarmNavigationState {\n return this.navigationState;\n }\n\n subscribeNavigation(listener: FarmNavigationListener): () => void {\n this.navigationListeners.add(listener);\n listener(this.navigationState);\n return () => {\n this.navigationListeners.delete(listener);\n };\n }\n\n registerScrollElement(key: string, element: HTMLElement): () => void {\n this.scrollElements.set(key, element);\n this.restoreScrollElement(window.location.pathname + window.location.search, key, element);\n return () => {\n if (this.scrollElements.get(key) === element) {\n this.scrollElements.delete(key);\n }\n };\n }\n\n pushState(state: unknown, href?: string): void {\n this.writePageState(\"push\", state, href);\n }\n\n replaceState(state: unknown, href?: string): void {\n this.writePageState(\"replace\", state, href);\n }\n\n /** @internal Keep shallow URL-search writes inside the router's history bookkeeping. */\n writeURLSearch(action: \"push\" | \"replace\", href: string): void {\n this.writePageState(action, readPageState(), href, false);\n }\n\n private async commitNavigation(options: {\n fullPath: string;\n pageData: PageData;\n pathname: string;\n replace: boolean;\n scroll: boolean;\n state: unknown;\n url: URL;\n }): Promise<void> {\n const historyUrl = new URL(\n options.pageData.canonicalPath || options.fullPath,\n window.location.origin,\n );\n historyUrl.hash = options.url.hash;\n const historyPath = historyUrl.pathname + historyUrl.search + historyUrl.hash;\n const historyState = createHistoryState(\n historyPath,\n options.state,\n options.replace ? window.history.state : undefined,\n options.pageData.interception?.from ?? null,\n ) as Record<string, unknown>;\n const nextHistoryIndex =\n this.currentHistoryIndex == null\n ? null\n : options.replace\n ? this.currentHistoryIndex\n : this.currentHistoryIndex + 1;\n if (nextHistoryIndex != null) {\n historyState[FARM_HISTORY_INDEX_KEY] = nextHistoryIndex;\n }\n if (options.replace) {\n window.history.replaceState(historyState, \"\", historyPath);\n } else {\n window.history.pushState(historyState, \"\", historyPath);\n }\n this.currentHistoryIndex = nextHistoryIndex;\n this.currentHistoryPath =\n new URL(historyPath, window.location.origin).pathname +\n new URL(historyPath, window.location.origin).search;\n notifyRouterHistoryChange();\n\n this.updateDocumentMetadata(options.pageData.metadata);\n\n _hydrateFarmI18n(options.pageData.i18n);\n\n if (this.onNavigate) {\n await this.onNavigate(options.pageData);\n }\n\n if (options.scroll) {\n if (options.url.hash) {\n const element = getHashTargetElement(options.url.hash);\n if (element) {\n element.scrollIntoView();\n }\n } else {\n window.scrollTo(0, 0);\n }\n } else if (this.options.scrollRestoration) {\n this.restoreScrollPosition(this.currentHistoryPath ?? options.fullPath);\n }\n }\n\n private async runViewTransition(\n mode: FarmViewTransitionMode,\n callback: () => Promise<void>,\n ): Promise<void> {\n if (!mode || typeof document === \"undefined\") {\n await callback();\n return;\n }\n\n const startViewTransition = (document as any).startViewTransition;\n if (typeof startViewTransition !== \"function\") {\n await callback();\n return;\n }\n\n const transition = startViewTransition.call(document, () => callback());\n const updateDone = transition?.updateCallbackDone || transition?.ready;\n if (updateDone && typeof updateDone.then === \"function\") {\n await updateDone;\n }\n transition?.finished?.catch?.(() => undefined);\n }\n\n /**\n * Fetch page data from cache or server\n */\n private async fetchPageData(\n path: string,\n recover = true,\n interceptFrom?: string,\n fresh = false,\n signal?: AbortSignal,\n ): Promise<PageData> {\n const cacheKey = getPageDataCacheKey(path, interceptFrom);\n // Check cache first\n const cached = fresh ? undefined : this.cache.get(cacheKey);\n if (cached && Date.now() - cached.timestamp < this.options.cacheMaxAge) {\n return cached.data;\n }\n\n // Fetch from server. The active layout chain lets the server omit shared\n // shell HTML from the fragment without inspecting component source.\n const activeLayoutChain = getActiveLayoutChainHeader();\n const response = await fetch(`/__farm/page-data?path=${encodeURIComponent(path)}`, {\n signal,\n headers: createFarmDeploymentRequestHeaders(this.options.deploymentId, {\n Accept: \"application/x-farm-deferred+json, application/json\",\n \"X-Farm-SPA\": \"1\",\n ...(activeLayoutChain ? { \"X-Farm-Layout-Chain\": activeLayoutChain } : {}),\n ...(interceptFrom ? { \"X-Farm-Intercept-From\": interceptFrom } : {}),\n }),\n });\n\n if (isFarmDeploymentMismatchResponse(response, this.options.deploymentId)) {\n const error = createFarmDeploymentMismatchError(\n response,\n this.options.deploymentId || \"unknown\",\n );\n dispatchDeploymentMismatch(error);\n if (recover) {\n window.location.assign(path);\n }\n throw error;\n }\n\n if (!response.ok) {\n throw new Error(`Failed to fetch page data: ${response.status}`);\n }\n\n const data = await readDeferredDataResponse<PageData>(response);\n\n // Cache the result\n this.cache.set(cacheKey, {\n data,\n timestamp: Date.now(),\n });\n\n return data;\n }\n\n /**\n * Put the browser URL back on the rendered page after a blocked pop. When\n * both entries carry a Farm history index the traversal is reversed\n * exactly; otherwise the current path is pushed again, which restores the\n * address bar at the cost of one extra history entry.\n */\n private revertBlockedPopState(event: PopStateEvent, from: string): void {\n const eventIndex = readHistoryIndex(event.state);\n if (eventIndex != null && this.currentHistoryIndex != null) {\n const delta = eventIndex - this.currentHistoryIndex;\n if (delta !== 0) {\n this.suppressNextPopState = true;\n window.history.go(-delta);\n return;\n }\n }\n\n try {\n const restoredState: Record<string, unknown> = {\n path: from,\n };\n if (this.currentHistoryIndex != null && eventIndex != null) {\n restoredState[FARM_HISTORY_INDEX_KEY] = eventIndex + 1;\n this.currentHistoryIndex = eventIndex + 1;\n }\n window.history.pushState(restoredState, \"\", from);\n } catch {\n // Leave the URL as-is if the history API rejects the write; the\n // rendered page is still the blocked-from page.\n }\n }\n\n /**\n * Handle browser back/forward navigation\n */\n private async handlePopState(event: PopStateEvent): Promise<void> {\n if (document.documentElement.dataset.farmDocsRuntime === \"true\") return;\n\n if (this.suppressNextPopState) {\n // This traversal is our own revert of a blocked pop; the rendered page\n // never changed.\n this.suppressNextPopState = false;\n return;\n }\n\n const path = window.location.pathname + window.location.search;\n // The browser has already moved to the destination entry, so its state\n // describes `to`; the page still rendered is the tracked current path.\n const from = this.currentHistoryPath ?? path;\n\n if (\n await this.shouldBlockNavigation({\n from,\n to: path,\n action: \"pop\",\n })\n ) {\n this.revertBlockedPopState(event, from);\n return;\n }\n\n this.currentHistoryPath = path;\n this.currentHistoryIndex = readHistoryIndex(event.state);\n\n const navigation = this.startNavigation({\n from,\n to: createNavigationLocation(new URL(window.location.href)),\n action: \"pop\",\n });\n\n let clientNavigation: FarmClientNavigationSession | undefined;\n try {\n clientNavigation = await this.clientPlugins?.beginNavigation({\n from: null,\n to: window.location.href,\n action: \"pop\",\n });\n if (!this.isCurrentNavigation(navigation, clientNavigation)) return;\n const interceptFrom =\n typeof event.state?.[FARM_INTERCEPT_FROM_KEY] === \"string\"\n ? event.state[FARM_INTERCEPT_FROM_KEY]\n : undefined;\n const pageData = await this.fetchPageData(\n path,\n true,\n interceptFrom,\n false,\n navigation.controller.signal,\n );\n if (!this.isCurrentNavigation(navigation, clientNavigation)) return;\n if (clientNavigation) {\n await this.clientPlugins?.markNavigationLoaded(clientNavigation, pageData);\n }\n if (!this.isCurrentNavigation(navigation, clientNavigation)) return;\n\n this.updateDocumentMetadata(pageData.metadata);\n\n _hydrateFarmI18n(pageData.i18n);\n\n // Call the navigation handler to update React\n if (this.onNavigate) {\n await this.onNavigate(pageData);\n }\n\n // A fragment in the destination URL is an explicit scroll target and\n // takes precedence over saved-position restoration, matching forward\n // navigation and native browser back/forward. Saved positions are keyed\n // without the hash, so restoreScrollPosition would not cover it.\n if (window.location.hash) {\n getHashTargetElement(window.location.hash)?.scrollIntoView();\n } else if (this.options.scrollRestoration) {\n this.restoreScrollPosition(window.location.pathname + window.location.search);\n }\n\n if (clientNavigation) {\n await this.clientPlugins?.resolveNavigation(clientNavigation);\n void this.clientPlugins?.scheduleNavigationRendered(clientNavigation);\n }\n this.finishNavigation(navigation);\n } catch (error) {\n if (!this.isCurrentNavigation(navigation, clientNavigation)) return;\n if (clientNavigation) {\n await this.clientPlugins?.failNavigation(clientNavigation, error);\n }\n this.finishNavigation(navigation);\n console.error(\"[Farm.js] Popstate navigation error:\", error);\n // Reload the page as fallback\n window.location.reload();\n }\n }\n\n /**\n * Check if URL is cached\n */\n private isCached(path: string, interceptFrom?: string): boolean {\n const cached = this.cache.get(getPageDataCacheKey(path, interceptFrom));\n return cached !== undefined && Date.now() - cached.timestamp < this.options.cacheMaxAge;\n }\n\n /**\n * Check if URL is external\n */\n private isExternalUrl(href: string): boolean {\n return href.startsWith(\"http://\") || href.startsWith(\"https://\") || href.startsWith(\"//\");\n }\n\n private async shouldBlockNavigation(context: FarmNavigationBlockerContext): Promise<boolean> {\n for (const blocker of this.blockers) {\n if (await blocker(context)) {\n return true;\n }\n }\n return false;\n }\n\n private evaluateBlockerForUnload(blocker: FarmNavigationBlocker): boolean {\n const path = window.location.pathname + window.location.search;\n const result = blocker({ from: path, to: path, action: \"replace\" });\n if (result && typeof result !== \"boolean\") {\n void result.catch(() => undefined);\n return true;\n }\n return result === true;\n }\n\n private shouldBlockUnload(): boolean {\n for (const blocker of this.blockers) {\n try {\n if (this.unloadBlockers.get(blocker)?.()) return true;\n } catch {\n return true;\n }\n }\n return false;\n }\n\n private updateDocumentMetadata(metadata: PageData[\"metadata\"]): void {\n document.title = metadata?.title || \"Farm.js App\";\n\n let description = document.querySelector('meta[name=\"description\"]');\n if (!metadata?.description) {\n description?.remove();\n return;\n }\n\n if (!description) {\n description = document.createElement(\"meta\");\n description.setAttribute(\"name\", \"description\");\n document.head.appendChild(description);\n }\n description.setAttribute(\"content\", metadata.description);\n }\n\n private startNavigation(options: {\n from: string;\n to: FarmNavigationLocation;\n action: FarmNavigationBlockerContext[\"action\"];\n }): { id: number; controller: AbortController } {\n this.activeNavigation?.controller.abort(\"superseded\");\n const navigation = {\n id: ++this.navigationSequence,\n controller: new AbortController(),\n };\n this.activeNavigation = navigation;\n this.setNavigationState({\n state: \"loading\",\n pending: true,\n from: options.from,\n to: options.to,\n action: options.action,\n startedAt: Date.now(),\n });\n return navigation;\n }\n\n private isCurrentNavigation(\n navigation: { id: number; controller: AbortController },\n clientNavigation?: FarmClientNavigationSession,\n ): boolean {\n return (\n this.activeNavigation?.id === navigation.id &&\n !navigation.controller.signal.aborted &&\n !clientNavigation?.signal.aborted\n );\n }\n\n private finishNavigation(navigation: { id: number; controller: AbortController }): void {\n if (this.activeNavigation?.id !== navigation.id) return;\n this.activeNavigation = undefined;\n this.setNavigationState(IDLE_NAVIGATION_STATE);\n }\n\n private cancelActiveNavigation(): void {\n if (!this.activeNavigation) return;\n this.activeNavigation.controller.abort(\"superseded\");\n this.activeNavigation = undefined;\n this.setNavigationState(IDLE_NAVIGATION_STATE);\n }\n\n private setNavigationState(state: FarmNavigationState): void {\n this.navigationState = state;\n for (const listener of this.navigationListeners) {\n listener(state);\n }\n }\n\n private writePageState(\n action: \"push\" | \"replace\",\n state: unknown,\n href?: string,\n notify = true,\n ): void {\n if (typeof window === \"undefined\") return;\n\n const url = href ? new URL(href, window.location.origin).toString() : window.location.href;\n const parsedUrl = new URL(url);\n const nextPath = parsedUrl.pathname + parsedUrl.search;\n const historyPath = nextPath + parsedUrl.hash;\n const nextState = createHistoryState(historyPath, state, window.history.state) as Record<\n string,\n unknown\n >;\n\n if (action === \"replace\") {\n window.history.replaceState(nextState, \"\", url);\n } else {\n if (this.currentHistoryIndex != null) {\n nextState[FARM_HISTORY_INDEX_KEY] = this.currentHistoryIndex + 1;\n }\n window.history.pushState(nextState, \"\", url);\n this.currentHistoryIndex =\n this.currentHistoryIndex == null ? null : this.currentHistoryIndex + 1;\n }\n this.currentHistoryPath = nextPath;\n\n if (notify) notifyHistoryChange(\"page-state\");\n }\n\n /**\n * Save scroll position for a path\n */\n private saveScrollPosition(path: string): void {\n try {\n sessionStorage.setItem(\n `farm-scroll-${path}`,\n JSON.stringify({ x: window.scrollX, y: window.scrollY }),\n );\n for (const [key, element] of this.scrollElements) {\n sessionStorage.setItem(\n getScrollElementStorageKey(path, key),\n JSON.stringify({ x: element.scrollLeft, y: element.scrollTop }),\n );\n }\n } catch {\n // Ignore storage errors\n }\n }\n\n /**\n * Restore scroll position for a path\n */\n private restoreScrollPosition(path: string): void {\n try {\n const saved = sessionStorage.getItem(`farm-scroll-${path}`);\n if (saved) {\n const { x, y } = JSON.parse(saved);\n setTimeout(() => window.scrollTo(x, y), 0);\n }\n for (const [key, element] of this.scrollElements) {\n this.restoreScrollElement(path, key, element);\n }\n } catch {\n // Ignore storage errors\n }\n }\n\n private restoreScrollElement(path: string, key: string, element: HTMLElement): void {\n try {\n const saved = sessionStorage.getItem(getScrollElementStorageKey(path, key));\n if (!saved) return;\n const { x, y } = JSON.parse(saved);\n setTimeout(() => {\n element.scrollLeft = x;\n element.scrollTop = y;\n }, 0);\n } catch {\n // Ignore storage errors\n }\n }\n\n /**\n * Clear the page cache\n */\n clearCache(): void {\n this.cache.clear();\n }\n}\n\nfunction readBrowserDeploymentId(): string | undefined {\n if (typeof window === \"undefined\") return undefined;\n\n const runtimeId = (window as Window & { __FARM_DEPLOYMENT_ID__?: unknown })\n .__FARM_DEPLOYMENT_ID__;\n if (typeof runtimeId === \"string\" && runtimeId) return runtimeId;\n\n return document.querySelector<HTMLMetaElement>('meta[name=\"farm-deployment-id\"]')?.content;\n}\n\nfunction dispatchDeploymentMismatch(error: Error): void {\n if (typeof window === \"undefined\" || typeof CustomEvent === \"undefined\") return;\n window.dispatchEvent(new CustomEvent(\"farm:deployment-mismatch\", { detail: error }));\n}\n\n/**\n * Get or create the global router instance\n */\nexport function getInstalledFarmSPARouter(): SPARouter | undefined {\n if (typeof window === \"undefined\") return undefined;\n return (window as Window & { __FARM_SPA_ROUTER__?: SPARouter }).__FARM_SPA_ROUTER__;\n}\n\nexport function getRouter(): SPARouter {\n if (typeof window === \"undefined\") {\n // Return a no-op router for SSR\n return new SPARouter();\n }\n\n const installedRouter = getInstalledFarmSPARouter();\n if (installedRouter) {\n routerInstance = installedRouter;\n return installedRouter;\n }\n\n if (!routerInstance) {\n routerInstance = new SPARouter();\n }\n\n return routerInstance;\n}\n\n/**\n * Navigate to a URL using the SPA router\n */\nexport function navigateTo(href: string, options?: FarmNavigateOptions): Promise<void> {\n return getRouter().navigate(href, options);\n}\n\n/**\n * Prefetch a URL\n */\nexport function prefetch(href: string): Promise<void> {\n return getRouter().prefetch(href);\n}\n\nexport function pushState(state: unknown, href?: string): void {\n getRouter().pushState(state, href);\n}\n\nexport function replaceState(state: unknown, href?: string): void {\n getRouter().replaceState(state, href);\n}\n\nexport function readPageState<TState = unknown>(): TState | null {\n if (typeof window === \"undefined\") return null;\n const state = window.history.state;\n if (!state || typeof state !== \"object\") return null;\n return ((state as Record<string, unknown>)[FARM_PAGE_STATE_KEY] as TState | undefined) ?? null;\n}\n\nfunction createHistoryState(\n path: string,\n pageState: unknown,\n currentState?: unknown,\n interceptFrom?: string | null,\n) {\n const base =\n currentState && typeof currentState === \"object\" ? { ...(currentState as object) } : {};\n const nextState: Record<string, unknown> = {\n ...base,\n path,\n [FARM_PAGE_STATE_KEY]: pageState,\n };\n if (interceptFrom === null) {\n delete nextState[FARM_INTERCEPT_FROM_KEY];\n } else if (interceptFrom) {\n nextState[FARM_INTERCEPT_FROM_KEY] = interceptFrom;\n }\n return nextState;\n}\n\nfunction getPageDataCacheKey(path: string, interceptFrom?: string): string {\n return interceptFrom ? `${path}\\nintercept:${interceptFrom}` : path;\n}\n\nfunction createNavigationLocation(url: URL): FarmNavigationLocation {\n return {\n href: url.href,\n pathname: url.pathname,\n search: url.search,\n hash: url.hash,\n };\n}\n\nfunction getScrollElementStorageKey(path: string, key: string): string {\n return `farm-scroll-${path}:${key}`;\n}\n","import { getInstalledFarmSPARouter, type SPARouter } from \"./spa-router\";\n\n/** Fired after programmatic history writes that must not start a navigation. */\nexport const FARM_HISTORY_CHANGE_EVENT = \"farm:historychange\";\n\nexport type FarmHistoryChangeKind = \"url-search\" | \"page-state\";\n\nexport interface FarmHistoryChangeDetail {\n kind: FarmHistoryChangeKind;\n}\n\n/** Write shallow URL history through the installed SPA router when available. */\nexport function writeFarmURLSearchHistory(action: \"push\" | \"replace\", href: string): boolean {\n const router = getInstalledFarmSPARouter();\n if (!router) return false;\n const writeURLSearch = (router as { writeURLSearch?: SPARouter[\"writeURLSearch\"] })\n .writeURLSearch;\n if (typeof writeURLSearch !== \"function\") return false;\n if (window.history.state !== null && typeof window.history.state !== \"object\") return false;\n writeURLSearch.call(router, action, href);\n return true;\n}\n\nfunction dispatchHistoryChange(kind: FarmHistoryChangeKind): void {\n window.dispatchEvent(\n new CustomEvent<FarmHistoryChangeDetail>(FARM_HISTORY_CHANGE_EVENT, {\n detail: { kind },\n }),\n );\n}\n\n/**\n * Notify history observers after pushState/replaceState.\n *\n * Farm's SPA router treats `popstate` as real back/forward navigation, so a\n * dedicated event is used instead. `url-search` keeps the nuqs-style synthetic\n * `popstate` when no Farm router is installed, so standalone `useQueryState`\n * consumers still resync; `page-state` is Farm-internal and never falls back.\n */\nexport function notifyHistoryChange(kind: FarmHistoryChangeKind): void {\n if (typeof window === \"undefined\") return;\n\n setTimeout(() => {\n if (kind === \"url-search\" && !getInstalledFarmSPARouter()) {\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n return;\n }\n\n dispatchHistoryChange(kind);\n }, 0);\n}\n\n/** Notify observers after a Farm router commit without simulating traversal. */\nexport function notifyRouterHistoryChange(): void {\n if (typeof window === \"undefined\") return;\n setTimeout(() => dispatchHistoryChange(\"url-search\"), 0);\n}\n\nexport function subscribeHistoryChange(listener: () => void): () => void {\n if (typeof window === \"undefined\") return () => {};\n\n window.addEventListener(\"popstate\", listener);\n window.addEventListener(FARM_HISTORY_CHANGE_EVENT, listener);\n\n return () => {\n window.removeEventListener(\"popstate\", listener);\n window.removeEventListener(FARM_HISTORY_CHANGE_EVENT, listener);\n };\n}\n","type CurrentRequestResolver = () => Request | undefined;\n\nconst CURRENT_REQUEST_RESOLVER_KEY = Symbol.for(\"farm.currentRequestResolver\");\n\ntype GlobalWithCurrentRequestResolver = typeof globalThis & {\n [CURRENT_REQUEST_RESOLVER_KEY]?: CurrentRequestResolver;\n};\n\nfunction getGlobalState(): GlobalWithCurrentRequestResolver {\n return globalThis as GlobalWithCurrentRequestResolver;\n}\n\nexport function _setCurrentRequestResolver(resolver: CurrentRequestResolver | undefined): void {\n getGlobalState()[CURRENT_REQUEST_RESOLVER_KEY] = resolver;\n}\n\nexport function _resolveCurrentRequest(): Request | undefined {\n return getGlobalState()[CURRENT_REQUEST_RESOLVER_KEY]?.();\n}\n","/**\n * Cross-hook synchronization system for query state\n * Inspired by nuqs implementation\n */\n\ntype Listener = (searchParams: URLSearchParams) => void;\nexport type KeyUpdate = { state: any; query: string | null; source?: object };\ntype KeyListener = (payload: KeyUpdate) => void;\n\nclass Emitter {\n private listeners: Map<string, Set<Listener>> = new Map();\n private keyListeners: Map<string, Set<KeyListener>> = new Map();\n\n /**\n * Emit a global update event (all hooks should sync)\n */\n emitUpdate(searchParams: URLSearchParams): void {\n const listeners = this.listeners.get(\"update\") || new Set();\n listeners.forEach((listener) => listener(searchParams));\n }\n\n /**\n * Emit a key-specific update (for cross-hook sync)\n */\n emitKey(key: string, payload: KeyUpdate): void {\n const listeners = this.keyListeners.get(key) || new Set();\n listeners.forEach((listener) => listener(payload));\n }\n\n /**\n * Subscribe to global updates\n */\n on(event: \"update\", listener: Listener): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(listener);\n }\n\n /**\n * Subscribe to key-specific updates\n */\n onKey(key: string, listener: KeyListener): void {\n if (!this.keyListeners.has(key)) {\n this.keyListeners.set(key, new Set());\n }\n this.keyListeners.get(key)!.add(listener);\n }\n\n /**\n * Unsubscribe from global updates\n */\n off(event: \"update\", listener: Listener): void {\n const listeners = this.listeners.get(event);\n if (listeners) {\n listeners.delete(listener);\n }\n }\n\n /**\n * Unsubscribe from key-specific updates\n */\n offKey(key: string, listener: KeyListener): void {\n const listeners = this.keyListeners.get(key);\n if (listeners) {\n listeners.delete(listener);\n }\n }\n}\n\nexport const emitter = new Emitter();\n","import type { Parser } from \"./parsers\";\n\nexport type RouteParamsInput =\n | Record<string, string | undefined>\n | URLSearchParams\n | Promise<Record<string, string | undefined> | URLSearchParams>;\n\nfunction normalizeParams(input: Record<string, string | undefined> | URLSearchParams) {\n if (input instanceof URLSearchParams) {\n const params: Record<string, string | undefined> = {};\n input.forEach((value, key) => {\n params[key] = value;\n });\n return params;\n }\n return input;\n}\n\nexport async function loadRouteParams<T extends Record<string, Parser<any>>>(\n input: RouteParamsInput,\n parsers: T,\n options: { strict?: boolean } = {},\n): Promise<{ [K in keyof T]: ReturnType<T[K][\"parse\"]> }> {\n const resolved = await Promise.resolve(input);\n const params = normalizeParams(resolved);\n const result = {} as { [K in keyof T]: ReturnType<T[K][\"parse\"]> };\n\n for (const [key, parser] of Object.entries(parsers)) {\n const raw = params[key] ?? \"\";\n const parsed = parser.parse(raw);\n if (parsed === null && options.strict) {\n throw new Error(`Failed to parse route param \"${key}\" with value \"${raw}\"`);\n }\n result[key as keyof T] = parsed as ReturnType<T[typeof key][\"parse\"]>;\n }\n\n return result;\n}\n\nexport function parseRouteParams<T extends Record<string, Parser<any>>>(\n input: Record<string, string | undefined> | URLSearchParams,\n parsers: T,\n options: { strict?: boolean } = {},\n): { [K in keyof T]: ReturnType<T[K][\"parse\"]> } {\n const params = normalizeParams(input);\n const result = {} as { [K in keyof T]: ReturnType<T[K][\"parse\"]> };\n\n for (const [key, parser] of Object.entries(parsers)) {\n const raw = params[key] ?? \"\";\n const parsed = parser.parse(raw);\n if (parsed === null && options.strict) {\n throw new Error(`Failed to parse route param \"${key}\" with value \"${raw}\"`);\n }\n result[key as keyof T] = parsed as ReturnType<T[typeof key][\"parse\"]>;\n }\n\n return result;\n}\n","/**\n * Farm.js Query State Parsers\n *\n * Shared parsers that can be used in both client and server contexts\n */\n\nexport interface Parser<T> {\n parse: (value: string) => T | null;\n serialize: (value: T) => string;\n withDefault?: (defaultValue: T) => Parser<T>;\n}\n\nconst INTEGER_PATTERN = /^[+-]?\\d+$/;\nconst FLOAT_PATTERN = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?$/;\nconst ISO_DATE_PATTERN = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\nconst ISO_DATE_TIME_PATTERN =\n /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(?:\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})$/;\n\nfunction parseInteger(value: string): number | null {\n if (!INTEGER_PATTERN.test(value)) return null;\n const parsed = Number(value);\n return Number.isSafeInteger(parsed) ? parsed : null;\n}\n\nfunction parseFloatValue(value: string): number | null {\n if (!FLOAT_PATTERN.test(value)) return null;\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : null;\n}\n\nfunction isValidCalendarDate(year: number, month: number, day: number): boolean {\n if (month < 1 || month > 12 || day < 1) return false;\n const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);\n const daysInMonth = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n return day <= daysInMonth[month - 1];\n}\n\nfunction parseIsoDate(value: string): Date | null {\n const match = value.match(ISO_DATE_PATTERN);\n if (!match) return null;\n\n const year = Number(match[1]);\n const month = Number(match[2]);\n const day = Number(match[3]);\n if (!isValidCalendarDate(year, month, day)) return null;\n\n const date = new Date(0);\n date.setUTCHours(0, 0, 0, 0);\n date.setUTCFullYear(year, month - 1, day);\n return date;\n}\n\nfunction parseIsoDateTime(value: string): Date | null {\n const match = value.match(ISO_DATE_TIME_PATTERN);\n if (!match) return null;\n\n const year = Number(match[1]);\n const month = Number(match[2]);\n const day = Number(match[3]);\n const hour = Number(match[4]);\n const minute = Number(match[5]);\n const second = Number(match[6]);\n const timezone = match[7];\n if (!isValidCalendarDate(year, month, day) || hour > 23 || minute > 59 || second > 59) {\n return null;\n }\n\n if (timezone !== \"Z\") {\n const [offsetHour, offsetMinute] = timezone.slice(1).split(\":\").map(Number);\n if (offsetHour > 23 || offsetMinute > 59) return null;\n }\n\n const date = new Date(value);\n return Number.isFinite(date.getTime()) ? date : null;\n}\n\n// String parser\nexport const asString: Parser<string> = {\n parse: (value: string) => (value && value.trim()) || null,\n serialize: (value: string) => value,\n withDefault: (defaultValue: string) => ({\n parse: (value: string) => (value && value.trim()) || defaultValue,\n serialize: (value: string) => value || defaultValue,\n }),\n};\n\n// Integer parser\nexport const asInteger: Parser<number> = {\n parse: parseInteger,\n serialize: (value: number) => value.toString(),\n withDefault: (defaultValue: number) => ({\n parse: (value: string) => parseInteger(value) ?? defaultValue,\n serialize: (value: number) => value.toString(),\n }),\n};\n\n// Float parser\nexport const asFloat: Parser<number> = {\n parse: parseFloatValue,\n serialize: (value: number) => value.toString(),\n withDefault: (defaultValue: number) => ({\n parse: (value: string) => parseFloatValue(value) ?? defaultValue,\n serialize: (value: number) => value.toString(),\n }),\n};\n\n// Boolean parser\nexport const asBoolean: Parser<boolean> = {\n parse: (value: string) => {\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n return null;\n },\n serialize: (value: boolean) => value.toString(),\n withDefault: (defaultValue: boolean) => ({\n parse: (value: string) => {\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n return defaultValue;\n },\n serialize: (value: boolean) => value.toString(),\n }),\n};\n\n// Array parser\nconst STRUCTURED_ARRAY_PREFIX = \"~farm-array:v1:\";\nexport interface ArrayParserOptions {\n /** Preserve comma URLs by default; opt in when item delimiters must round-trip. */\n format?: \"comma\" | \"structured\";\n}\n\nfunction parseArrayItems(value: string, structured: boolean): string[] {\n if (structured && value.startsWith(STRUCTURED_ARRAY_PREFIX)) {\n try {\n const parsed = JSON.parse(value.slice(STRUCTURED_ARRAY_PREFIX.length));\n if (Array.isArray(parsed) && parsed.every((item) => typeof item === \"string\")) {\n return parsed;\n }\n } catch {\n // Keep accepting legacy values that happen to begin with the prefix.\n }\n }\n\n return value\n .split(\",\")\n .filter(Boolean)\n .map((item) => item.trim());\n}\n\nfunction serializeArrayItems(values: string[], structured: boolean): string {\n if (!structured) return values.join(\",\");\n\n const needsStructuredEncoding = values.some(\n (value, index) =>\n value === \"\" ||\n value.trim() !== value ||\n value.includes(\",\") ||\n (index === 0 && value.startsWith(STRUCTURED_ARRAY_PREFIX)),\n );\n return needsStructuredEncoding\n ? `${STRUCTURED_ARRAY_PREFIX}${JSON.stringify(values)}`\n : values.join(\",\");\n}\n\nexport function asArrayOf<T>(itemParser: Parser<T>, options: ArrayParserOptions = {}): Parser<T[]> {\n const structured = options.format === \"structured\";\n const parse = (value: string): T[] | null => {\n if (!value) return null;\n return parseArrayItems(value, structured)\n .map((item) => itemParser.parse(item))\n .filter((item) => item !== null) as T[];\n };\n const serialize = (value: T[]) =>\n serializeArrayItems(\n value.map((item) => itemParser.serialize(item)),\n structured,\n );\n\n return {\n parse,\n serialize,\n withDefault: (defaultValue: T[]) => ({\n parse: (value: string) => parse(value) ?? defaultValue,\n serialize,\n }),\n };\n}\n\n// JSON parser\nexport function asJson<T>(): Parser<T> {\n return {\n parse: (value: string) => {\n try {\n return JSON.parse(value);\n } catch {\n return null;\n }\n },\n serialize: (value: T) => JSON.stringify(value),\n withDefault: (defaultValue: T) => ({\n parse: (value: string) => {\n try {\n return JSON.parse(value);\n } catch {\n return defaultValue;\n }\n },\n serialize: (value: T) => JSON.stringify(value),\n }),\n };\n}\n\n// ISO Date parser\nexport const asIsoDate: Parser<Date> = {\n parse: parseIsoDate,\n serialize: (value: Date) => value.toISOString().slice(0, 10),\n withDefault: (defaultValue: Date) => ({\n parse: (value: string) => parseIsoDate(value) ?? defaultValue,\n serialize: (value: Date) => value.toISOString().slice(0, 10),\n }),\n};\n\n// ISO DateTime parser\nexport const asIsoDateTime: Parser<Date> = {\n parse: parseIsoDateTime,\n serialize: (value: Date) => value.toISOString(),\n withDefault: (defaultValue: Date) => ({\n parse: (value: string) => parseIsoDateTime(value) ?? defaultValue,\n serialize: (value: Date) => value.toISOString(),\n }),\n};\n\n// Custom parser creator\nexport function createParser<T>(config: {\n parse: (value: string) => T | null;\n serialize: (value: T) => string;\n}): Parser<T> {\n return {\n parse: config.parse,\n serialize: config.serialize,\n withDefault: (defaultValue: T) => ({\n parse: (value: string) => config.parse(value) ?? defaultValue,\n serialize: config.serialize,\n }),\n };\n}\n\n// Type inference helper\nexport type inferParserType<T> = T extends Parser<infer U> ? U : never;\n"],"mappings":"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","names":["IntlMessageFormat","knownNext","applyChange"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/query/index.ts","../../src/query/parsers.ts","../../src/query/params.ts"],"sourcesContent":["/**\n * Farm.js Query State Management\n *\n * Type-safe URL search parameter state management\n * Provides useState-like API for managing URL query parameters\n *\n * This module exports shared parsers and types that can be used in both client and server contexts.\n * For client-specific hooks, use 'farm/query/client'\n * For server-specific utilities, use 'farm/query/server'\n */\n\n// Re-export shared parsers that work in both client and server\nexport {\n asString,\n asInteger,\n asFloat,\n asBoolean,\n asArrayOf,\n asJson,\n asIsoDate,\n asIsoDateTime,\n createParser,\n type ArrayParserOptions,\n type Parser,\n type inferParserType,\n} from \"./parsers\";\nexport { parseRouteParams, loadRouteParams, type RouteParamsInput } from \"./params\";\n\n// Re-export types\nexport type {\n PagePropsSafe,\n LayoutPropsSafe,\n QueryStateConfig,\n FarmQueryStateContext,\n QueryStateProvider,\n} from \"./types\";\n","/**\n * Farm.js Query State Parsers\n *\n * Shared parsers that can be used in both client and server contexts\n */\n\nexport interface Parser<T> {\n parse: (value: string) => T | null;\n serialize: (value: T) => string;\n withDefault?: (defaultValue: T) => Parser<T>;\n}\n\nconst INTEGER_PATTERN = /^[+-]?\\d+$/;\nconst FLOAT_PATTERN = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?$/;\nconst ISO_DATE_PATTERN = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\nconst ISO_DATE_TIME_PATTERN =\n /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(?:\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})$/;\n\nfunction parseInteger(value: string): number | null {\n if (!INTEGER_PATTERN.test(value)) return null;\n const parsed = Number(value);\n return Number.isSafeInteger(parsed) ? parsed : null;\n}\n\nfunction parseFloatValue(value: string): number | null {\n if (!FLOAT_PATTERN.test(value)) return null;\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : null;\n}\n\nfunction isValidCalendarDate(year: number, month: number, day: number): boolean {\n if (month < 1 || month > 12 || day < 1) return false;\n const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);\n const daysInMonth = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n return day <= daysInMonth[month - 1];\n}\n\nfunction parseIsoDate(value: string): Date | null {\n const match = value.match(ISO_DATE_PATTERN);\n if (!match) return null;\n\n const year = Number(match[1]);\n const month = Number(match[2]);\n const day = Number(match[3]);\n if (!isValidCalendarDate(year, month, day)) return null;\n\n const date = new Date(0);\n date.setUTCHours(0, 0, 0, 0);\n date.setUTCFullYear(year, month - 1, day);\n return date;\n}\n\nfunction parseIsoDateTime(value: string): Date | null {\n const match = value.match(ISO_DATE_TIME_PATTERN);\n if (!match) return null;\n\n const year = Number(match[1]);\n const month = Number(match[2]);\n const day = Number(match[3]);\n const hour = Number(match[4]);\n const minute = Number(match[5]);\n const second = Number(match[6]);\n const timezone = match[7];\n if (!isValidCalendarDate(year, month, day) || hour > 23 || minute > 59 || second > 59) {\n return null;\n }\n\n if (timezone !== \"Z\") {\n const [offsetHour, offsetMinute] = timezone.slice(1).split(\":\").map(Number);\n if (offsetHour > 23 || offsetMinute > 59) return null;\n }\n\n const date = new Date(value);\n return Number.isFinite(date.getTime()) ? date : null;\n}\n\n// String parser\nexport const asString: Parser<string> = {\n parse: (value: string) => (value && value.trim()) || null,\n serialize: (value: string) => value,\n withDefault: (defaultValue: string) => ({\n parse: (value: string) => (value && value.trim()) || defaultValue,\n serialize: (value: string) => value || defaultValue,\n }),\n};\n\n// Integer parser\nexport const asInteger: Parser<number> = {\n parse: parseInteger,\n serialize: (value: number) => value.toString(),\n withDefault: (defaultValue: number) => ({\n parse: (value: string) => parseInteger(value) ?? defaultValue,\n serialize: (value: number) => value.toString(),\n }),\n};\n\n// Float parser\nexport const asFloat: Parser<number> = {\n parse: parseFloatValue,\n serialize: (value: number) => value.toString(),\n withDefault: (defaultValue: number) => ({\n parse: (value: string) => parseFloatValue(value) ?? defaultValue,\n serialize: (value: number) => value.toString(),\n }),\n};\n\n// Boolean parser\nexport const asBoolean: Parser<boolean> = {\n parse: (value: string) => {\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n return null;\n },\n serialize: (value: boolean) => value.toString(),\n withDefault: (defaultValue: boolean) => ({\n parse: (value: string) => {\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n return defaultValue;\n },\n serialize: (value: boolean) => value.toString(),\n }),\n};\n\n// Array parser\nconst STRUCTURED_ARRAY_PREFIX = \"~farm-array:v1:\";\nexport interface ArrayParserOptions {\n /** Preserve comma URLs by default; opt in when item delimiters must round-trip. */\n format?: \"comma\" | \"structured\";\n}\n\nfunction parseArrayItems(value: string, structured: boolean): string[] {\n if (structured && value.startsWith(STRUCTURED_ARRAY_PREFIX)) {\n try {\n const parsed = JSON.parse(value.slice(STRUCTURED_ARRAY_PREFIX.length));\n if (Array.isArray(parsed) && parsed.every((item) => typeof item === \"string\")) {\n return parsed;\n }\n } catch {\n // Keep accepting legacy values that happen to begin with the prefix.\n }\n }\n\n return value\n .split(\",\")\n .filter(Boolean)\n .map((item) => item.trim());\n}\n\nfunction serializeArrayItems(values: string[], structured: boolean): string {\n if (!structured) return values.join(\",\");\n\n const needsStructuredEncoding = values.some(\n (value, index) =>\n value === \"\" ||\n value.trim() !== value ||\n value.includes(\",\") ||\n (index === 0 && value.startsWith(STRUCTURED_ARRAY_PREFIX)),\n );\n return needsStructuredEncoding\n ? `${STRUCTURED_ARRAY_PREFIX}${JSON.stringify(values)}`\n : values.join(\",\");\n}\n\nexport function asArrayOf<T>(itemParser: Parser<T>, options: ArrayParserOptions = {}): Parser<T[]> {\n const structured = options.format === \"structured\";\n const parse = (value: string): T[] | null => {\n if (!value) return null;\n return parseArrayItems(value, structured)\n .map((item) => itemParser.parse(item))\n .filter((item) => item !== null) as T[];\n };\n const serialize = (value: T[]) =>\n serializeArrayItems(\n value.map((item) => itemParser.serialize(item)),\n structured,\n );\n\n return {\n parse,\n serialize,\n withDefault: (defaultValue: T[]) => ({\n parse: (value: string) => parse(value) ?? defaultValue,\n serialize,\n }),\n };\n}\n\n// JSON parser\nexport function asJson<T>(): Parser<T> {\n return {\n parse: (value: string) => {\n try {\n return JSON.parse(value);\n } catch {\n return null;\n }\n },\n serialize: (value: T) => JSON.stringify(value),\n withDefault: (defaultValue: T) => ({\n parse: (value: string) => {\n try {\n return JSON.parse(value);\n } catch {\n return defaultValue;\n }\n },\n serialize: (value: T) => JSON.stringify(value),\n }),\n };\n}\n\n// ISO Date parser\nexport const asIsoDate: Parser<Date> = {\n parse: parseIsoDate,\n serialize: (value: Date) => value.toISOString().slice(0, 10),\n withDefault: (defaultValue: Date) => ({\n parse: (value: string) => parseIsoDate(value) ?? defaultValue,\n serialize: (value: Date) => value.toISOString().slice(0, 10),\n }),\n};\n\n// ISO DateTime parser\nexport const asIsoDateTime: Parser<Date> = {\n parse: parseIsoDateTime,\n serialize: (value: Date) => value.toISOString(),\n withDefault: (defaultValue: Date) => ({\n parse: (value: string) => parseIsoDateTime(value) ?? defaultValue,\n serialize: (value: Date) => value.toISOString(),\n }),\n};\n\n// Custom parser creator\nexport function createParser<T>(config: {\n parse: (value: string) => T | null;\n serialize: (value: T) => string;\n}): Parser<T> {\n return {\n parse: config.parse,\n serialize: config.serialize,\n withDefault: (defaultValue: T) => ({\n parse: (value: string) => config.parse(value) ?? defaultValue,\n serialize: config.serialize,\n }),\n };\n}\n\n// Type inference helper\nexport type inferParserType<T> = T extends Parser<infer U> ? U : never;\n","import type { Parser } from \"./parsers\";\n\nexport type RouteParamsInput =\n | Record<string, string | undefined>\n | URLSearchParams\n | Promise<Record<string, string | undefined> | URLSearchParams>;\n\nfunction normalizeParams(input: Record<string, string | undefined> | URLSearchParams) {\n if (input instanceof URLSearchParams) {\n const params: Record<string, string | undefined> = {};\n input.forEach((value, key) => {\n params[key] = value;\n });\n return params;\n }\n return input;\n}\n\nexport async function loadRouteParams<T extends Record<string, Parser<any>>>(\n input: RouteParamsInput,\n parsers: T,\n options: { strict?: boolean } = {},\n): Promise<{ [K in keyof T]: ReturnType<T[K][\"parse\"]> }> {\n const resolved = await Promise.resolve(input);\n const params = normalizeParams(resolved);\n const result = {} as { [K in keyof T]: ReturnType<T[K][\"parse\"]> };\n\n for (const [key, parser] of Object.entries(parsers)) {\n const raw = params[key] ?? \"\";\n const parsed = parser.parse(raw);\n if (parsed === null && options.strict) {\n throw new Error(`Failed to parse route param \"${key}\" with value \"${raw}\"`);\n }\n result[key as keyof T] = parsed as ReturnType<T[typeof key][\"parse\"]>;\n }\n\n return result;\n}\n\nexport function parseRouteParams<T extends Record<string, Parser<any>>>(\n input: Record<string, string | undefined> | URLSearchParams,\n parsers: T,\n options: { strict?: boolean } = {},\n): { [K in keyof T]: ReturnType<T[K][\"parse\"]> } {\n const params = normalizeParams(input);\n const result = {} as { [K in keyof T]: ReturnType<T[K][\"parse\"]> };\n\n for (const [key, parser] of Object.entries(parsers)) {\n const raw = params[key] ?? \"\";\n const parsed = parser.parse(raw);\n if (parsed === null && options.strict) {\n throw new Error(`Failed to parse route param \"${key}\" with value \"${raw}\"`);\n }\n result[key as keyof T] = parsed as ReturnType<T[typeof key][\"parse\"]>;\n }\n\n return result;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/query/parsers.ts"],"sourcesContent":["/**\n * Farm.js Query State Parsers\n *\n * Shared parsers that can be used in both client and server contexts\n */\n\nexport interface Parser<T> {\n parse: (value: string) => T | null;\n serialize: (value: T) => string;\n withDefault?: (defaultValue: T) => Parser<T>;\n}\n\nconst INTEGER_PATTERN = /^[+-]?\\d+$/;\nconst FLOAT_PATTERN = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?$/;\nconst ISO_DATE_PATTERN = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\nconst ISO_DATE_TIME_PATTERN =\n /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(?:\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})$/;\n\nfunction parseInteger(value: string): number | null {\n if (!INTEGER_PATTERN.test(value)) return null;\n const parsed = Number(value);\n return Number.isSafeInteger(parsed) ? parsed : null;\n}\n\nfunction parseFloatValue(value: string): number | null {\n if (!FLOAT_PATTERN.test(value)) return null;\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : null;\n}\n\nfunction isValidCalendarDate(year: number, month: number, day: number): boolean {\n if (month < 1 || month > 12 || day < 1) return false;\n const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);\n const daysInMonth = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n return day <= daysInMonth[month - 1];\n}\n\nfunction parseIsoDate(value: string): Date | null {\n const match = value.match(ISO_DATE_PATTERN);\n if (!match) return null;\n\n const year = Number(match[1]);\n const month = Number(match[2]);\n const day = Number(match[3]);\n if (!isValidCalendarDate(year, month, day)) return null;\n\n const date = new Date(0);\n date.setUTCHours(0, 0, 0, 0);\n date.setUTCFullYear(year, month - 1, day);\n return date;\n}\n\nfunction parseIsoDateTime(value: string): Date | null {\n const match = value.match(ISO_DATE_TIME_PATTERN);\n if (!match) return null;\n\n const year = Number(match[1]);\n const month = Number(match[2]);\n const day = Number(match[3]);\n const hour = Number(match[4]);\n const minute = Number(match[5]);\n const second = Number(match[6]);\n const timezone = match[7];\n if (!isValidCalendarDate(year, month, day) || hour > 23 || minute > 59 || second > 59) {\n return null;\n }\n\n if (timezone !== \"Z\") {\n const [offsetHour, offsetMinute] = timezone.slice(1).split(\":\").map(Number);\n if (offsetHour > 23 || offsetMinute > 59) return null;\n }\n\n const date = new Date(value);\n return Number.isFinite(date.getTime()) ? date : null;\n}\n\n// String parser\nexport const asString: Parser<string> = {\n parse: (value: string) => (value && value.trim()) || null,\n serialize: (value: string) => value,\n withDefault: (defaultValue: string) => ({\n parse: (value: string) => (value && value.trim()) || defaultValue,\n serialize: (value: string) => value || defaultValue,\n }),\n};\n\n// Integer parser\nexport const asInteger: Parser<number> = {\n parse: parseInteger,\n serialize: (value: number) => value.toString(),\n withDefault: (defaultValue: number) => ({\n parse: (value: string) => parseInteger(value) ?? defaultValue,\n serialize: (value: number) => value.toString(),\n }),\n};\n\n// Float parser\nexport const asFloat: Parser<number> = {\n parse: parseFloatValue,\n serialize: (value: number) => value.toString(),\n withDefault: (defaultValue: number) => ({\n parse: (value: string) => parseFloatValue(value) ?? defaultValue,\n serialize: (value: number) => value.toString(),\n }),\n};\n\n// Boolean parser\nexport const asBoolean: Parser<boolean> = {\n parse: (value: string) => {\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n return null;\n },\n serialize: (value: boolean) => value.toString(),\n withDefault: (defaultValue: boolean) => ({\n parse: (value: string) => {\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n return defaultValue;\n },\n serialize: (value: boolean) => value.toString(),\n }),\n};\n\n// Array parser\nconst STRUCTURED_ARRAY_PREFIX = \"~farm-array:v1:\";\nexport interface ArrayParserOptions {\n /** Preserve comma URLs by default; opt in when item delimiters must round-trip. */\n format?: \"comma\" | \"structured\";\n}\n\nfunction parseArrayItems(value: string, structured: boolean): string[] {\n if (structured && value.startsWith(STRUCTURED_ARRAY_PREFIX)) {\n try {\n const parsed = JSON.parse(value.slice(STRUCTURED_ARRAY_PREFIX.length));\n if (Array.isArray(parsed) && parsed.every((item) => typeof item === \"string\")) {\n return parsed;\n }\n } catch {\n // Keep accepting legacy values that happen to begin with the prefix.\n }\n }\n\n return value\n .split(\",\")\n .filter(Boolean)\n .map((item) => item.trim());\n}\n\nfunction serializeArrayItems(values: string[], structured: boolean): string {\n if (!structured) return values.join(\",\");\n\n const needsStructuredEncoding = values.some(\n (value, index) =>\n value === \"\" ||\n value.trim() !== value ||\n value.includes(\",\") ||\n (index === 0 && value.startsWith(STRUCTURED_ARRAY_PREFIX)),\n );\n return needsStructuredEncoding\n ? `${STRUCTURED_ARRAY_PREFIX}${JSON.stringify(values)}`\n : values.join(\",\");\n}\n\nexport function asArrayOf<T>(itemParser: Parser<T>, options: ArrayParserOptions = {}): Parser<T[]> {\n const structured = options.format === \"structured\";\n const parse = (value: string): T[] | null => {\n if (!value) return null;\n return parseArrayItems(value, structured)\n .map((item) => itemParser.parse(item))\n .filter((item) => item !== null) as T[];\n };\n const serialize = (value: T[]) =>\n serializeArrayItems(\n value.map((item) => itemParser.serialize(item)),\n structured,\n );\n\n return {\n parse,\n serialize,\n withDefault: (defaultValue: T[]) => ({\n parse: (value: string) => parse(value) ?? defaultValue,\n serialize,\n }),\n };\n}\n\n// JSON parser\nexport function asJson<T>(): Parser<T> {\n return {\n parse: (value: string) => {\n try {\n return JSON.parse(value);\n } catch {\n return null;\n }\n },\n serialize: (value: T) => JSON.stringify(value),\n withDefault: (defaultValue: T) => ({\n parse: (value: string) => {\n try {\n return JSON.parse(value);\n } catch {\n return defaultValue;\n }\n },\n serialize: (value: T) => JSON.stringify(value),\n }),\n };\n}\n\n// ISO Date parser\nexport const asIsoDate: Parser<Date> = {\n parse: parseIsoDate,\n serialize: (value: Date) => value.toISOString().slice(0, 10),\n withDefault: (defaultValue: Date) => ({\n parse: (value: string) => parseIsoDate(value) ?? defaultValue,\n serialize: (value: Date) => value.toISOString().slice(0, 10),\n }),\n};\n\n// ISO DateTime parser\nexport const asIsoDateTime: Parser<Date> = {\n parse: parseIsoDateTime,\n serialize: (value: Date) => value.toISOString(),\n withDefault: (defaultValue: Date) => ({\n parse: (value: string) => parseIsoDateTime(value) ?? defaultValue,\n serialize: (value: Date) => value.toISOString(),\n }),\n};\n\n// Custom parser creator\nexport function createParser<T>(config: {\n parse: (value: string) => T | null;\n serialize: (value: T) => string;\n}): Parser<T> {\n return {\n parse: config.parse,\n serialize: config.serialize,\n withDefault: (defaultValue: T) => ({\n parse: (value: string) => config.parse(value) ?? defaultValue,\n serialize: config.serialize,\n }),\n };\n}\n\n// Type inference helper\nexport type inferParserType<T> = T extends Parser<infer U> ? U : never;\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/query/server.ts","../../src/query/params.ts","../../src/query/parsers.ts"],"sourcesContent":["/**\n * Farm.js Server-Side Query State Management\n *\n * Server-side utilities for parsing and handling URL search parameters\n */\n\nimport type { Parser } from \"./parsers\";\nexport { parseRouteParams, loadRouteParams, type RouteParamsInput } from \"./params\";\n\nexport {\n asString,\n asInteger,\n asFloat,\n asBoolean,\n asArrayOf,\n asJson,\n asIsoDate,\n asIsoDateTime,\n createParser,\n type ArrayParserOptions,\n type Parser,\n type inferParserType,\n} from \"./parsers\";\n\nexport type SearchParams = Record<string, string | string[] | undefined>;\n\n/**\n * Server-side utility to load and parse search parameters\n *\n * @example\n * ```tsx\n * // In a server component\n * import { loadSearchParams, parseAsString, parseAsInteger } from 'farm/query/server';\n *\n * export default async function MyPage({ searchParams }: PageProps) {\n * const params = await loadSearchParams(searchParams, {\n * search: parseAsString.withDefault!(''),\n * page: parseAsInteger.withDefault!(1),\n * });\n *\n * return <div>Search: {params.search}, Page: {params.page}</div>;\n * }\n * ```\n */\nexport async function loadSearchParams<T extends Record<string, Parser<any>>>(\n searchParams: Promise<URLSearchParams | Record<string, string | string[] | undefined>>,\n parsers: T,\n): Promise<{ [K in keyof T]: ReturnType<T[K][\"parse\"]> }> {\n const params = await searchParams;\n\n let urlParams: URLSearchParams;\n if (params instanceof URLSearchParams) {\n urlParams = params;\n } else {\n urlParams = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (Array.isArray(value)) {\n for (const v of value) {\n urlParams.append(key, v);\n }\n } else if (value !== undefined && value !== null) {\n urlParams.set(key, String(value));\n }\n }\n }\n\n const result = {} as { [K in keyof T]: ReturnType<T[K][\"parse\"]> };\n\n for (const [key, parser] of Object.entries(parsers)) {\n // Read every value, not just the first. A repeated key is joined with commas,\n // the format `asArrayOf` parses and its `serialize` writes, so a repeated\n // parameter round-trips. A single value is passed through untouched, so a\n // value that already contains commas keeps its meaning.\n const values = urlParams.getAll(key);\n const value = values.length > 1 ? values.join(\",\") : (values[0] ?? null);\n\n if (value !== null && value !== \"\") {\n try {\n result[key as keyof T] = parser.parse(value);\n } catch (error) {\n console.error(`Failed to parse parameter \"${key}\":`, error);\n throw error;\n }\n } else {\n result[key as keyof T] = parser.parse(\"\");\n }\n }\n\n return result;\n}\n\n/**\n * Creates pagination metadata for server components.\n *\n * @param searchParams The search parameters promise.\n * @param options Configuration options for pagination.\n * @returns Pagination metadata.\n */\nexport async function createPaginationMeta(\n searchParams: Promise<URLSearchParams | Record<string, string | string[] | undefined>>,\n options: {\n totalItems: number;\n itemsPerPage?: number;\n pageParam?: string;\n },\n) {\n const params = await searchParams;\n\n let urlParams: URLSearchParams;\n if (params instanceof URLSearchParams) {\n urlParams = params;\n } else {\n urlParams = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (Array.isArray(value)) {\n for (const v of value) {\n urlParams.append(key, v);\n }\n } else if (value !== undefined && value !== null) {\n urlParams.set(key, String(value));\n }\n }\n }\n\n const pageParam = options.pageParam || \"page\";\n const itemsPerPage = options.itemsPerPage ?? 10;\n assertPaginationInteger(options.totalItems, \"totalItems\", true);\n assertPaginationInteger(itemsPerPage, \"itemsPerPage\", false);\n\n const requestedPage = parsePositivePaginationInteger(urlParams.get(pageParam));\n const currentPage =\n requestedPage !== null && Number.isSafeInteger((requestedPage - 1) * itemsPerPage)\n ? requestedPage\n : 1;\n\n const totalPages = Math.ceil(options.totalItems / itemsPerPage);\n const offset = (currentPage - 1) * itemsPerPage;\n const limit = itemsPerPage;\n\n return {\n currentPage,\n itemsPerPage,\n totalItems: options.totalItems,\n totalPages,\n offset,\n limit,\n hasNextPage: currentPage < totalPages,\n hasPreviousPage: currentPage > 1,\n };\n}\n\nfunction parsePositivePaginationInteger(value: string | null): number | null {\n if (!value || !/^[+]?[0-9]+$/.test(value)) return null;\n const parsed = Number(value);\n return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;\n}\n\nfunction assertPaginationInteger(value: number, name: string, allowZero: boolean): void {\n const minimum = allowZero ? 0 : 1;\n if (!Number.isSafeInteger(value) || value < minimum) {\n throw new RangeError(\n `Pagination ${name} must be a safe integer greater than or equal to ${minimum}.`,\n );\n }\n}\n","import type { Parser } from \"./parsers\";\n\nexport type RouteParamsInput =\n | Record<string, string | undefined>\n | URLSearchParams\n | Promise<Record<string, string | undefined> | URLSearchParams>;\n\nfunction normalizeParams(input: Record<string, string | undefined> | URLSearchParams) {\n if (input instanceof URLSearchParams) {\n const params: Record<string, string | undefined> = {};\n input.forEach((value, key) => {\n params[key] = value;\n });\n return params;\n }\n return input;\n}\n\nexport async function loadRouteParams<T extends Record<string, Parser<any>>>(\n input: RouteParamsInput,\n parsers: T,\n options: { strict?: boolean } = {},\n): Promise<{ [K in keyof T]: ReturnType<T[K][\"parse\"]> }> {\n const resolved = await Promise.resolve(input);\n const params = normalizeParams(resolved);\n const result = {} as { [K in keyof T]: ReturnType<T[K][\"parse\"]> };\n\n for (const [key, parser] of Object.entries(parsers)) {\n const raw = params[key] ?? \"\";\n const parsed = parser.parse(raw);\n if (parsed === null && options.strict) {\n throw new Error(`Failed to parse route param \"${key}\" with value \"${raw}\"`);\n }\n result[key as keyof T] = parsed as ReturnType<T[typeof key][\"parse\"]>;\n }\n\n return result;\n}\n\nexport function parseRouteParams<T extends Record<string, Parser<any>>>(\n input: Record<string, string | undefined> | URLSearchParams,\n parsers: T,\n options: { strict?: boolean } = {},\n): { [K in keyof T]: ReturnType<T[K][\"parse\"]> } {\n const params = normalizeParams(input);\n const result = {} as { [K in keyof T]: ReturnType<T[K][\"parse\"]> };\n\n for (const [key, parser] of Object.entries(parsers)) {\n const raw = params[key] ?? \"\";\n const parsed = parser.parse(raw);\n if (parsed === null && options.strict) {\n throw new Error(`Failed to parse route param \"${key}\" with value \"${raw}\"`);\n }\n result[key as keyof T] = parsed as ReturnType<T[typeof key][\"parse\"]>;\n }\n\n return result;\n}\n","/**\n * Farm.js Query State Parsers\n *\n * Shared parsers that can be used in both client and server contexts\n */\n\nexport interface Parser<T> {\n parse: (value: string) => T | null;\n serialize: (value: T) => string;\n withDefault?: (defaultValue: T) => Parser<T>;\n}\n\nconst INTEGER_PATTERN = /^[+-]?\\d+$/;\nconst FLOAT_PATTERN = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?$/;\nconst ISO_DATE_PATTERN = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\nconst ISO_DATE_TIME_PATTERN =\n /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(?:\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})$/;\n\nfunction parseInteger(value: string): number | null {\n if (!INTEGER_PATTERN.test(value)) return null;\n const parsed = Number(value);\n return Number.isSafeInteger(parsed) ? parsed : null;\n}\n\nfunction parseFloatValue(value: string): number | null {\n if (!FLOAT_PATTERN.test(value)) return null;\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : null;\n}\n\nfunction isValidCalendarDate(year: number, month: number, day: number): boolean {\n if (month < 1 || month > 12 || day < 1) return false;\n const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);\n const daysInMonth = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n return day <= daysInMonth[month - 1];\n}\n\nfunction parseIsoDate(value: string): Date | null {\n const match = value.match(ISO_DATE_PATTERN);\n if (!match) return null;\n\n const year = Number(match[1]);\n const month = Number(match[2]);\n const day = Number(match[3]);\n if (!isValidCalendarDate(year, month, day)) return null;\n\n const date = new Date(0);\n date.setUTCHours(0, 0, 0, 0);\n date.setUTCFullYear(year, month - 1, day);\n return date;\n}\n\nfunction parseIsoDateTime(value: string): Date | null {\n const match = value.match(ISO_DATE_TIME_PATTERN);\n if (!match) return null;\n\n const year = Number(match[1]);\n const month = Number(match[2]);\n const day = Number(match[3]);\n const hour = Number(match[4]);\n const minute = Number(match[5]);\n const second = Number(match[6]);\n const timezone = match[7];\n if (!isValidCalendarDate(year, month, day) || hour > 23 || minute > 59 || second > 59) {\n return null;\n }\n\n if (timezone !== \"Z\") {\n const [offsetHour, offsetMinute] = timezone.slice(1).split(\":\").map(Number);\n if (offsetHour > 23 || offsetMinute > 59) return null;\n }\n\n const date = new Date(value);\n return Number.isFinite(date.getTime()) ? date : null;\n}\n\n// String parser\nexport const asString: Parser<string> = {\n parse: (value: string) => (value && value.trim()) || null,\n serialize: (value: string) => value,\n withDefault: (defaultValue: string) => ({\n parse: (value: string) => (value && value.trim()) || defaultValue,\n serialize: (value: string) => value || defaultValue,\n }),\n};\n\n// Integer parser\nexport const asInteger: Parser<number> = {\n parse: parseInteger,\n serialize: (value: number) => value.toString(),\n withDefault: (defaultValue: number) => ({\n parse: (value: string) => parseInteger(value) ?? defaultValue,\n serialize: (value: number) => value.toString(),\n }),\n};\n\n// Float parser\nexport const asFloat: Parser<number> = {\n parse: parseFloatValue,\n serialize: (value: number) => value.toString(),\n withDefault: (defaultValue: number) => ({\n parse: (value: string) => parseFloatValue(value) ?? defaultValue,\n serialize: (value: number) => value.toString(),\n }),\n};\n\n// Boolean parser\nexport const asBoolean: Parser<boolean> = {\n parse: (value: string) => {\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n return null;\n },\n serialize: (value: boolean) => value.toString(),\n withDefault: (defaultValue: boolean) => ({\n parse: (value: string) => {\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n return defaultValue;\n },\n serialize: (value: boolean) => value.toString(),\n }),\n};\n\n// Array parser\nconst STRUCTURED_ARRAY_PREFIX = \"~farm-array:v1:\";\nexport interface ArrayParserOptions {\n /** Preserve comma URLs by default; opt in when item delimiters must round-trip. */\n format?: \"comma\" | \"structured\";\n}\n\nfunction parseArrayItems(value: string, structured: boolean): string[] {\n if (structured && value.startsWith(STRUCTURED_ARRAY_PREFIX)) {\n try {\n const parsed = JSON.parse(value.slice(STRUCTURED_ARRAY_PREFIX.length));\n if (Array.isArray(parsed) && parsed.every((item) => typeof item === \"string\")) {\n return parsed;\n }\n } catch {\n // Keep accepting legacy values that happen to begin with the prefix.\n }\n }\n\n return value\n .split(\",\")\n .filter(Boolean)\n .map((item) => item.trim());\n}\n\nfunction serializeArrayItems(values: string[], structured: boolean): string {\n if (!structured) return values.join(\",\");\n\n const needsStructuredEncoding = values.some(\n (value, index) =>\n value === \"\" ||\n value.trim() !== value ||\n value.includes(\",\") ||\n (index === 0 && value.startsWith(STRUCTURED_ARRAY_PREFIX)),\n );\n return needsStructuredEncoding\n ? `${STRUCTURED_ARRAY_PREFIX}${JSON.stringify(values)}`\n : values.join(\",\");\n}\n\nexport function asArrayOf<T>(itemParser: Parser<T>, options: ArrayParserOptions = {}): Parser<T[]> {\n const structured = options.format === \"structured\";\n const parse = (value: string): T[] | null => {\n if (!value) return null;\n return parseArrayItems(value, structured)\n .map((item) => itemParser.parse(item))\n .filter((item) => item !== null) as T[];\n };\n const serialize = (value: T[]) =>\n serializeArrayItems(\n value.map((item) => itemParser.serialize(item)),\n structured,\n );\n\n return {\n parse,\n serialize,\n withDefault: (defaultValue: T[]) => ({\n parse: (value: string) => parse(value) ?? defaultValue,\n serialize,\n }),\n };\n}\n\n// JSON parser\nexport function asJson<T>(): Parser<T> {\n return {\n parse: (value: string) => {\n try {\n return JSON.parse(value);\n } catch {\n return null;\n }\n },\n serialize: (value: T) => JSON.stringify(value),\n withDefault: (defaultValue: T) => ({\n parse: (value: string) => {\n try {\n return JSON.parse(value);\n } catch {\n return defaultValue;\n }\n },\n serialize: (value: T) => JSON.stringify(value),\n }),\n };\n}\n\n// ISO Date parser\nexport const asIsoDate: Parser<Date> = {\n parse: parseIsoDate,\n serialize: (value: Date) => value.toISOString().slice(0, 10),\n withDefault: (defaultValue: Date) => ({\n parse: (value: string) => parseIsoDate(value) ?? defaultValue,\n serialize: (value: Date) => value.toISOString().slice(0, 10),\n }),\n};\n\n// ISO DateTime parser\nexport const asIsoDateTime: Parser<Date> = {\n parse: parseIsoDateTime,\n serialize: (value: Date) => value.toISOString(),\n withDefault: (defaultValue: Date) => ({\n parse: (value: string) => parseIsoDateTime(value) ?? defaultValue,\n serialize: (value: Date) => value.toISOString(),\n }),\n};\n\n// Custom parser creator\nexport function createParser<T>(config: {\n parse: (value: string) => T | null;\n serialize: (value: T) => string;\n}): Parser<T> {\n return {\n parse: config.parse,\n serialize: config.serialize,\n withDefault: (defaultValue: T) => ({\n parse: (value: string) => config.parse(value) ?? defaultValue,\n serialize: config.serialize,\n }),\n };\n}\n\n// Type inference helper\nexport type inferParserType<T> = T extends Parser<infer U> ? U : never;\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/renderer/react/client.ts"],"sourcesContent":["import React from \"react\";\nimport { createRoot, hydrateRoot } from \"react-dom/client\";\n\nexport { createRoot, hydrateRoot };\nexport default React;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkB;AAClB,oBAAwC;AAGxC,IAAO,iBAAQ,aAAAA;","names":["React"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/renderer/react/server.ts","../../../src/client/isolated-boundary.ts"],"sourcesContent":["import React from \"react\";\nimport {\n renderToPipeableStream as reactRenderToPipeableStream,\n renderToString as reactRenderToString,\n} from \"react-dom/server\";\nimport { wrapFarmIsolatedClientGraph } from \"../../client/isolated-boundary\";\n\nexport class ErrorBoundary extends React.Component<\n {\n Fallback: React.ComponentType<any>;\n fallbackProps: Record<string, any>;\n children: React.ReactNode;\n },\n { hasError: boolean; error: unknown }\n> {\n constructor(props: any) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: unknown) {\n return { hasError: true, error };\n }\n\n render() {\n if (this.state.hasError) {\n const Fallback = this.props.Fallback;\n return React.createElement(Fallback, {\n ...this.props.fallbackProps,\n error: this.state.error,\n reset: () => this.setState({ hasError: false, error: null }),\n });\n }\n return this.props.children as React.ReactElement;\n }\n}\n\nexport const name = \"react\";\nexport const capabilities = {\n streaming: { node: true, web: false },\n} as const;\nexport const Fragment = React.Fragment;\nexport const Suspense = React.Suspense;\nexport const createElement = React.createElement;\nexport const isValidElement = React.isValidElement;\nexport const wrapClientGraph = (element: React.ReactNode) =>\n wrapFarmIsolatedClientGraph(React, element);\nexport const renderToString = reactRenderToString;\nexport const renderToPipeableStream = reactRenderToPipeableStream;\n\nexport default React;\n","import type React from \"react\";\nimport type { FarmIslandStrategy } from \"../island\";\n\nconst REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\");\nconst LEGACY_REACT_ELEMENT_TYPE = Symbol.for(\"react.element\");\nconst BOUNDARY_GRAPH_CONTEXT = Symbol.for(\"farm.isolated-hydration.client-graph-context\");\n\nfunction getBoundaryGraphContext(ReactRuntime: typeof React): React.Context<boolean> {\n const shared = globalThis as typeof globalThis &\n Record<symbol, WeakMap<object, React.Context<boolean>> | undefined>;\n const contexts = shared[BOUNDARY_GRAPH_CONTEXT] ?? new WeakMap();\n shared[BOUNDARY_GRAPH_CONTEXT] = contexts;\n const runtimeIdentity = ReactRuntime.createElement;\n const existing = contexts.get(runtimeIdentity);\n if (existing) return existing;\n\n const context = ReactRuntime.createContext(false);\n contexts.set(runtimeIdentity, context);\n return context;\n}\n\nfunction serializeBoundaryProps(value: unknown, seen = new Set<object>()): unknown {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return value;\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) throw new TypeError(\"non-finite numbers are not serializable\");\n return value;\n }\n if (typeof value === \"undefined\") {\n throw new TypeError(\"undefined values are not serializable\");\n }\n if (typeof value !== \"object\") {\n throw new TypeError(`${typeof value} values are not serializable`);\n }\n if (\n (value as { $$typeof?: symbol }).$$typeof === REACT_ELEMENT_TYPE ||\n (value as { $$typeof?: symbol }).$$typeof === LEGACY_REACT_ELEMENT_TYPE\n ) {\n throw new TypeError(\"React elements cannot cross an isolated hydration boundary\");\n }\n if (seen.has(value)) throw new TypeError(\"circular props are not serializable\");\n seen.add(value);\n try {\n if (Array.isArray(value)) return value.map((entry) => serializeBoundaryProps(entry, seen));\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) {\n throw new TypeError(\"class instances are not serializable\");\n }\n return Object.fromEntries(\n Object.entries(value).map(([key, entry]) => [key, serializeBoundaryProps(entry, seen)]),\n );\n } finally {\n seen.delete(value);\n }\n}\n\nfunction serializeBoundaryPayload(value: unknown): string {\n return JSON.stringify(serializeBoundaryProps(value))\n .replace(/&/g, \"\\\\u0026\")\n .replace(/</g, \"\\\\u003c\")\n .replace(/>/g, \"\\\\u003e\")\n .replace(/\\u2028/g, \"\\\\u2028\")\n .replace(/\\u2029/g, \"\\\\u2029\");\n}\n\n/** @internal Keeps client-to-client imports inside one isolated React root. */\nexport function wrapFarmIsolatedClientGraph(\n ReactRuntime: typeof React,\n element: React.ReactNode,\n): React.ReactElement {\n const Context = getBoundaryGraphContext(ReactRuntime);\n return ReactRuntime.createElement(Context.Provider, { value: true }, element);\n}\n\n/** @internal Generated by Farm's experimental isolated-hydration transform. */\nexport function createFarmIsolatedClientBoundary(\n ReactRuntime: typeof React,\n Component: React.ComponentType<any>,\n moduleReference: string,\n exportName: string,\n islandStrategy: FarmIslandStrategy,\n): React.ComponentType<any> {\n function FarmIsolatedClientBoundary(props: Record<string, unknown>) {\n const Context = getBoundaryGraphContext(ReactRuntime);\n const belongsToParentClientGraph = ReactRuntime.useContext(Context);\n const boundaryId = ReactRuntime.useId();\n\n if (belongsToParentClientGraph) {\n return ReactRuntime.createElement(Component, props);\n }\n\n let serializedProps: string;\n try {\n serializedProps = serializeBoundaryPayload(props);\n } catch (error) {\n if (typeof window === \"undefined\") {\n console.warn(\n `[Farm.js] Could not isolate ${moduleReference}#${exportName}: ${\n error instanceof Error ? error.message : String(error)\n }. The server-rendered component was preserved without client hydration.`,\n );\n }\n return ReactRuntime.createElement(Component, props);\n }\n\n return ReactRuntime.createElement(\n ReactRuntime.Fragment,\n null,\n ReactRuntime.createElement(\n \"farm-client-boundary\",\n {\n \"data-farm-client-boundary\": moduleReference,\n \"data-farm-client-id\": boundaryId,\n \"data-farm-client-export\": exportName,\n \"data-farm-island-strategy\": islandStrategy,\n style: { display: \"contents\" },\n },\n ReactRuntime.createElement(\n Context.Provider,\n { value: true },\n ReactRuntime.createElement(Component, props),\n ),\n ),\n ReactRuntime.createElement(\"script\", {\n type: \"application/json\",\n \"data-farm-client-props\": boundaryId,\n dangerouslySetInnerHTML: { __html: serializedProps },\n }),\n );\n }\n\n FarmIsolatedClientBoundary.displayName = `FarmIsolated(${\n Component.displayName || Component.name || exportName\n })`;\n return FarmIsolatedClientBoundary;\n}\n\ntype FarmIsolatedRoot = {\n render(element: React.ReactNode): void;\n unmount(): void;\n};\n\ninterface FarmIsolatedRootRecord {\n root: FarmIsolatedRoot;\n reference: string;\n exportName: string;\n props: Record<string, unknown>;\n serverHTML: string;\n restore(error: unknown): void;\n}\n\ninterface FarmIsolatedHydrationRootOptions {\n onUncaughtError?: (error: unknown) => void;\n}\n\nexport interface FarmIsolatedHydrationRuntimeOptions {\n ReactRuntime: typeof React;\n hydrateRoot(\n container: Element,\n element: React.ReactNode,\n options?: FarmIsolatedHydrationRootOptions,\n ): FarmIsolatedRoot;\n load(reference: string): Promise<Record<string, unknown>>;\n schedule(options: {\n container: Element;\n strategy: FarmIslandStrategy;\n signal?: AbortSignal;\n hydrate(): Promise<void>;\n }): Promise<unknown>;\n wrap?(element: React.ReactElement): React.ReactNode;\n report?(message: string, error?: unknown): void;\n}\n\nfunction findBoundaryPayload(container: Element, boundaryId: string): HTMLScriptElement | null {\n const sibling = container.nextElementSibling;\n if (\n sibling instanceof HTMLScriptElement &&\n sibling.type === \"application/json\" &&\n sibling.getAttribute(\"data-farm-client-props\") === boundaryId\n ) {\n return sibling;\n }\n\n for (const candidate of container.ownerDocument.querySelectorAll<HTMLScriptElement>(\n 'script[type=\"application/json\"][data-farm-client-props]',\n )) {\n if (candidate.getAttribute(\"data-farm-client-props\") === boundaryId) return candidate;\n }\n return null;\n}\n\n/** @internal Shared development and production runtime for isolated React roots. */\nexport function createFarmIsolatedHydrationRuntime(options: FarmIsolatedHydrationRuntimeOptions) {\n const roots = new Map<Element, FarmIsolatedRootRecord>();\n const pending = new Map<Element, AbortController>();\n const report =\n options.report ??\n ((message: string, error?: unknown) => console.warn(`[Farm.js] ${message}`, error));\n\n const failRoot = (\n container: Element,\n reference: string,\n exportName: string,\n serverHTML: string,\n error: unknown,\n ) => {\n report(\n `Could not hydrate isolated client boundary ${reference}#${exportName}. ` +\n \"The server-rendered HTML was restored.\",\n error,\n );\n queueMicrotask(() => {\n try {\n roots.get(container)?.root.unmount();\n } catch {\n // React may already have detached a root that failed during hydration.\n }\n roots.delete(container);\n container.removeAttribute(\"data-farm-hydrated\");\n container.removeAttribute(\"data-farm-island-hydrated\");\n container.innerHTML = serverHTML;\n });\n };\n\n class FarmIsolatedRootErrorBoundary extends options.ReactRuntime.Component<\n { children?: React.ReactNode; onError(error: unknown): void },\n { failed: boolean }\n > {\n state = { failed: false };\n\n static getDerivedStateFromError() {\n return { failed: true };\n }\n\n componentDidCatch(error: unknown) {\n this.props.onError(error);\n }\n\n render() {\n return this.state.failed ? null : this.props.children;\n }\n }\n\n const createBoundaryGraph = (\n Component: React.ComponentType<any>,\n props: Record<string, unknown>,\n restore: (error: unknown) => void,\n ) => {\n const componentElement = options.ReactRuntime.createElement(Component, props);\n const wrappedElement = options.wrap ? options.wrap(componentElement) : componentElement;\n return wrapFarmIsolatedClientGraph(\n options.ReactRuntime,\n options.ReactRuntime.createElement(\n FarmIsolatedRootErrorBoundary,\n { onError: restore },\n wrappedElement,\n ),\n );\n };\n\n async function hydrate(scope: ParentNode = document, signal?: AbortSignal): Promise<void> {\n const candidates = Array.from(\n scope.querySelectorAll<Element>(\"farm-client-boundary[data-farm-client-boundary]\"),\n );\n if (\n scope instanceof Element &&\n scope.matches(\"farm-client-boundary[data-farm-client-boundary]\")\n ) {\n candidates.unshift(scope);\n }\n const boundaries = candidates.filter((container) => {\n if (roots.has(container) || pending.has(container)) return false;\n return !container.parentElement?.closest(\"farm-client-boundary[data-farm-client-boundary]\");\n });\n\n await Promise.all(\n boundaries.map(async (container) => {\n const reference = container.getAttribute(\"data-farm-client-boundary\");\n const boundaryId = container.getAttribute(\"data-farm-client-id\");\n const exportName = container.getAttribute(\"data-farm-client-export\") || \"default\";\n const strategy =\n (container.getAttribute(\"data-farm-island-strategy\") as FarmIslandStrategy | null) ??\n \"load\";\n if (!reference || !boundaryId) {\n report(\"An isolated client boundary is missing its module reference or payload ID.\");\n return;\n }\n\n const controller = new AbortController();\n pending.set(container, controller);\n const abort = () => controller.abort();\n if (signal?.aborted) abort();\n else signal?.addEventListener(\"abort\", abort, { once: true });\n const cleanup = () => {\n signal?.removeEventListener(\"abort\", abort);\n if (pending.get(container) === controller) pending.delete(container);\n };\n\n let scheduled: Promise<unknown>;\n try {\n scheduled = options.schedule({\n container,\n strategy,\n signal: controller.signal,\n hydrate: async () => {\n if (controller.signal.aborted || !container.isConnected) return;\n const serverHTML = container.innerHTML;\n try {\n const module = await options.load(reference);\n if (controller.signal.aborted || !container.isConnected) return;\n const originals = module.__farm_client_boundary_originals__ as\n | Record<string, unknown>\n | undefined;\n const Component = originals?.[exportName];\n if (typeof Component !== \"function\" && typeof Component !== \"object\") {\n throw new Error(\"compiled original export was not found\");\n }\n const payload = findBoundaryPayload(container, boundaryId);\n if (!payload) throw new Error(`serialized props ${boundaryId} were not found`);\n const props = JSON.parse(payload.textContent || \"{}\");\n if (!props || typeof props !== \"object\" || Array.isArray(props)) {\n throw new Error(\"serialized props must be an object\");\n }\n\n let rootFailure: unknown;\n const restore = (error: unknown) => {\n if (rootFailure !== undefined) return;\n rootFailure = error;\n failRoot(container, reference, exportName, serverHTML, error);\n controller.abort();\n };\n const graphElement = createBoundaryGraph(\n Component as React.ComponentType<any>,\n props as Record<string, unknown>,\n restore,\n );\n const root = options.hydrateRoot(container, graphElement, {\n onUncaughtError: restore,\n });\n roots.set(container, {\n root,\n reference,\n exportName,\n props: props as Record<string, unknown>,\n serverHTML,\n restore,\n });\n container.setAttribute(\"data-farm-hydrated\", \"true\");\n } catch (error) {\n failRoot(container, reference, exportName, serverHTML, error);\n controller.abort();\n }\n },\n });\n } catch (error) {\n failRoot(container, reference, exportName, container.innerHTML, error);\n controller.abort();\n cleanup();\n return;\n }\n\n const tracked = Promise.resolve(scheduled)\n .catch((error) => {\n if (!controller.signal.aborted) {\n failRoot(container, reference, exportName, container.innerHTML, error);\n controller.abort();\n }\n })\n .finally(cleanup);\n if (strategy === \"load\") await tracked;\n else void tracked;\n }),\n );\n }\n\n function updateModule(reference: string, module: Record<string, unknown>): number {\n const originals = module.__farm_client_boundary_originals__ as\n | Record<string, unknown>\n | undefined;\n let updated = 0;\n\n for (const [container, record] of roots) {\n if (record.reference !== reference) continue;\n const Component = originals?.[record.exportName];\n if (typeof Component !== \"function\" && typeof Component !== \"object\") {\n failRoot(\n container,\n record.reference,\n record.exportName,\n record.serverHTML,\n new Error(\"updated compiled original export was not found\"),\n );\n continue;\n }\n\n try {\n record.root.render(\n createBoundaryGraph(Component as React.ComponentType<any>, record.props, record.restore),\n );\n updated++;\n } catch (error) {\n failRoot(container, record.reference, record.exportName, record.serverHTML, error);\n }\n }\n\n return updated;\n }\n\n function dispose(scope: Node): void {\n for (const [container, controller] of pending) {\n if (container === scope || scope.contains(container)) {\n controller.abort();\n pending.delete(container);\n }\n }\n for (const [container, record] of roots) {\n if (container === scope || scope.contains(container)) {\n try {\n record.root.unmount();\n } catch {\n // The DOM owner may already have removed a failed root.\n }\n roots.delete(container);\n container.removeAttribute(\"data-farm-hydrated\");\n container.removeAttribute(\"data-farm-island-hydrated\");\n }\n }\n }\n\n return {\n hydrate,\n updateModule,\n dispose,\n rootCount: () => roots.size,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkB;AAClB,oBAGO;;;ACCP,IAAM,yBAAyB,uBAAO,IAAI,8CAA8C;AAExF,SAAS,wBAAwB,cAAoD;AACnF,QAAM,SAAS;AAEf,QAAM,WAAW,OAAO,sBAAsB,KAAK,oBAAI,QAAQ;AAC/D,SAAO,sBAAsB,IAAI;AACjC,QAAM,kBAAkB,aAAa;AACrC,QAAM,WAAW,SAAS,IAAI,eAAe;AAC7C,MAAI,SAAU,QAAO;AAErB,QAAM,UAAU,aAAa,cAAc,KAAK;AAChD,WAAS,IAAI,iBAAiB,OAAO;AACrC,SAAO;AACT;AAZS;AA0DF,SAAS,4BACd,cACA,SACoB;AACpB,QAAM,UAAU,wBAAwB,YAAY;AACpD,SAAO,aAAa,cAAc,QAAQ,UAAU,EAAE,OAAO,KAAK,GAAG,OAAO;AAC9E;AANgB;;;AD1DT,IAAM,iBAAN,MAAM,uBAAsB,aAAAA,QAAM,UAOvC;AAAA,EACA,YAAY,OAAY;AACtB,UAAM,KAAK;AACX,SAAK,QAAQ,EAAE,UAAU,OAAO,OAAO,KAAK;AAAA,EAC9C;AAAA,EAEA,OAAO,yBAAyB,OAAgB;AAC9C,WAAO,EAAE,UAAU,MAAM,MAAM;AAAA,EACjC;AAAA,EAEA,SAAS;AACP,QAAI,KAAK,MAAM,UAAU;AACvB,YAAM,WAAW,KAAK,MAAM;AAC5B,aAAO,aAAAA,QAAM,cAAc,UAAU;AAAA,QACnC,GAAG,KAAK,MAAM;AAAA,QACd,OAAO,KAAK,MAAM;AAAA,QAClB,OAAO,6BAAM,KAAK,SAAS,EAAE,UAAU,OAAO,OAAO,KAAK,CAAC,GAApD;AAAA,MACT,CAAC;AAAA,IACH;AACA,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;AArBE;AAPK,IAAM,gBAAN;AA8BA,IAAM,OAAO;AACb,IAAM,eAAe;AAAA,EAC1B,WAAW,EAAE,MAAM,MAAM,KAAK,MAAM;AACtC;AACO,IAAM,WAAW,aAAAA,QAAM;AACvB,IAAM,WAAW,aAAAA,QAAM;AACvB,IAAM,gBAAgB,aAAAA,QAAM;AAC5B,IAAM,iBAAiB,aAAAA,QAAM;AAC7B,IAAM,kBAAkB,wBAAC,YAC9B,4BAA4B,aAAAA,SAAO,OAAO,GADb;AAExB,IAAM,iBAAiB,cAAAC;AACvB,IAAM,yBAAyB,cAAAC;AAEtC,IAAO,iBAAQ,aAAAF;","names":["React","reactRenderToString","reactRenderToPipeableStream"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/renderer/react/vite.ts"],"sourcesContent":["/** React remains Vite's default JSX runtime, so Farm doesn't need an extra transform plugin. */\nexport function createFarmRendererPlugin(): readonly [] {\n return [];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACO,SAAS,2BAAwC;AACtD,SAAO,CAAC;AACV;AAFgB;","names":[]}
|