@farm.js/core 0.1.0-beta.97 → 0.1.0-beta.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/after.cjs.map +1 -0
- package/dist/agent-runtime.cjs +7 -3
- package/dist/agent-runtime.cjs.map +1 -0
- package/dist/agent-runtime.d.mts +2 -2
- package/dist/agent-runtime.d.ts +2 -2
- package/dist/agent-runtime.mjs +2 -1
- package/dist/agent-runtime.mjs.map +1 -1
- package/dist/api/route-manager.cjs.map +1 -0
- package/dist/api/route-manager.d.mts +2 -2
- package/dist/api/route-manager.d.ts +2 -2
- package/dist/api/runtime.cjs.map +1 -0
- package/dist/api.cjs +26 -1
- package/dist/api.cjs.map +1 -0
- package/dist/api.d.mts +3 -3
- package/dist/api.d.ts +3 -3
- package/dist/api.mjs +2 -2
- package/dist/{app-CIOx3LvY.d.ts → app-CGjrKNoN.d.ts} +4 -4
- package/dist/{app-DBd6437H.d.mts → app-DOcLs_iq.d.mts} +4 -4
- package/dist/app-markdown.cjs +21 -0
- package/dist/app-markdown.cjs.map +1 -0
- package/dist/app-markdown.d.mts +19 -4
- package/dist/app-markdown.d.ts +19 -4
- package/dist/app-markdown.mjs +7 -1
- package/dist/cache.cjs.map +1 -0
- package/dist/{chunk-VMCHLH3Y.mjs → chunk-26BCDVJS.mjs} +19 -1
- package/dist/chunk-26BCDVJS.mjs.map +1 -0
- package/dist/{chunk-FP5Q67FO.mjs → chunk-2HYYZCCI.mjs} +308 -19
- package/dist/chunk-2HYYZCCI.mjs.map +1 -0
- package/dist/{chunk-WKDAA6V2.mjs → chunk-3BTAMIQE.mjs} +100 -41
- package/dist/chunk-3BTAMIQE.mjs.map +1 -0
- package/dist/{chunk-WD2EBM3I.mjs → chunk-3CQJV3NC.mjs} +2 -2
- package/dist/{chunk-I3OOUWO5.mjs → chunk-3GDRV7SG.mjs} +2 -2
- package/dist/{chunk-YIBV77KZ.mjs → chunk-4WLAVHCY.mjs} +2 -2
- package/dist/{chunk-KDP5ZSWP.mjs → chunk-7PS5NKOM.mjs} +26 -11
- package/dist/chunk-7PS5NKOM.mjs.map +1 -0
- package/dist/{chunk-X4SFHKFH.mjs → chunk-BU65A3LZ.mjs} +10 -6
- package/dist/chunk-BU65A3LZ.mjs.map +1 -0
- package/dist/{chunk-WMJGA32P.mjs → chunk-BXVOHG6B.mjs} +27 -2
- package/dist/{chunk-WMJGA32P.mjs.map → chunk-BXVOHG6B.mjs.map} +1 -1
- package/dist/{chunk-BZAIS65C.mjs → chunk-DIHNOVZZ.mjs} +40 -13
- package/dist/chunk-DIHNOVZZ.mjs.map +1 -0
- package/dist/{chunk-ISSFLGJ5.mjs → chunk-FDWECN3W.mjs} +8 -4
- package/dist/chunk-FDWECN3W.mjs.map +1 -0
- package/dist/chunk-FDWXXTWR.mjs +114 -0
- package/dist/chunk-FDWXXTWR.mjs.map +1 -0
- package/dist/{chunk-FSIXEIOB.mjs → chunk-L7FSTPGS.mjs} +2 -2
- package/dist/{chunk-J3MPQ4MQ.mjs → chunk-LG4XB6RN.mjs} +2 -2
- package/dist/{chunk-J3MPQ4MQ.mjs.map → chunk-LG4XB6RN.mjs.map} +1 -1
- package/dist/{chunk-AAC66ILR.mjs → chunk-LXXG3K2Y.mjs} +61 -2
- package/dist/chunk-LXXG3K2Y.mjs.map +1 -0
- package/dist/{chunk-GJ7W6LNK.mjs → chunk-N5RK4LK6.mjs} +3 -3
- package/dist/{chunk-D7F7YZ7L.mjs → chunk-NCVFPT67.mjs} +100 -40
- package/dist/{chunk-D7F7YZ7L.mjs.map → chunk-NCVFPT67.mjs.map} +1 -1
- package/dist/{chunk-UMUWR5XA.mjs → chunk-PURU7FXR.mjs} +2 -2
- package/dist/{chunk-2SKCXYLB.mjs → chunk-QQCCBMTH.mjs} +60 -6
- package/dist/chunk-QQCCBMTH.mjs.map +1 -0
- package/dist/chunk-RKUPOYQV.mjs +28 -0
- package/dist/chunk-RKUPOYQV.mjs.map +1 -0
- package/dist/{chunk-52BR7LTX.mjs → chunk-STSPSJUI.mjs} +3 -3
- package/dist/{chunk-EPDIF432.mjs → chunk-UOGX6UNO.mjs} +37 -17
- package/dist/chunk-UOGX6UNO.mjs.map +1 -0
- package/dist/{chunk-IZBX2TEU.mjs → chunk-VQG3QWWK.mjs} +2 -2
- package/dist/{chunk-35NPLKQJ.mjs → chunk-XWM2C267.mjs} +21 -105
- package/dist/chunk-XWM2C267.mjs.map +1 -0
- package/dist/{chunk-7ZVN3YZI.mjs → chunk-Z5ARESQG.mjs} +43 -1
- package/dist/chunk-Z5ARESQG.mjs.map +1 -0
- package/dist/client/lifecycle.cjs.map +1 -0
- package/dist/client/lifecycle.mjs +2 -2
- package/dist/{client-plugins-B6-07YmP.d.mts → client-plugins-BqtHoJ9C.d.mts} +91 -3
- package/dist/{client-plugins-By6MVUX-.d.ts → client-plugins-DYprkCKN.d.ts} +91 -3
- package/dist/client-plugins.cjs +1 -1
- package/dist/client-plugins.cjs.map +1 -0
- package/dist/client-plugins.d.mts +2 -2
- package/dist/client-plugins.d.ts +2 -2
- package/dist/client-plugins.mjs +2 -2
- package/dist/client.cjs +61 -16
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.mts +5 -5
- package/dist/client.d.ts +5 -5
- package/dist/client.mjs +7 -7
- package/dist/config.cjs.map +1 -0
- package/dist/config.d.mts +2 -2
- package/dist/config.d.ts +2 -2
- package/dist/cron.cjs +48 -12
- package/dist/cron.cjs.map +1 -0
- package/dist/cron.mjs +2 -1
- package/dist/deferred.cjs.map +1 -0
- package/dist/deployment.cjs.map +1 -0
- package/dist/{devtools-XWZX6CCL.mjs → devtools-24N3U5IG.mjs} +9 -7
- package/dist/{devtools-XWZX6CCL.mjs.map → devtools-24N3U5IG.mjs.map} +1 -1
- package/dist/docs.cjs +7 -3
- package/dist/docs.cjs.map +1 -0
- package/dist/docs.mjs +9 -7
- package/dist/env-types.cjs.map +1 -0
- package/dist/env.cjs.map +1 -0
- package/dist/environment/vite.cjs.map +1 -0
- package/dist/environment.cjs.map +1 -0
- package/dist/font.cjs.map +1 -0
- package/dist/headers.cjs.map +1 -0
- package/dist/i18n/client.cjs.map +1 -0
- package/dist/i18n/index.cjs.map +1 -0
- package/dist/i18n/server.cjs.map +1 -0
- package/dist/image/server.cjs +99 -40
- package/dist/image/server.cjs.map +1 -0
- package/dist/image/server.d.mts +6 -0
- package/dist/image/server.d.ts +6 -0
- package/dist/image/server.mjs +1 -1
- package/dist/image/sharp.cjs +1 -0
- package/dist/image/sharp.cjs.map +1 -0
- package/dist/image/sharp.d.mts +1 -1
- package/dist/image/sharp.d.ts +1 -1
- package/dist/image/sharp.mjs +1 -1
- package/dist/image/sharp.mjs.map +1 -1
- package/dist/image.cjs.map +1 -0
- package/dist/index.cjs +943 -231
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.mts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.mjs +38 -24
- package/dist/index.mjs.map +1 -1
- package/dist/instrumentation.cjs.map +1 -0
- package/dist/{integration-orm-LLW6WZNK.mjs → integration-orm-G5BPBT5X.mjs} +3 -3
- package/dist/integrations.cjs +168 -5
- package/dist/integrations.cjs.map +1 -0
- package/dist/integrations.d.mts +2 -2
- package/dist/integrations.d.ts +2 -2
- package/dist/integrations.mjs +10 -3
- package/dist/internal/build-runtime.cjs +745 -139
- package/dist/internal/build-runtime.cjs.map +1 -0
- package/dist/internal/build-runtime.d.mts +4 -4
- package/dist/internal/build-runtime.d.ts +4 -4
- package/dist/internal/build-runtime.mjs +16 -14
- package/dist/internal/client-runtime.cjs +7 -2
- package/dist/internal/client-runtime.cjs.map +1 -0
- package/dist/internal/client-runtime.mjs +8 -3
- package/dist/internal/client-runtime.mjs.map +1 -1
- package/dist/internal/config-runtime.cjs +59 -42
- package/dist/internal/config-runtime.cjs.map +1 -0
- package/dist/internal/config-runtime.d.mts +3 -3
- package/dist/internal/config-runtime.d.ts +3 -3
- package/dist/internal/config-runtime.mjs +8 -6
- package/dist/internal/isolated-boundary.cjs.map +1 -0
- package/dist/internal/metadata-image-runtime.cjs.map +1 -0
- package/dist/internal/product-telemetry-runtime.cjs +52 -5
- package/dist/internal/product-telemetry-runtime.cjs.map +1 -0
- package/dist/internal/product-telemetry-runtime.d.mts +12 -1
- package/dist/internal/product-telemetry-runtime.d.ts +12 -1
- package/dist/internal/product-telemetry-runtime.mjs +50 -5
- package/dist/internal/product-telemetry-runtime.mjs.map +1 -1
- package/dist/internal/production-node-env.cjs.map +1 -0
- package/dist/internal/production-runtime.cjs +56 -10
- package/dist/internal/production-runtime.cjs.map +1 -0
- package/dist/internal/production-runtime.d.mts +8 -8
- package/dist/internal/production-runtime.d.ts +8 -8
- package/dist/internal/production-runtime.mjs +2 -2
- package/dist/markdown.cjs.map +1 -0
- package/dist/{metadata-route-8_V3UonT.d.ts → metadata-route-D2be_0kC.d.ts} +17 -2
- package/dist/{metadata-route-CWP_HjGU.d.mts → metadata-route-Dw5CrDIZ.d.mts} +17 -2
- package/dist/middleware.cjs.map +1 -0
- package/dist/middleware.d.mts +4 -4
- package/dist/middleware.d.ts +4 -4
- package/dist/navigation.cjs.map +1 -0
- package/dist/{nitro-EGRNOB5P.mjs → nitro-YJEP3FWM.mjs} +4 -3
- package/dist/{nitro-EGRNOB5P.mjs.map → nitro-YJEP3FWM.mjs.map} +1 -1
- package/dist/observability.cjs.map +1 -0
- package/dist/plugin.cjs +599 -104
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.mts +2 -2
- package/dist/plugin.d.ts +2 -2
- package/dist/plugin.mjs +13 -11
- package/dist/{production-runtime-CdmzsDax.d.ts → production-runtime-CTqpD1C8.d.ts} +2 -2
- package/dist/{production-runtime-BGRH1dKG.d.mts → production-runtime-HNqNZd4D.d.mts} +2 -2
- package/dist/query/client.cjs.map +1 -0
- package/dist/query/index.cjs.map +1 -0
- package/dist/query/parsers.cjs.map +1 -0
- package/dist/query/server.cjs.map +1 -0
- package/dist/{render-plan-DLxJYAA5.d.mts → render-plan-COscpW-i.d.mts} +1 -1
- package/dist/{render-plan-0GeHiGVZ.d.ts → render-plan-Z4kSxaT_.d.ts} +1 -1
- package/dist/renderer/react/client.cjs.map +1 -0
- package/dist/renderer/react/server.cjs.map +1 -0
- package/dist/renderer/react/vite.cjs.map +1 -0
- package/dist/renderer-client.cjs +26 -1
- package/dist/renderer-client.cjs.map +1 -0
- package/dist/renderer-client.d.mts +4 -4
- package/dist/renderer-client.d.ts +4 -4
- package/dist/renderer-client.mjs +2 -2
- package/dist/renderer.cjs.map +1 -0
- package/dist/{request-BstWbZ6O.d.ts → request-BEDb2jE9.d.ts} +1 -1
- package/dist/{request-BCNXSXLh.d.mts → request-CbIAqJY9.d.mts} +1 -1
- package/dist/request.cjs.map +1 -0
- package/dist/request.d.mts +3 -3
- package/dist/request.d.ts +3 -3
- package/dist/router.cjs.map +1 -0
- package/dist/routes.cjs.map +1 -0
- package/dist/routes.d.mts +2 -2
- package/dist/routes.d.ts +2 -2
- package/dist/server-action-security.cjs +117 -104
- package/dist/server-action-security.cjs.map +1 -0
- package/dist/server-action-security.mjs +2 -1
- package/dist/server-fn-client.cjs.map +1 -0
- package/dist/server-fn.cjs.map +1 -0
- package/dist/server-fn.mjs +3 -2
- package/dist/server-plugins.cjs.map +1 -0
- package/dist/server-plugins.d.mts +3 -3
- package/dist/server-plugins.d.ts +3 -3
- package/dist/server-query-client.cjs +26 -1
- package/dist/server-query-client.cjs.map +1 -0
- package/dist/server-query-client.mjs +3 -3
- package/dist/server-query.cjs.map +1 -0
- package/dist/server-query.mjs +4 -3
- package/dist/server.cjs +686 -170
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.mts +8 -8
- package/dist/server.d.ts +8 -8
- package/dist/server.mjs +16 -14
- package/dist/server.mjs.map +1 -1
- package/dist/{spa-router-COgu4txb.d.ts → spa-router-CjeQites.d.ts} +1 -1
- package/dist/{spa-router-BeyAVSc6.d.mts → spa-router-FJbNou1a.d.mts} +1 -1
- package/dist/storage.cjs +7 -3
- package/dist/storage.cjs.map +1 -0
- package/dist/storage.mjs +1 -1
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.mts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/testing.mjs +2 -1
- package/dist/testing.mjs.map +1 -1
- package/dist/theme/client.cjs.map +1 -0
- package/dist/theme/index.cjs.map +1 -0
- package/dist/theme/runtime.cjs.map +1 -0
- package/dist/theme/server.cjs.map +1 -0
- package/dist/{utils-DL2VwDQl.d.mts → utils-BiMJv9Ys.d.mts} +1 -1
- package/dist/{utils-DkU2c_1B.d.ts → utils-BpnKRFv9.d.ts} +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -0
- package/dist/version.mjs +1 -1
- package/dist/vite.cjs +599 -104
- package/dist/vite.cjs.map +1 -0
- package/dist/vite.d.mts +2 -2
- package/dist/vite.d.ts +2 -2
- package/dist/vite.mjs +13 -11
- package/dist/{workflows-ChyK_oTu.d.mts → workflows-BantWytQ.d.mts} +7 -0
- package/dist/{workflows-ChyK_oTu.d.ts → workflows-BantWytQ.d.ts} +7 -0
- package/dist/workflows.cjs +73 -5
- package/dist/workflows.cjs.map +1 -0
- package/dist/workflows.d.mts +1 -1
- package/dist/workflows.d.ts +1 -1
- package/dist/workflows.mjs +2 -1
- package/package.json +17 -17
- package/dist/chunk-2SKCXYLB.mjs.map +0 -1
- package/dist/chunk-35NPLKQJ.mjs.map +0 -1
- package/dist/chunk-7ZVN3YZI.mjs.map +0 -1
- package/dist/chunk-AAC66ILR.mjs.map +0 -1
- package/dist/chunk-BZAIS65C.mjs.map +0 -1
- package/dist/chunk-EPDIF432.mjs.map +0 -1
- package/dist/chunk-FP5Q67FO.mjs.map +0 -1
- package/dist/chunk-ISSFLGJ5.mjs.map +0 -1
- package/dist/chunk-KDP5ZSWP.mjs.map +0 -1
- package/dist/chunk-VMCHLH3Y.mjs.map +0 -1
- package/dist/chunk-WKDAA6V2.mjs.map +0 -1
- package/dist/chunk-X4SFHKFH.mjs.map +0 -1
- /package/dist/{chunk-WD2EBM3I.mjs.map → chunk-3CQJV3NC.mjs.map} +0 -0
- /package/dist/{chunk-I3OOUWO5.mjs.map → chunk-3GDRV7SG.mjs.map} +0 -0
- /package/dist/{chunk-YIBV77KZ.mjs.map → chunk-4WLAVHCY.mjs.map} +0 -0
- /package/dist/{chunk-FSIXEIOB.mjs.map → chunk-L7FSTPGS.mjs.map} +0 -0
- /package/dist/{chunk-GJ7W6LNK.mjs.map → chunk-N5RK4LK6.mjs.map} +0 -0
- /package/dist/{chunk-UMUWR5XA.mjs.map → chunk-PURU7FXR.mjs.map} +0 -0
- /package/dist/{chunk-52BR7LTX.mjs.map → chunk-STSPSJUI.mjs.map} +0 -0
- /package/dist/{chunk-IZBX2TEU.mjs.map → chunk-VQG3QWWK.mjs.map} +0 -0
- /package/dist/{integration-orm-LLW6WZNK.mjs.map → integration-orm-G5BPBT5X.mjs.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mutation-client.ts","../src/client-network-status.ts","../src/fetcher-client.tsx","../src/cache-invalidation-broadcast.ts","../src/client-cache-persistence.ts","../src/store.ts","../src/client/link.tsx","../src/provider.tsx"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useMemo, useRef, useState } from \"react\";\nimport {\n applyServerFnOptimisticUpdates,\n isAPIRouteRef,\n resolveServerFnInvalidateTargets,\n settleServerFnOptimisticUpdates,\n type APIResult,\n type ClientOptions,\n} from \"./api/client\";\nimport { notifyFarmCacheInvalidation } from \"./cache-invalidation\";\nimport { isNavigatorOnline, subscribeOnline } from \"./client-network-status\";\nimport { notifyClientObserver } from \"./client-observers\";\nimport { invokeMutationWithRetry } from \"./mutation-retry\";\n\nexport type MutationStatus = \"idle\" | \"pending\" | \"success\" | \"error\";\n\nexport type AnyMutationTarget = (...args: any[]) => Promise<any>;\n\nexport type InferMutationVariables<TTarget extends AnyMutationTarget> =\n Parameters<TTarget> extends [] ? undefined : Parameters<TTarget>[0];\n\nexport type InferMutationData<TTarget extends AnyMutationTarget> = TTarget extends {\n readonly __farmRouteData: infer TData;\n}\n ? TData\n : Awaited<ReturnType<TTarget>>;\n\nexport type InferMutationError<TTarget extends AnyMutationTarget> = TTarget extends {\n readonly __farmServerFnError: infer TError;\n}\n ? TError\n : TTarget extends (...args: any[]) => Promise<APIResult<any, infer TError>>\n ? TError\n : Error;\n\nexport type MutationOptimisticContext<TVariables, TData> = {\n variables: TVariables | undefined;\n current: TData | null;\n};\n\nexport type MutationNetworkMode = \"always\" | \"online\";\n\nexport type UseMutationOptions<TVariables, TData, TError = Error> = {\n initialData?: TData | null;\n resetOnMutate?: boolean;\n /**\n * `\"always\"` (default) dispatches regardless of connectivity, preserving\n * existing behavior. `\"online\"` pauses a submission while the browser is\n * offline — including one whose dispatch failed while offline — and resumes\n * it on the `online` event instead of failing it.\n */\n networkMode?: MutationNetworkMode;\n optimistic?: (context: MutationOptimisticContext<TVariables, TData>) => TData | null | undefined;\n rollbackOnError?: boolean;\n /**\n * Options forwarded to generated `api.route.method` clients.\n * Server-function targets honor `request.retry`, key-targeted\n * `request.optimistic` updates, and key-targeted `request.invalidate`;\n * the remaining request options apply to API routes only.\n */\n request?: ClientOptions<TData, TError>;\n onSuccess?: (data: TData, variables: TVariables | undefined) => void;\n onError?: (error: TError, variables: TVariables | undefined) => void;\n onSettled?: (data: TData | null, error: TError | null, variables: TVariables | undefined) => void;\n};\n\ntype MutationInput<TTarget extends AnyMutationTarget> = InferMutationVariables<TTarget>;\n\ntype MutationData<TTarget extends AnyMutationTarget> = InferMutationData<TTarget>;\n\ntype MutationError<TTarget extends AnyMutationTarget> = InferMutationError<TTarget>;\n\nexport type MutationAsync<TTarget extends AnyMutationTarget, TData = MutationData<TTarget>> =\n [] extends Parameters<TTarget>\n ? (variables?: MutationInput<TTarget>) => Promise<TData>\n : (variables: MutationInput<TTarget>) => Promise<TData>;\n\nexport type MutationTrigger<TTarget extends AnyMutationTarget> =\n [] extends Parameters<TTarget>\n ? (variables?: MutationInput<TTarget>) => void\n : (variables: MutationInput<TTarget>) => void;\n\nexport type UseMutationReturn<\n TTarget extends AnyMutationTarget,\n TData = MutationData<TTarget>,\n TError = MutationError<TTarget>,\n> = {\n pending: boolean;\n /** True while a submission is waiting for the browser to come back online. */\n paused: boolean;\n status: MutationStatus;\n data: TData | null;\n error: TError | null;\n variables: MutationInput<TTarget> | undefined;\n mutate: MutationTrigger<TTarget>;\n mutateAsync: MutationAsync<TTarget, TData>;\n reset: () => void;\n};\n\ntype MutationState<TVariables, TData, TError> = {\n pendingCount: number;\n pausedCount: number;\n status: MutationStatus;\n data: TData | null;\n error: TError | null;\n variables: TVariables | undefined;\n};\n\n/**\n * Track a generated API route mutation or a Farm server function with one\n * React lifecycle.\n *\n * API routes keep using their existing fetch transport and request options.\n * Server functions keep using their configured server-function transport.\n */\nexport function useMutation<TTarget extends AnyMutationTarget>(\n target: TTarget,\n options: UseMutationOptions<\n MutationInput<TTarget>,\n MutationData<TTarget>,\n MutationError<TTarget>\n > = {},\n): UseMutationReturn<TTarget> {\n return useMutationLifecycle(target, options).mutation;\n}\n\n/** Internal shared lifecycle: fetchers prepare form input before dispatch. */\nexport function useMutationLifecycle<\n TTarget extends AnyMutationTarget,\n TError = MutationError<TTarget>,\n>(\n target: TTarget,\n options: Omit<\n UseMutationOptions<MutationInput<TTarget>, MutationData<TTarget>, TError>,\n \"request\"\n > & {\n request?: ClientOptions<MutationData<TTarget>, MutationError<TTarget>>;\n } = {},\n) {\n type TVariables = MutationInput<TTarget>;\n type TData = MutationData<TTarget>;\n\n const initialData = options.initialData ?? null;\n const optionsRef = useRef(options);\n const targetRef = useRef(target);\n const requestIdRef = useRef(0);\n const lastResetIdRef = useRef(0);\n const initialState: MutationState<TVariables, TData, TError> = {\n pendingCount: 0,\n pausedCount: 0,\n status: \"idle\",\n data: initialData,\n error: null,\n variables: undefined,\n };\n const stateRef = useRef(initialState);\n const resetWakersRef = useRef(new Set<() => void>());\n const [state, setState] = useState<MutationState<TVariables, TData, TError>>(initialState);\n\n optionsRef.current = options;\n targetRef.current = target;\n\n const setMutationState = useCallback(\n (\n value:\n | MutationState<TVariables, TData, TError>\n | ((\n current: MutationState<TVariables, TData, TError>,\n ) => MutationState<TVariables, TData, TError>),\n ) => {\n // Advance the authoritative snapshot before React processes its queue.\n // A second submission in this batch must see the preceding transition.\n const next = typeof value === \"function\" ? value(stateRef.current) : value;\n stateRef.current = next;\n setState(next);\n },\n [],\n );\n\n const waitForReconnect = useCallback(\n async (requestId: number) => {\n while (!isNavigatorOnline()) {\n if (requestId < lastResetIdRef.current) return;\n setMutationState((current) => ({ ...current, pausedCount: current.pausedCount + 1 }));\n try {\n await new Promise<void>((resolve) => {\n const wake = () => {\n unsubscribe();\n resetWakersRef.current.delete(wake);\n resolve();\n };\n const unsubscribe = subscribeOnline(wake);\n resetWakersRef.current.add(wake);\n });\n } finally {\n setMutationState((current) => ({\n ...current,\n pausedCount: Math.max(0, current.pausedCount - 1),\n }));\n }\n }\n },\n [setMutationState],\n );\n\n const mutatePreparedAsync = useCallback(\n async (prepare: () => TVariables | undefined) => {\n const requestId = ++requestIdRef.current;\n const currentOptions = optionsRef.current;\n const previousData = stateRef.current.data;\n let variables: TVariables | undefined;\n let preparationFailed = false;\n let preparationError: unknown;\n try {\n variables = prepare();\n } catch (error) {\n preparationFailed = true;\n preparationError = error;\n }\n const optimisticData = preparationFailed\n ? undefined\n : currentOptions.optimistic?.({ variables, current: previousData });\n const hasOptimisticData = optimisticData !== undefined;\n\n setMutationState((current) => {\n // Preparation is app code and may reset or submit again synchronously.\n if (requestId < lastResetIdRef.current) return current;\n const pendingCount = current.pendingCount + 1;\n if (requestId !== requestIdRef.current) return { ...current, pendingCount };\n return {\n pendingCount,\n pausedCount: current.pausedCount,\n status: \"pending\",\n data: hasOptimisticData\n ? optimisticData\n : currentOptions.resetOnMutate === false\n ? current.data\n : null,\n error: null,\n variables,\n };\n });\n\n const mutationTarget = targetRef.current;\n const isAPITarget = isAPIRouteRef(mutationTarget);\n // API routes run their own cache-layered optimistic engine; server\n // functions apply key-targeted updates to the shared cache here.\n const sharedOptimistic =\n !preparationFailed && !isAPITarget ? currentOptions.request?.optimistic : undefined;\n const sharedSnapshots = sharedOptimistic?.update?.length\n ? applyServerFnOptimisticUpdates(sharedOptimistic.update)\n : [];\n\n try {\n if (preparationFailed) throw preparationError;\n let data!: TData;\n while (true) {\n if (currentOptions.networkMode === \"online\") {\n await waitForReconnect(requestId);\n if (requestId < lastResetIdRef.current) {\n throw new Error(\"Mutation reset while waiting for reconnection\");\n }\n }\n try {\n const rawResult = isAPITarget\n ? await mutationTarget(variables, currentOptions.request)\n : await invokeMutationWithRetry(\n () => targetRef.current(variables),\n currentOptions.request?.retry,\n // A reset disowns this submission; stop scheduling retries then.\n () => requestId >= lastResetIdRef.current,\n );\n data = unwrapMutationResult<TData, TError>(rawResult, isAPITarget);\n break;\n } catch (cause) {\n // A dispatch that failed while offline pauses and rides the next\n // reconnect instead of surfacing a connectivity error.\n if (\n currentOptions.networkMode === \"online\" &&\n !isNavigatorOnline() &&\n requestId >= lastResetIdRef.current\n ) {\n continue;\n }\n throw cause;\n }\n }\n\n settleServerFnOptimisticUpdates(sharedSnapshots, \"commit\");\n if (!isAPITarget && currentOptions.request?.invalidate) {\n // Server-function invalidations travel the shared bus, matching\n // server-declared `invalidates`, so every subscribed cache observes them.\n for (const key of resolveServerFnInvalidateTargets(currentOptions.request.invalidate)) {\n notifyFarmCacheInvalidation(key);\n }\n }\n\n const isLatestRequest = requestId === requestIdRef.current;\n\n setMutationState((current) => {\n if (requestId < lastResetIdRef.current) return current;\n const pendingCount = Math.max(0, current.pendingCount - 1);\n if (!isLatestRequest) {\n return {\n ...current,\n pendingCount,\n };\n }\n\n return {\n pendingCount,\n pausedCount: current.pausedCount,\n status: \"success\",\n data,\n error: null,\n variables,\n };\n });\n\n if (isLatestRequest) {\n notifyClientObserver(currentOptions.onSuccess, [data, variables], \"Mutation onSuccess\");\n if (requestId === requestIdRef.current) {\n notifyClientObserver(\n currentOptions.onSettled,\n [data, null, variables],\n \"Mutation onSettled\",\n );\n }\n }\n\n return data;\n } catch (cause) {\n settleServerFnOptimisticUpdates(\n sharedSnapshots,\n sharedOptimistic?.rollbackOnError ? \"rollback\" : \"invalidate\",\n );\n const error = normalizeMutationError(cause) as TError;\n const isLatestRequest = requestId === requestIdRef.current;\n\n setMutationState((current) => {\n if (requestId < lastResetIdRef.current) return current;\n const pendingCount = Math.max(0, current.pendingCount - 1);\n if (!isLatestRequest) {\n return {\n ...current,\n pendingCount,\n };\n }\n\n return {\n pendingCount,\n pausedCount: current.pausedCount,\n status: \"error\",\n data:\n hasOptimisticData && currentOptions.rollbackOnError\n ? previousData\n : currentOptions.resetOnMutate === false\n ? current.data\n : null,\n error,\n variables,\n };\n });\n\n if (isLatestRequest) {\n notifyClientObserver(currentOptions.onError, [error, variables], \"Mutation onError\");\n if (requestId === requestIdRef.current) {\n notifyClientObserver(\n currentOptions.onSettled,\n [null, error, variables],\n \"Mutation onSettled\",\n );\n }\n }\n\n throw error;\n }\n },\n [setMutationState, waitForReconnect],\n );\n\n const mutateAsync = useCallback(\n (variables?: TVariables) => mutatePreparedAsync(() => variables),\n [mutatePreparedAsync],\n ) as MutationAsync<TTarget, TData>;\n\n const mutate = useCallback(\n (variables?: TVariables) => {\n void mutateAsync(variables as never).catch(() => {});\n },\n [mutateAsync],\n ) as MutationTrigger<TTarget>;\n\n const reset = useCallback(() => {\n // Pre-reset requests no longer own any of the current pending count.\n lastResetIdRef.current = ++requestIdRef.current;\n setMutationState({\n pendingCount: 0,\n pausedCount: 0,\n status: \"idle\",\n data: optionsRef.current.initialData ?? null,\n error: null,\n variables: undefined,\n });\n // Wake paused submissions so they reject instead of waiting for `online`.\n const wakers = Array.from(resetWakersRef.current);\n resetWakersRef.current.clear();\n for (const wake of wakers) wake();\n }, [setMutationState]);\n\n const mutation: UseMutationReturn<TTarget, TData, TError> = useMemo(\n () => ({\n pending: state.pendingCount > 0,\n paused: state.pausedCount > 0,\n status: state.status,\n data: state.data,\n error: state.error,\n variables: state.variables,\n mutate,\n mutateAsync,\n reset,\n }),\n [\n mutate,\n mutateAsync,\n reset,\n state.data,\n state.error,\n state.pausedCount,\n state.pendingCount,\n state.status,\n state.variables,\n ],\n );\n return { mutation, mutatePreparedAsync };\n}\n\nfunction unwrapMutationResult<TData, TError>(result: unknown, apiRoute: boolean): TData {\n if (!apiRoute) return result as TData;\n\n const apiResult = result as APIResult<TData, TError>;\n if (apiResult.error) {\n throw apiResult.error;\n }\n\n return apiResult.data as TData;\n}\n\nfunction normalizeMutationError(error: unknown): Error {\n if (error instanceof Error) return error;\n\n const normalized = new Error(typeof error === \"string\" ? error : \"Mutation failed\");\n (normalized as Error & { cause?: unknown }).cause = error;\n return normalized;\n}\n","/**\n * Connectivity observation for the client data layer. Environments without a\n * navigator (server rendering, tests) report online so nothing ever pauses\n * there.\n */\nexport function isNavigatorOnline(): boolean {\n if (typeof navigator === \"undefined\" || typeof navigator.onLine !== \"boolean\") return true;\n return navigator.onLine;\n}\n\n/** Subscribe to the browser `online` event. Returns a disposer; no-op outside the browser. */\nexport function subscribeOnline(listener: () => void): () => void {\n if (typeof window === \"undefined\") return () => {};\n window.addEventListener(\"online\", listener);\n return () => window.removeEventListener(\"online\", listener);\n}\n","\"use client\";\n\nimport {\n createElement,\n useCallback,\n useMemo,\n useRef,\n useState,\n type ComponentType,\n type FormEvent,\n type FormHTMLAttributes,\n} from \"react\";\nimport { getAPIRouteRefMetadata, isAPIRouteRef } from \"./api/client\";\nimport {\n useMutationLifecycle,\n type AnyMutationTarget,\n type InferMutationData,\n type InferMutationError,\n type InferMutationVariables,\n type MutationStatus,\n type UseMutationOptions,\n} from \"./mutation-client\";\n\nexport type FetcherState = \"idle\" | \"submitting\";\n\n/** Local form conversion failed before the target was called. */\nexport class FetcherInputError extends Error {\n readonly name = \"FetcherInputError\" as const;\n readonly code = \"input_error\" as const;\n readonly status = 0 as const;\n readonly data = undefined;\n readonly cause: unknown;\n\n constructor(cause: unknown) {\n super(\n cause instanceof Error\n ? cause.message\n : typeof cause === \"string\"\n ? cause\n : \"Could not prepare form input\",\n );\n this.cause = cause;\n }\n}\n\nexport type FetcherFormDataContext = {\n form: HTMLFormElement | null;\n submitter: HTMLElement | null;\n};\n\nexport type UseFetcherOptions<TTarget extends AnyMutationTarget> = Omit<\n UseMutationOptions<\n InferMutationVariables<TTarget>,\n InferMutationData<TTarget>,\n InferMutationError<TTarget> | FetcherInputError\n >,\n \"request\"\n> & {\n request?: UseMutationOptions<\n InferMutationVariables<TTarget>,\n InferMutationData<TTarget>,\n InferMutationError<TTarget>\n >[\"request\"];\n /**\n * Convert browser FormData into the target's typed variables.\n *\n * Generated API routes preserve multipart forms and file values as a FormData\n * body; text-only submissions default to a JSON object (or query for GET/HEAD).\n * Server functions receive FormData directly. This mapper overrides defaults.\n */\n mapFormData?: (\n formData: FormData,\n context: FetcherFormDataContext,\n ) => InferMutationVariables<TTarget>;\n};\n\nexport type FetcherFormProps = Omit<FormHTMLAttributes<HTMLFormElement>, \"action\" | \"onSubmit\"> & {\n /**\n * Override the native form fallback. By default server functions remain the\n * action and generated GET/POST API routes use their real URL.\n */\n action?: string | ((formData: FormData) => void | Promise<void>);\n onSubmit?: (event: FormEvent<HTMLFormElement>) => void;\n};\n\ntype FetcherInput<TTarget extends AnyMutationTarget> = InferMutationVariables<TTarget> | FormData;\n\nexport type FetcherSubmitAsync<TTarget extends AnyMutationTarget> =\n [] extends Parameters<TTarget>\n ? (input?: FetcherInput<TTarget>) => Promise<InferMutationData<TTarget>>\n : (input: FetcherInput<TTarget>) => Promise<InferMutationData<TTarget>>;\n\nexport type FetcherSubmit<TTarget extends AnyMutationTarget> =\n [] extends Parameters<TTarget>\n ? (input?: FetcherInput<TTarget>) => void\n : (input: FetcherInput<TTarget>) => void;\n\nexport type UseFetcherReturn<TTarget extends AnyMutationTarget> = {\n state: FetcherState;\n status: MutationStatus;\n pending: boolean;\n /** True while a submission is waiting for the browser to come back online. */\n paused: boolean;\n data: InferMutationData<TTarget> | null;\n error: InferMutationError<TTarget> | FetcherInputError | null;\n variables: InferMutationVariables<TTarget> | undefined;\n formData: FormData | null;\n submit: FetcherSubmit<TTarget>;\n submitAsync: FetcherSubmitAsync<TTarget>;\n Form: ComponentType<FetcherFormProps>;\n reset: () => void;\n};\n\nconst formDataContexts = new WeakMap<FormData, FetcherFormDataContext>();\n\n/**\n * Run a typed server function or generated API operation without navigating.\n *\n * `fetcher.Form` progressively keeps a server function as the native form\n * action, while hydration intercepts submissions into this fetcher lifecycle.\n */\nexport function useFetcher<TTarget extends AnyMutationTarget>(\n target: TTarget,\n options: UseFetcherOptions<TTarget> = {},\n): UseFetcherReturn<TTarget> {\n const targetRef = useRef(target);\n const optionsRef = useRef(options);\n const submissionIdRef = useRef(0);\n const [formData, setFormData] = useState<FormData | null>(null);\n const { mutation, mutatePreparedAsync } = useMutationLifecycle<\n TTarget,\n InferMutationError<TTarget> | FetcherInputError\n >(target, options);\n\n targetRef.current = target;\n optionsRef.current = options;\n\n const submitAsync = useCallback(\n async (input?: FetcherInput<TTarget>) => {\n const submissionId = ++submissionIdRef.current;\n const submittedFormData = isFormData(input) ? input : null;\n setFormData(submittedFormData);\n\n try {\n return await mutatePreparedAsync(() => {\n try {\n return (\n submittedFormData\n ? mapFetcherFormData(targetRef.current, submittedFormData, optionsRef.current)\n : input\n ) as InferMutationVariables<TTarget>;\n } catch (error) {\n throw new FetcherInputError(error);\n }\n });\n } finally {\n if (submissionId === submissionIdRef.current) {\n setFormData(null);\n }\n }\n },\n [mutatePreparedAsync],\n ) as FetcherSubmitAsync<TTarget>;\n\n const submit = useCallback(\n (input?: FetcherInput<TTarget>) => {\n void submitAsync(input as never).catch(() => {});\n },\n [submitAsync],\n ) as FetcherSubmit<TTarget>;\n\n const Form = useMemo(() => {\n const FetcherForm = ({ action, method, encType, onSubmit, ...props }: FetcherFormProps) => {\n const targetValue = targetRef.current;\n const metadata = getAPIRouteRefMetadata(targetValue);\n const nativeAction = action ?? resolveFetcherFormAction(targetValue, metadata);\n const nativeMethod =\n method ??\n (metadata && (metadata.method === \"GET\" || metadata.method === \"POST\")\n ? metadata.method.toLowerCase()\n : metadata\n ? \"post\"\n : undefined);\n const functionAction = typeof nativeAction === \"function\";\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n onSubmit?.(event);\n if (event.defaultPrevented) return;\n\n event.preventDefault();\n const submitter = getSubmitter(event);\n const nextFormData = createSubmitterFormData(event.currentTarget, submitter);\n formDataContexts.set(nextFormData, {\n form: event.currentTarget,\n submitter,\n });\n void submitAsync(nextFormData as never).catch(() => {});\n };\n\n return createElement(\"form\", {\n ...props,\n action: nativeAction as FormHTMLAttributes<HTMLFormElement>[\"action\"],\n method: functionAction ? undefined : nativeMethod,\n encType: functionAction ? undefined : encType,\n onSubmit: handleSubmit,\n });\n };\n\n FetcherForm.displayName = \"FetcherForm\";\n return FetcherForm;\n }, [submitAsync]);\n\n const reset = useCallback(() => {\n submissionIdRef.current += 1;\n setFormData(null);\n mutation.reset();\n }, [mutation.reset]);\n\n return useMemo(\n () => ({\n state: mutation.pending ? \"submitting\" : \"idle\",\n status: mutation.status,\n pending: mutation.pending,\n paused: mutation.paused,\n data: mutation.data,\n error: mutation.error,\n variables: mutation.variables,\n formData,\n submit,\n submitAsync,\n Form,\n reset,\n }),\n [\n Form,\n formData,\n mutation.data,\n mutation.error,\n mutation.paused,\n mutation.pending,\n mutation.status,\n mutation.variables,\n reset,\n submit,\n submitAsync,\n ],\n );\n}\n\nfunction mapFetcherFormData<TTarget extends AnyMutationTarget>(\n target: TTarget,\n formData: FormData,\n options: UseFetcherOptions<TTarget>,\n): InferMutationVariables<TTarget> | FormData {\n const context = formDataContexts.get(formData) ?? { form: null, submitter: null };\n if (options.mapFormData) {\n return options.mapFormData(formData, context);\n }\n if (!isAPIRouteRef(target)) {\n return formData;\n }\n\n const method = getAPIRouteRefMetadata(target)?.method;\n const query = method === \"GET\" || method === \"HEAD\";\n const encoding = context.submitter?.getAttribute(\"formenctype\") ?? context.form?.enctype;\n if (\n !query &&\n (encoding?.toLowerCase() === \"multipart/form-data\" ||\n Array.from(formData.values()).some((value) => typeof value !== \"string\"))\n ) {\n // Keep files and duplicate fields intact without changing the caller's input\n // or bypassing the unsafe-key filtering used by the JSON mapping path.\n const body = new FormData();\n for (const [key, value] of formData) {\n if (!isUnsafeFormKey(key)) body.append(key, value);\n }\n return { body } as InferMutationVariables<TTarget>;\n }\n\n const values = formDataToObject(formData);\n return (query ? { query: values } : { body: values }) as InferMutationVariables<TTarget>;\n}\n\nfunction resolveFetcherFormAction(\n target: AnyMutationTarget,\n metadata: ReturnType<typeof getAPIRouteRefMetadata>,\n): string | AnyMutationTarget | undefined {\n if (!metadata) return isProgressiveFormAction(target) ? target : undefined;\n if (metadata.sameOrigin) return metadata.path;\n\n return new URL(metadata.path, metadata.baseURL).href;\n}\n\nfunction formDataToObject(\n formData: FormData,\n): Record<string, FormDataEntryValue | FormDataEntryValue[]> {\n const output: Record<string, FormDataEntryValue | FormDataEntryValue[]> = Object.create(null);\n for (const [key, value] of formData.entries()) {\n if (isUnsafeFormKey(key)) continue;\n const current = output[key];\n if (current === undefined) {\n output[key] = value;\n } else if (Array.isArray(current)) {\n current.push(value);\n } else {\n output[key] = [current, value];\n }\n }\n return output;\n}\n\nfunction isUnsafeFormKey(key: string): boolean {\n return key === \"__proto__\" || key === \"constructor\" || key === \"prototype\";\n}\n\nfunction createSubmitterFormData(form: HTMLFormElement, submitter: HTMLElement | null): FormData {\n try {\n return new FormData(form, submitter as HTMLElement | undefined);\n } catch {\n const formData = new FormData(form);\n const candidate = submitter as\n | (HTMLElement & { disabled?: boolean; name?: string; value?: string })\n | null;\n if (candidate && !candidate.disabled && candidate.name) {\n formData.append(candidate.name, candidate.value ?? \"\");\n }\n return formData;\n }\n}\n\nfunction getSubmitter(event: FormEvent<HTMLFormElement>): HTMLElement | null {\n const nativeEvent = event.nativeEvent as SubmitEvent;\n return nativeEvent.submitter instanceof HTMLElement ? nativeEvent.submitter : null;\n}\n\nfunction isProgressiveFormAction(target: AnyMutationTarget): boolean {\n const candidate = target as AnyMutationTarget & {\n __farmServerFn?: unknown;\n $$FORM_ACTION?: unknown;\n $$typeof?: unknown;\n };\n return (\n candidate.__farmServerFn === true ||\n typeof candidate.$$FORM_ACTION === \"function\" ||\n candidate.$$typeof === Symbol.for(\"react.server.reference\")\n );\n}\n\nfunction isFormData(value: unknown): value is FormData {\n if (!value || typeof value !== \"object\") return false;\n return (\n (typeof FormData !== \"undefined\" && value instanceof FormData) ||\n (Object.prototype.toString.call(value) === \"[object FormData]\" &&\n typeof (value as { entries?: unknown }).entries === \"function\")\n );\n}\n","import {\n decodeFarmCacheInvalidations,\n encodeFarmCacheInvalidations,\n notifyFarmCacheInvalidation,\n subscribeFarmCacheInvalidation,\n} from \"./cache-invalidation\";\n\nexport const FARM_CACHE_INVALIDATION_CHANNEL = \"farm:cache-invalidation\";\n\nexport type CrossTabCacheInvalidationOptions = {\n /** Override the BroadcastChannel name, e.g. to isolate multiple apps on one origin. */\n channelName?: string;\n};\n\ntype ActiveBridge = {\n channelName: string;\n refCount: number;\n teardown: () => void;\n};\n\n// One bridge per tab regardless of how many callers enable it: a second\n// BroadcastChannel in the same tab would receive this tab's own posts and\n// re-apply every local invalidation as if it were remote.\n//\n// The guard lives on globalThis under the same registry the invalidation bus\n// uses, so duplicate copies of this module share it. A module-local guard only\n// protects the copy that declares it, while the bus underneath is global, so a\n// second copy would build its own bridge and the two would echo one local\n// invalidation between them without end (each bridge's applyingRemote flag is\n// private to its own closure and cannot suppress the other's replay).\nconst FARM_CACHE_INVALIDATION_BRIDGE = Symbol.for(\"farm.cacheInvalidationBridge\");\nconst bridgeGlobal = globalThis as typeof globalThis & {\n [FARM_CACHE_INVALIDATION_BRIDGE]?: ActiveBridge;\n};\n\n/**\n * Bridge the cache invalidation bus across tabs of the same origin.\n *\n * Local invalidations are posted to a BroadcastChannel and applied in every\n * other tab through the normal invalidation path, so mounted stale queries\n * there refetch on their own. Only invalidation keys cross the channel, never\n * cached data, which keeps private and credentialed cache scoping untouched.\n *\n * Opt-in and idempotent. Returns a disposer; a no-op where BroadcastChannel\n * is unavailable (server rendering, older browsers).\n */\nexport function enableCrossTabCacheInvalidation(\n options: CrossTabCacheInvalidationOptions = {},\n): () => void {\n if (typeof BroadcastChannel !== \"function\") return () => {};\n\n const channelName = options.channelName ?? FARM_CACHE_INVALIDATION_CHANNEL;\n const existing = bridgeGlobal[FARM_CACHE_INVALIDATION_BRIDGE];\n let bridge: ActiveBridge;\n if (existing) {\n if (existing.channelName !== channelName) {\n throw new Error(\n `Cross-tab cache invalidation is already enabled on channel \"${existing.channelName}\".`,\n );\n }\n existing.refCount += 1;\n bridge = existing;\n } else {\n bridge = createBridge(channelName);\n bridgeGlobal[FARM_CACHE_INVALIDATION_BRIDGE] = bridge;\n }\n\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n // Release the bridge this caller actually claimed, so a disposer that\n // outlives a teardown/re-enable cycle cannot decrement a later bridge.\n bridge.refCount -= 1;\n if (bridge.refCount === 0) {\n bridge.teardown();\n if (bridgeGlobal[FARM_CACHE_INVALIDATION_BRIDGE] === bridge) {\n bridgeGlobal[FARM_CACHE_INVALIDATION_BRIDGE] = undefined;\n }\n }\n };\n}\n\nfunction createBridge(channelName: string): ActiveBridge {\n const channel = new BroadcastChannel(channelName);\n let applyingRemote = false;\n let pending: string[] = [];\n let flushScheduled = false;\n let closed = false;\n\n const flush = () => {\n flushScheduled = false;\n if (closed || pending.length === 0) return;\n const encoded = encodeFarmCacheInvalidations(pending);\n pending = [];\n if (encoded !== null) channel.postMessage(encoded);\n };\n\n const unsubscribe = subscribeFarmCacheInvalidation((key) => {\n if (applyingRemote || closed) return;\n // A mutation can invalidate several keys back to back; batch them into\n // one message per microtask instead of one post per key.\n pending.push(key);\n if (!flushScheduled) {\n flushScheduled = true;\n queueMicrotask(flush);\n }\n });\n\n channel.onmessage = (event: MessageEvent) => {\n const keys = decodeFarmCacheInvalidations(\n typeof event.data === \"string\" ? event.data : undefined,\n );\n if (keys.length === 0) return;\n applyingRemote = true;\n try {\n for (const key of keys) notifyFarmCacheInvalidation(key);\n } finally {\n applyingRemote = false;\n }\n };\n\n return {\n channelName,\n refCount: 1,\n teardown() {\n closed = true;\n pending = [];\n unsubscribe();\n channel.onmessage = null;\n channel.close();\n },\n };\n}\n","import {\n getFarmClientDataCache,\n type FarmClientCacheEntry,\n type FarmClientCachePersistenceSink,\n type FarmClientDataCache,\n} from \"./client-cache\";\n\n/**\n * Protocol version stamped into every persisted entry. Bump when the\n * persisted shape changes; mismatched entries are dropped on load.\n */\nexport const FARM_CLIENT_CACHE_PERSIST_VERSION = \"1\";\n\n/** Snapshot of a confirmed cache entry as stored by an adapter. */\nexport type PersistedEntry = {\n data: unknown;\n updatedAt: number;\n staleAt: number;\n gcAt?: number;\n version: string;\n};\n\n/**\n * Storage contract for client cache persistence. Implement these callbacks\n * over any storage: IndexedDB, localStorage, OPFS, a native bridge. Farm owns\n * every policy decision (what, when, and whether to persist); the adapter is\n * plain keyed storage. `set` is an upsert.\n */\nexport type FarmClientCacheAdapter = {\n keys(): Promise<string[]>;\n get(key: string): Promise<PersistedEntry | null>;\n set(key: string, entry: PersistedEntry): Promise<void>;\n delete(key: string): Promise<void>;\n clear(): Promise<void>;\n /** Optional batch fast paths; the engine prefers them when present. */\n getMany?(keys: string[]): Promise<Array<PersistedEntry | null>>;\n setMany?(entries: Array<[string, PersistedEntry]>): Promise<void>;\n};\n\n/** Key-value client shape accepted by {@link storageClientCacheAdapter}. */\nexport type FarmClientCacheStorage = {\n getItem<T = unknown>(key: string): Promise<T | null>;\n setItem<T = unknown>(key: string, value: T): Promise<unknown>;\n removeItem(key: string): Promise<unknown>;\n getKeys?(base?: string): Promise<string[]>;\n keys?(base?: string): Promise<string[]>;\n clear?(base?: string): Promise<unknown>;\n};\n\nexport type ClientCachePersistenceOptions = {\n /**\n * Extra version salt, typically an app build or deploy id. Entries written\n * under a different value are dropped on load.\n */\n version?: string;\n /** Coarse additional filter on top of per-declaration `persist: true`. */\n persistKey?: (key: string) => boolean;\n /** Debounce for write-behind flushes. */\n flushDelayMs?: number;\n};\n\n/**\n * Validate and type an adapter definition. Identity at runtime beyond shape\n * checking, mirroring `defineConfig`-style helpers.\n */\nexport function defineClientCacheAdapter(adapter: FarmClientCacheAdapter): FarmClientCacheAdapter {\n for (const method of [\"keys\", \"get\", \"set\", \"delete\", \"clear\"] as const) {\n if (typeof adapter?.[method] !== \"function\") {\n throw new TypeError(\n `defineClientCacheAdapter expects a \"${method}\" method. ` +\n \"Implement keys/get/set/delete/clear over your storage.\",\n );\n }\n }\n return adapter;\n}\n\n/**\n * Adapt any Farm/unstorage-compatible key-value client to the client cache\n * adapter contract, mirroring the server's `storageCacheAdapter`. Without a\n * key enumeration method the adapter still persists but cannot warm-start.\n */\nexport function storageClientCacheAdapter(\n storage: FarmClientCacheStorage,\n options: { base?: string } = {},\n): FarmClientCacheAdapter {\n if (\n !storage ||\n typeof storage.getItem !== \"function\" ||\n typeof storage.setItem !== \"function\" ||\n typeof storage.removeItem !== \"function\"\n ) {\n throw new TypeError(\"storageClientCacheAdapter expects a compatible key-value client.\");\n }\n\n const base = options.base ?? \"farm-client-cache\";\n const entryKey = (key: string) => `${base}:${key}`;\n const enumerate = storage.getKeys?.bind(storage) ?? storage.keys?.bind(storage);\n\n return {\n async keys() {\n if (!enumerate) return [];\n const keys = await enumerate(base);\n const prefix = `${base}:`;\n return keys.filter((key) => key.startsWith(prefix)).map((key) => key.slice(prefix.length));\n },\n async get(key) {\n return (await storage.getItem<PersistedEntry>(entryKey(key))) ?? null;\n },\n async set(key, entry) {\n await storage.setItem(entryKey(key), entry);\n },\n async delete(key) {\n await storage.removeItem(entryKey(key));\n },\n async clear() {\n if (storage.clear) {\n await storage.clear(base);\n return;\n }\n if (!enumerate) return;\n const prefix = `${base}:`;\n for (const key of await enumerate(base)) {\n if (key.startsWith(prefix)) await storage.removeItem(key);\n }\n },\n };\n}\n\ntype PersistenceEngine = {\n adapter: FarmClientCacheAdapter;\n cache: FarmClientDataCache;\n version: string;\n persistKey?: (key: string) => boolean;\n flushDelayMs: number;\n pendingSets: Map<string, PersistedEntry>;\n pendingDeletes: Set<string>;\n flushTimer: ReturnType<typeof setTimeout> | undefined;\n hydrating: boolean;\n disabled: boolean;\n clearing: boolean;\n};\n\nlet activeEngine: PersistenceEngine | undefined;\n\nfunction reportPersistenceFailure(error: unknown): void {\n const report =\n typeof reportError === \"function\" ? reportError : (console.error as (value: unknown) => void);\n if (error instanceof Error) {\n report(error);\n return;\n }\n const normalized = new Error(\"Client cache persistence failed\");\n (normalized as Error & { cause?: unknown }).cause = error;\n report(normalized);\n}\n\nfunction disableEngine(engine: PersistenceEngine, error: unknown): void {\n if (engine.disabled) return;\n // The cache is disposable: on any adapter failure fall back to memory-only\n // for the rest of the session instead of failing reads or writes.\n engine.disabled = true;\n engine.pendingSets.clear();\n engine.pendingDeletes.clear();\n if (engine.flushTimer !== undefined) {\n clearTimeout(engine.flushTimer);\n engine.flushTimer = undefined;\n }\n reportPersistenceFailure(error);\n}\n\nfunction scheduleFlush(engine: PersistenceEngine): void {\n if (engine.disabled || engine.flushTimer !== undefined) return;\n const timer = setTimeout(() => {\n engine.flushTimer = undefined;\n void flushEngine(engine);\n }, engine.flushDelayMs);\n (timer as unknown as { unref?: () => void }).unref?.();\n engine.flushTimer = timer;\n}\n\nasync function flushEngine(engine: PersistenceEngine): Promise<void> {\n if (engine.disabled) return;\n const sets = Array.from(engine.pendingSets.entries());\n const deletes = Array.from(engine.pendingDeletes);\n engine.pendingSets.clear();\n engine.pendingDeletes.clear();\n\n try {\n if (sets.length > 0) {\n if (engine.adapter.setMany) await engine.adapter.setMany(sets);\n else for (const [key, entry] of sets) await engine.adapter.set(key, entry);\n }\n for (const key of deletes) await engine.adapter.delete(key);\n } catch (error) {\n disableEngine(engine, error);\n }\n}\n\nasync function hydrateEngine(engine: PersistenceEngine): Promise<void> {\n const now = Date.now();\n const keys = await engine.adapter.keys();\n if (keys.length === 0) return;\n\n const persisted = engine.adapter.getMany\n ? await engine.adapter.getMany(keys)\n : await Promise.all(keys.map((key) => engine.adapter.get(key)));\n\n engine.hydrating = true;\n try {\n for (let index = 0; index < keys.length; index += 1) {\n const key = keys[index]!;\n const entry = persisted[index];\n if (engine.disabled) return;\n\n if (\n !entry ||\n entry.version !== engine.version ||\n (entry.gcAt !== undefined && now >= entry.gcAt)\n ) {\n engine.pendingDeletes.add(key);\n continue;\n }\n\n // A live entry came from this session's server work and always wins.\n if (engine.cache.get(key, now)) continue;\n\n // Stale-but-visible: render the persisted data immediately and let the\n // normal SWR path revalidate it on first read.\n engine.cache.set(key, {\n data: entry.data,\n updatedAt: entry.updatedAt,\n staleAt: 0,\n gcAt: entry.gcAt,\n status: \"success\",\n error: null,\n persist: true,\n });\n }\n } finally {\n engine.hydrating = false;\n }\n if (engine.pendingDeletes.size > 0) scheduleFlush(engine);\n}\n\nfunction createSink(engine: PersistenceEngine): FarmClientCachePersistenceSink {\n return {\n onSet(key, entry: FarmClientCacheEntry) {\n if (engine.disabled || engine.hydrating) return;\n if (!entry.persist || entry.fetching || entry.error || entry.status === \"pending\") return;\n if (engine.persistKey && !engine.persistKey(key)) return;\n engine.pendingDeletes.delete(key);\n engine.pendingSets.set(key, {\n data: entry.data,\n updatedAt: entry.updatedAt,\n staleAt: entry.staleAt,\n gcAt: entry.gcAt,\n version: engine.version,\n });\n scheduleFlush(engine);\n },\n onDelete(key) {\n if (engine.disabled) return;\n engine.pendingSets.delete(key);\n engine.pendingDeletes.add(key);\n scheduleFlush(engine);\n },\n onClear() {\n // clearPersistedCache awaits the adapter itself; skip the fire-and-forget\n // clear so one logout does not race two clears (and two error reports).\n if (engine.disabled || engine.clearing) return;\n engine.pendingSets.clear();\n engine.pendingDeletes.clear();\n void engine.adapter.clear().catch((error) => disableEngine(engine, error));\n },\n };\n}\n\n/**\n * @internal Wire an adapter to the shared client cache. Called by the\n * generated client entry from the `cache.client.adapter` configuration; not\n * part of the public API. Returns a disposer.\n */\nexport function initPersistedClientCache(\n adapter: FarmClientCacheAdapter,\n options: ClientCachePersistenceOptions = {},\n): () => void {\n defineClientCacheAdapter(adapter);\n disposePersistedClientCache();\n\n const engine: PersistenceEngine = {\n adapter,\n cache: getFarmClientDataCache(),\n version: options.version\n ? `${FARM_CLIENT_CACHE_PERSIST_VERSION}:${options.version}`\n : FARM_CLIENT_CACHE_PERSIST_VERSION,\n persistKey: options.persistKey,\n flushDelayMs: options.flushDelayMs ?? 300,\n pendingSets: new Map(),\n pendingDeletes: new Set(),\n flushTimer: undefined,\n hydrating: false,\n disabled: false,\n clearing: false,\n };\n\n activeEngine = engine;\n engine.cache.attachPersistence(createSink(engine));\n void hydrateEngine(engine).catch((error) => disableEngine(engine, error));\n\n return () => {\n if (activeEngine !== engine) return;\n disposePersistedClientCache();\n };\n}\n\n/**\n * @internal Entry point used by the generated client entries for the\n * `cache.client.adapter` configuration. Accepts the imported module namespace\n * and reports a misconfigured adapter without breaking application startup:\n * persistence is optional capability and must never block hydration.\n */\nexport function initConfiguredClientCachePersistence(\n adapterModule: unknown,\n options: ClientCachePersistenceOptions = {},\n): void {\n try {\n const adapter = (adapterModule as { default?: unknown } | null | undefined)?.default;\n if (!adapter) {\n throw new Error(\n \"cache.client.adapter must default-export an adapter. \" +\n \"Export defineClientCacheAdapter({ keys, get, set, delete, clear }) as the module default.\",\n );\n }\n initPersistedClientCache(adapter as FarmClientCacheAdapter, options);\n } catch (error) {\n reportPersistenceFailure(error);\n }\n}\n\n/** @internal Detach the active engine, flushing nothing further. */\nexport function disposePersistedClientCache(): void {\n const engine = activeEngine;\n if (!engine) return;\n activeEngine = undefined;\n // Hydration is asynchronous and may already be parked on an adapter read.\n // Marking the engine disabled makes that in-flight pass stop before it writes,\n // so a disposed engine cannot repopulate the shared cache after logout — or\n // push the previous user's entries into whichever adapter is attached next.\n engine.disabled = true;\n engine.cache.attachPersistence(undefined);\n if (engine.flushTimer !== undefined) {\n clearTimeout(engine.flushTimer);\n engine.flushTimer = undefined;\n }\n engine.pendingSets.clear();\n engine.pendingDeletes.clear();\n}\n\n/**\n * Remove every persisted cache entry. Call on logout or any session change so\n * the next visitor on this device cannot warm-start into another user's data.\n * Safe to call when persistence is not configured.\n */\nexport async function clearPersistedCache(): Promise<void> {\n const engine = activeEngine;\n if (!engine) {\n // Persistence is optional, but logout must mean the same thing with or\n // without an adapter: the previous session's data stops being readable.\n getFarmClientDataCache().clear();\n return;\n }\n engine.pendingSets.clear();\n engine.pendingDeletes.clear();\n // Clearing the persisted copy alone leaves the in-memory cache holding the\n // signed-out user's data, which a single-page app keeps serving to whoever\n // uses the tab next. Drop both.\n engine.clearing = true;\n try {\n engine.cache.clear();\n } finally {\n engine.clearing = false;\n }\n engine.pendingSets.clear();\n engine.pendingDeletes.clear();\n try {\n await engine.adapter.clear();\n } catch (error) {\n disableEngine(engine, error);\n }\n}\n\n/** @internal Test hook: flush pending writes immediately. */\nexport async function flushPersistedClientCache(): Promise<void> {\n const engine = activeEngine;\n if (!engine) return;\n if (engine.flushTimer !== undefined) {\n clearTimeout(engine.flushTimer);\n engine.flushTimer = undefined;\n }\n await flushEngine(engine);\n}\n","import { useSyncExternalStore } from \"react\";\n\nexport type StoreState = Record<string, any>;\nexport type StoreValueUpdater<T> = T | ((previous: T) => T);\nexport type StorePatch<T extends StoreState> = Partial<T> | ((state: T) => Partial<T>);\nexport type StoreListener<T extends StoreState> = (state: T, previousState: T) => void;\nexport type StoreKeyListener<T extends StoreState, K extends keyof T> = (\n value: T[K],\n previousValue: T[K],\n) => void;\nexport type StoreKeysListener<T extends StoreState, K extends keyof T> = (\n value: Pick<T, K>,\n previousValue: Pick<T, K>,\n) => void;\n\ntype StoreSubscription<T extends StoreState> = {\n keys: readonly PropertyKey[] | null;\n notify: (state: T, previousState: T) => void;\n};\n\ntype ReservedStoreKey = \"use\" | \"get\" | \"set\" | \"replace\" | \"reset\" | \"subscribe\";\n\ntype FieldAccessor<T extends StoreState, K extends keyof T> = {\n (): T[K];\n get(): T[K];\n set(value: StoreValueUpdater<T[K]>): T[K];\n subscribe(listener: StoreKeyListener<T, K>): () => void;\n};\n\nexport type StoreFields<T extends StoreState> = {\n [K in keyof T]: FieldAccessor<T, K>;\n};\n\nexport interface StoreApi<T extends StoreState> {\n use(): T;\n use<K extends keyof T>(key: K): T[K];\n use<K extends keyof T>(keys: readonly K[]): Pick<T, K>;\n get(): T;\n get<K extends keyof T>(key: K): T[K];\n set<K extends keyof T>(key: K, value: StoreValueUpdater<T[K]>): T[K];\n set(patch: StorePatch<T>): T;\n replace(nextState: T | ((state: T) => T)): T;\n reset(): T;\n subscribe(listener: StoreListener<T>): () => void;\n subscribe<K extends keyof T>(key: K, listener: StoreKeyListener<T, K>): () => void;\n subscribe<K extends keyof T>(keys: readonly K[], listener: StoreKeysListener<T, K>): () => void;\n}\n\nexport type Store<T extends StoreState, TMethods extends Record<string, any> = {}> = StoreApi<T> &\n StoreFields<T> &\n TMethods;\n\nconst RESERVED_STORE_KEYS = new Set<ReservedStoreKey>([\n \"use\",\n \"get\",\n \"set\",\n \"replace\",\n \"reset\",\n \"subscribe\",\n]);\n\nfunction cloneState<T extends StoreState>(state: T): T {\n return { ...state };\n}\n\nfunction pickState<T extends StoreState, K extends keyof T>(\n state: T,\n keys: readonly K[],\n): Pick<T, K> {\n const slice = {} as Pick<T, K>;\n\n for (const key of keys) {\n slice[key] = state[key];\n }\n\n return slice;\n}\n\nfunction getEnumerableKeys<T extends StoreState>(state: T): (keyof T)[] {\n return Reflect.ownKeys(state).filter((key) =>\n Object.prototype.propertyIsEnumerable.call(state, key),\n ) as (keyof T)[];\n}\n\nfunction getChangedKeys<T extends StoreState>(state: T, previousState: T): (keyof T)[] {\n const keys = new Set<keyof T>([...getEnumerableKeys(state), ...getEnumerableKeys(previousState)]);\n\n return [...keys].filter((key) => !Object.is(state[key], previousState[key]));\n}\n\nfunction normalizeKeys<T extends StoreState, K extends keyof T>(keys: readonly K[]): readonly K[] {\n return Array.from(new Set(keys));\n}\n\nfunction resolveValue<T>(value: StoreValueUpdater<T>, previousValue: T): T {\n return typeof value === \"function\" ? (value as (previousValue: T) => T)(previousValue) : value;\n}\n\nfunction isStoreKey(value: unknown): value is string | number | symbol {\n return typeof value === \"string\" || typeof value === \"number\" || typeof value === \"symbol\";\n}\n\nexport function createStore<T extends StoreState, TMethods extends Record<string, any> = {}>(\n initialState: T,\n extend?: (store: Store<T>) => TMethods,\n): Store<T, TMethods> {\n const initialSnapshot = cloneState(initialState);\n let state = cloneState(initialState);\n const subscriptions = new Set<StoreSubscription<T>>();\n\n const addSubscription = (\n keys: readonly (keyof T)[] | null,\n notify: (state: T, previousState: T) => void,\n ) => {\n const subscription: StoreSubscription<T> = {\n // Object property enumeration returns numeric keys as strings.\n keys: keys?.map((key) => (typeof key === \"number\" ? String(key) : key)) ?? null,\n notify,\n };\n subscriptions.add(subscription);\n return () => {\n subscriptions.delete(subscription);\n };\n };\n\n const emit = (nextState: T, previousState: T) => {\n const changedKeys = getChangedKeys(nextState, previousState);\n\n if (changedKeys.length === 0) {\n return;\n }\n\n const changedKeySet = new Set<PropertyKey>(changedKeys);\n\n for (const subscription of subscriptions) {\n if (subscription.keys === null || subscription.keys.some((key) => changedKeySet.has(key))) {\n subscription.notify(nextState, previousState);\n }\n }\n };\n\n const getState = (key?: keyof T) => {\n return key === undefined ? state : state[key];\n };\n\n const replaceState = (nextState: T | ((state: T) => T)) => {\n const previousState = state;\n const resolvedState =\n typeof nextState === \"function\" ? (nextState as (state: T) => T)(previousState) : nextState;\n state = resolvedState;\n emit(state, previousState);\n return state;\n };\n\n const setState = (keyOrPatch: keyof T | StorePatch<T>, value?: StoreValueUpdater<T[keyof T]>) => {\n const previousState = state;\n let nextState: T;\n\n if (isStoreKey(keyOrPatch)) {\n const key = keyOrPatch as keyof T;\n const nextValue = resolveValue(value as StoreValueUpdater<T[keyof T]>, previousState[key]);\n\n if (Object.is(previousState[key], nextValue)) {\n return nextValue;\n }\n\n nextState = {\n ...previousState,\n [key]: nextValue,\n };\n state = nextState;\n emit(nextState, previousState);\n return nextValue;\n }\n\n const patch: Partial<T> =\n typeof keyOrPatch === \"function\"\n ? (keyOrPatch as (state: T) => Partial<T>)(previousState)\n : (keyOrPatch as Partial<T>);\n\n nextState = {\n ...previousState,\n ...patch,\n };\n state = nextState;\n emit(nextState, previousState);\n return nextState;\n };\n\n const subscribeState = (\n keyOrListener: keyof T | readonly (keyof T)[] | StoreListener<T>,\n listener?: StoreKeyListener<T, keyof T> | StoreKeysListener<T, keyof T>,\n ) => {\n if (typeof keyOrListener === \"function\") {\n return addSubscription(null, (nextState, previousState) => {\n (keyOrListener as StoreListener<T>)(nextState, previousState);\n });\n }\n\n if (Array.isArray(keyOrListener)) {\n const keys = normalizeKeys(keyOrListener);\n return addSubscription(keys, (nextState, previousState) => {\n (listener as StoreKeysListener<T, keyof T>)(\n pickState(nextState, keys),\n pickState(previousState, keys),\n );\n });\n }\n\n const key = keyOrListener as keyof T;\n return addSubscription([key], (nextState, previousState) => {\n (listener as StoreKeyListener<T, keyof T>)(nextState[key], previousState[key]);\n });\n };\n\n const useStateValue = <K extends keyof T>(keyOrKeys?: K | readonly K[]) => {\n if (Array.isArray(keyOrKeys)) {\n const keys = normalizeKeys(keyOrKeys);\n let lastState = state;\n let lastSlice = pickState(state, keys);\n const getSnapshot = () => {\n if (lastState !== state) {\n lastState = state;\n lastSlice = pickState(state, keys);\n }\n\n return lastSlice;\n };\n\n return useSyncExternalStore(\n (notify) => addSubscription(keys, () => notify()),\n getSnapshot,\n getSnapshot,\n );\n }\n\n if (isStoreKey(keyOrKeys)) {\n return useSyncExternalStore(\n (notify) => addSubscription([keyOrKeys], () => notify()),\n () => state[keyOrKeys],\n () => state[keyOrKeys],\n );\n }\n\n return useSyncExternalStore(\n (notify) => addSubscription(null, () => notify()),\n () => state,\n () => state,\n );\n };\n\n const store = {\n use: useStateValue,\n get: getState,\n set: setState,\n replace: replaceState,\n reset: () => replaceState(cloneState(initialSnapshot)),\n subscribe: subscribeState,\n } as Store<T>;\n\n for (const key of getEnumerableKeys(initialSnapshot)) {\n if (RESERVED_STORE_KEYS.has(key as ReservedStoreKey)) {\n throw new Error(\n `createStore does not allow the reserved key \"${String(key)}\" in the initial state.`,\n );\n }\n\n const field = (() => useStateValue(key)) as FieldAccessor<T, typeof key>;\n field.get = () => state[key];\n field.set = (value) => setState(key, value) as T[typeof key];\n field.subscribe = (listener) => subscribeState(key, listener as StoreKeyListener<T, keyof T>);\n\n Object.defineProperty(store, key, {\n configurable: false,\n enumerable: true,\n value: field,\n writable: false,\n });\n }\n\n if (extend) {\n const methods = extend(store);\n\n for (const [name, method] of Object.entries(methods)) {\n if (name in store) {\n throw new Error(\n `createStore cannot attach the method \"${name}\" because it already exists.`,\n );\n }\n\n Object.defineProperty(store, name, {\n configurable: false,\n enumerable: true,\n value: method,\n writable: false,\n });\n }\n }\n\n return store as Store<T, TMethods>;\n}\n","\"use client\";\n\nimport type React from \"react\";\nimport { forwardRef, useEffect, useRef, useCallback, type AnchorHTMLAttributes } from \"react\";\nimport {\n buildFarmRoutePath,\n type FarmRouterBuildOptions,\n type FarmRouterPathParam,\n type FarmRouterPathParams,\n} from \"../router\";\nimport type { FarmViewTransitionMode } from \"./spa-router\";\nimport { isFarmLocaleChangeHref, localizeActiveFarmHref } from \"../i18n/client-runtime\";\nimport type { FarmI18nLocale } from \"../i18n/types\";\nimport { getFarmTrailingSlashPreference } from \"../trailing-slash\";\nimport { applyFarmBasePath, getFarmBasePath } from \"../base-path\";\nimport { useOptionalFarm } from \"../provider\";\n\n/**\n * Prefetch strategy (TanStack Router–style):\n * - \"intent\": prefetch on hover and touchstart (with prefetchDelay)\n * - \"viewport\": prefetch when link enters viewport (IntersectionObserver)\n * - \"render\": prefetch as soon as the link is mounted\n * - \"none\" | false: no prefetch\n */\nexport type PrefetchBehavior = false | \"intent\" | \"viewport\" | \"render\" | \"none\";\n\n/** @internal Legacy prefetch mode for backward compatibility */\ntype PrefetchLegacy = boolean | \"hover\" | \"viewport\" | \"none\";\n\n/**\n * Augment this interface via the generated farm.d.ts so Link href is typed\n * without passing a generic. Defaults to string when not augmented.\n */\nexport interface LinkDefaultRoute {}\n\nexport type DefaultRoutePath = LinkDefaultRoute extends { _: infer TRoute extends string }\n ? TRoute\n : string;\n\nexport type DefaultRoutePattern = LinkDefaultRoute extends {\n pattern: infer TRoute extends string;\n}\n ? TRoute\n : DefaultRoutePath;\n\nexport type DefaultRouteHref = DefaultRoutePath | DefaultRoutePattern;\n\nexport type RouteHref<TRoute extends string> =\n | TRoute\n | `${TRoute}?${string}`\n | `${TRoute}#${string}`\n | `${TRoute}?${string}#${string}`;\n\n/** A generated route with params already filled into its pathname. */\nexport type ResolvedRouteHref = RouteHref<DefaultRoutePath>;\n\nexport type RouteParamValue = Exclude<FarmRouterPathParam, null | undefined>;\nexport type RouteOptionalParamValue = FarmRouterPathParam;\nexport type RouteParams<TRoute extends string> = string extends TRoute\n ? FarmRouterPathParams\n : ExtractRouteParams<StripRouteSuffix<TRoute>>;\n\n/** URI schemes recognized as typed external Link targets. Apps may augment this interface. */\nexport interface LinkExternalUriSchemes {\n about: true;\n blob: true;\n data: true;\n file: true;\n ftp: true;\n ftps: true;\n geo: true;\n git: true;\n http: true;\n https: true;\n im: true;\n intent: true;\n irc: true;\n ircs: true;\n magnet: true;\n mailto: true;\n market: true;\n sms: true;\n ssh: true;\n tel: true;\n urn: true;\n vscode: true;\n webcal: true;\n ws: true;\n wss: true;\n}\n\ntype ExternalUriScheme = Extract<keyof LinkExternalUriSchemes, string>;\n\ntype UriSchemeLetter =\n | \"a\"\n | \"b\"\n | \"c\"\n | \"d\"\n | \"e\"\n | \"f\"\n | \"g\"\n | \"h\"\n | \"i\"\n | \"j\"\n | \"k\"\n | \"l\"\n | \"m\"\n | \"n\"\n | \"o\"\n | \"p\"\n | \"q\"\n | \"r\"\n | \"s\"\n | \"t\"\n | \"u\"\n | \"v\"\n | \"w\"\n | \"x\"\n | \"y\"\n | \"z\";\ntype UriSchemeStart = UriSchemeLetter | Uppercase<UriSchemeLetter>;\ntype UriSchemeCharacter =\n | UriSchemeStart\n | \"0\"\n | \"1\"\n | \"2\"\n | \"3\"\n | \"4\"\n | \"5\"\n | \"6\"\n | \"7\"\n | \"8\"\n | \"9\"\n | \"+\"\n | \"-\"\n | \".\";\ntype IsUriSchemeTail<TValue extends string> = TValue extends \"\"\n ? true\n : TValue extends `${infer First}${infer Rest}`\n ? First extends UriSchemeCharacter\n ? IsUriSchemeTail<Rest>\n : false\n : false;\ntype IsUriScheme<TValue extends string> = TValue extends `${infer First}${infer Rest}`\n ? First extends UriSchemeStart\n ? IsUriSchemeTail<Rest>\n : false\n : false;\n\ntype KnownExternalHref = `//${string}` | `${ExternalUriScheme}:${string}`;\n\n/** External URLs; these are never type-checked as routes. */\nexport type ExternalHref<THref extends string = string> = string extends THref\n ? KnownExternalHref\n : THref extends `//${string}`\n ? THref\n : THref extends `${infer Scheme}:${string}`\n ? IsUriScheme<Scheme> extends true\n ? THref\n : never\n : never;\n\ntype StripRouteSuffix<TRoute extends string> = TRoute extends `${infer Path}?${string}`\n ? StripRouteSuffix<Path>\n : TRoute extends `${infer Path}#${string}`\n ? StripRouteSuffix<Path>\n : TRoute;\n\ntype ExtractRouteParams<TRoute extends string> = Simplify<\n ExtractOptionalCatchAllParams<TRoute> &\n ExtractCatchAllParams<TRoute> &\n ExtractDynamicParams<TRoute>\n>;\n\ntype ExtractOptionalCatchAllParams<TRoute extends string> =\n TRoute extends `${string}[[...${infer Param}]]${infer Rest}`\n ? { [Key in Param]?: RouteOptionalParamValue } & ExtractOptionalCatchAllParams<Rest>\n : {};\n\ntype ExtractCatchAllParams<TRoute extends string> =\n TRoute extends `${string}[...${infer Param}]${infer Rest}`\n ? Param extends `[...${string}`\n ? ExtractCatchAllParams<Rest>\n : { [Key in Param]: RouteParamValue } & ExtractCatchAllParams<Rest>\n : {};\n\ntype ExtractDynamicParams<TRoute extends string> =\n TRoute extends `${string}[${infer Param}]${infer Rest}`\n ? Param extends `...${string}` | `[...${string}`\n ? ExtractDynamicParams<Rest>\n : { [Key in Param]: RouteParamValue } & ExtractDynamicParams<Rest>\n : {};\n\ntype Simplify<T> = { [Key in keyof T]: T[Key] } & {};\n\ntype HasRouteParams<TRoute extends string> = keyof RouteParams<TRoute> extends never ? false : true;\n\ntype RoutesWithRequiredParams<TRoute extends string> = TRoute extends string\n ? HasRouteParams<TRoute> extends true\n ? TRoute\n : never\n : never;\n\ntype LinkRouteParamsProps<TRoute extends string> = string extends TRoute\n ? { params?: FarmRouterPathParams }\n : HasRouteParams<TRoute> extends true\n ? { params: RouteParams<TRoute> }\n : { params?: FarmRouterPathParams };\n\ntype LinkRouteTargetProps<TRoute extends string> = [RoutesWithRequiredParams<TRoute>] extends [\n never,\n]\n ? {\n /** Internal route path with all params already resolved. */\n href: RouteHref<TRoute>;\n params?: FarmRouterPathParams;\n }\n : TRoute extends string\n ? {\n /** Internal route path or route pattern. */\n href: RouteHref<TRoute>;\n } & LinkRouteParamsProps<TRoute>\n : never;\n\ntype LinkExternalTargetProps<THref extends string = string> = {\n /** External URL; these are never type-checked as app routes. */\n href: ExternalHref<THref>;\n params?: never;\n};\n\ntype LinkTargetProps<TRoute extends string, THref extends string> =\n | LinkExternalTargetProps<THref>\n | LinkRouteTargetProps<TRoute>;\n\nexport type LinkProps<\n TRoute extends string = DefaultRouteHref,\n THref extends string = string,\n> = Omit<AnchorHTMLAttributes<HTMLAnchorElement>, \"href\"> &\n LinkTargetProps<TRoute, THref> & {\n /**\n * When to prefetch. TanStack-style: \"intent\" (hover+touch), \"viewport\", \"render\", or \"none\".\n * Legacy: true (intent+viewport), \"hover\" (intent), \"viewport\", false/\"none\".\n */\n prefetch?: PrefetchBehavior | PrefetchLegacy;\n /** Search params appended after route params are resolved. */\n query?: FarmRouterBuildOptions[\"query\"];\n /** Hash appended after route params and search params are resolved. */\n hash?: string;\n /** Add a trailing slash to the generated internal href. */\n trailingSlash?: boolean;\n /** Delay in ms before intent-based prefetch (hover/touch). Default 50. */\n prefetchDelay?: number;\n /** Replace current history entry instead of pushing */\n replace?: boolean;\n /** Scroll to top after navigation (default: true) */\n scroll?: boolean;\n /** Wrap this SPA navigation in a browser View Transition when supported. */\n viewTransition?: FarmViewTransitionMode;\n /** Preserve the active locale by default, or navigate using this locale. */\n locale?: FarmI18nLocale;\n };\n\nfunction isModifierEvent(e: React.MouseEvent): boolean {\n return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);\n}\n\nfunction isExternalUrl(href: string): boolean {\n return href.startsWith(\"//\") || /^[a-zA-Z][a-zA-Z\\d+.-]*:/.test(href);\n}\n\nfunction getRouter(): {\n prefetch(href: string): Promise<void>;\n observeForPrefetch(el: HTMLAnchorElement): void;\n unobserveForPrefetch(el: HTMLAnchorElement): void;\n navigate(\n href: string,\n opts: { replace?: boolean; scroll?: boolean; viewTransition?: FarmViewTransitionMode },\n ): void;\n} | null {\n if (typeof window !== \"undefined\" && (window as any).__FARM_SPA_ROUTER__) {\n return (window as any).__FARM_SPA_ROUTER__;\n }\n return null;\n}\n\nfunction normalizePrefetch(prefetch: LinkProps[\"prefetch\"]): {\n intent: boolean;\n viewport: boolean;\n render: boolean;\n} {\n if (prefetch === false || prefetch === \"none\") {\n return { intent: false, viewport: false, render: false };\n }\n if (prefetch === true) {\n return { intent: true, viewport: true, render: false };\n }\n if (prefetch === \"hover\") {\n return { intent: true, viewport: false, render: false };\n }\n if (prefetch === \"intent\") {\n return { intent: true, viewport: false, render: false };\n }\n if (prefetch === \"viewport\") {\n return { intent: false, viewport: true, render: false };\n }\n if (prefetch === \"render\") {\n return { intent: false, viewport: false, render: true };\n }\n return { intent: false, viewport: false, render: false };\n}\n\nfunction LinkInner<TRoute extends string = DefaultRouteHref, THref extends string = string>(\n {\n href,\n params,\n query,\n hash,\n trailingSlash,\n prefetch = true,\n prefetchDelay = 50,\n replace = false,\n scroll = true,\n viewTransition = false,\n locale,\n onClick,\n target,\n onMouseEnter,\n onMouseLeave,\n onFocus,\n onBlur,\n onTouchStart,\n ...props\n }: LinkProps<TRoute, THref>,\n ref: React.ForwardedRef<HTMLAnchorElement>,\n) {\n const elementRef = useRef<HTMLAnchorElement | null>(null);\n const intentTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const activePrefetch = useRef<symbol | null>(null);\n const farm = useOptionalFarm();\n\n const { intent, viewport, render } = normalizePrefetch(prefetch);\n const baseHref = resolveLinkHref(href, params, {\n query,\n hash,\n trailingSlash: trailingSlash ?? getFarmTrailingSlashPreference(),\n });\n const localizedHref = localizeActiveFarmHref(baseHref, locale);\n const resolvedHref = isExternalUrl(localizedHref)\n ? localizedHref\n : applyFarmBasePath(localizedHref, farm?.basePath ?? getFarmBasePath());\n const isExternal = isExternalUrl(resolvedHref);\n\n const doPrefetch = useCallback(() => {\n if (isExternal || activePrefetch.current) return;\n const router = getRouter();\n if (!router) return;\n const token = Symbol(resolvedHref);\n activePrefetch.current = token;\n const reset = () => {\n if (activePrefetch.current === token) activePrefetch.current = null;\n };\n try {\n void router.prefetch(resolvedHref).then(reset, reset);\n } catch {\n reset();\n }\n }, [resolvedHref, isExternal]);\n\n useEffect(() => {\n activePrefetch.current = null;\n }, [resolvedHref]);\n\n useEffect(() => {\n const element = elementRef.current;\n if (!element || isExternal) return;\n\n const router = getRouter();\n if (!router) return;\n\n if (viewport) {\n router.observeForPrefetch(element);\n return () => router.unobserveForPrefetch(element);\n }\n }, [resolvedHref, viewport, isExternal]);\n\n useEffect(() => {\n if (!render || isExternal) return;\n\n let cancelled = false;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const tryRenderPrefetch = () => {\n if (cancelled || activePrefetch.current) return;\n\n const router = getRouter();\n if (!router) {\n timeoutId = setTimeout(tryRenderPrefetch, 30);\n return;\n }\n\n doPrefetch();\n };\n\n tryRenderPrefetch();\n\n return () => {\n cancelled = true;\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n };\n }, [render, isExternal, resolvedHref, doPrefetch]);\n\n useEffect(() => {\n return () => {\n if (intentTimeoutRef.current) {\n clearTimeout(intentTimeoutRef.current);\n intentTimeoutRef.current = null;\n }\n };\n }, []);\n\n const cancelIntent = useCallback(() => {\n if (intentTimeoutRef.current) {\n clearTimeout(intentTimeoutRef.current);\n intentTimeoutRef.current = null;\n }\n }, []);\n\n const scheduleIntentPrefetch = useCallback(() => {\n if (isExternal || !intent || activePrefetch.current) return;\n cancelIntent();\n intentTimeoutRef.current = setTimeout(() => {\n intentTimeoutRef.current = null;\n doPrefetch();\n }, prefetchDelay);\n }, [intent, isExternal, prefetchDelay, doPrefetch, cancelIntent]);\n\n const handleMouseEnter = useCallback(\n (event: React.MouseEvent<HTMLAnchorElement>) => {\n onMouseEnter?.(event);\n scheduleIntentPrefetch();\n },\n [onMouseEnter, scheduleIntentPrefetch],\n );\n\n const handleMouseLeave = useCallback(\n (event: React.MouseEvent<HTMLAnchorElement>) => {\n onMouseLeave?.(event);\n cancelIntent();\n },\n [onMouseLeave, cancelIntent],\n );\n\n const handleTouchStart = useCallback(\n (event: React.TouchEvent<HTMLAnchorElement>) => {\n onTouchStart?.(event);\n scheduleIntentPrefetch();\n },\n [onTouchStart, scheduleIntentPrefetch],\n );\n\n const handleFocus = useCallback(\n (event: React.FocusEvent<HTMLAnchorElement>) => {\n onFocus?.(event);\n scheduleIntentPrefetch();\n },\n [onFocus, scheduleIntentPrefetch],\n );\n\n const handleBlur = useCallback(\n (event: React.FocusEvent<HTMLAnchorElement>) => {\n onBlur?.(event);\n cancelIntent();\n },\n [onBlur, cancelIntent],\n );\n\n const handleClick = useCallback(\n (event: React.MouseEvent<HTMLAnchorElement>) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n if (isExternal) return;\n if (event.currentTarget.hasAttribute(\"download\")) return;\n if (target && target !== \"_self\") return;\n if (isModifierEvent(event)) return;\n if (event.button !== 0) return;\n\n if (typeof window !== \"undefined\") {\n event.preventDefault();\n if (isFarmLocaleChangeHref(localizedHref)) {\n window.location.assign(resolvedHref);\n return;\n }\n const router = getRouter();\n if (router) {\n router.navigate(resolvedHref, { replace, scroll, viewTransition });\n } else {\n if (replace) window.location.replace(resolvedHref);\n else window.location.href = resolvedHref;\n }\n }\n },\n [localizedHref, resolvedHref, replace, scroll, viewTransition, target, isExternal, onClick],\n );\n\n const setRefs = useCallback(\n (node: HTMLAnchorElement | null) => {\n elementRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) (ref as React.MutableRefObject<HTMLAnchorElement | null>).current = node;\n },\n [ref],\n );\n\n return (\n <a\n ref={setRefs}\n href={resolvedHref}\n target={target}\n onClick={handleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onTouchStart={handleTouchStart}\n {...props}\n data-farm-link=\"\"\n data-replace={replace ? \"\" : undefined}\n data-no-scroll={!scroll ? \"\" : undefined}\n data-view-transition={\n viewTransition === \"auto\" ? \"auto\" : viewTransition ? \"true\" : undefined\n }\n />\n );\n}\n\nconst LinkWithRef = forwardRef(LinkInner);\nLinkWithRef.displayName = \"Link\";\n\ntype LinkComponentType = <TRoute extends string = DefaultRouteHref, THref extends string = string>(\n props: LinkProps<TRoute, THref> & { ref?: React.ForwardedRef<HTMLAnchorElement> },\n) => React.ReactElement;\n\nexport const Link = LinkWithRef as unknown as LinkComponentType;\n\nfunction resolveLinkHref(\n href: string,\n params: FarmRouterPathParams | undefined,\n options: FarmRouterBuildOptions,\n) {\n if (isExternalUrl(href)) return href;\n\n const { pathname, query, hash } = splitInternalHref(href);\n\n const resolvedHref = buildFarmRoutePath(pathname, params, {\n query: mergeQueryParams(query, options.query),\n hash: options.hash ?? hash,\n trailingSlash: options.trailingSlash,\n });\n\n return applyPreservedSearchParams(resolvedHref);\n}\n\nfunction splitInternalHref(href: string) {\n try {\n const url = new URL(href, \"http://farm.local\");\n return {\n pathname: url.pathname || \"/\",\n query: url.searchParams,\n hash: url.hash ? url.hash.slice(1) : undefined,\n };\n } catch {\n const [withoutHash, rawHash] = href.split(\"#\", 2);\n const [pathname, rawQuery] = withoutHash.split(\"?\", 2);\n return {\n pathname: pathname || \"/\",\n query: new URLSearchParams(rawQuery || \"\"),\n hash: rawHash,\n };\n }\n}\n\nfunction mergeQueryParams(\n current: URLSearchParams,\n next: FarmRouterBuildOptions[\"query\"],\n): URLSearchParams | undefined {\n const merged = new URLSearchParams(current);\n\n if (next instanceof URLSearchParams) {\n for (const [key, value] of next.entries()) {\n merged.append(key, value);\n }\n } else if (next) {\n for (const [key, value] of Object.entries(next)) {\n const values = Array.isArray(value) ? value : [value];\n for (const item of values) {\n if (item == null) continue;\n merged.append(key, String(item));\n }\n }\n }\n\n return merged.toString() ? merged : undefined;\n}\n\nfunction applyPreservedSearchParams(href: string): string {\n if (typeof window === \"undefined\") return href;\n\n const manifest = (window as any).__FARM_MANIFEST__;\n const routes =\n manifest?.routes && typeof manifest.routes === \"object\" ? Object.values(manifest.routes) : [];\n if (routes.length === 0) return href;\n\n const url = new URL(href, window.location.origin);\n const route = routes.find((candidate: any) => matchManifestRoute(url.pathname, candidate));\n const preserve = Array.isArray((route as any)?.search?.preserve)\n ? ((route as any).search.preserve as string[])\n : [];\n if (preserve.length === 0) return href;\n\n const current = new URLSearchParams(window.location.search);\n let changed = false;\n\n for (const key of preserve) {\n if (url.searchParams.has(key) || !current.has(key)) continue;\n for (const value of current.getAll(key)) {\n url.searchParams.append(key, value);\n changed = true;\n }\n }\n\n if (!changed) return href;\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nfunction matchManifestRoute(pathname: string, route: any): boolean {\n if (!route || !Array.isArray(route.segments)) return false;\n const routeSegments = route.segments;\n const normalized = pathname === \"/\" ? \"\" : pathname.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const pathSegments = normalized ? normalized.split(\"/\") : [];\n const hasCatchAll = routeSegments.some((segment: any) => segment.isCatchAll);\n\n if (!hasCatchAll && pathSegments.length !== routeSegments.length) {\n return false;\n }\n\n for (let index = 0; index < routeSegments.length; index++) {\n const routeSegment = routeSegments[index];\n const pathSegment = pathSegments[index];\n\n if (routeSegment.isCatchAll) {\n return true;\n }\n\n if (pathSegment === undefined) {\n if (routeSegment.isOptional) continue;\n return false;\n }\n\n if (!routeSegment.isDynamic && routeSegment.segment !== pathSegment) {\n return false;\n }\n }\n\n return pathSegments.length === routeSegments.length || hasCatchAll;\n}\n","import React, { createContext, useContext, type ReactNode } from \"react\";\nimport type { FarmConfig } from \"./types\";\nimport { normalizeFarmBasePath } from \"./base-path\";\n\ninterface FarmContextValue {\n config: FarmConfig;\n basePath: string;\n}\n\nconst FarmContext = createContext<FarmContextValue | null>(null);\n\ninterface FarmProviderProps {\n children: ReactNode;\n config: FarmConfig;\n}\n\n/**\n * Farm.js context provider for client-side components\n */\nexport function FarmProvider({ children, config }: FarmProviderProps) {\n const value: FarmContextValue = {\n config,\n basePath: normalizeFarmBasePath(config.basePath),\n };\n\n return <FarmContext.Provider value={value}>{children}</FarmContext.Provider>;\n}\n\n/**\n * Hook to access Farm.js configuration and utilities\n */\nexport function useFarm(): FarmContextValue {\n const context = useContext(FarmContext);\n\n if (!context) {\n throw new Error(\"useFarm must be used within a FarmProvider\");\n }\n\n return context;\n}\n\n/** @internal Read Farm context when a component can also use a runtime fallback. */\nexport function useOptionalFarm(): FarmContextValue | null {\n return useContext(FarmContext);\n}\n\n/**\n * Hook to get the current base path\n */\nexport function useBasePath(): string {\n const { basePath } = useFarm();\n return basePath;\n}\n"],"mappings":"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","names":["useCallback","useMemo","useRef","useState","useRef","useState","useCallback","useMemo","replaceState","useRef","useCallback","jsx","prefetch","useRef","useCallback"]}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
FarmClientDataCache,
|
|
6
6
|
getFarmClientDataCache,
|
|
7
7
|
normalizeFarmClientCacheKey
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-BXVOHG6B.mjs";
|
|
9
9
|
import {
|
|
10
10
|
resolveAPIRequestRuntime
|
|
11
11
|
} from "./chunk-YECMFULZ.mjs";
|
|
@@ -2334,4 +2334,4 @@ export {
|
|
|
2334
2334
|
settleServerFnOptimisticUpdates,
|
|
2335
2335
|
resolveServerFnInvalidateTargets
|
|
2336
2336
|
};
|
|
2337
|
-
//# sourceMappingURL=chunk-
|
|
2337
|
+
//# sourceMappingURL=chunk-VQG3QWWK.mjs.map
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getRequestSourceOrigin,
|
|
3
|
+
matchesAllowedOrigin,
|
|
4
|
+
matchesHostHeader,
|
|
5
|
+
normalizeAllowedOriginPattern
|
|
6
|
+
} from "./chunk-FDWXXTWR.mjs";
|
|
1
7
|
import {
|
|
2
8
|
parseBodySizeLimit
|
|
3
9
|
} from "./chunk-ZHQMHJAV.mjs";
|
|
@@ -73,6 +79,7 @@ function isSerializedServerFnFailure(value) {
|
|
|
73
79
|
__name(isSerializedServerFnFailure, "isSerializedServerFnFailure");
|
|
74
80
|
|
|
75
81
|
// src/server-action-security.ts
|
|
82
|
+
var SERVER_ACTION_ALLOWED_ORIGINS_LABEL = "serverActions.allowedOrigins";
|
|
76
83
|
var DEFAULT_SERVER_ACTION_BODY_SIZE_LIMIT = 1e6;
|
|
77
84
|
var _ServerActionRequestError = class _ServerActionRequestError extends Error {
|
|
78
85
|
constructor(code, status, message) {
|
|
@@ -97,7 +104,9 @@ var JAVASCRIPT_ACTION_CONTENT_TYPES = /* @__PURE__ */ new Set([
|
|
|
97
104
|
"text/plain"
|
|
98
105
|
]);
|
|
99
106
|
function resolveServerActionsConfig(config) {
|
|
100
|
-
const allowedOrigins = (config?.allowedOrigins ?? []).map(
|
|
107
|
+
const allowedOrigins = (config?.allowedOrigins ?? []).map(
|
|
108
|
+
(value) => normalizeAllowedOriginPattern(value, SERVER_ACTION_ALLOWED_ORIGINS_LABEL)
|
|
109
|
+
);
|
|
101
110
|
const bodySizeLimit = parseBodySizeLimit(
|
|
102
111
|
config?.bodySizeLimit ?? DEFAULT_SERVER_ACTION_BODY_SIZE_LIMIT,
|
|
103
112
|
"serverActions.bodySizeLimit"
|
|
@@ -117,7 +126,7 @@ function validateServerActionRequest(request, config) {
|
|
|
117
126
|
);
|
|
118
127
|
}
|
|
119
128
|
const requestUrl = new URL(request.url);
|
|
120
|
-
const sourceOrigin =
|
|
129
|
+
const sourceOrigin = resolveSourceOrigin(request);
|
|
121
130
|
const fetchSite = request.headers.get("sec-fetch-site")?.trim().toLowerCase();
|
|
122
131
|
if (!sourceOrigin) {
|
|
123
132
|
if (fetchSite !== "same-origin") {
|
|
@@ -249,111 +258,18 @@ function getFallbackAbortController() {
|
|
|
249
258
|
return globalState[FALLBACK_ABORT_CONTROLLER_KEY];
|
|
250
259
|
}
|
|
251
260
|
__name(getFallbackAbortController, "getFallbackAbortController");
|
|
252
|
-
function
|
|
253
|
-
const
|
|
254
|
-
if (!
|
|
255
|
-
throw new
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
throw new TypeError(`Invalid serverActions.allowedOrigins pattern: ${JSON.stringify(value)}`);
|
|
260
|
-
}
|
|
261
|
-
return pattern;
|
|
262
|
-
}
|
|
263
|
-
if (pattern.includes("://")) {
|
|
264
|
-
let parsed;
|
|
265
|
-
try {
|
|
266
|
-
parsed = new URL(pattern);
|
|
267
|
-
} catch {
|
|
268
|
-
throw new TypeError(`Invalid serverActions.allowedOrigins value: ${JSON.stringify(value)}`);
|
|
269
|
-
}
|
|
270
|
-
if (parsed.protocol !== "http:" && parsed.protocol !== "https:" || parsed.username || parsed.password || parsed.pathname !== "/" || parsed.search || parsed.hash) {
|
|
271
|
-
throw new TypeError(
|
|
272
|
-
`serverActions.allowedOrigins must contain origins without paths: ${JSON.stringify(value)}`
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
return parsed.origin;
|
|
276
|
-
}
|
|
277
|
-
if (/[/@?#]/.test(pattern)) {
|
|
278
|
-
throw new TypeError(
|
|
279
|
-
`serverActions.allowedOrigins must contain origins or hosts: ${JSON.stringify(value)}`
|
|
261
|
+
function resolveSourceOrigin(request) {
|
|
262
|
+
const result = getRequestSourceOrigin(request);
|
|
263
|
+
if (!result.ok) {
|
|
264
|
+
throw new ServerActionRequestError(
|
|
265
|
+
"INVALID_ORIGIN",
|
|
266
|
+
403,
|
|
267
|
+
result.reason === "opaque-origin" ? "Opaque origins are not allowed" : "Invalid request origin"
|
|
280
268
|
);
|
|
281
269
|
}
|
|
282
|
-
|
|
283
|
-
return new URL(`http://${pattern}`).host;
|
|
284
|
-
} catch {
|
|
285
|
-
throw new TypeError(`Invalid serverActions.allowedOrigins value: ${JSON.stringify(value)}`);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
__name(normalizeAllowedOriginPattern, "normalizeAllowedOriginPattern");
|
|
289
|
-
function getRequestSourceOrigin(request) {
|
|
290
|
-
const origin = request.headers.get("origin")?.trim();
|
|
291
|
-
if (origin) {
|
|
292
|
-
return parseSourceOrigin(origin);
|
|
293
|
-
}
|
|
294
|
-
const referer = request.headers.get("referer")?.trim();
|
|
295
|
-
if (referer) {
|
|
296
|
-
return parseSourceOrigin(referer);
|
|
297
|
-
}
|
|
298
|
-
return null;
|
|
299
|
-
}
|
|
300
|
-
__name(getRequestSourceOrigin, "getRequestSourceOrigin");
|
|
301
|
-
function parseSourceOrigin(value) {
|
|
302
|
-
if (value === "null") {
|
|
303
|
-
throw new ServerActionRequestError("INVALID_ORIGIN", 403, "Opaque origins are not allowed");
|
|
304
|
-
}
|
|
305
|
-
try {
|
|
306
|
-
const parsed = new URL(value);
|
|
307
|
-
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
308
|
-
throw new Error("Unsupported protocol");
|
|
309
|
-
}
|
|
310
|
-
return parsed.origin;
|
|
311
|
-
} catch {
|
|
312
|
-
throw new ServerActionRequestError("INVALID_ORIGIN", 403, "Invalid request origin");
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
__name(parseSourceOrigin, "parseSourceOrigin");
|
|
316
|
-
function matchesHostHeader(sourceOrigin, request) {
|
|
317
|
-
const host = request.headers.get("host")?.trim().toLowerCase();
|
|
318
|
-
if (!host) return false;
|
|
319
|
-
try {
|
|
320
|
-
const source = new URL(sourceOrigin);
|
|
321
|
-
const target = new URL(request.url);
|
|
322
|
-
return source.protocol === target.protocol && source.host.toLowerCase() === host;
|
|
323
|
-
} catch {
|
|
324
|
-
return false;
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
__name(matchesHostHeader, "matchesHostHeader");
|
|
328
|
-
function matchesAllowedOrigin(sourceOrigin, pattern) {
|
|
329
|
-
const source = new URL(sourceOrigin);
|
|
330
|
-
if (!pattern.includes("*")) {
|
|
331
|
-
return pattern.includes("://") ? source.origin === pattern : source.host === pattern;
|
|
332
|
-
}
|
|
333
|
-
const schemeEnd = pattern.indexOf("://");
|
|
334
|
-
const scheme = schemeEnd === -1 ? null : pattern.slice(0, schemeEnd + 1);
|
|
335
|
-
const hostPattern = pattern.slice(schemeEnd === -1 ? 0 : schemeEnd + 3);
|
|
336
|
-
const [wildcardHost, port] = splitHostAndPort(hostPattern);
|
|
337
|
-
const baseHost = wildcardHost.slice(2);
|
|
338
|
-
if (scheme && source.protocol !== scheme) return false;
|
|
339
|
-
if (port && getEffectivePort(source) !== port) return false;
|
|
340
|
-
if (!port && source.port) return false;
|
|
341
|
-
return source.hostname.endsWith(`.${baseHost}`) && source.hostname !== baseHost;
|
|
342
|
-
}
|
|
343
|
-
__name(matchesAllowedOrigin, "matchesAllowedOrigin");
|
|
344
|
-
function splitHostAndPort(value) {
|
|
345
|
-
const separator = value.lastIndexOf(":");
|
|
346
|
-
if (separator === -1) return [value, null];
|
|
347
|
-
return [value.slice(0, separator), value.slice(separator + 1)];
|
|
348
|
-
}
|
|
349
|
-
__name(splitHostAndPort, "splitHostAndPort");
|
|
350
|
-
function getEffectivePort(url) {
|
|
351
|
-
if (url.port) return url.port;
|
|
352
|
-
if (url.protocol === "https:") return "443";
|
|
353
|
-
if (url.protocol === "http:") return "80";
|
|
354
|
-
return "";
|
|
270
|
+
return result.origin;
|
|
355
271
|
}
|
|
356
|
-
__name(
|
|
272
|
+
__name(resolveSourceOrigin, "resolveSourceOrigin");
|
|
357
273
|
function validateActionId(actionId) {
|
|
358
274
|
if (!actionId || actionId.length > 4096 || hasControlCharacters(actionId)) {
|
|
359
275
|
throw new ServerActionRequestError("INVALID_ACTION_ID", 400, "Invalid server action id");
|
|
@@ -499,4 +415,4 @@ export {
|
|
|
499
415
|
getServerActionSignal,
|
|
500
416
|
getServerActionInvalidations
|
|
501
417
|
};
|
|
502
|
-
//# sourceMappingURL=chunk-
|
|
418
|
+
//# sourceMappingURL=chunk-XWM2C267.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server-action-security.ts","../src/server-fn-error.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { subscribeFarmCacheInvalidation, subscribeFarmCacheTask } from \"./cache-invalidation\";\nimport {\n getRequestSourceOrigin,\n matchesAllowedOrigin,\n matchesHostHeader,\n normalizeAllowedOriginPattern,\n} from \"./request-origin\";\nimport { serializeServerFnFailure, type SerializedServerFnFailure } from \"./server-fn-error\";\nimport { parseBodySizeLimit } from \"./server-http\";\n\nconst SERVER_ACTION_ALLOWED_ORIGINS_LABEL = \"serverActions.allowedOrigins\";\n\nexport const DEFAULT_SERVER_ACTION_BODY_SIZE_LIMIT = 1_000_000;\n\nexport interface FarmServerActionsConfig {\n /** Additional trusted origins or host patterns, such as https://app.example.com. */\n allowedOrigins?: readonly string[];\n /** Maximum encoded request body size in bytes or as a size string such as \"1mb\". */\n bodySizeLimit?: number | string;\n}\n\nexport interface ResolvedFarmServerActionsConfig {\n allowedOrigins: readonly string[];\n bodySizeLimit: number;\n}\n\nexport type ServerActionRequestKind = \"javascript\" | \"form\";\n\nexport interface PreparedServerActionRequest {\n body: string | FormData;\n contentType: string;\n}\n\nexport type SanitizedServerActionError =\n | {\n name: \"ServerActionError\";\n message: \"Server function failed\";\n }\n | SerializedServerFnFailure;\n\ntype ServerActionRequestErrorCode =\n | \"BODY_TOO_LARGE\"\n | \"INVALID_ACTION_ID\"\n | \"INVALID_BODY\"\n | \"INVALID_CONTENT_LENGTH\"\n | \"INVALID_METHOD\"\n | \"INVALID_ORIGIN\"\n | \"MISSING_ORIGIN\"\n | \"UNSUPPORTED_CONTENT_TYPE\";\n\nexport class ServerActionRequestError extends Error {\n readonly code: ServerActionRequestErrorCode;\n readonly status: number;\n\n constructor(code: ServerActionRequestErrorCode, status: number, message: string) {\n super(message);\n this.name = \"ServerActionRequestError\";\n this.code = code;\n this.status = status;\n }\n}\n\ntype ServerActionExecutionContext = {\n request: Request;\n signal: AbortSignal;\n invalidations: Set<string>;\n cacheTasks: Set<Promise<void>>;\n};\n\nconst SERVER_ACTION_STORAGE_KEY = Symbol.for(\"farm.serverActionStorage\");\nconst FALLBACK_ABORT_CONTROLLER_KEY = Symbol.for(\"farm.serverActionFallbackAbortController\");\nconst FORM_ACTION_CONTENT_TYPES = new Set([\n \"application/x-www-form-urlencoded\",\n \"multipart/form-data\",\n]);\nconst JAVASCRIPT_ACTION_CONTENT_TYPES = new Set([\n \"application/octet-stream\",\n \"application/x-www-form-urlencoded\",\n \"multipart/form-data\",\n \"text/plain\",\n]);\n\ntype GlobalWithServerActionStorage = typeof globalThis & {\n [SERVER_ACTION_STORAGE_KEY]?: AsyncLocalStorage<ServerActionExecutionContext>;\n [FALLBACK_ABORT_CONTROLLER_KEY]?: AbortController;\n};\n\nexport function resolveServerActionsConfig(\n config: FarmServerActionsConfig | undefined,\n): ResolvedFarmServerActionsConfig {\n const allowedOrigins = (config?.allowedOrigins ?? []).map((value) =>\n normalizeAllowedOriginPattern(value, SERVER_ACTION_ALLOWED_ORIGINS_LABEL),\n );\n const bodySizeLimit = parseBodySizeLimit(\n config?.bodySizeLimit ?? DEFAULT_SERVER_ACTION_BODY_SIZE_LIMIT,\n \"serverActions.bodySizeLimit\",\n );\n\n return Object.freeze({\n allowedOrigins: Object.freeze(allowedOrigins),\n bodySizeLimit,\n });\n}\n\nexport function validateServerActionRequest(\n request: Request,\n config: ResolvedFarmServerActionsConfig,\n): void {\n if (request.method.toUpperCase() !== \"POST\") {\n throw new ServerActionRequestError(\n \"INVALID_METHOD\",\n 405,\n \"Server actions only accept POST requests\",\n );\n }\n\n const requestUrl = new URL(request.url);\n const sourceOrigin = resolveSourceOrigin(request);\n const fetchSite = request.headers.get(\"sec-fetch-site\")?.trim().toLowerCase();\n\n if (!sourceOrigin) {\n if (fetchSite !== \"same-origin\") {\n throw new ServerActionRequestError(\n \"MISSING_ORIGIN\",\n 403,\n \"Server action request is missing same-origin metadata\",\n );\n }\n return;\n }\n\n const matchesRequest =\n sourceOrigin === requestUrl.origin || matchesHostHeader(sourceOrigin, request);\n const matchesConfiguredOrigin = config.allowedOrigins.some((pattern) =>\n matchesAllowedOrigin(sourceOrigin, pattern),\n );\n\n if (!matchesRequest && !matchesConfiguredOrigin) {\n throw new ServerActionRequestError(\n \"INVALID_ORIGIN\",\n 403,\n \"Server action origin does not match the request origin\",\n );\n }\n\n if (fetchSite === \"cross-site\" && !matchesConfiguredOrigin) {\n throw new ServerActionRequestError(\n \"INVALID_ORIGIN\",\n 403,\n \"Cross-site server action request was rejected\",\n );\n }\n}\n\nexport async function prepareServerActionRequest(\n request: Request,\n config: ResolvedFarmServerActionsConfig,\n kind: ServerActionRequestKind,\n actionId?: string | null,\n): Promise<PreparedServerActionRequest> {\n validateServerActionRequest(request, config);\n\n if (kind === \"javascript\") {\n validateActionId(actionId);\n }\n\n const contentType = getSupportedContentType(request, kind);\n const bytes = await readBodyWithLimit(request, config.bodySizeLimit);\n\n if (kind === \"form\" || contentType === \"multipart/form-data\") {\n return {\n body: await parseFormData(request, bytes),\n contentType,\n };\n }\n\n return {\n body: new TextDecoder().decode(bytes),\n contentType,\n };\n}\n\nexport function createServerActionRequestErrorResponse(error: unknown): Response | null {\n if (!(error instanceof ServerActionRequestError)) {\n return null;\n }\n\n const headers = new Headers({\n \"cache-control\": \"no-store\",\n \"content-type\": \"text/plain; charset=utf-8\",\n \"x-content-type-options\": \"nosniff\",\n });\n if (error.status === 405) {\n headers.set(\"allow\", \"POST\");\n }\n\n return new Response(getPublicErrorMessage(error.status), {\n status: error.status,\n headers,\n });\n}\n\nexport function sanitizeServerActionError(error: unknown): SanitizedServerActionError {\n const declaredFailure = serializeServerFnFailure(error);\n if (declaredFailure) return declaredFailure;\n\n return {\n name: \"ServerActionError\",\n message: \"Server function failed\",\n };\n}\n\nexport async function runWithServerActionRequest<T>(\n request: Request,\n callback: () => T | Promise<T>,\n): Promise<T> {\n throwIfAborted(request.signal);\n const context: ServerActionExecutionContext = {\n request,\n signal: request.signal,\n invalidations: new Set(),\n cacheTasks: new Set(),\n };\n\n return getServerActionStorage().run(context, async () => {\n try {\n const result = await callback();\n await Promise.all(context.cacheTasks);\n return result;\n } catch (error) {\n await Promise.allSettled(context.cacheTasks);\n throw error;\n }\n });\n}\n\nexport function getServerActionExecutionContext(): ServerActionExecutionContext | undefined {\n return getServerActionStorage().getStore();\n}\n\nexport function getServerActionSignal(): AbortSignal {\n return getServerActionExecutionContext()?.signal ?? getFallbackAbortController().signal;\n}\n\nexport function getServerActionInvalidations(): readonly string[] {\n return Array.from(getServerActionExecutionContext()?.invalidations ?? []);\n}\n\nsubscribeFarmCacheInvalidation((key) => {\n getServerActionExecutionContext()?.invalidations.add(key);\n});\n\nsubscribeFarmCacheTask((task) => {\n getServerActionExecutionContext()?.cacheTasks.add(task);\n});\n\nfunction getServerActionStorage(): AsyncLocalStorage<ServerActionExecutionContext> {\n const globalState = globalThis as GlobalWithServerActionStorage;\n if (!globalState[SERVER_ACTION_STORAGE_KEY]) {\n globalState[SERVER_ACTION_STORAGE_KEY] = new AsyncLocalStorage<ServerActionExecutionContext>();\n }\n return globalState[SERVER_ACTION_STORAGE_KEY]!;\n}\n\nfunction getFallbackAbortController(): AbortController {\n const globalState = globalThis as GlobalWithServerActionStorage;\n if (!globalState[FALLBACK_ABORT_CONTROLLER_KEY]) {\n globalState[FALLBACK_ABORT_CONTROLLER_KEY] = new AbortController();\n }\n return globalState[FALLBACK_ABORT_CONTROLLER_KEY]!;\n}\n\n/**\n * Adapt the shared origin resolution onto the server-action error contract:\n * an unusable Origin/Referer is a 403 here, while a request that simply\n * carried neither header returns null for the caller to judge.\n */\nfunction resolveSourceOrigin(request: Request): string | null {\n const result = getRequestSourceOrigin(request);\n\n if (!result.ok) {\n throw new ServerActionRequestError(\n \"INVALID_ORIGIN\",\n 403,\n result.reason === \"opaque-origin\"\n ? \"Opaque origins are not allowed\"\n : \"Invalid request origin\",\n );\n }\n\n return result.origin;\n}\n\nfunction validateActionId(actionId?: string | null): asserts actionId is string {\n if (!actionId || actionId.length > 4096 || hasControlCharacters(actionId)) {\n throw new ServerActionRequestError(\"INVALID_ACTION_ID\", 400, \"Invalid server action id\");\n }\n}\n\nfunction hasControlCharacters(value: string): boolean {\n for (let index = 0; index < value.length; index++) {\n const code = value.charCodeAt(index);\n if (code <= 31 || code === 127) return true;\n }\n return false;\n}\n\nfunction getSupportedContentType(request: Request, kind: ServerActionRequestKind): string {\n const header = request.headers.get(\"content-type\")?.trim().toLowerCase();\n const contentType = header?.split(\";\", 1)[0]?.trim() ?? \"\";\n const supported = kind === \"form\" ? FORM_ACTION_CONTENT_TYPES : JAVASCRIPT_ACTION_CONTENT_TYPES;\n\n if (!supported.has(contentType)) {\n throw new ServerActionRequestError(\n \"UNSUPPORTED_CONTENT_TYPE\",\n 415,\n \"Unsupported server action content type\",\n );\n }\n\n return contentType;\n}\n\nasync function readBodyWithLimit(request: Request, limit: number): Promise<Uint8Array> {\n const contentLength = request.headers.get(\"content-length\")?.trim();\n if (contentLength) {\n if (!/^\\d+$/.test(contentLength)) {\n throw new ServerActionRequestError(\n \"INVALID_CONTENT_LENGTH\",\n 400,\n \"Invalid content-length header\",\n );\n }\n if (Number(contentLength) > limit) {\n throw new ServerActionRequestError(\"BODY_TOO_LARGE\", 413, \"Server action body is too large\");\n }\n }\n\n throwIfAborted(request.signal);\n if (!request.body) return new Uint8Array();\n\n const reader = request.body.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n const cancelBodyRead = () => {\n void reader.cancel(request.signal.reason).catch(() => {});\n };\n\n request.signal.addEventListener(\"abort\", cancelBodyRead, { once: true });\n\n try {\n while (true) {\n throwIfAborted(request.signal);\n const { done, value } = await reader.read();\n if (done) break;\n if (!value) continue;\n\n total += value.byteLength;\n if (total > limit) {\n const error = new ServerActionRequestError(\n \"BODY_TOO_LARGE\",\n 413,\n \"Server action body is too large\",\n );\n // As with API bodies, a cloned stream may wait for its untouched tee\n // branch. Cleanup must neither delay rejection nor replace its error.\n void reader.cancel(error).catch(() => {});\n throw error;\n }\n chunks.push(value);\n }\n } catch (error) {\n if (request.signal.aborted) throwIfAborted(request.signal);\n throw error;\n } finally {\n request.signal.removeEventListener(\"abort\", cancelBodyRead);\n reader.releaseLock();\n }\n\n throwIfAborted(request.signal);\n const body = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n body.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return body;\n}\n\nasync function parseFormData(request: Request, bytes: Uint8Array): Promise<FormData> {\n const body = new ArrayBuffer(bytes.byteLength);\n new Uint8Array(body).set(bytes);\n const copy = new Request(request.url, {\n method: \"POST\",\n headers: request.headers,\n body,\n });\n\n try {\n return await copy.formData();\n } catch {\n throw new ServerActionRequestError(\"INVALID_BODY\", 400, \"Invalid server action form body\");\n }\n}\n\nfunction getPublicErrorMessage(status: number): string {\n switch (status) {\n case 400:\n return \"Bad Request\";\n case 403:\n return \"Forbidden\";\n case 405:\n return \"Method Not Allowed\";\n case 413:\n return \"Payload Too Large\";\n case 415:\n return \"Unsupported Media Type\";\n default:\n return \"Server Action Request Failed\";\n }\n}\n\nfunction throwIfAborted(signal: AbortSignal): void {\n if (!signal.aborted) return;\n if (signal.reason !== undefined) throw signal.reason;\n throw new DOMException(\"The operation was aborted\", \"AbortError\");\n}\n","export const FARM_SERVER_FN_FAILURE_SYMBOL = Symbol.for(\"farm.server-fn.failure\");\n\nexport type SerializedServerFnFailure = {\n name: \"ServerFnFailure\";\n message: string;\n code: string;\n status: number;\n data: unknown;\n};\n\nexport class ServerFnFailure<\n TCode extends string = string,\n TData = unknown,\n TStatus extends number = number,\n> extends Error {\n readonly name = \"ServerFnFailure\" as const;\n readonly code: TCode;\n readonly data: TData;\n readonly status: TStatus;\n\n constructor(\n code: TCode,\n data: TData,\n options: {\n status: TStatus;\n message: string;\n },\n ) {\n super(options.message);\n this.code = code;\n this.data = data;\n this.status = options.status;\n\n Object.defineProperty(this, FARM_SERVER_FN_FAILURE_SYMBOL, {\n value: true,\n enumerable: false,\n });\n }\n}\n\nexport class ServerActionError extends Error {\n readonly name = \"ServerActionError\" as const;\n\n constructor(message = \"Server function failed\") {\n super(message);\n }\n}\n\nexport function isServerFnFailure(value: unknown): value is ServerFnFailure {\n if (!value || typeof value !== \"object\") return false;\n\n const candidate = value as Partial<ServerFnFailure> & {\n [FARM_SERVER_FN_FAILURE_SYMBOL]?: unknown;\n };\n return (\n candidate[FARM_SERVER_FN_FAILURE_SYMBOL] === true &&\n candidate.name === \"ServerFnFailure\" &&\n typeof candidate.code === \"string\" &&\n Number.isInteger(candidate.status) &&\n (candidate.status ?? 0) >= 400 &&\n (candidate.status ?? 0) <= 599\n );\n}\n\nexport function serializeServerFnFailure(value: unknown): SerializedServerFnFailure | null {\n if (!isServerFnFailure(value)) return null;\n\n return {\n name: \"ServerFnFailure\",\n message: value.message,\n code: value.code,\n status: value.status,\n data: value.data,\n };\n}\n\nexport function createServerFnTransportError(value: unknown): ServerFnFailure | ServerActionError {\n if (isSerializedServerFnFailure(value)) {\n return new ServerFnFailure(value.code, value.data, {\n status: value.status,\n message: value.message,\n });\n }\n\n const message =\n value && typeof value === \"object\" && \"message\" in value && typeof value.message === \"string\"\n ? value.message\n : \"Server function failed\";\n return new ServerActionError(message);\n}\n\nfunction isSerializedServerFnFailure(value: unknown): value is SerializedServerFnFailure {\n if (!value || typeof value !== \"object\") return false;\n\n const candidate = value as Partial<SerializedServerFnFailure>;\n return (\n candidate.name === \"ServerFnFailure\" &&\n typeof candidate.message === \"string\" &&\n typeof candidate.code === \"string\" &&\n Number.isInteger(candidate.status) &&\n (candidate.status ?? 0) >= 400 &&\n (candidate.status ?? 0) <= 599 &&\n \"data\" in candidate\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -323,11 +323,53 @@ function normalizeBudget(value, fallback) {
|
|
|
323
323
|
}
|
|
324
324
|
__name(normalizeBudget, "normalizeBudget");
|
|
325
325
|
|
|
326
|
+
// src/agent-config.ts
|
|
327
|
+
function resolveFarmAgentConfig(input) {
|
|
328
|
+
const jsonLd = input?.jsonLd;
|
|
329
|
+
if (!jsonLd) return { jsonLd: false };
|
|
330
|
+
return { jsonLd: jsonLd === true ? {} : jsonLd };
|
|
331
|
+
}
|
|
332
|
+
__name(resolveFarmAgentConfig, "resolveFarmAgentConfig");
|
|
333
|
+
function pruneUndefined(object) {
|
|
334
|
+
const result = {};
|
|
335
|
+
for (const [key, value] of Object.entries(object)) {
|
|
336
|
+
if (value !== void 0 && value !== null && value !== "") result[key] = value;
|
|
337
|
+
}
|
|
338
|
+
return result;
|
|
339
|
+
}
|
|
340
|
+
__name(pruneUndefined, "pruneUndefined");
|
|
341
|
+
function serializeJsonLd(value) {
|
|
342
|
+
return JSON.stringify(value).replace(/</g, "\\u003c");
|
|
343
|
+
}
|
|
344
|
+
__name(serializeJsonLd, "serializeJsonLd");
|
|
345
|
+
function renderFarmAgentJsonLd(config, context) {
|
|
346
|
+
const base = pruneUndefined({
|
|
347
|
+
name: config.name ?? context.siteName ?? context.title,
|
|
348
|
+
url: config.url ?? context.metadataBase,
|
|
349
|
+
description: config.description ?? context.description,
|
|
350
|
+
logo: config.logo,
|
|
351
|
+
sameAs: config.sameAs && config.sameAs.length > 0 ? config.sameAs : void 0
|
|
352
|
+
});
|
|
353
|
+
const object = {
|
|
354
|
+
"@context": "https://schema.org",
|
|
355
|
+
"@type": config.type || "Organization",
|
|
356
|
+
...base,
|
|
357
|
+
...config.properties || {}
|
|
358
|
+
};
|
|
359
|
+
if (Object.keys(object).length <= 2 && !config.properties) {
|
|
360
|
+
return "";
|
|
361
|
+
}
|
|
362
|
+
return `<script type="application/ld+json">${serializeJsonLd(object)}</script>`;
|
|
363
|
+
}
|
|
364
|
+
__name(renderFarmAgentJsonLd, "renderFarmAgentJsonLd");
|
|
365
|
+
|
|
326
366
|
export {
|
|
367
|
+
resolveFarmAgentConfig,
|
|
368
|
+
renderFarmAgentJsonLd,
|
|
327
369
|
resolveFarmPerformanceConfig,
|
|
328
370
|
manageFarmHtmlPreloads,
|
|
329
371
|
manageFarmLinkHeaderPreloads,
|
|
330
372
|
manageFarmDocumentPreloads,
|
|
331
373
|
reportFarmPreloadWarnings
|
|
332
374
|
};
|
|
333
|
-
//# sourceMappingURL=chunk-
|
|
375
|
+
//# sourceMappingURL=chunk-Z5ARESQG.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/preload.ts","../src/agent-config.ts"],"sourcesContent":["export type FarmPreloadMode = \"warn\" | \"enforce\";\n\nexport interface FarmPreloadUserConfig {\n /** Report excess hints or remove the lower-priority hints. @default \"enforce\" */\n mode?: FarmPreloadMode;\n /** Maximum image preload hints per document. @default 1 */\n maxImages?: number;\n /** Maximum font preload hints per document. @default 2 */\n maxFonts?: number;\n}\n\nexport interface ResolvedFarmPreloadConfig {\n mode: FarmPreloadMode;\n maxImages: number;\n maxFonts: number;\n}\n\nexport interface FarmPerformanceConfig {\n preload?: FarmPreloadUserConfig;\n}\n\nexport interface ResolvedFarmPerformanceConfig {\n preload: ResolvedFarmPreloadConfig;\n}\n\nexport type FarmPreloadKind = \"image\" | \"font\";\n\nexport interface FarmPreloadBudgetWarning {\n kind: FarmPreloadKind;\n count: number;\n budget: number;\n removed: number;\n}\n\nexport interface FarmManagedPreloads {\n value: string;\n warnings: FarmPreloadBudgetWarning[];\n}\n\nexport interface FarmManagedDocumentPreloads {\n html: string;\n linkHeader: string;\n warnings: FarmPreloadBudgetWarning[];\n}\n\nconst DEFAULT_PRELOAD_CONFIG: ResolvedFarmPreloadConfig = {\n mode: \"enforce\",\n maxImages: 1,\n maxFonts: 2,\n};\n\nconst reportedWarnings = new Map<string, number>();\nconst PRELOAD_WARNING_TTL_MS = 60_000;\nconst MAX_REPORTED_PRELOAD_WARNINGS = 256;\n\nexport function resolveFarmPerformanceConfig(\n config: FarmPerformanceConfig | undefined,\n): ResolvedFarmPerformanceConfig {\n return {\n preload: {\n mode: config?.preload?.mode === \"warn\" ? \"warn\" : \"enforce\",\n maxImages: normalizeBudget(config?.preload?.maxImages, DEFAULT_PRELOAD_CONFIG.maxImages),\n maxFonts: normalizeBudget(config?.preload?.maxFonts, DEFAULT_PRELOAD_CONFIG.maxFonts),\n },\n };\n}\n\n/**\n * Apply image and font budgets to HTML preload elements. High-priority image\n * hints are retained before ordinary hints, making an explicitly preloaded LCP\n * image the winner when a document contains too many React-generated hints.\n */\nexport function manageFarmHtmlPreloads(\n html: string,\n config: ResolvedFarmPreloadConfig,\n): FarmManagedPreloads {\n const elements = findHtmlLinkElements(html);\n const candidates = elements.flatMap((element, index) => {\n const kind = getHtmlPreloadKind(element.value);\n return kind\n ? [\n {\n index,\n kind,\n highPriority:\n readHtmlAttribute(element.value, \"fetchpriority\")?.toLowerCase() === \"high\",\n },\n ]\n : [];\n });\n\n const budget = selectPreloadsWithinBudget(candidates, config);\n if (config.mode === \"warn\" || budget.removed.size === 0) {\n return { value: html, warnings: budget.warnings };\n }\n\n return {\n value: removeHtmlLinkElements(html, elements, budget.removed),\n warnings: budget.warnings,\n };\n}\n\n/** Apply the same budgets to HTTP Link preload hints, including Farm fonts. */\nexport function manageFarmLinkHeaderPreloads(\n value: string,\n config: ResolvedFarmPreloadConfig,\n): FarmManagedPreloads {\n if (!value) return { value, warnings: [] };\n\n const links = splitLinkHeader(value);\n const candidates = links.flatMap((link, index) => {\n const kind = getLinkHeaderPreloadKind(link);\n return kind\n ? [\n {\n index,\n kind,\n highPriority: getLinkHeaderParameter(link, \"fetchpriority\")?.toLowerCase() === \"high\",\n },\n ]\n : [];\n });\n const budget = selectPreloadsWithinBudget(candidates, config);\n\n return {\n value:\n config.mode === \"enforce\"\n ? links.filter((_, index) => !budget.removed.has(index)).join(\", \")\n : value,\n warnings: budget.warnings,\n };\n}\n\n/** Apply a single document budget across HTML and HTTP Link header hints. */\nexport function manageFarmDocumentPreloads(\n html: string,\n linkHeader: string,\n config: ResolvedFarmPreloadConfig,\n): FarmManagedDocumentPreloads {\n const elements = findHtmlLinkElements(html);\n const links = linkHeader ? splitLinkHeader(linkHeader) : [];\n const headerOffset = elements.length;\n const candidates: PreloadCandidate[] = [];\n\n for (const [index, element] of elements.entries()) {\n const kind = getHtmlPreloadKind(element.value);\n if (!kind) continue;\n candidates.push({\n index,\n kind,\n highPriority: readHtmlAttribute(element.value, \"fetchpriority\")?.toLowerCase() === \"high\",\n });\n }\n for (const [index, link] of links.entries()) {\n const kind = getLinkHeaderPreloadKind(link);\n if (!kind) continue;\n candidates.push({\n index: headerOffset + index,\n kind,\n highPriority: getLinkHeaderParameter(link, \"fetchpriority\")?.toLowerCase() === \"high\",\n });\n }\n\n const budget = selectPreloadsWithinBudget(candidates, config);\n if (config.mode === \"warn\" || budget.removed.size === 0) {\n return { html, linkHeader, warnings: budget.warnings };\n }\n\n return {\n html: removeHtmlLinkElements(html, elements, budget.removed),\n linkHeader: links.filter((_, index) => !budget.removed.has(headerOffset + index)).join(\", \"),\n warnings: budget.warnings,\n };\n}\n\n/** Rate-limit identical route-and-budget warnings within a server process. */\nexport function reportFarmPreloadWarnings(\n warnings: FarmPreloadBudgetWarning[],\n context = \"the rendered document\",\n): void {\n const now = Date.now();\n for (const [key, reportedAt] of reportedWarnings) {\n if (now - reportedAt >= PRELOAD_WARNING_TTL_MS) reportedWarnings.delete(key);\n }\n\n for (const warning of warnings) {\n const key = `${context}:${warning.kind}:${warning.count}:${warning.budget}:${warning.removed}`;\n const reportedAt = reportedWarnings.get(key);\n if (reportedAt !== undefined && now - reportedAt < PRELOAD_WARNING_TTL_MS) continue;\n reportedWarnings.set(key, now);\n while (reportedWarnings.size > MAX_REPORTED_PRELOAD_WARNINGS) {\n const oldest = reportedWarnings.keys().next().value;\n if (oldest === undefined) break;\n reportedWarnings.delete(oldest);\n }\n\n const action = warning.removed > 0 ? ` Removed ${warning.removed} lower-priority hint(s).` : \"\";\n const recommendation =\n warning.kind === \"image\"\n ? ' Mark only the LCP image with `preload` or `fetchPriority=\"high\"`.'\n : \" Set `preload: false` on fonts that are not required above the fold.\";\n console.warn(\n `[Farm.js] ${context} emitted ${warning.count} ${warning.kind} preload hints ` +\n `(budget: ${warning.budget}).${action}${recommendation}`,\n );\n }\n}\n\nexport function clearReportedFarmPreloadWarnings(): void {\n reportedWarnings.clear();\n}\n\ninterface PreloadCandidate {\n index: number;\n kind: FarmPreloadKind;\n highPriority: boolean;\n}\n\nfunction selectPreloadsWithinBudget(\n candidates: PreloadCandidate[],\n config: ResolvedFarmPreloadConfig,\n): { removed: Set<number>; warnings: FarmPreloadBudgetWarning[] } {\n const removed = new Set<number>();\n const warnings: FarmPreloadBudgetWarning[] = [];\n\n for (const kind of [\"image\", \"font\"] as const) {\n const matching = candidates.filter((candidate) => candidate.kind === kind);\n const limit = kind === \"image\" ? config.maxImages : config.maxFonts;\n if (matching.length <= limit) continue;\n\n const retained = new Set(\n [...matching]\n .sort(\n (left, right) =>\n Number(right.highPriority) - Number(left.highPriority) || left.index - right.index,\n )\n .slice(0, limit)\n .map((candidate) => candidate.index),\n );\n\n if (config.mode === \"enforce\") {\n for (const candidate of matching) {\n if (!retained.has(candidate.index)) removed.add(candidate.index);\n }\n }\n\n warnings.push({\n kind,\n count: matching.length,\n budget: limit,\n removed: config.mode === \"enforce\" ? matching.length - retained.size : 0,\n });\n }\n\n return { removed, warnings };\n}\n\nfunction getHtmlPreloadKind(link: string): FarmPreloadKind | undefined {\n const rel = readHtmlAttribute(link, \"rel\")?.toLowerCase().split(/\\s+/) || [];\n if (!rel.includes(\"preload\")) return undefined;\n return normalizePreloadKind(readHtmlAttribute(link, \"as\"));\n}\n\nfunction getLinkHeaderPreloadKind(link: string): FarmPreloadKind | undefined {\n const relations = getLinkHeaderParameter(link, \"rel\")?.toLowerCase().split(/\\s+/) ?? [];\n if (!relations.includes(\"preload\")) return undefined;\n return normalizePreloadKind(getLinkHeaderParameter(link, \"as\"));\n}\n\nfunction getLinkHeaderParameter(link: string, name: string): string | undefined {\n const uriEnd = link.indexOf(\">\");\n if (uriEnd === -1) return undefined;\n\n for (const parameter of splitLinkParameters(link.slice(uriEnd + 1))) {\n const separator = parameter.indexOf(\"=\");\n const parameterName = (separator === -1 ? parameter : parameter.slice(0, separator))\n .trim()\n .toLowerCase();\n if (parameterName !== name.toLowerCase() || separator === -1) continue;\n const rawValue = parameter.slice(separator + 1).trim();\n if (rawValue.startsWith('\"') && rawValue.endsWith('\"')) {\n return rawValue.slice(1, -1).replace(/\\\\([\\\\\"])/g, \"$1\");\n }\n return rawValue;\n }\n return undefined;\n}\n\nfunction splitLinkParameters(value: string): string[] {\n const parameters: string[] = [];\n let start = 0;\n let quoted = false;\n for (let index = 0; index < value.length; index += 1) {\n const character = value[index];\n if (character === '\"' && !isEscaped(value, index)) quoted = !quoted;\n else if (character === \";\" && !quoted) {\n const parameter = value.slice(start, index).trim();\n if (parameter) parameters.push(parameter);\n start = index + 1;\n }\n }\n const parameter = value.slice(start).trim();\n if (parameter) parameters.push(parameter);\n return parameters;\n}\n\nfunction normalizePreloadKind(value: string | undefined): FarmPreloadKind | undefined {\n const normalized = value?.toLowerCase();\n return normalized === \"image\" || normalized === \"font\" ? normalized : undefined;\n}\n\nfunction readHtmlAttribute(element: string, name: string): string | undefined {\n const match = element.match(\n new RegExp(`\\\\s${name}\\\\s*=\\\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\\\s>]+))`, \"i\"),\n );\n return match?.[1] ?? match?.[2] ?? match?.[3];\n}\n\ninterface HtmlLinkElement {\n start: number;\n end: number;\n value: string;\n}\n\nfunction findHtmlLinkElements(html: string): HtmlLinkElement[] {\n const elements: HtmlLinkElement[] = [];\n const lowerHtml = html.toLowerCase();\n let cursor = 0;\n\n while (cursor < html.length) {\n const start = html.indexOf(\"<\", cursor);\n if (start === -1) break;\n\n if (lowerHtml.startsWith(\"<!--\", start)) {\n const commentEnd = lowerHtml.indexOf(\"-->\", start + 4);\n cursor = commentEnd === -1 ? html.length : commentEnd + 3;\n continue;\n }\n\n const rawText = lowerHtml\n .slice(start)\n .match(/^<(script|style|template|textarea|title|noscript|svg)(?=[\\s/>])/);\n if (rawText?.[1]) {\n const openingEnd = findHtmlTagEnd(html, start);\n if (openingEnd === -1) break;\n const closingStart = findHtmlClosingTag(lowerHtml, rawText[1], openingEnd);\n if (closingStart === -1) {\n cursor = html.length;\n continue;\n }\n const closingEnd = findHtmlTagEnd(html, closingStart);\n cursor = closingEnd === -1 ? html.length : closingEnd;\n continue;\n }\n\n if (/^<link(?=[\\s/>])/i.test(html.slice(start))) {\n const end = findHtmlTagEnd(html, start);\n if (end === -1) break;\n elements.push({ start, end, value: html.slice(start, end) });\n cursor = end;\n continue;\n }\n\n if (/^<\\/?[A-Za-z][\\w:-]*(?=[\\s/>])/.test(html.slice(start))) {\n const end = findHtmlTagEnd(html, start);\n cursor = end === -1 ? html.length : end;\n continue;\n }\n\n cursor = start + 1;\n }\n\n return elements;\n}\n\nfunction findHtmlClosingTag(html: string, tagName: string, start: number): number {\n const prefix = `</${tagName}`;\n let candidate = html.indexOf(prefix, start);\n while (candidate !== -1) {\n const boundary = html[candidate + prefix.length];\n if (boundary === \">\" || boundary === \"/\" || /\\s/.test(boundary ?? \"\")) return candidate;\n candidate = html.indexOf(prefix, candidate + prefix.length);\n }\n return -1;\n}\n\nfunction findHtmlTagEnd(html: string, start: number): number {\n let quote: '\"' | \"'\" | undefined;\n for (let index = start + 1; index < html.length; index += 1) {\n const character = html[index];\n if (quote) {\n if (character === quote) quote = undefined;\n } else if (character === '\"' || character === \"'\") {\n quote = character;\n } else if (character === \">\") {\n return index + 1;\n }\n }\n return -1;\n}\n\nfunction removeHtmlLinkElements(\n html: string,\n elements: HtmlLinkElement[],\n removed: ReadonlySet<number>,\n): string {\n let cursor = 0;\n let output = \"\";\n for (const [index, element] of elements.entries()) {\n if (!removed.has(index)) continue;\n output += html.slice(cursor, element.start);\n cursor = element.end;\n }\n return output + html.slice(cursor);\n}\n\nfunction splitLinkHeader(value: string): string[] {\n const links: string[] = [];\n let start = 0;\n let insideAngleBrackets = false;\n let quoted = false;\n\n for (let index = 0; index < value.length; index += 1) {\n const character = value[index];\n if (quoted) {\n if (character === '\"' && !isEscaped(value, index)) quoted = false;\n continue;\n }\n if (character === '\"') {\n quoted = true;\n } else if (character === \"<\") {\n insideAngleBrackets = true;\n } else if (character === \">\") {\n insideAngleBrackets = false;\n } else if (character === \",\" && !insideAngleBrackets) {\n links.push(value.slice(start, index).trim());\n start = index + 1;\n }\n }\n\n links.push(value.slice(start).trim());\n return links.filter(Boolean);\n}\n\nfunction isEscaped(value: string, index: number): boolean {\n let backslashes = 0;\n for (let cursor = index - 1; cursor >= 0 && value[cursor] === \"\\\\\"; cursor -= 1) {\n backslashes += 1;\n }\n return backslashes % 2 === 1;\n}\n\nfunction normalizeBudget(value: number | undefined, fallback: number): number {\n return typeof value === \"number\" && Number.isFinite(value) && value >= 0\n ? Math.floor(value)\n : fallback;\n}\n","/**\n * Agent-readiness configuration: opt-in primitives that make a Farm site easier\n * for AI agents and crawlers to discover, resolve, and use. Off by default so\n * sites that do not want agent exposure (internal tools, private dashboards) are\n * unaffected.\n */\n\n/** schema.org JSON-LD emitted in the document head to identify the site. */\nexport interface FarmAgentJsonLd {\n /**\n * schema.org `@type`. Common values: `\"Organization\"` for a company or\n * project, `\"SoftwareApplication\"` for a product, `\"WebSite\"`, `\"Person\"`.\n *\n * @default \"Organization\"\n */\n type?: string;\n /** Entity name. Defaults to the site's Open Graph site name or page title. */\n name?: string;\n /** Canonical URL for the entity. Defaults to the configured `metadataBase`. */\n url?: string;\n /** Short description. Defaults to the page/site metadata description. */\n description?: string;\n /** Logo URL. */\n logo?: string;\n /** URLs that also represent this entity (social profiles, repos) — schema.org `sameAs`. */\n sameAs?: string[];\n /** Additional schema.org properties merged into the emitted object. */\n properties?: Record<string, unknown>;\n}\n\nexport interface FarmAgentUserConfig {\n /**\n * Emit schema.org JSON-LD in the document head so agents and crawlers can\n * resolve the site's identity. `true` emits an `Organization` built from the\n * site's metadata; an object customizes the type and fields.\n *\n * @default false\n */\n jsonLd?: boolean | FarmAgentJsonLd;\n}\n\nexport interface ResolvedFarmAgentConfig {\n jsonLd: FarmAgentJsonLd | false;\n}\n\nexport function resolveFarmAgentConfig(\n input: FarmAgentUserConfig | undefined,\n): ResolvedFarmAgentConfig {\n const jsonLd = input?.jsonLd;\n if (!jsonLd) return { jsonLd: false };\n return { jsonLd: jsonLd === true ? {} : jsonLd };\n}\n\nexport interface FarmAgentJsonLdContext {\n metadataBase?: string;\n siteName?: string;\n title?: string;\n description?: string;\n}\n\nfunction pruneUndefined(object: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(object)) {\n if (value !== undefined && value !== null && value !== \"\") result[key] = value;\n }\n return result;\n}\n\n/**\n * Serialize a JSON-LD object for inline `<script>` embedding, escaping `<` so a\n * value containing `</script>` cannot break out of the tag.\n */\nfunction serializeJsonLd(value: unknown): string {\n return JSON.stringify(value).replace(/</g, \"\\\\u003c\");\n}\n\n/**\n * Build a JSON-LD `<script>` tag for the site identity, or an empty string when\n * there is not enough information to emit meaningful structured data.\n */\nexport function renderFarmAgentJsonLd(\n config: FarmAgentJsonLd,\n context: FarmAgentJsonLdContext,\n): string {\n const base = pruneUndefined({\n name: config.name ?? context.siteName ?? context.title,\n url: config.url ?? context.metadataBase,\n description: config.description ?? context.description,\n logo: config.logo,\n sameAs: config.sameAs && config.sameAs.length > 0 ? config.sameAs : undefined,\n });\n\n const object = {\n \"@context\": \"https://schema.org\",\n \"@type\": config.type || \"Organization\",\n ...base,\n ...(config.properties || {}),\n };\n\n // Nothing beyond @context/@type and no custom properties: not worth emitting.\n if (Object.keys(object).length <= 2 && !config.properties) {\n return \"\";\n }\n\n return `<script type=\"application/ld+json\">${serializeJsonLd(object)}</script>`;\n}\n"],"mappings":"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","names":["parameter"]}
|