@farm.js/core 0.1.0-beta.80 → 0.1.0-beta.81
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/agent-runtime.d.mts +1 -1
- package/dist/agent-runtime.d.ts +1 -1
- package/dist/{app-D1fYgNSZ.d.mts → app-B9tbSdKW.d.mts} +3 -3
- package/dist/{app-DKW_R78N.d.ts → app-C7twWiJY.d.ts} +3 -3
- package/dist/app-markdown.d.mts +2 -2
- package/dist/app-markdown.d.ts +2 -2
- package/dist/{chunk-OEI62POE.mjs → chunk-6NV2RJSZ.mjs} +2 -2
- package/dist/{chunk-OEI62POE.mjs.map → chunk-6NV2RJSZ.mjs.map} +1 -1
- package/dist/{chunk-DNPQOJQW.mjs → chunk-CRK3RQ7C.mjs} +3 -3
- package/dist/{chunk-DBG42367.mjs → chunk-CVCIL6KH.mjs} +37 -14
- package/dist/chunk-CVCIL6KH.mjs.map +1 -0
- package/dist/{chunk-3UGGCJT5.mjs → chunk-HSCQGINR.mjs} +2 -2
- package/dist/{chunk-YSX4KDLV.mjs → chunk-VPEC2CWG.mjs} +42 -8
- package/dist/chunk-VPEC2CWG.mjs.map +1 -0
- package/dist/{chunk-3HIATXA4.mjs → chunk-XSUYR4Q3.mjs} +67 -25
- package/dist/chunk-XSUYR4Q3.mjs.map +1 -0
- package/dist/{chunk-3S7V7QHJ.mjs → chunk-Z73XASLT.mjs} +46 -19
- package/dist/chunk-Z73XASLT.mjs.map +1 -0
- package/dist/client/lifecycle.mjs +2 -2
- package/dist/{client-plugins-BtfLE4dW.d.mts → client-plugins-HizW0gLc.d.mts} +13 -1
- package/dist/{client-plugins-C4me5UPd.d.ts → client-plugins-w_b1wA8e.d.ts} +13 -1
- package/dist/client-plugins.cjs +1 -1
- package/dist/client-plugins.cjs.map +1 -1
- package/dist/client-plugins.d.mts +1 -1
- package/dist/client-plugins.d.ts +1 -1
- package/dist/client-plugins.mjs +2 -2
- package/dist/client.cjs +102 -37
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.mts +4 -4
- package/dist/client.d.ts +4 -4
- package/dist/client.mjs +4 -4
- package/dist/config.d.mts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/index.cjs +186 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +9 -9
- package/dist/index.d.ts +9 -9
- package/dist/index.mjs +7 -7
- package/dist/integrations.d.mts +1 -1
- package/dist/integrations.d.ts +1 -1
- package/dist/internal/build-runtime.cjs +85 -24
- package/dist/internal/build-runtime.cjs.map +1 -1
- package/dist/internal/build-runtime.d.mts +3 -3
- package/dist/internal/build-runtime.d.ts +3 -3
- package/dist/internal/build-runtime.mjs +3 -3
- package/dist/internal/client-runtime.cjs +1 -1
- package/dist/internal/client-runtime.cjs.map +1 -1
- package/dist/internal/client-runtime.mjs +2 -2
- package/dist/internal/config-runtime.d.mts +2 -2
- package/dist/internal/config-runtime.d.ts +2 -2
- package/dist/internal/product-telemetry-runtime.cjs +1 -1
- package/dist/internal/product-telemetry-runtime.cjs.map +1 -1
- package/dist/internal/product-telemetry-runtime.mjs +1 -1
- package/dist/internal/production-runtime.d.mts +5 -5
- package/dist/internal/production-runtime.d.ts +5 -5
- package/dist/{metadata-route-Bf4aVrYO.d.mts → metadata-route-CjF_sf9F.d.mts} +1 -1
- package/dist/{metadata-route-CUPYRgfT.d.ts → metadata-route-DkyJlQFD.d.ts} +1 -1
- package/dist/middleware.d.mts +3 -3
- package/dist/middleware.d.ts +3 -3
- package/dist/navigation.cjs +66 -24
- package/dist/navigation.cjs.map +1 -1
- package/dist/navigation.mjs +3 -3
- package/dist/plugin.cjs +40 -7
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.mts +1 -1
- package/dist/plugin.d.ts +1 -1
- package/dist/plugin.mjs +2 -2
- package/dist/{production-runtime-D5ECiSmc.d.mts → production-runtime-CDSs0Rwo.d.mts} +1 -1
- package/dist/{production-runtime-Cb29k5Oi.d.ts → production-runtime-CSPVu_3h.d.ts} +1 -1
- package/dist/query/client.cjs +9 -5
- package/dist/query/client.cjs.map +1 -1
- package/dist/query/client.mjs +1 -1
- package/dist/{render-plan-DZ0LA8wX.d.ts → render-plan-C62oFdVD.d.ts} +1 -1
- package/dist/{render-plan-HL0ChBbH.d.mts → render-plan-D3TuPEmY.d.mts} +1 -1
- package/dist/renderer-client.cjs +66 -24
- package/dist/renderer-client.cjs.map +1 -1
- package/dist/renderer-client.d.mts +3 -3
- package/dist/renderer-client.d.ts +3 -3
- package/dist/renderer-client.mjs +1 -1
- package/dist/{request-8__ppqcz.d.ts → request-C-ZYE89s.d.ts} +1 -1
- package/dist/{request-DAZMscB9.d.mts → request-DPMdCOtv.d.mts} +1 -1
- package/dist/request.d.mts +2 -2
- package/dist/request.d.ts +2 -2
- package/dist/routes.d.mts +1 -1
- package/dist/routes.d.ts +1 -1
- package/dist/server-plugins.d.mts +2 -2
- package/dist/server-plugins.d.ts +2 -2
- package/dist/server.cjs +40 -7
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.mts +7 -7
- package/dist/server.d.ts +7 -7
- package/dist/server.mjs +2 -2
- package/dist/{spa-router-DMKCWHT5.d.ts → spa-router-C7RwU8o-.d.ts} +6 -2
- package/dist/{spa-router-BM-OHflh.d.mts → spa-router-Cr39oWnX.d.mts} +6 -2
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/{utils-B8t0bZ5X.d.ts → utils-B6Jk-ITz.d.ts} +1 -1
- package/dist/{utils-B7dij0CU.d.mts → utils-U4zuTiDB.d.mts} +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.mjs +1 -1
- package/dist/vite.cjs +42 -7
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.mts +1 -1
- package/dist/vite.d.ts +1 -1
- package/dist/vite.mjs +4 -2
- package/package.json +1 -1
- package/dist/chunk-3HIATXA4.mjs.map +0 -1
- package/dist/chunk-3S7V7QHJ.mjs.map +0 -1
- package/dist/chunk-DBG42367.mjs.map +0 -1
- package/dist/chunk-YSX4KDLV.mjs.map +0 -1
- /package/dist/{chunk-DNPQOJQW.mjs.map → chunk-CRK3RQ7C.mjs.map} +0 -0
- /package/dist/{chunk-3UGGCJT5.mjs.map → chunk-HSCQGINR.mjs.map} +0 -0
package/dist/plugin.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { bj as APIHandlerLifecyclePayload, bf as APIRouteDiscoveredPayload, bm as BundleLifecyclePayload, a6 as BundleResultPayload, bk as ErrorLifecyclePayload, a7 as FarmPlugin, b9 as FarmPluginBuildHooks, bb as FarmPluginClientConfig, aO as FarmPluginContext, ba as FarmPluginDevHooks, b6 as FarmPluginDiscoveredRoute, aP as FarmPluginIntegrationContext, aQ as FarmPluginLifecycle, b8 as FarmPluginRenderHooks, aU as FarmPluginRouteRuntimePayload, b7 as FarmPluginRouterHooks, a_ as FarmPluginRuntimeAfterEvent, aX as FarmPluginRuntimeBaseEvent, aZ as FarmPluginRuntimeBeforeEvent, b1 as FarmPluginRuntimeCloseEvent, aY as FarmPluginRuntimeContextEvent, a$ as FarmPluginRuntimeErrorEvent, b2 as FarmPluginRuntimeHooks, aT as FarmPluginRuntimeKind, b4 as FarmPluginRuntimeRequestHandler, b3 as FarmPluginRuntimeRequestOptions, b5 as FarmPluginRuntimeSession, b0 as FarmPluginRuntimeStartEvent, aV as FarmPluginSetupContext, aW as FarmPluginStateContext, aR as FarmRequestPluginContext, aS as FarmRequestStore, an as FarmRuntimeShutdownError, bl as HMRUpdatePayload, be as MiddlewareDiscoveredPayload, bn as NitroBuildLifecyclePayload, ao as PluginManager, aN as PluginRequestContext, bi as RenderLifecyclePayload, bc as RouteDiscoveredPayload, bg as RouteMatchPayload, bh as RouteMatchResultPayload, bd as RoutesGeneratedPayload, bo as ShutdownPayload, am as definePlugin, f as farmPlugin } from './client-plugins-
|
|
1
|
+
export { bj as APIHandlerLifecyclePayload, bf as APIRouteDiscoveredPayload, bm as BundleLifecyclePayload, a6 as BundleResultPayload, bk as ErrorLifecyclePayload, a7 as FarmPlugin, b9 as FarmPluginBuildHooks, bb as FarmPluginClientConfig, aO as FarmPluginContext, ba as FarmPluginDevHooks, b6 as FarmPluginDiscoveredRoute, aP as FarmPluginIntegrationContext, aQ as FarmPluginLifecycle, b8 as FarmPluginRenderHooks, aU as FarmPluginRouteRuntimePayload, b7 as FarmPluginRouterHooks, a_ as FarmPluginRuntimeAfterEvent, aX as FarmPluginRuntimeBaseEvent, aZ as FarmPluginRuntimeBeforeEvent, b1 as FarmPluginRuntimeCloseEvent, aY as FarmPluginRuntimeContextEvent, a$ as FarmPluginRuntimeErrorEvent, b2 as FarmPluginRuntimeHooks, aT as FarmPluginRuntimeKind, b4 as FarmPluginRuntimeRequestHandler, b3 as FarmPluginRuntimeRequestOptions, b5 as FarmPluginRuntimeSession, b0 as FarmPluginRuntimeStartEvent, aV as FarmPluginSetupContext, aW as FarmPluginStateContext, aR as FarmRequestPluginContext, aS as FarmRequestStore, an as FarmRuntimeShutdownError, bl as HMRUpdatePayload, be as MiddlewareDiscoveredPayload, bn as NitroBuildLifecyclePayload, ao as PluginManager, aN as PluginRequestContext, bi as RenderLifecyclePayload, bc as RouteDiscoveredPayload, bg as RouteMatchPayload, bh as RouteMatchResultPayload, bd as RoutesGeneratedPayload, bo as ShutdownPayload, am as definePlugin, f as farmPlugin } from './client-plugins-HizW0gLc.mjs';
|
|
2
2
|
import 'vite';
|
|
3
3
|
import './lifecycle-De0vQG45.mjs';
|
|
4
4
|
import './env.mjs';
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { bj as APIHandlerLifecyclePayload, bf as APIRouteDiscoveredPayload, bm as BundleLifecyclePayload, a6 as BundleResultPayload, bk as ErrorLifecyclePayload, a7 as FarmPlugin, b9 as FarmPluginBuildHooks, bb as FarmPluginClientConfig, aO as FarmPluginContext, ba as FarmPluginDevHooks, b6 as FarmPluginDiscoveredRoute, aP as FarmPluginIntegrationContext, aQ as FarmPluginLifecycle, b8 as FarmPluginRenderHooks, aU as FarmPluginRouteRuntimePayload, b7 as FarmPluginRouterHooks, a_ as FarmPluginRuntimeAfterEvent, aX as FarmPluginRuntimeBaseEvent, aZ as FarmPluginRuntimeBeforeEvent, b1 as FarmPluginRuntimeCloseEvent, aY as FarmPluginRuntimeContextEvent, a$ as FarmPluginRuntimeErrorEvent, b2 as FarmPluginRuntimeHooks, aT as FarmPluginRuntimeKind, b4 as FarmPluginRuntimeRequestHandler, b3 as FarmPluginRuntimeRequestOptions, b5 as FarmPluginRuntimeSession, b0 as FarmPluginRuntimeStartEvent, aV as FarmPluginSetupContext, aW as FarmPluginStateContext, aR as FarmRequestPluginContext, aS as FarmRequestStore, an as FarmRuntimeShutdownError, bl as HMRUpdatePayload, be as MiddlewareDiscoveredPayload, bn as NitroBuildLifecyclePayload, ao as PluginManager, aN as PluginRequestContext, bi as RenderLifecyclePayload, bc as RouteDiscoveredPayload, bg as RouteMatchPayload, bh as RouteMatchResultPayload, bd as RoutesGeneratedPayload, bo as ShutdownPayload, am as definePlugin, f as farmPlugin } from './client-plugins-
|
|
1
|
+
export { bj as APIHandlerLifecyclePayload, bf as APIRouteDiscoveredPayload, bm as BundleLifecyclePayload, a6 as BundleResultPayload, bk as ErrorLifecyclePayload, a7 as FarmPlugin, b9 as FarmPluginBuildHooks, bb as FarmPluginClientConfig, aO as FarmPluginContext, ba as FarmPluginDevHooks, b6 as FarmPluginDiscoveredRoute, aP as FarmPluginIntegrationContext, aQ as FarmPluginLifecycle, b8 as FarmPluginRenderHooks, aU as FarmPluginRouteRuntimePayload, b7 as FarmPluginRouterHooks, a_ as FarmPluginRuntimeAfterEvent, aX as FarmPluginRuntimeBaseEvent, aZ as FarmPluginRuntimeBeforeEvent, b1 as FarmPluginRuntimeCloseEvent, aY as FarmPluginRuntimeContextEvent, a$ as FarmPluginRuntimeErrorEvent, b2 as FarmPluginRuntimeHooks, aT as FarmPluginRuntimeKind, b4 as FarmPluginRuntimeRequestHandler, b3 as FarmPluginRuntimeRequestOptions, b5 as FarmPluginRuntimeSession, b0 as FarmPluginRuntimeStartEvent, aV as FarmPluginSetupContext, aW as FarmPluginStateContext, aR as FarmRequestPluginContext, aS as FarmRequestStore, an as FarmRuntimeShutdownError, bl as HMRUpdatePayload, be as MiddlewareDiscoveredPayload, bn as NitroBuildLifecyclePayload, ao as PluginManager, aN as PluginRequestContext, bi as RenderLifecyclePayload, bc as RouteDiscoveredPayload, bg as RouteMatchPayload, bh as RouteMatchResultPayload, bd as RoutesGeneratedPayload, bo as ShutdownPayload, am as definePlugin, f as farmPlugin } from './client-plugins-w_b1wA8e.js';
|
|
2
2
|
import 'vite';
|
|
3
3
|
import './lifecycle-De0vQG45.js';
|
|
4
4
|
import './env.js';
|
package/dist/plugin.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
import "./chunk-RQ633A5I.mjs";
|
|
7
7
|
import {
|
|
8
8
|
farmPlugin
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-VPEC2CWG.mjs";
|
|
10
10
|
import "./chunk-IMVMQFV3.mjs";
|
|
11
11
|
import "./chunk-C6JEXU6F.mjs";
|
|
12
12
|
import "./chunk-AMZZCRQ7.mjs";
|
|
@@ -67,7 +67,7 @@ import "./chunk-RBRLLZL5.mjs";
|
|
|
67
67
|
import "./chunk-WZ5QFROO.mjs";
|
|
68
68
|
import "./chunk-ZRBCBOEX.mjs";
|
|
69
69
|
import "./chunk-FXG2PS27.mjs";
|
|
70
|
-
import "./chunk-
|
|
70
|
+
import "./chunk-6NV2RJSZ.mjs";
|
|
71
71
|
import "./chunk-I3FMD5VJ.mjs";
|
|
72
72
|
import "./chunk-OMQWEX4N.mjs";
|
|
73
73
|
import "./chunk-44ZCFSKE.mjs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a9 as ReadonlyMiddlewareStore, aa as FarmMiddlewareConfig, ab as MiddlewareModule } from './client-plugins-
|
|
1
|
+
import { a9 as ReadonlyMiddlewareStore, aa as FarmMiddlewareConfig, ab as MiddlewareModule } from './client-plugins-HizW0gLc.mjs';
|
|
2
2
|
import { R as ResolvedFarmI18nConfig } from './types-mP6R6CzS.mjs';
|
|
3
3
|
import { R as ResolvedFarmServerConfig } from './workflows-CkDu_SeN.mjs';
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a9 as ReadonlyMiddlewareStore, aa as FarmMiddlewareConfig, ab as MiddlewareModule } from './client-plugins-
|
|
1
|
+
import { a9 as ReadonlyMiddlewareStore, aa as FarmMiddlewareConfig, ab as MiddlewareModule } from './client-plugins-w_b1wA8e.js';
|
|
2
2
|
import { R as ResolvedFarmI18nConfig } from './types-mP6R6CzS.js';
|
|
3
3
|
import { R as ResolvedFarmServerConfig } from './workflows-CkDu_SeN.js';
|
|
4
4
|
|
package/dist/query/client.cjs
CHANGED
|
@@ -109,6 +109,14 @@ __name(getInstalledFarmSPARouter, "getInstalledFarmSPARouter");
|
|
|
109
109
|
|
|
110
110
|
// src/client/history-sync.ts
|
|
111
111
|
var FARM_HISTORY_CHANGE_EVENT = "farm:historychange";
|
|
112
|
+
function dispatchHistoryChange(kind) {
|
|
113
|
+
window.dispatchEvent(
|
|
114
|
+
new CustomEvent(FARM_HISTORY_CHANGE_EVENT, {
|
|
115
|
+
detail: { kind }
|
|
116
|
+
})
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
__name(dispatchHistoryChange, "dispatchHistoryChange");
|
|
112
120
|
function notifyHistoryChange(kind) {
|
|
113
121
|
if (typeof window === "undefined") return;
|
|
114
122
|
setTimeout(() => {
|
|
@@ -116,11 +124,7 @@ function notifyHistoryChange(kind) {
|
|
|
116
124
|
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
117
125
|
return;
|
|
118
126
|
}
|
|
119
|
-
|
|
120
|
-
new CustomEvent(FARM_HISTORY_CHANGE_EVENT, {
|
|
121
|
-
detail: { kind }
|
|
122
|
-
})
|
|
123
|
-
);
|
|
127
|
+
dispatchHistoryChange(kind);
|
|
124
128
|
}, 0);
|
|
125
129
|
}
|
|
126
130
|
__name(notifyHistoryChange, "notifyHistoryChange");
|
|
@@ -1 +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 { notifyHistoryChange, subscribeHistoryChange } from \"../client/history-sync\";\nimport { _resolveCurrentRequest } from \"../server/request-bridge\";\nimport { emitter } 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 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\") return new URLSearchParams(window.location.search);\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 throttleTimers = new Map<string, ReturnType<typeof setTimeout>>();\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 // Preserve Farm's history state (page state, interception markers) and\n // keep its recorded path in sync with the new query string so pops\n // report the entry's real location.\n const historyState = window.history.state;\n const nextHistoryState =\n historyState && typeof historyState === \"object\" && \"path\" in historyState\n ? { ...historyState, path: newUrl }\n : historyState;\n\n if (history === \"replaceState\") {\n window.history.replaceState(nextHistoryState, \"\", newUrl);\n } else {\n window.history.pushState(nextHistoryState, \"\", newUrl);\n }\n\n if (emitUpdate) {\n const actualSearchParams = new URLSearchParams(window.location.search);\n emitter.emitUpdate(actualSearchParams);\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) => {\n if (typeof window === \"undefined\") return;\n\n const { throttleMs } = options;\n if (!throttleMs || throttleMs <= 0) {\n commitURLUpdate(updates, options, emitUpdate);\n return;\n }\n\n const throttleKey = Object.keys(updates).sort().join(\",\");\n const existingTimeout = throttleTimers.get(throttleKey);\n if (existingTimeout) {\n clearTimeout(existingTimeout);\n throttleTimers.delete(throttleKey);\n }\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 if (throttleTimers.get(throttleKey) === timeout) {\n throttleTimers.delete(throttleKey);\n }\n commitURLUpdate(updates, options, emitUpdate);\n }, throttleMs);\n\n throttleTimers.set(throttleKey, timeout);\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 value = searchParams.get(key);\n const parsed = parser.parse(value ?? \"\");\n return parsed;\n });\n\n const stateRef = useRef(state);\n const stateKeyRef = useRef(key);\n const isInternalUpdateRef = useRef(false);\n stateRef.current = state;\n\n const setValue = useCallback(\n (value: T | null) => {\n isInternalUpdateRef.current = true;\n\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 });\n\n updateURL({ [key]: serialized }, options, true);\n\n setTimeout(() => {\n isInternalUpdateRef.current = false;\n }, 10);\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 value = searchParams.get(key);\n const parsed = parser.parse(value ?? \"\");\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 if (isInternalUpdateRef.current) {\n return;\n }\n\n const value = searchParams.get(key);\n const parsed = parser.parse(value ?? \"\");\n if (!areParsedValuesEqual(parser, stateRef.current, parsed)) {\n setState(parsed);\n stateRef.current = parsed;\n }\n };\n\n const onKeyUpdate = (payload: { state: any; query: string | null }) => {\n if (isInternalUpdateRef.current) {\n return;\n }\n\n if (!areParsedValuesEqual(parser, stateRef.current, payload.state)) {\n setState(payload.state);\n stateRef.current = payload.state;\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 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 const value = searchParams.get(key);\n result[key as keyof T] = parser.parse(value ?? \"\");\n });\n\n return result;\n });\n\n const stateRef = useRef(state);\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 });\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 updateURL(urlUpdates, options, true);\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 value = searchParams.get(key);\n const parsed = parser.parse(value ?? \"\");\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\n return () => {\n unsubscribeHistory();\n emitter.off(\"update\", onEmitterUpdate);\n };\n }, [watchKeys, parsers]);\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 } 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 blockers: Set<FarmNavigationBlocker> = new Set();\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.blockers.size > 0) {\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 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 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\n const observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting) {\n // Delay prefetch slightly to avoid prefetching during scroll\n setTimeout(() => {\n this.prefetch(href);\n }, this.options.prefetchTimeout);\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 }\n\n addBlocker(blocker: FarmNavigationBlocker): () => void {\n this.blockers.add(blocker);\n return () => {\n this.blockers.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 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 historyPath = options.pageData.canonicalPath || options.fullPath;\n const historyState = createHistoryState(\n historyPath,\n options.state,\n 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\n if (options.pageData.metadata?.title) {\n document.title = options.pageData.metadata.title;\n }\n\n if (options.pageData.metadata?.description) {\n let metaDesc = document.querySelector('meta[name=\"description\"]');\n if (!metaDesc) {\n metaDesc = document.createElement(\"meta\");\n metaDesc.setAttribute(\"name\", \"description\");\n document.head.appendChild(metaDesc);\n }\n metaDesc.setAttribute(\"content\", options.pageData.metadata.description);\n }\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 // Update document title\n if (pageData.metadata?.title) {\n document.title = pageData.metadata.title;\n }\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 // Restore scroll position\n 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 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(action: \"push\" | \"replace\", state: unknown, href?: string): void {\n if (typeof window === \"undefined\") return;\n\n const url = href ? new URL(href, window.location.origin).toString() : window.location.href;\n const nextPath = new URL(url).pathname + new URL(url).search;\n const nextState = createHistoryState(nextPath, 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 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 } 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/**\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 window.dispatchEvent(\n new CustomEvent<FarmHistoryChangeDetail>(FARM_HISTORY_CHANGE_EVENT, {\n detail: { kind },\n }),\n );\n }, 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;\ntype KeyListener = (payload: { state: any; query: string | null }) => 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: { state: any; query: string | null }): 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\nexport function asArrayOf<T>(itemParser: Parser<T>): Parser<T[]> {\n return {\n parse: (value: string) => {\n if (!value) return null;\n return value\n .split(\",\")\n .filter(Boolean)\n .map((item) => itemParser.parse(item.trim()))\n .filter((item) => item !== null) as T[];\n },\n serialize: (value: T[]) => value.map((item) => itemParser.serialize(item)).join(\",\"),\n withDefault: (defaultValue: T[]) => ({\n parse: (value: string) => {\n if (!value) return defaultValue;\n return value\n .split(\",\")\n .filter(Boolean)\n .map((item) => itemParser.parse(item.trim()))\n .filter((item) => item !== null) as T[];\n },\n serialize: (value: T[]) => value.map((item) => itemParser.serialize(item)).join(\",\"),\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"]}
|
|
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 { notifyHistoryChange, subscribeHistoryChange } from \"../client/history-sync\";\nimport { _resolveCurrentRequest } from \"../server/request-bridge\";\nimport { emitter } 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 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\") return new URLSearchParams(window.location.search);\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 throttleTimers = new Map<string, ReturnType<typeof setTimeout>>();\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 // Preserve Farm's history state (page state, interception markers) and\n // keep its recorded path in sync with the new query string so pops\n // report the entry's real location.\n const historyState = window.history.state;\n const nextHistoryState =\n historyState && typeof historyState === \"object\" && \"path\" in historyState\n ? { ...historyState, path: newUrl }\n : historyState;\n\n if (history === \"replaceState\") {\n window.history.replaceState(nextHistoryState, \"\", newUrl);\n } else {\n window.history.pushState(nextHistoryState, \"\", newUrl);\n }\n\n if (emitUpdate) {\n const actualSearchParams = new URLSearchParams(window.location.search);\n emitter.emitUpdate(actualSearchParams);\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) => {\n if (typeof window === \"undefined\") return;\n\n const { throttleMs } = options;\n if (!throttleMs || throttleMs <= 0) {\n commitURLUpdate(updates, options, emitUpdate);\n return;\n }\n\n const throttleKey = Object.keys(updates).sort().join(\",\");\n const existingTimeout = throttleTimers.get(throttleKey);\n if (existingTimeout) {\n clearTimeout(existingTimeout);\n throttleTimers.delete(throttleKey);\n }\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 if (throttleTimers.get(throttleKey) === timeout) {\n throttleTimers.delete(throttleKey);\n }\n commitURLUpdate(updates, options, emitUpdate);\n }, throttleMs);\n\n throttleTimers.set(throttleKey, timeout);\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 value = searchParams.get(key);\n const parsed = parser.parse(value ?? \"\");\n return parsed;\n });\n\n const stateRef = useRef(state);\n const stateKeyRef = useRef(key);\n const isInternalUpdateRef = useRef(false);\n stateRef.current = state;\n\n const setValue = useCallback(\n (value: T | null) => {\n isInternalUpdateRef.current = true;\n\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 });\n\n updateURL({ [key]: serialized }, options, true);\n\n setTimeout(() => {\n isInternalUpdateRef.current = false;\n }, 10);\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 value = searchParams.get(key);\n const parsed = parser.parse(value ?? \"\");\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 if (isInternalUpdateRef.current) {\n return;\n }\n\n const value = searchParams.get(key);\n const parsed = parser.parse(value ?? \"\");\n if (!areParsedValuesEqual(parser, stateRef.current, parsed)) {\n setState(parsed);\n stateRef.current = parsed;\n }\n };\n\n const onKeyUpdate = (payload: { state: any; query: string | null }) => {\n if (isInternalUpdateRef.current) {\n return;\n }\n\n if (!areParsedValuesEqual(parser, stateRef.current, payload.state)) {\n setState(payload.state);\n stateRef.current = payload.state;\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 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 const value = searchParams.get(key);\n result[key as keyof T] = parser.parse(value ?? \"\");\n });\n\n return result;\n });\n\n const stateRef = useRef(state);\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 });\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 updateURL(urlUpdates, options, true);\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 value = searchParams.get(key);\n const parsed = parser.parse(value ?? \"\");\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\n return () => {\n unsubscribeHistory();\n emitter.off(\"update\", onEmitterUpdate);\n };\n }, [watchKeys, parsers]);\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 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 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\n const observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting) {\n // Delay prefetch slightly to avoid prefetching during scroll\n setTimeout(() => {\n this.prefetch(href);\n }, this.options.prefetchTimeout);\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 }\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 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 // Restore scroll position\n 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(action: \"push\" | \"replace\", state: unknown, href?: string): void {\n if (typeof window === \"undefined\") return;\n\n const url = href ? new URL(href, window.location.origin).toString() : window.location.href;\n const nextPath = new URL(url).pathname + new URL(url).search;\n const nextState = createHistoryState(nextPath, 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 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 } 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\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;\ntype KeyListener = (payload: { state: any; query: string | null }) => 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: { state: any; query: string | null }): 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\nexport function asArrayOf<T>(itemParser: Parser<T>): Parser<T[]> {\n return {\n parse: (value: string) => {\n if (!value) return null;\n return value\n .split(\",\")\n .filter(Boolean)\n .map((item) => itemParser.parse(item.trim()))\n .filter((item) => item !== null) as T[];\n },\n serialize: (value: T[]) => value.map((item) => itemParser.serialize(item)).join(\",\"),\n withDefault: (defaultValue: T[]) => ({\n parse: (value: string) => {\n if (!value) return defaultValue;\n return value\n .split(\",\")\n .filter(Boolean)\n .map((item) => itemParser.parse(item.trim()))\n .filter((item) => item !== null) as T[];\n },\n serialize: (value: T[]) => value.map((item) => itemParser.serialize(item)).join(\",\"),\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"]}
|
package/dist/query/client.mjs
CHANGED