gemi 0.133.0 → 0.135.0
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/ai/index.d.ts +2 -2
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +9 -9
- package/dist/ai/index.js.map +4 -4
- package/dist/ai/providers/realtime.d.ts +75 -4
- package/dist/ai/providers/realtime.d.ts.map +1 -1
- package/dist/ai/providers/sideband.d.ts +7 -2
- package/dist/ai/providers/sideband.d.ts.map +1 -1
- package/dist/ai/voice/energyVad.d.ts +42 -0
- package/dist/ai/voice/energyVad.d.ts.map +1 -0
- package/dist/ai/voice/index.d.ts +7 -0
- package/dist/ai/voice/index.d.ts.map +1 -1
- package/dist/ai/voice/index.js +601 -1
- package/dist/ai/voice/index.js.map +1 -1
- package/dist/ai/voice/liveTranscription.d.ts +99 -0
- package/dist/ai/voice/liveTranscription.d.ts.map +1 -0
- package/dist/ai/voice/transcriptionState.d.ts +52 -0
- package/dist/ai/voice/transcriptionState.d.ts.map +1 -0
- package/dist/ai/voice/useLiveTranscription.d.ts +86 -0
- package/dist/ai/voice/useLiveTranscription.d.ts.map +1 -0
- package/dist/bin/gemi.js.map +1 -1
- package/dist/chunk-6hstj70n.js +24 -0
- package/dist/{chunk-s21kn0x8.js.map → chunk-6hstj70n.js.map} +3 -3
- package/dist/{chunk-wevj4981.js → chunk-e2tjw0qx.js} +7 -7
- package/dist/{chunk-wevj4981.js.map → chunk-e2tjw0qx.js.map} +4 -4
- package/dist/{chunk-s55t7rxw.js → chunk-n68a4r72.js} +1 -1
- package/dist/{chunk-b6yb3svm.js → chunk-rhjh79np.js} +2 -2
- package/dist/{chunk-b6yb3svm.js.map → chunk-rhjh79np.js.map} +1 -1
- package/dist/{chunk-4pvv8qs0.js → chunk-sxcxmwbt.js} +1 -1
- package/dist/client/index.js +8 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/islands.d.ts +10 -0
- package/dist/client/islands.d.ts.map +1 -1
- package/dist/facades/index.js +1 -1
- package/dist/http/index.js +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/kernel/index.js +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/modulePreloads.d.ts +14 -2
- package/dist/server/modulePreloads.d.ts.map +1 -1
- package/dist/services/index.js +1 -1
- package/dist/services/router/staticDocument.d.ts +6 -3
- package/dist/services/router/staticDocument.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-s21kn0x8.js +0 -24
- /package/dist/{chunk-s55t7rxw.js.map → chunk-n68a4r72.js.map} +0 -0
- /package/dist/{chunk-4pvv8qs0.js.map → chunk-sxcxmwbt.js.map} +0 -0
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../client/ServerQueryContext.tsx","../../client/useRouteData.ts","../../client/isPlainObject.ts","../../client/useQuery.ts","../../client/useInfiniteQuery.ts","../../services/broadcast/socketHeader.ts","../../client/mutationModules.ts","../../client/useMutation.ts","../../client/useMutate.ts","../../client/fetchFile.ts","../../client/useSetQueryData.ts","../../client/useSubscription.ts","../../client/useChannel.ts","../../client/Mutation.tsx","../../client/useDomain.ts","../../client/useIsNavigationPending.ts","../../client/useNavigationProgress.ts","../../client/usePrefetch.ts","../../client/useBreadcrumbs.ts","../../client/Link.tsx","../../client/Redirect.tsx","../../client/htmlAttributes.ts","../../client/fonts.ts","../../client/Head.tsx","../../utils/partialRender.ts","../../client/helpers/mergeCarriedSegments.ts","../../client/helpers/loadRoutePayload.ts","../../utils/intendedUrl.ts","../../client/ClientRouter.tsx","../../client/init.tsx","../../client/DictionarySinkContext.ts","../../client/createRoot.tsx","../../client/Image.tsx","../../client/auth/useForgotPassword.ts","../../client/auth/useSignIn.tsx","../../client/auth/useSignUp.ts","../../client/auth/useSignOut.ts","../../client/auth/useResetPassword.ts","../../client/auth/useUser.ts","../../client/auth/useIntendedUrl.ts","../../client/auth/useEmailCode.ts","../../client/useFeature.ts","../../utils/parseTranslation.tsx","../../client/useTranslator.ts","../../i18n/formatter.ts","../../client/useFormatter.ts","../../client/useDictionary.ts","../../i18n/dictionaryShape.ts","../../i18n/defineDictionary.ts","../../client/useLocale.ts","../../client/OpenGraphImage.tsx","../../client/useAppIdMissmatch.ts","../../client/islands.tsx","../../client/staticNavigation.ts"],"sourcesContent":["import { createContext } from \"react\";\n\n/**\n * The structural slice of the server's `ServerQueryStore` that `useQuery`\n * needs during a streaming server render. Declared here — not imported from\n * `services/router` — because this file ships in the browser bundle; only the\n * shape crosses over, never the implementation.\n */\nexport interface ServerQueryEntryLike {\n status: \"pending\" | \"resolved\" | \"rejected\";\n data?: any;\n error?: any;\n promise: Promise<void>;\n}\n\nexport interface ServerQueriesLike {\n ensure(\n path: string,\n options?: {\n params?: Record<string, any>;\n search?: Record<string, string | number | boolean | null>;\n },\n source?: \"prefetch\" | \"render\",\n ): ServerQueryEntryLike;\n}\n\n/**\n * Populated only during a streaming server render (`createRoot` threads the\n * request's store through); always `null` in the browser, where suspension\n * runs on `QueryResource` instead.\n */\nexport const ServerQueryContext = createContext<ServerQueriesLike | null>(null);\n","import { useContext } from \"react\";\nimport { RouteStateContext } from \"./RouteStateContext\";\n\nexport function useRouteData() {\n const { data, i18n, prefetchedData, breadcrumbs } =\n useContext(RouteStateContext);\n\n return { data, i18n, prefetchedData, breadcrumbs };\n}\n","export function isPlainObject(\n value: unknown,\n): value is Record<string, unknown> {\n return (\n value !== null &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n Object.getPrototypeOf(value) === Object.prototype\n );\n}\n","import {\n useCallback,\n useContext,\n useDeferredValue,\n useEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport type { RPC } from \"./rpc\";\nimport type { NestedPrettify } from \"../utils/type\";\n\nimport type { ApiRouterHandler } from \"../http/ApiRouter\";\nimport type { UnwrapPromise } from \"../utils/type\";\nimport { QueryConfigContext, QueryManagerContext } from \"./QueryManagerContext\";\nimport { ServerQueryContext } from \"./ServerQueryContext\";\nimport { DEFAULT_STALE_TIME } from \"./QueryResource\";\nimport { applyParams } from \"../utils/applyParams\";\nimport type { UrlParser } from \"./types\";\nimport { toVariantKey } from \"../utils/variantKey\";\nimport { useParams } from \"./useParams\";\nimport { useRouteData } from \"./useRouteData\";\nimport { isPlainObject } from \"./isPlainObject\";\nimport {\n DEFAULT_RETRY,\n retryDelayFor,\n shouldRetryQuery,\n type QueryFailure,\n type RetryDelayOption,\n type RetryOption,\n} from \"./retryPolicy\";\nimport type { LiveChannel } from \"./realtime/live\";\nimport { followLive } from \"./realtime/loader\";\nimport { RealtimeContext } from \"./realtime/RealtimeContext\";\n\n/**\n * A DOM event or React's synthetic one. Never a plain object, so a cached\n * value that happens to have a `nativeEvent` key is not mistaken for one.\n */\nfunction isEventLike(value: unknown): boolean {\n if (typeof value !== \"object\" || value === null || isPlainObject(value)) {\n return false;\n }\n if (typeof Event !== \"undefined\" && value instanceof Event) return true;\n return (\n \"nativeEvent\" in value &&\n typeof (value as { preventDefault?: unknown }).preventDefault === \"function\"\n );\n}\n\nexport interface Config<T> {\n fallbackData?: T;\n /**\n * When true (the default), a variant change keeps rendering the previous\n * variant's data while the new one loads. Under suspense this reads through\n * a deferred variant key, so changing `search`/`params` never flashes the\n * segment fallback and needs no `startTransition` at the call site — the\n * pending window is exposed as `loading: true`. Set to `false` to get the\n * suspend-on-variant-change semantics back (e.g. tab-like switches where\n * stale rows would mislead). First mount always suspends either way.\n */\n keepPreviousData?: boolean;\n /**\n * Background retries for a failed `suspense: false` query (under suspense\n * the error goes to the error boundary instead). Default `3`: network\n * failures, 408, 429 and 5xx are retried up to three times in a row with\n * exponential backoff; any other 4xx (401, 403, 404, 422, …) is returned\n * once and never retried, because sending the same request again gets the\n * same answer. `false` turns retries off, `true` removes the cap, and a\n * function `(failureCount, error) => boolean` decides alone.\n */\n retry?: RetryOption;\n /**\n * The wait before each retry, in ms, or `(failureCount, error) => ms`.\n * Default: `1000 * 2^(failureCount - 1)` capped at 30s — 1s, 2s, 4s. A\n * `Retry-After` header on the failed response (a 429 or 503) wins.\n */\n retryDelay?: RetryDelayOption;\n /**\n * @deprecated Use `retryDelay`. Kept as the base of the default backoff:\n * the first retry waits this long, each next one twice as long.\n */\n retryIntervalOnError?: number;\n refreshInterval?: number;\n /**\n * When true, the query revalidates whenever the tab comes back to the\n * foreground. Off by default. `staleTime` still gates it, so a quick\n * tab-out-and-back costs nothing and only data that has actually aged goes\n * back to the wire — silently, keeping what's on screen rendered.\n */\n revalidateOnFocus?: boolean;\n /**\n * Minimum gap between two `revalidateOnFocus` revalidations of the same\n * query, in ms (default 5000). `focus` fires on far more than tab returns —\n * dismissing a file picker, closing a popup, clicking in and out of an\n * embedded iframe — and `staleTime: 0` would otherwise turn each of those\n * into a request per mounted query.\n */\n focusThrottleInterval?: number;\n /** How long cached data stays fresh before a read revalidates it, in ms. */\n staleTime?: number;\n debug?: boolean;\n lazy?: boolean;\n /**\n * When true (the default), a query with no cached data suspends the nearest\n * `Suspense` boundary instead of returning `loading: true`, and an HTTP\n * failure throws into the nearest error boundary. `lazy: true` implies\n * `suspense: false`.\n */\n suspense?: boolean;\n /**\n * Polls while it returns a delay in ms: after data lands, the query refetches\n * that long later; `0` stops. `duration` is the delay it returned last (`0`\n * at first), for backoff. It is read from the current render after every\n * commit, so it can depend on props and state too\n * (`(d) => (d.active || building ? 2000 : 0)`): a stopped poll restarts as\n * soon as it returns a delay again, and a pending one is cancelled when it\n * returns `0`. Keep it pure and cheap.\n */\n refetchUntil?: (data: T, duration: number) => number;\n /**\n * A broadcast channel that keeps this query fresh: its events and resyncs\n * refetch the query (every cached variant; the rendered ones now). While\n * the channel is open, `refetchUntil` and `refreshInterval` are paused;\n * while it is not (connecting, denied, offline, on the server), they run\n * as the fallback.\n *\n * ```ts\n * useQuery(\"/site-imports/:importId\", { params }, { refetchUntil: (d) => (d.active ? 2000 : 0), live: \"user\" });\n * ```\n */\n live?: LiveChannel;\n}\n\ntype WithOptionalValues<T> = {\n [K in keyof T]: T[K] | null;\n};\n\nconst defaultConfig: Config<any> = {\n fallbackData: null,\n keepPreviousData: true,\n retry: DEFAULT_RETRY,\n refreshInterval: 999999,\n revalidateOnFocus: false,\n focusThrottleInterval: 5000,\n staleTime: DEFAULT_STALE_TIME,\n debug: false,\n lazy: false,\n suspense: true,\n};\n\nexport type GetRPC = {\n [K in keyof RPC as K extends `GET:${infer P}` ? P : never]: RPC[K];\n};\n\nexport type Data<T extends keyof GetRPC> =\n GetRPC[T] extends ApiRouterHandler<any, infer Data, any>\n ? UnwrapPromise<Data>\n : never;\n\ntype Input<T extends keyof GetRPC> =\n GetRPC[T] extends ApiRouterHandler<infer I, any, any> ? I : never;\n\ntype QueryOptions<T extends keyof GetRPC> = {\n search?: Partial<WithOptionalValues<Input<T>>>;\n};\n\ntype Error = Record<string, unknown>;\n\nconst defaultOptions: QueryOptions<any> & { params?: Record<string, any> } = {\n params: {} as Record<string, string>,\n search: {} as Record<string, string>,\n};\n\nexport type QueryResult<T extends keyof GetRPC> = NestedPrettify<Data<T> & {}>;\n\nexport type Options<T extends keyof GetRPC> = {\n search?: Record<string, string | number | boolean | null>;\n params?: Partial<UrlParser<`${T & string}`>>;\n};\n\ninterface QueryReturn<T extends keyof GetRPC, D> {\n data: D;\n loading: boolean;\n error: Error;\n mutate: {\n (fn?: NestedPrettify<Data<T>>): void;\n (fn?: (data: NestedPrettify<Data<T>>) => NestedPrettify<Data<T>>): void;\n };\n trigger: () => void;\n prefetch: () => void;\n refetch: () => void;\n version: number;\n}\n\n/**\n * A suspense-enabled query never renders without data, so `data` is\n * non-nullable. Opting out — `suspense: false` or `lazy: true` — brings back\n * the `loading` flag and with it a `data` that can be `undefined`.\n */\ninterface SuspenseConfig<T> extends Omit<Config<T>, \"suspense\" | \"lazy\"> {\n suspense?: true;\n lazy?: false;\n}\n\n/** A per-call `suspense: true` opt-in — wins over an app-wide `suspense: false`. */\ninterface ExplicitSuspenseConfig<T> extends Omit<\n Config<T>,\n \"suspense\" | \"lazy\"\n> {\n suspense: true;\n lazy?: false;\n}\n\n/**\n * The type-level mirror of a provider-level `queryConfig: { suspense: false }`.\n * The `useQuery` overloads reflect the call site only — they cannot see the\n * value threaded through `createRoot` — so an app that turns suspense off\n * app-wide flips the default `data` nullability with the same\n * module-augmentation switch RPC types use:\n *\n * ```ts\n * declare module \"gemi/client\" {\n * interface GemiQueryDefaults {\n * suspense: false;\n * }\n * }\n * ```\n *\n * A per-call `suspense: true` still narrows `data` back to non-nullable.\n */\nexport interface GemiQueryDefaults {}\n\ntype DefaultData<T extends keyof GetRPC> = GemiQueryDefaults extends {\n suspense: false;\n}\n ? NestedPrettify<Data<T>> | undefined\n : NestedPrettify<Data<T>>;\n\nexport function useQuery<T extends keyof GetRPC>(\n url: T,\n options: Options<T> | undefined,\n config: ExplicitSuspenseConfig<Data<T>>,\n): QueryReturn<T, NestedPrettify<Data<T>>>;\nexport function useQuery<T extends keyof GetRPC>(\n url: T,\n options?: Options<T>,\n config?: SuspenseConfig<Data<T>>,\n): QueryReturn<T, DefaultData<T>>;\nexport function useQuery<T extends keyof GetRPC>(\n url: T,\n options?: Options<T>,\n config?: Config<Data<T>>,\n): QueryReturn<T, NestedPrettify<Data<T>> | undefined>;\nexport function useQuery<T extends keyof GetRPC>(\n url: T,\n ...args: [options?: Options<T>, config?: Config<Data<T>>]\n) {\n const [options, config] = args;\n // Resolution order: per-call config → provider `queryConfig` → framework\n // defaults. The first two merge here; `useFrameworkQuery` applies the last.\n // Only *defined* per-call keys participate: a key explicitly set to\n // `undefined` (`{ suspense: cond ? true : undefined }`, forwarding an\n // optional prop) must fall through to the provider default, not clobber it\n // — a plain spread would copy the `undefined` over it. The provider value\n // is already sanitized at the provider (see `QueryManagerProvider`).\n // `user` is `useUser`'s own section, not a query default.\n const { user: _user, ...queryConfig } = useContext(QueryConfigContext) ?? {};\n const merged: Config<Data<T>> = { ...queryConfig };\n if (config) {\n for (const key of Object.keys(config) as Array<keyof Config<Data<T>>>) {\n if (config[key] !== undefined) {\n (merged as Record<string, unknown>)[key] = config[key];\n }\n }\n }\n return useFrameworkQuery(url, options, merged);\n}\n\n/**\n * `useQuery` minus the app's provider-level `queryConfig`: per-call config\n * resolves straight against the framework defaults. Framework-internal hooks\n * (`useUser`'s `suspense: false`, `useSignIn`'s `lazy`) build on this so an\n * app-wide `queryConfig` can never change their semantics. Deliberately not\n * exported from the package root.\n */\nexport function useFrameworkQuery<T extends keyof GetRPC>(\n url: T,\n ...args: [options?: Options<T>, config?: Config<Data<T>>]\n): QueryReturn<T, NestedPrettify<Data<T>> | undefined> {\n const _params = useParams();\n const [_options = defaultOptions, _config = defaultConfig] = args;\n const options = { ...defaultOptions, ..._options };\n const config = { ...defaultConfig, ..._config };\n const suspense = config.suspense !== false && !config.lazy;\n const params =\n \"params\" in options ? { ..._params, ...options.params } : _params;\n const search = \"search\" in options ? (options.search ?? {}) : {};\n const { getResource } = useContext(QueryManagerContext);\n const serverQueries = useContext(ServerQueryContext);\n const currentPath = applyParams(url, params);\n const currentVariantKey = toVariantKey(search);\n // `keepPreviousData` under suspense: read through deferred keys so a\n // variant change never suspends the committed tree. The urgent render keeps\n // showing the previous variant's data; React re-renders in the background\n // with the new keys, suspends *that* attempt only (no fallback flash), and\n // commits when the data lands — no `startTransition` needed at the call\n // site. First mount is unchanged: deferred and current keys are equal, so\n // an uncached query suspends into the segment fallback as today. Both hooks\n // run unconditionally (hook order); the values are only *used* when\n // deferring applies.\n //\n // Deliberate: during the pending window the imperative callbacks\n // (`mutate`/`refetch`/`trigger`/`prefetch`) and the revalidation effects\n // close over the deferred — i.e. *visible* — variant and resource, so they\n // act on the data the user is looking at, not the variant still loading in\n // the background. The window ends when the deferred render commits, at\n // which point they re-bind to the new keys.\n const deferredPath = useDeferredValue(currentPath);\n const deferredVariantKey = useDeferredValue(currentVariantKey);\n const deferVariant = suspense && config.keepPreviousData;\n const normalPath = deferVariant ? deferredPath : currentPath;\n const variantKey = deferVariant ? deferredVariantKey : currentVariantKey;\n // The pending signal for pager UI: true while the visible data belongs to\n // the previous variant and the new one is still loading in the background.\n const isDeferred =\n normalPath !== currentPath || variantKey !== currentVariantKey;\n const { prefetchedData } = useRouteData();\n // `fallbackData` is a single variant's value, so it seeds under this\n // query's variant key; `prefetchedData[normalPath]` is already the full\n // `{ [variantKey]: data }` map the server produced.\n const seed =\n config.fallbackData != null\n ? { [variantKey]: config.fallbackData }\n : prefetchedData?.[normalPath];\n // A memoized map lookup on the provider's ref: stable and cheap, so the\n // resource is derived every render — a params change swaps it in the same\n // render pass instead of flashing through an effect.\n const resource = getResource(normalPath, seed ?? undefined);\n const lazy = config.lazy;\n\n const configRef = useRef(config);\n configRef.current = config;\n\n // `live`: the channel's events and resyncs refetch every cached variant of\n // this path (the rendered ones now), and polling pauses while it is open.\n // `followLive` loads the subscription on first use (#891), so a page whose\n // queries are not live carries none of it. Keyed on the option's value: an\n // inline `live` object is a new one every render.\n const realtime = useContext(RealtimeContext);\n const [liveOpen, setLiveOpen] = useState(false);\n const liveResourceRef = useRef(resource);\n liveResourceRef.current = resource;\n const liveKey = config.live ? JSON.stringify(config.live) : null;\n useEffect(() => {\n if (liveKey === null) return;\n return followLive(realtime, JSON.parse(liveKey), () => liveResourceRef.current, setLiveOpen);\n }, [realtime, liveKey]);\n\n const refreshIntervalRef = useRef<ReturnType<typeof setInterval> | null>(\n null,\n );\n const fetchedRef = useRef(!lazy);\n // `refetchUntil`'s poll: the pending timer, the last delay it returned\n // (handed back as `duration`), the snapshot/variant it was last evaluated\n // against, and whether a poll's refetch is on the wire.\n const pollRef = useRef<{\n timer: ReturnType<typeof setTimeout> | null;\n duration: number;\n snapshot: unknown;\n resource: unknown;\n variantKey: string | null;\n awaiting: boolean;\n }>({\n timer: null,\n duration: 0,\n snapshot: undefined,\n resource: null,\n variantKey: null,\n awaiting: false,\n });\n const prefetchedRef = useRef(false);\n // Focus revalidation eligibility, deliberately *not* `fetchedRef`: that one\n // is flipped by `prefetch()` too, and a hover prefetch is documented as\n // \"fetch once\" for data the user may never look at — enrolling it in focus\n // revalidation would keep re-requesting it for the life of the component.\n // Only the reads that put data on screen (`trigger`, `refetch`, `mutate`,\n // or simply not being lazy) count.\n const focusEligibleRef = useRef(!lazy);\n // The away latch: `focus` fires for things that never left the page —\n // dismissing an `alert`, returning from devtools — so a revalidation is only\n // owed when the window actually lost focus or the tab was hidden first.\n const wasAwayRef = useRef(false);\n const lastFocusRevalidationRef = useRef(0);\n\n // Subscribing also retains the variant, so an `invalidate` across search\n // variants knows this one is on screen and refetches it now.\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n const release = resource.retain(variantKey);\n const unsubscribe = resource.store.subscribe(onStoreChange);\n return () => {\n unsubscribe();\n release();\n };\n },\n [resource, variantKey],\n );\n // `peek` hands back the object stored in the map — its identity only\n // changes on a real write, so the snapshot is stable across render\n // attempts. Also the server snapshot: SSR renders whatever the prefetch\n // payload seeded, and never fetches.\n //\n // uSES and transitions: store updates are always urgent, so a write landing\n // mid-transition restarts the pending transition — wasted work, never wrong\n // UI. Exposure is kept small by design: render-phase reads never write the\n // store synchronously (fetches are silent), and a suspended component has no\n // subscription — it is woken by its thrown promise, not the store. The\n // navigation-shaped consequences are pinned in `useQuery.transition.test.tsx`.\n const getSnapshot = useCallback(\n () => resource.peek(variantKey),\n [resource, variantKey],\n );\n const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n // `keepPreviousData`: remember the last snapshot that had data, and show it\n // whenever the current one is loading without data (e.g. a variant change\n // with `suspense: false`). Presence is `hasData`, never `data`'s truthiness\n // — `null`/`0`/`false`/`\"\"` are legitimate response bodies.\n const lastDataRef = useRef(snapshot?.hasData ? snapshot : null);\n useEffect(() => {\n if (snapshot?.hasData) {\n lastDataRef.current = snapshot;\n }\n }, [snapshot]);\n\n let state = snapshot;\n if (\n config.keepPreviousData &&\n !snapshot?.hasData &&\n snapshot?.loading &&\n lastDataRef.current\n ) {\n state = { ...lastDataRef.current, loading: true };\n }\n\n // The render-phase read for the suspense path. Only when there is nothing\n // to show — data in hand always renders, and revalidation stays where it\n // was (the mount effect below). Both reads dedupe across the render\n // attempts React discards, so this is safe to hit on every attempt.\n //\n // On a streaming server render the read goes to the request's\n // `ServerQueryStore` instead of the client resource: a prefetched query is\n // already in flight there and is joined, an undiscovered one starts now\n // (the store logs the late-discovery hint when that cost something).\n let readPromise: Promise<void> | undefined;\n let serverError: unknown;\n if (suspense && !state?.hasData && !state?.error) {\n if (typeof window === \"undefined\") {\n if (serverQueries) {\n const entry = serverQueries.ensure(url, { params, search });\n if (entry.status === \"resolved\") {\n state = {\n loading: false,\n data: entry.data,\n hasData: true,\n error: null,\n version: 0,\n };\n } else if (entry.status === \"rejected\") {\n serverError = entry.error;\n } else {\n readPromise = entry.promise;\n }\n }\n } else {\n readPromise = resource.read(variantKey, config.staleTime).promise;\n }\n }\n\n if (\n suspense &&\n typeof window === \"undefined\" &&\n !serverQueries &&\n !state?.hasData &&\n process.env.NODE_ENV !== \"production\"\n ) {\n const searchHint = variantKey\n ? `, { search: ${JSON.stringify(\n Object.fromEntries(new URLSearchParams(variantKey)),\n )} }`\n : \"\";\n console.warn(\n `[gemi] useQuery(\"${url}\") rendered on the server without data. ` +\n `The server never fetches, so this page ships without it and the ` +\n `client suspends after hydration. Add ` +\n `\\`Query.prefetch(\"${url}\"${searchHint})\\` to the route's view handler.`,\n );\n }\n\n // While a `keepPreviousData` variant change is pending, the variant loading\n // in the background has no subscription yet — only the visible one does.\n // Hold it too, so that when `search`/`params` change again before it lands,\n // letting go of it aborts its request (#659) instead of leaving it to run\n // to completion for nobody. Seeded like the render-path lookup, since this\n // may be the first `getResource` for the new path.\n useEffect(() => {\n if (!isDeferred) return;\n const targetSeed =\n configRef.current.fallbackData != null\n ? { [currentVariantKey]: configRef.current.fallbackData }\n : prefetchedData?.[currentPath];\n return getResource(currentPath, targetSeed ?? undefined).retain(\n currentVariantKey,\n );\n }, [isDeferred, getResource, currentPath, currentVariantKey, prefetchedData]);\n\n // Mount / variant-change revalidation — unchanged semantics: `getVariant`\n // fetches when the variant is missing or stale, and now joins an in-flight\n // render-initiated read instead of racing it.\n useEffect(() => {\n if (fetchedRef.current) {\n resource.getVariant(variantKey, configRef.current.staleTime);\n }\n }, [variantKey, resource]);\n\n // With `suspense: false` an error is returned and, when the retry policy\n // allows, retried in the background; under suspense it throws below\n // instead. The resource owns the timer — one per variant however many\n // readers render it — and drops it once none of them is mounted.\n useEffect(() => {\n if (suspense || !snapshot?.error || snapshot.loading) return;\n const cfg = configRef.current;\n const error = snapshot.error as QueryFailure;\n const failureCount = Math.max(1, resource.failureCount(variantKey));\n if (!shouldRetryQuery(failureCount, error, cfg.retry)) return;\n const delay = retryDelayFor(\n failureCount,\n error,\n cfg.retryDelay,\n cfg.retryIntervalOnError,\n );\n if (cfg.debug) console.log(\"retrying\", variantKey, \"in\", delay);\n resource.scheduleRetry(variantKey, delay);\n }, [snapshot, suspense, resource, variantKey]);\n\n // Coming back online retries a query that failed in a way another attempt\n // might fix — e.g. one that ran out of retries while offline — as long as\n // its retry policy would retry that error at all. Silent, and it starts a\n // fresh run of failures.\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const onOnline = () => {\n const state = resource.peek(variantKey);\n if (!state?.error) return;\n if (!shouldRetryQuery(1, state.error, configRef.current.retry)) return;\n resource.retryNow(variantKey);\n };\n window.addEventListener(\"online\", onOnline);\n return () => window.removeEventListener(\"online\", onOnline);\n }, [resource, variantKey]);\n\n // `refetchUntil` runs after every commit, not only when the data changes,\n // so the predicate always sees the current render's closure: one that also\n // reads props or state (`d.active || building`) restarts a stopped poll, or\n // cancels a pending one, as soon as that state changes. New data clears the\n // pending timer and asks the predicate again, as before. On a plain\n // re-render a pending timer is kept, so frequent renders never push the\n // next refetch back.\n useEffect(() => {\n const poll = pollRef.current;\n const clear = () => {\n if (poll.timer) clearTimeout(poll.timer);\n poll.timer = null;\n };\n if (\n poll.snapshot !== snapshot ||\n poll.resource !== resource ||\n poll.variantKey !== variantKey\n ) {\n clear();\n poll.awaiting = false;\n poll.snapshot = snapshot;\n poll.resource = resource;\n poll.variantKey = variantKey;\n }\n const refetchUntil = configRef.current.refetchUntil;\n if (\n !refetchUntil ||\n liveOpen ||\n !snapshot ||\n snapshot.loading ||\n !snapshot.hasData ||\n snapshot.error\n ) {\n clear();\n return;\n }\n // The poll's own refetch is on the wire; its answer re-runs this.\n if (poll.awaiting) return;\n const nextDuration = refetchUntil(snapshot.data, poll.duration);\n if (!(nextDuration > 0)) {\n clear();\n poll.duration = 0;\n return;\n }\n if (poll.timer) return;\n poll.duration = nextDuration;\n poll.timer = setTimeout(() => {\n poll.timer = null;\n poll.awaiting = true;\n resource.refetch(variantKey);\n }, nextDuration);\n });\n\n useEffect(\n () => () => {\n const poll = pollRef.current;\n if (poll.timer) clearTimeout(poll.timer);\n poll.timer = null;\n // A StrictMode remount re-runs the effect above with the same snapshot.\n poll.snapshot = undefined;\n poll.awaiting = false;\n },\n [],\n );\n\n const handleReload = useCallback(() => {\n if (configRef.current.debug) {\n console.log(\"Reloading query for\", variantKey);\n }\n const data = resource.getVariant(\n variantKey,\n configRef.current.staleTime,\n ).data;\n resource.mutate(variantKey, () => data);\n }, [variantKey, resource]);\n\n useEffect(() => {\n if (!fetchedRef.current || liveOpen) return;\n refreshIntervalRef.current = setInterval(() => {\n handleReload();\n }, config.refreshInterval);\n\n return () => {\n if (refreshIntervalRef.current) {\n clearInterval(refreshIntervalRef.current);\n }\n };\n }, [config.refreshInterval, handleReload, liveOpen]);\n\n // Revalidate when the tab comes back to the foreground — opt-in via\n // `revalidateOnFocus` (per call or app-wide). `resource.revalidate` applies\n // `staleTime` like the mount effect does, but always fetches silently, so\n // data still inside its freshness window is left alone and anything older\n // is refreshed without what's on screen ever flashing a loading state.\n //\n // Three guards decide whether a return to the foreground is owed a request,\n // because `focus` alone is a poor proxy for one:\n // - eligibility — an untriggered lazy query has nothing on screen;\n // - the away latch — `focus` also fires for a dismissed `alert` or a\n // closed devtools pane, neither of which is a return from anywhere;\n // - the throttle — clicking in and out of an embedded iframe (a payment\n // form, a video) blurs and focuses the window every time, and `focus`\n // runs this for *every* mounted query, so a dashboard would otherwise\n // fire a dozen requests per interaction under `staleTime: 0`.\n //\n // Both events are listened for because neither covers the other: switching\n // between windows fires `focus` while the document stays visible, and\n // switching tabs (or unlocking the device) fires `visibilitychange` without\n // necessarily firing `focus`. They land on one guarded call, so the overlap\n // costs nothing — the latch is already spent by the time the second fires.\n useEffect(() => {\n if (!config.revalidateOnFocus) return;\n const markAway = () => {\n wasAwayRef.current = true;\n };\n const revalidate = () => {\n if (!focusEligibleRef.current) return;\n if (document.visibilityState === \"hidden\") return;\n if (!wasAwayRef.current) return;\n const now = Date.now();\n // Throttled: leave the latch armed so the next return, once the\n // interval has passed, still revalidates.\n if (\n now - lastFocusRevalidationRef.current <\n configRef.current.focusThrottleInterval\n ) {\n return;\n }\n wasAwayRef.current = false;\n lastFocusRevalidationRef.current = now;\n resource.revalidate(variantKey, configRef.current.staleTime);\n };\n const onVisibilityChange = () => {\n if (document.visibilityState === \"hidden\") {\n markAway();\n } else {\n revalidate();\n }\n };\n window.addEventListener(\"blur\", markAway);\n window.addEventListener(\"focus\", revalidate);\n document.addEventListener(\"visibilitychange\", onVisibilityChange);\n return () => {\n window.removeEventListener(\"blur\", markAway);\n window.removeEventListener(\"focus\", revalidate);\n document.removeEventListener(\"visibilitychange\", onVisibilityChange);\n };\n }, [config.revalidateOnFocus, resource, variantKey]);\n\n useEffect(() => {\n // Feature-checked per method: vitest's `import.meta.hot` shim has `on`\n // but not `off`.\n // @ts-ignore\n if (typeof import.meta.hot?.on === \"function\") {\n // @ts-ignore\n import.meta.hot.on(\"http-reload\", handleReload);\n }\n return () => {\n // @ts-ignore\n if (typeof import.meta.hot?.off === \"function\") {\n // @ts-ignore\n import.meta.hot.off(\"http-reload\", handleReload);\n }\n };\n }, [handleReload]);\n\n const trigger = useCallback(() => {\n fetchedRef.current = true;\n focusEligibleRef.current = true;\n const store = resource.store.getValue();\n const variant = store.get(variantKey);\n if (!variant || (!variant.loading && !variant.hasData)) {\n resource.refetch(variantKey);\n }\n }, [resource, variantKey]);\n\n const prefetch = useCallback(() => {\n if (prefetchedRef.current) return;\n prefetchedRef.current = true;\n fetchedRef.current = true;\n // `read`, not `refetch`: a suspending read that follows joins this\n // request instead of racing it, and fresh data is a no-op.\n resource.read(variantKey, configRef.current.staleTime);\n }, [resource, variantKey]);\n\n const refetch = useCallback(() => {\n fetchedRef.current = true;\n focusEligibleRef.current = true;\n resource.refetch(variantKey);\n }, [resource, variantKey]);\n\n function mutate(fn?: NestedPrettify<Data<T>>): void;\n function mutate(\n fn?: (data: NestedPrettify<Data<T>>) => NestedPrettify<Data<T>>,\n ): void;\n function mutate(fn?: any) {\n // `onClick={mutate}` hands React's event to `mutate` as if it were the\n // new data. It is not a plain object, so the shape check below threw —\n // and where the data is untyped nothing caught it at compile time. An\n // event carries no data to write, so it means what a bare `mutate()`\n // means: refetch.\n if (isEventLike(fn)) fn = undefined;\n // Either form ends in a fetch whose result the component renders, so a\n // lazy query mutated by hand is as focus-eligible as a triggered one.\n focusEligibleRef.current = true;\n if (!fn) {\n fetchedRef.current = true;\n resource.refetch(variantKey);\n return;\n }\n return resource.mutate(variantKey, (data: any) => {\n // `null` is a legitimate cached body; only `undefined` means the query\n // hasn't produced anything (and `mutate` refetches instead of calling\n // this in that case).\n if (data === undefined) {\n console.warn(\"Mutate function called before the query.\");\n return data;\n }\n\n // The callback's return value *replaces* the cached data. The type checks\n // below only ensure the shape matches so a stray value can't corrupt the\n // cache; they do not merge or append.\n const updatedData = typeof fn === \"function\" ? fn(data) : fn;\n\n if (isPlainObject(data)) {\n if (isPlainObject(updatedData)) {\n return updatedData;\n }\n throw new Error(\n \"Mutate function must return an object when the current data is an object.\",\n );\n }\n\n if (Array.isArray(data)) {\n if (Array.isArray(updatedData)) {\n return updatedData;\n }\n throw new Error(\n \"Mutate function must return an array when the current data is an array.\",\n );\n }\n\n if (typeof data !== typeof updatedData) {\n throw new Error(\n \"Mutate function must return the same type as the current data.\",\n );\n }\n\n return updatedData;\n });\n }\n\n // Suspend last, after every hook has run: the attempt React discards ran\n // them all, and the retry re-runs them identically. The promise is *thrown*\n // rather than passed to `use()` — the thenable-throw protocol is what\n // React's ping-and-retry machinery is built around (React.lazy, SWR, React\n // Query), whereas `use()` on a client-created promise is documented as\n // unsupported outside a Suspense-compatible framework and React never\n // retries it. A streaming server render takes the same paths: a pending\n // entry suspends (React streams the fallback and resumes on settle), and a\n // rejected one throws so the segment falls back to client rendering, where\n // the browser's own fetch surfaces the error into the boundary.\n if (suspense) {\n if (serverError) {\n throw serverError;\n }\n if (state?.error && !state?.hasData) {\n throw state.error;\n }\n if (!state?.hasData && readPromise) {\n throw readPromise;\n }\n }\n\n return {\n data: state?.data as NestedPrettify<Data<T>>,\n loading: isDeferred || (state?.loading ?? !lazy),\n error: state?.error as Error,\n mutate,\n trigger,\n prefetch,\n refetch,\n version: state?.version as number,\n };\n}\n","import {\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\n\nimport type { NestedPrettify } from \"../utils/type\";\nimport { applyParams } from \"../utils/applyParams\";\nimport { toVariantKey } from \"../utils/variantKey\";\nimport { QueryConfigContext, QueryManagerContext } from \"./QueryManagerContext\";\nimport type { QueryResource } from \"./QueryResource\";\nimport { useParams } from \"./useParams\";\nimport { useRouteData } from \"./useRouteData\";\nimport {\n useQuery,\n type Config,\n type Data,\n type GetRPC,\n type Options,\n} from \"./useQuery\";\n\ntype Page<T extends keyof GetRPC> = NestedPrettify<Data<T>>;\n\n/** What a page's `getNextPage` points at: a page number or a cursor. */\ntype PageCursor = string | number;\n\n/** A page that is an array is its own list of items. */\ntype DefaultItem<P> = P extends readonly (infer U)[] ? U : never;\n\nexport interface InfiniteQueryConfig<P, Item> extends Omit<\n Config<P>,\n \"lazy\" | \"refetchUntil\" | \"fallbackData\"\n> {\n /**\n * The next page's cursor, read off the pages loaded so far — usually a page\n * number, e.g. `(last, pages) => last.length === 48 ? pages.length + 1 :\n * null`. `null`/`undefined`/`false` means there is no next page, which is\n * what `hasMore` reports.\n */\n getNextPage: (\n lastPage: P,\n pages: P[],\n ) => PageCursor | null | undefined | false;\n /**\n * The search key the cursor is sent under (default `\"page\"`). The first\n * page is requested *without* it, so it is the same cached variant a plain\n * `useQuery` — and a `Query.prefetch` — with the same `search` reads.\n */\n pageParam?: string;\n /** A page's rows. Defaults to the page itself when it is an array. */\n getItems?: (page: P) => readonly Item[];\n /**\n * An item's identity. With it, a row that shifts into the next page (an\n * insert or delete between two offset-based fetches) is kept at its first\n * position instead of being rendered twice.\n */\n getKey?: (item: Item) => unknown;\n}\n\nexport interface InfiniteQueryReturn<P, Item> {\n /** Every loaded page, in order. Empty until the first page has data. */\n pages: P[];\n /** The pages' rows flattened, de-duplicated by `getKey` when given. */\n items: Item[];\n /** Whether `getNextPage` points past the last loaded page. */\n hasMore: boolean;\n /**\n * Load the next page. A no-op while one is loading or when there is none;\n * when the last requested page failed, it retries that page.\n */\n fetchNextPage: () => void;\n isFetchingNextPage: boolean;\n /** The first page's `loading` — see `useQuery`. */\n loading: boolean;\n error: Record<string, unknown> | null;\n /** Refetch every loaded page. */\n refetch: () => void;\n}\n\ntype VariantState = ReturnType<QueryResource[\"peek\"]>;\n\n/**\n * Follows the cursor chain through the cache: the first page, then\n * `getNextPage` of it, and so on, up to `count` pages. Stops at the first page\n * that has no data yet — that one is loading (or failed).\n */\nfunction walkPages(\n resource: QueryResource,\n firstKey: string,\n search: Record<string, unknown>,\n pageParam: string,\n count: number,\n getNextPage: (\n last: any,\n pages: any[],\n ) => PageCursor | null | undefined | false,\n) {\n const keys = [firstKey];\n const states: VariantState[] = [resource.peek(firstKey)];\n const pages: any[] = [];\n let next: PageCursor | null | undefined | false = null;\n for (let i = 0; i < count; i++) {\n const state = states[i];\n if (!state?.hasData) break;\n pages.push(state.data);\n next = getNextPage(state.data, pages.slice());\n if (next === null || next === undefined || next === false) break;\n if (i + 1 === count) break;\n const key = toVariantKey({ ...search, [pageParam]: next });\n keys.push(key);\n states.push(resource.peek(key));\n }\n return { keys, states, pages, next };\n}\n\n/**\n * A paged list whose pages live in the query cache: page 1 is a plain\n * `useQuery` (so it suspends, SSR-renders and `Query.prefetch`es exactly like\n * one), and each further page is the same path with `pageParam` added to the\n * search — its own cached variant, which `useMutate` updates and invalidates\n * like any other. Changing `params` or `search` starts over from page 1.\n */\nexport function useInfiniteQuery<\n T extends keyof GetRPC,\n Item = DefaultItem<Page<T>>,\n>(\n url: T,\n options: Options<T> | undefined,\n config: InfiniteQueryConfig<Page<T>, Item>,\n): InfiniteQueryReturn<Page<T>, Item> {\n const {\n getNextPage,\n pageParam = \"page\",\n getItems,\n getKey,\n ...queryConfig\n } = config;\n\n const first = useQuery(url, options, queryConfig as Config<Data<T>>);\n\n const routeParams = useParams();\n const params =\n options && \"params\" in options\n ? { ...routeParams, ...options.params }\n : routeParams;\n const search: Record<string, unknown> = options?.search ?? {};\n const path = applyParams(url, params);\n const firstKey = toVariantKey(search);\n const listKey = `${path}?${firstKey}`;\n const { getResource } = useContext(QueryManagerContext);\n const appConfig = useContext(QueryConfigContext);\n const { prefetchedData } = useRouteData();\n // Seeded the way `useQuery` seeds it: during a params change `useQuery` is\n // still reading the previous path, so this may be the first `getResource`\n // for the new one, and the prefetch payload must not be lost to it.\n const resource = getResource(path, prefetchedData?.[path] ?? undefined);\n\n // How many pages this list has asked for. Keyed by the list, so a\n // params/search change drops it back to one page in the same render.\n const [requested, setRequested] = useState({ listKey, count: 1 });\n const count = requested.listKey === listKey ? requested.count : 1;\n\n const getNextPageRef = useRef(getNextPage);\n getNextPageRef.current = getNextPage;\n\n // The snapshot is the tuple of variant states along the chain; it keeps its\n // identity until one of them is written, as `useSyncExternalStore` needs.\n const snapshotRef = useRef<ReturnType<typeof walkPages> | null>(null);\n const getSnapshot = useCallback(() => {\n const walked = walkPages(\n resource,\n firstKey,\n search,\n pageParam,\n count,\n getNextPageRef.current,\n );\n const previous = snapshotRef.current;\n if (\n previous &&\n previous.keys.length === walked.keys.length &&\n previous.keys.every((key, i) => key === walked.keys[i]) &&\n previous.states.every((state, i) => state === walked.states[i])\n ) {\n return previous;\n }\n snapshotRef.current = walked;\n return walked;\n // `search` is captured through `firstKey`, its serialization.\n }, [resource, firstKey, pageParam, count]);\n const chain = useSyncExternalStore(\n resource.store.subscribe,\n getSnapshot,\n getSnapshot,\n );\n\n // Pages past the first: `useQuery` owns page 1. Retained while on screen so\n // an invalidation refetches them now, and fetched when missing or stale.\n const laterKeys = chain.keys.slice(1);\n const laterKeysId = laterKeys.join(\"\\n\");\n const staleTime = queryConfig.staleTime ?? appConfig?.staleTime;\n const staleTimeRef = useRef(staleTime);\n staleTimeRef.current = staleTime;\n // Each page is read once when it joins the list — fetched when missing,\n // revalidated when stale — not again on every later `fetchNextPage`. A new\n // list (params/search change) starts a new record, so returning to a filter\n // revalidates its pages again as they are loaded.\n const ensuredRef = useRef({ listKey, keys: new Set<string>() });\n useEffect(() => {\n if (!laterKeysId) return;\n if (ensuredRef.current.listKey !== listKey) {\n ensuredRef.current = { listKey, keys: new Set() };\n }\n const ensured = ensuredRef.current.keys;\n const keys = laterKeysId.split(\"\\n\");\n const releases = keys.map((key) => resource.retain(key));\n for (const key of keys) {\n if (ensured.has(key)) continue;\n ensured.add(key);\n resource.getVariant(key, staleTimeRef.current);\n }\n return () => releases.forEach((release) => release());\n }, [resource, listKey, laterKeysId]);\n\n // Until this list's page 1 is cached, show what `useQuery` shows. During a\n // variant change under `keepPreviousData` that is the previous list's\n // data, so every page of the previous list stays on screen rather than\n // collapsing to its first; otherwise (the server render) it is page 1.\n const ownFirstPage = chain.states[0]?.hasData === true;\n const fallbackPage = ownFirstPage ? undefined : first.data;\n const keepingPrevious =\n !ownFirstPage && fallbackPage !== undefined && first.loading;\n const shownRef = useRef<Page<T>[] | null>(null);\n const pages = useMemo<Page<T>[]>(\n () =>\n ownFirstPage\n ? chain.pages\n : keepingPrevious && shownRef.current\n ? shownRef.current\n : fallbackPage !== undefined\n ? [fallbackPage as Page<T>]\n : [],\n [ownFirstPage, chain, keepingPrevious, fallbackPage],\n );\n useEffect(() => {\n if (ownFirstPage) shownRef.current = pages;\n }, [ownFirstPage, pages]);\n\n const pending = chain.states[chain.pages.length];\n const allLoaded = ownFirstPage && chain.pages.length === chain.keys.length;\n const hasMore =\n allLoaded &&\n chain.next !== null &&\n chain.next !== undefined &&\n chain.next !== false;\n const isFetchingNextPage =\n ownFirstPage && chain.pages.length < chain.keys.length && !pending?.error;\n const pageError =\n ownFirstPage && chain.pages.length < chain.keys.length\n ? (pending?.error ?? null)\n : null;\n\n const items = useMemo(() => {\n const out: Item[] = [];\n const seen = new Set<unknown>();\n for (const page of pages) {\n const rows = getItems\n ? getItems(page)\n : Array.isArray(page)\n ? (page as unknown as Item[])\n : [];\n for (const row of rows) {\n if (getKey) {\n const key = getKey(row);\n if (seen.has(key)) continue;\n seen.add(key);\n }\n out.push(row);\n }\n }\n return out;\n }, [pages, getItems, getKey]);\n\n const fetchNextPage = useCallback(() => {\n if (pageError) {\n resource.refetch(chain.keys[chain.keys.length - 1]);\n return;\n }\n if (!hasMore) return;\n setRequested((current) => ({\n listKey,\n count: (current.listKey === listKey ? current.count : 1) + 1,\n }));\n }, [pageError, hasMore, resource, chain, listKey]);\n\n const refetch = useCallback(() => {\n for (const key of chain.keys) {\n resource.refetch(key);\n }\n }, [resource, chain]);\n\n return {\n pages,\n items,\n hasMore,\n fetchNextPage,\n isFetchingNextPage,\n loading: first.loading,\n error: first.error ?? pageError,\n refetch,\n };\n}\n","/**\n * The request header a client sends its socket id in, for `toOthers`.\n *\n * A module of its own, re-exported by `./protocol`: every mutation in the\n * browser reads it, and anything else in `./protocol` it pulled along would\n * land in every route's entry chunk instead of the lazily loaded socket's.\n */\nexport const SOCKET_ID_HEADER = \"x-gemi-socket\";\n","import { loadLazy, type LazyModule } from \"./lazyModule\";\n\n/**\n * `./mutationExtras`, which a page only needs once it mutates: loaded when the\n * first mutation hook, or `useSetQueryData()`, mounts (#915), so no route's\n * entry chunk carries it. By the time a request settles it is normally there;\n * one that settles first waits for it.\n *\n * Keep this module out of `gemi/testing`'s imports. Shared with that entry, it\n * moves into the chunk both entries import, and there an app's bundler can\n * emit `./mutationExtras` even for an app that never mutates, which splits the\n * app's entry chunk (\"needs no chunk besides the entry to start\" in\n * `packaging.test.ts`).\n */\nexport const mutationExtras: LazyModule<typeof import(\"./mutationExtras\")> = {\n current: null,\n load: () => import(\"./mutationExtras.js\"),\n};\n\n/** Starts loading `./mutationExtras`: the hooks' mount effect. */\nexport function preloadMutationExtras() {\n loadLazy(mutationExtras).catch(() => {});\n}\n","import { useContext, useEffect, useRef, useState } from \"react\";\nimport type { RPC } from \"./rpc\";\nimport type { ApiRouterHandler } from \"../http/ApiRouter\";\nimport type { UnwrapPromise } from \"../utils/type\";\nimport type { UrlParser } from \"./types\";\nimport { useParams } from \"./useParams\";\nimport { ClientRouterContext } from \"./ClientRouterContext\";\nimport {\n isObject,\n mutationErrorFromBody,\n type MutationError,\n type WithMutationErrorHelpers,\n} from \"./MutationError\";\nimport { realtime } from \"./realtime/loader\";\nimport { SOCKET_ID_HEADER } from \"../services/broadcast/socketHeader\";\nimport { QueryManagerContext } from \"./QueryManagerContext\";\nimport type { QueryUpdate } from \"./useSetQueryData\";\nimport { loadLazy } from \"./lazyModule\";\nimport { mutationExtras, preloadMutationExtras } from \"./mutationModules\";\n\ntype Methods = {\n POST: {\n [K in keyof RPC as K extends `POST:${infer P}` ? P : never]: RPC[K];\n };\n PUT: {\n [K in keyof RPC as K extends `PUT:${infer P}` ? P : never]: RPC[K];\n };\n PATCH: {\n [K in keyof RPC as K extends `PATCH:${infer P}` ? P : never]: RPC[K];\n };\n DELETE: {\n [K in keyof RPC as K extends `DELETE:${infer P}` ? P : never]: RPC[K];\n };\n};\n\nfunction applyParams(url: string, params: Record<string, any> = {}) {\n let out = url;\n\n for (const [key, value] of Object.entries(params)) {\n out = out.replace(`:${key}?`, value).replace(`:${key}`, value);\n }\n return out;\n}\n\n/**\n * How a hook treats a `trigger` that starts while another is in flight.\n *\n * - `\"latest\"` (the default): the newest request wins. An older request that\n * settles afterwards is dropped: its callbacks don't run, it writes no state\n * and its `trigger` resolves `undefined`. Right for forms and edits, where a\n * newer submit supersedes the older one.\n * - `\"parallel\"`: every request stands on its own. Each one runs its callbacks\n * and resolves its own `trigger`, whatever else is in flight (issue #719).\n *\n * Neither mode aborts the older request; only `cancel()` does.\n */\nexport type MutationConcurrency = \"latest\" | \"parallel\";\n\ntype Config<T, E = never> = {\n autoInvalidate?: boolean;\n onSuccess: (data: T) => void;\n /**\n * A `MutationError`, or one of the route's typed errors (`E`): the bodies\n * its handler answers with `HttpResponse.error` / `httpError`.\n *\n * It carries `error.list()` and `error.field(name)`.\n *\n * Method syntax, so a handler written as `(error: MutationError) => …`\n * before the route had typed errors still compiles.\n */\n onError(error: WithMutationErrorHelpers<MutationError | E>): void;\n onCanceled?: () => void;\n concurrency?: MutationConcurrency;\n /**\n * Queries the answer is written into on success, before `onSuccess`, with\n * no refetch: `{ path, params?, search?, data? }`. Without `data` the\n * answer is written as is; `data(answer, current)` builds the next value\n * from it and what is cached (#897).\n */\n updates?: ReadonlyArray<QueryUpdate<T>>;\n};\n\n/**\n * Callbacks for one `trigger` call. They run after the hook's own, and only\n * when the hook's would: in `\"latest\"` mode a superseded call runs neither.\n */\nexport type MutationCallConfig<T, E = never> = {\n onSuccess?: (data: T) => void;\n onError?(error: WithMutationErrorHelpers<MutationError | E>): void;\n};\n\nconst defaultOptions: Config<any> = {\n autoInvalidate: false,\n onSuccess: () => {},\n onError: (_: MutationError) => {},\n onCanceled: () => {},\n};\n\ntype Data<\n M extends keyof Methods,\n K extends keyof Methods[M],\n> = Methods[M][K] extends ApiRouterHandler<any, infer T, any>\n ? UnwrapPromise<T>\n : never;\n\ntype Body<\n M extends keyof Methods,\n K extends keyof Methods[M],\n> = Methods[M][K] extends ApiRouterHandler<infer T, any, any> ? T : never;\n\n/**\n * The route's typed errors: what its handler answers with `HttpResponse.error`\n * or `httpError`, as `onError` receives them. `never` when it has none.\n */\ntype ErrorOf<\n M extends keyof Methods,\n K extends keyof Methods[M],\n> = Methods[M][K] extends ApiRouterHandler<any, any, any, infer E> ? E : never;\n\ntype ParseParams<T> = UrlParser<`${T & string}`>;\n\ntype State<T, E = never> = {\n data: T | null;\n // With `list()` and `field(name)`.\n error: WithMutationErrorHelpers<MutationError | E> | null;\n loading: boolean;\n // Requests on the wire, superseded ones included.\n pending: number;\n};\n\nexport function useMutation<\n M extends keyof Methods,\n K extends keyof Methods[M],\n T = Data<M, K>,\n U = Body<M, K>,\n E = ErrorOf<M, K>,\n>(\n method: M,\n url: K,\n ...args: [\n options?: { params?: Partial<ParseParams<K>>, search?: Record<string, string> },\n config?: Partial<Config<T, E>>,\n ]\n) {\n const _params = useParams();\n // A write may have moved the data behind any page warmed ahead of a click,\n // and a prefetched payload is committed wholesale — into the query cache too.\n const { clearPrefetchCache } = useContext(ClientRouterContext);\n const { getResource } = useContext(QueryManagerContext);\n const [state, setState] = useState<State<T, E>>({\n data: null,\n error: null,\n loading: false,\n pending: 0,\n });\n\n // A controller per request, held in a ref rather than state. Swapping it\n // through `setState` only took effect on the next render, so a `cancel()`\n // and a `trigger()` in one tick reused the signal `cancel()` had just\n // aborted and the new request never left the ground.\n const abortController = useRef(new AbortController());\n\n // Only the newest request may write state. Nothing tied a response to the\n // request that asked for it, so two submits in flight resolved in whatever\n // order the network returned them — and a slow first submit's validation\n // error could land after the corrected second one had already succeeded,\n // putting the message back and wiping the result.\n const latestRequest = useRef(0);\n\n // Every request still on the wire in `\"parallel\"` mode, so `cancel()` can\n // abort all of them rather than only the newest.\n const inFlight = useRef(new Set<AbortController>());\n\n const formData = useRef(new FormData());\n\n // `Partial<Config<T>>` means a caller may name only the callbacks it wants,\n // and the framework's own `useSignIn`/`useSignOut` name only `onSuccess`.\n // Taking the config as given left the rest undefined, so a success called\n // `options.onSuccess(data)` on `undefined` and reported its own `TypeError`\n // through `onError`.\n const [inputs = {}, config] = args ?? [];\n const options = { ...defaultOptions, ...config } as Config<T, E>;\n\n // Resolves `undefined` rather than rejecting whenever there is no result to\n // hand back: a non-2xx response or a network failure (both already reported\n // through `onError` and `error`), a `cancel()`, and a request superseded by a\n // newer `trigger`. It was typed `Promise<T>`, so `const r = await trigger()`\n // read `r.id` off `undefined` with nothing in the types to say it could.\n // Rejecting instead would turn every `onClick={() => trigger()}` — and\n // `<Form>`'s own submit — into an unhandled rejection, so the type changed\n // and the behaviour did not (issue #623).\n //\n // In `\"parallel\"` mode no call is superseded: each one resolves to its own\n // body and runs its own callbacks, and `data`/`error` hold the outcome of\n // whichever call settled last.\n const parallel = options.concurrency === \"parallel\";\n useEffect(preloadMutationExtras, []);\n\n async function trigger(\n input?: U,\n call: MutationCallConfig<T, E> = {},\n ): Promise<T | undefined> {\n const controller = new AbortController();\n abortController.current = controller;\n if (parallel) inFlight.current.add(controller);\n const requestId = ++latestRequest.current;\n const isSuperseded = () =>\n !parallel && latestRequest.current !== requestId;\n\n // The last response's error is about the last submit. Left in place, a\n // corrected resubmit shows the old validation message until it returns.\n // In parallel mode it belongs to another call, which is still the last\n // one to have settled.\n setState((prev) => ({\n data: prev.data,\n error: parallel ? prev.error : null,\n loading: true,\n pending: prev.pending + 1,\n }));\n // One request off the wire. `update` gives the state it leaves; `loading`\n // is `pending > 0` in parallel mode, while in latest mode it follows the\n // newest request alone, as it always has, so a superseded one settling\n // leaves it as it is.\n //\n // A call leaves `pending` once: an `onError` that throws lands in the\n // `catch` and settles the call a second time.\n let left = false;\n const settle = (\n update: (prev: State<T, E>) => Pick<State<T, E>, \"data\" | \"error\">,\n superseded = false,\n ) => {\n inFlight.current.delete(controller);\n const leaving = !left;\n left = true;\n setState((prev) => {\n const pending = leaving ? prev.pending - 1 : prev.pending;\n return {\n ...update(prev),\n pending,\n loading: parallel ? pending > 0 : superseded ? prev.loading : false,\n };\n });\n };\n // The accumulator this call sent, so a parallel call settling doesn't\n // empty fields gathered since for the next one.\n const sentFormData = typeof input === \"undefined\" ? formData.current : null;\n const resetFormData = () => {\n if (!parallel || formData.current === sentFormData) {\n formData.current = new FormData();\n }\n };\n const params =\n \"params\" in inputs ? { ..._params, ...inputs.params } : _params;\n const search = \"search\" in inputs ? inputs.search : {};\n const searchParams = new URLSearchParams(search);\n const finalUrl = [applyParams(String(url).replace(`${method}:`, \"\"), params), searchParams.toString()].filter(Boolean).join(\"?\");\n\n let body = null;\n\n const contentType =\n typeof input === \"undefined\" || input instanceof FormData\n ? {}\n : { \"Content-Type\": \"application/json\" };\n\n if (input instanceof FormData) {\n body = input;\n } else if (typeof input === \"undefined\") {\n body = formData.current;\n } else if (input) {\n body = JSON.stringify(input);\n }\n\n const socketId = realtime.client?.socketId;\n try {\n const response = await fetch(`/api${finalUrl}`, {\n method,\n headers: {\n ...contentType,\n // This tab's broadcast socket, while one is open, so a controller's\n // `Broadcast.toOthers(req)` skips the tab that made the change.\n ...(socketId ? { [SOCKET_ID_HEADER]: socketId } : {}),\n },\n ...(body ? { body } : {}),\n signal: controller.signal,\n });\n\n const data = await response.json();\n // `data.error` rather than the envelope around it: `onError` is typed\n // `(error: MutationError) => void`, and the envelope has no `kind` to\n // branch on. A body without one — an app's own `HttpResponse.json` —\n // is handed over whole.\n const error = response.ok\n ? null\n : await withErrorHelpers<MutationError | E>(mutationErrorFromBody(data, response.status));\n // Loaded before the check below, so a request superseded while it waits\n // for the module writes nothing.\n const extras = response.ok && options.updates ? await loadOrNull() : null;\n\n // A superseded request has nothing left to say: a newer submit is what\n // the user is waiting on, and its state is the state on screen.\n if (isSuperseded()) {\n settle((prev) => prev, true);\n return;\n }\n\n resetFormData();\n\n if (!response.ok) {\n // `data` is the last result the caller was given, and a rejected\n // submit did not replace it — the same reason the pending state above\n // keeps it.\n settle((prev) => ({ data: prev.data, error }));\n\n options.onError(error!);\n call.onError?.(error!);\n return;\n }\n\n clearPrefetchCache?.();\n extras?.applyQueryUpdates(getResource, _params, options.updates, data);\n options.onSuccess(data);\n call.onSuccess?.(data);\n\n settle(() => ({ data, error: null }));\n\n return data as T;\n } catch (thrown) {\n const error = await withErrorHelpers(thrown as MutationError);\n if (isSuperseded()) {\n settle((prev) => prev, true);\n return;\n }\n\n resetFormData();\n // `cancel()` aborts the request, so the fetch rejects here. A cancelled\n // submit is not a failed one: `onCanceled` has already reported it, and\n // a DOMException carries no `kind` for `<Form>` to read, so leaving it\n // in `error` only puts a value there that nothing can act on.\n if ((error as Error)?.name === \"AbortError\") {\n settle((prev) => prev);\n return;\n }\n // A `TypeError` from `fetch` (no answer) or a `SyntaxError` from\n // `response.json()` (an answer that was not JSON) — both `Error`s.\n options.onError(error);\n call.onError?.(error);\n // A parallel call's failure doesn't take back another call's result.\n settle((prev) => ({\n data: parallel ? prev.data : null,\n error,\n }));\n }\n }\n\n trigger.formData = (formData: FormData) => {\n return trigger(formData as U);\n };\n\n return {\n data: state.data as T,\n error: state.error,\n loading: state.loading,\n // How many requests are on the wire. In parallel mode `loading` is\n // `pending > 0`.\n pending: state.pending,\n formData: formData.current,\n // Aborts the newest request, or in parallel mode every one in flight.\n cancel: () => {\n if (parallel) {\n // Each aborted call takes itself off `pending` as it settles, and\n // `loading` follows.\n for (const controller of inFlight.current) controller.abort();\n } else {\n abortController.current.abort();\n setState((prev) => ({ ...prev, loading: false }));\n }\n\n formData.current = new FormData();\n options.onCanceled?.();\n },\n trigger,\n };\n}\n\nexport function usePost<\n K extends keyof Methods[\"POST\"],\n T = Data<\"POST\", K>,\n E = ErrorOf<\"POST\", K>,\n>(\n url: K,\n ...args: [\n options?: { params?: Partial<ParseParams<K>> },\n config?: Partial<Config<T, E>>,\n ]\n) {\n return useMutation(\"POST\", url, ...(args as any));\n}\n\nexport function usePut<\n K extends keyof Methods[\"PUT\"],\n T = Data<\"PUT\", K>,\n E = ErrorOf<\"PUT\", K>,\n>(\n url: K,\n ...args: [\n options?: { params?: Partial<ParseParams<K>> },\n config?: Partial<Config<T, E>>,\n ]\n) {\n return useMutation(\"PUT\", url, ...(args as any));\n}\n\nexport function usePatch<\n K extends keyof Methods[\"PATCH\"],\n T = Data<\"PATCH\", K>,\n E = ErrorOf<\"PATCH\", K>,\n>(\n url: K,\n ...args: [\n options?: { params?: Partial<ParseParams<K>> },\n config?: Partial<Config<T, E>>,\n ]\n) {\n return useMutation(\"PATCH\", url, ...(args as any));\n}\n\nexport function useDelete<\n K extends keyof Methods[\"DELETE\"],\n T = Data<\"DELETE\", K>,\n E = ErrorOf<\"DELETE\", K>,\n>(\n url: K,\n ...args: [\n options?: { params?: Partial<ParseParams<K>> },\n config?: Partial<Config<T, E>>,\n ]\n) {\n return useMutation(\"DELETE\", url, ...(args as any));\n}\n\nexport function useUpload<\n K extends keyof Methods[\"POST\"],\n T = Data<\"POST\", K>,\n E = ErrorOf<\"POST\", K>,\n>(\n url: K,\n ...args: [\n options?: { params?: Partial<ParseParams<K>> },\n config?: Partial<Omit<Config<T, E>, \"concurrency\">>,\n ]\n) {\n const [state, setState] = useState<\"idle\" | \"uploading\" | \"done\" | \"error\">(\n \"idle\",\n );\n const [progress, setProgress] = useState(0);\n const _params = useParams();\n const { clearPrefetchCache } = useContext(ClientRouterContext);\n const { getResource } = useContext(QueryManagerContext);\n const abortRef = useRef<VoidFunction | null>(null);\n\n const [inputs = {}, options = defaultOptions] = args ?? [];\n useEffect(preloadMutationExtras, []);\n\n // Clears the ref so a `cancel()` after the upload has settled does nothing:\n // it used to abort a finished request and report `onCanceled` for it.\n const cancel = () => {\n const abort = abortRef.current;\n if (!abort) return;\n abortRef.current = null;\n abort();\n options.onCanceled?.();\n setState(\"idle\");\n setProgress(0);\n };\n\n // `undefined` for no file, a failed upload (reported through `onError`), a\n // network error or a `cancel()`, the same contract as `useMutation`'s\n // `trigger`. A cancel is not an error: `onCanceled` reports it and `onError`\n // does not run.\n //\n // It settles on the request's `load`/`error`/`timeout`/`abort` events. It\n // used to settle on `readyState` 4 by wrapping the answer in a `Response`,\n // which throws for the status 0 an abort or a dropped connection leaves —\n // inside an async handler, so the throw was an unhandled rejection and a\n // cancelled upload's `trigger` never settled (issue #671).\n const trigger = async (\n fileList: FileList | null | File,\n ): Promise<T | undefined> => {\n if (!fileList) {\n return;\n }\n const params =\n \"params\" in inputs ? { ..._params, ...inputs.params } : _params;\n const finalUrl = applyParams(String(url).replace(\"POST:\", \"\"), params);\n\n const method = \"POST\";\n const action = `/api${finalUrl}`;\n const data = new FormData();\n if (fileList instanceof FileList) {\n for (const file of Array.from(fileList)) {\n data.append(\"file\", file);\n }\n } else {\n data.append(\"file\", fileList);\n }\n const xhr = new XMLHttpRequest();\n const abort = () => xhr.abort();\n abortRef.current = abort;\n // A newer `trigger` owns the ref once it has replaced it.\n const release = () => {\n if (abortRef.current === abort) abortRef.current = null;\n };\n\n setState(\"uploading\");\n setProgress(0);\n\n try {\n const outcome = await new Promise<\n | { type: \"load\"; status: number; statusText: string; body: string }\n | { type: \"abort\" }\n >((resolve, reject) => {\n xhr.addEventListener(\"load\", () => {\n resolve({\n type: \"load\",\n status: xhr.status,\n statusText: xhr.statusText,\n body: xhr.responseText,\n });\n });\n xhr.addEventListener(\"abort\", () => resolve({ type: \"abort\" }));\n xhr.addEventListener(\"error\", () => {\n reject(new TypeError(\"Failed to fetch\"));\n });\n xhr.addEventListener(\"timeout\", () => {\n reject(new TypeError(\"Failed to fetch\"));\n });\n\n xhr.upload.addEventListener(\"loadstart\", () => {\n setProgress(0);\n });\n // `load`, not `loadend`: `loadend` follows an abort too, and put the\n // progress of a cancelled upload back to 1.\n xhr.upload.addEventListener(\"load\", () => {\n setProgress(1);\n });\n xhr.upload.addEventListener(\"progress\", (event) => {\n // A total the browser cannot tell is 0, and the ratio was `NaN`.\n if (event.lengthComputable && event.total > 0) {\n setProgress(event.loaded / event.total);\n }\n });\n\n xhr.open(method, action, true);\n xhr.send(data);\n });\n release();\n\n // `cancel()` has already reported it and put the state back to idle.\n if (outcome.type === \"abort\") {\n return;\n }\n\n if (outcome.status < 200 || outcome.status > 299) {\n let error: MutationError | E = {\n kind: \"server_error\",\n message: outcome.statusText,\n status: outcome.status,\n };\n try {\n error = mutationErrorFromBody(\n JSON.parse(outcome.body),\n outcome.status,\n );\n } catch {\n // Not JSON: a proxy's error page, say.\n }\n const failure = await withErrorHelpers(error);\n setState(\"error\");\n options?.onError?.(failure);\n return;\n }\n const json = JSON.parse(outcome.body);\n clearPrefetchCache?.();\n if (options.updates) {\n (await loadOrNull())?.applyQueryUpdates(getResource, _params, options.updates, json);\n }\n options?.onSuccess?.(json);\n setState(\"done\");\n return json;\n } catch (error) {\n release();\n const failure = await withErrorHelpers(error as MutationError);\n setState(\"error\");\n options?.onError?.(failure);\n return;\n }\n };\n\n return {\n state,\n progress,\n trigger,\n cancel,\n };\n}\n\n\n// `./mutationExtras`, or `null` when it could not be loaded (a chunk gone\n// after a deploy, no network).\nfunction loadOrNull() {\n return loadLazy(mutationExtras).catch(() => null);\n}\n\n// `error.list()` and `error.field(name)` on what the hooks hand over. If\n// their module could not be loaded, stand-ins that only know the fallback\n// keep `error.list()` in a render from throwing.\nasync function withErrorHelpers<T>(error: T): Promise<WithMutationErrorHelpers<T>> {\n const extras = await loadOrNull();\n if (extras) return extras.withMutationErrorHelpers(error);\n if (isObject(error) && Object.isExtensible(error) && !(\"list\" in error)) {\n Object.defineProperties(error, {\n list: { value: (fallback = \"Something went wrong. Try again.\") => [fallback] },\n field: { value: () => [] },\n });\n }\n return error as WithMutationErrorHelpers<T>;\n}\n","import { useContext } from \"react\";\nimport type { ApiRouterHandler } from \"../http/ApiRouter\";\nimport type { NestedPrettify, UnwrapPromise } from \"../utils/type\";\nimport { isPlainObject } from \"./isPlainObject\";\n\nimport type { RPC } from \"./rpc\";\nimport { QueryManagerContext } from \"./QueryManagerContext\";\nimport type { UrlParser } from \"./types\";\nimport { applyParams } from \"../utils/applyParams\";\nimport { toVariantKey } from \"../utils/variantKey\";\ntype GetRPC = {\n [K in keyof RPC as K extends `GET:${infer P}` ? P : never]: RPC[K];\n};\n\ntype Data<T extends keyof GetRPC> =\n GetRPC[T] extends ApiRouterHandler<any, infer Data, any>\n ? UnwrapPromise<Data>\n : never;\n\n/**\n * Which cached search variants of the path a call updates: one search object\n * (the variant a `useQuery` with that `search` reads), or a predicate over\n * every variant the cache holds for the path.\n */\ntype SearchTarget =\n | Record<string, any>\n | ((search: URLSearchParams) => boolean);\n\n/**\n * The shape guard both `mutate` forms apply: the callback's return value\n * *replaces* the cached data, so it has to keep the data's shape — a stray\n * value must not corrupt the cache. It does not merge or append.\n */\nfunction applyUpdate(data: any, fn: unknown) {\n const updatedData = typeof fn === \"function\" ? fn(data) : fn;\n\n if (isPlainObject(data)) {\n if (isPlainObject(updatedData)) {\n return updatedData;\n }\n throw new Error(\n \"Mutate function must return an object when the current data is an object.\",\n );\n }\n\n if (Array.isArray(data)) {\n if (Array.isArray(updatedData)) {\n return updatedData;\n }\n throw new Error(\n \"Mutate function must return an array when the current data is an array.\",\n );\n }\n\n if (typeof data !== typeof updatedData) {\n throw new Error(\n \"Mutate function must return the same type as the current data.\",\n );\n }\n\n return updatedData;\n}\n\nexport function useMutate() {\n const { getResource } = useContext(QueryManagerContext);\n return function mutate<T extends keyof GetRPC>(\n options: {\n path: T;\n params?: UrlParser<`${T & string}`>;\n search?: SearchTarget;\n },\n fn?:\n | ((data: NestedPrettify<Data<T>>) => NestedPrettify<Data<T>>)\n | NestedPrettify<Data<T>>,\n ) {\n const { path, params = {}, search = {} } = options ?? {};\n const normalPath = applyParams(path, params);\n const resource = getResource(normalPath);\n\n if (typeof search === \"function\") {\n // Every cached variant the predicate accepts — e.g. `() => true` for\n // all of them, pages of a `useInfiniteQuery` included. Variants on\n // screen refetch now; the rest are marked stale and revalidate when\n // next read, so a path with many cached searches doesn't burst.\n for (const variantKey of resource.variantKeys()) {\n if (!search(new URLSearchParams(variantKey))) continue;\n resource.invalidate(\n variantKey,\n fn === undefined\n ? undefined\n : (data: any) => (data === null ? data : applyUpdate(data, fn)),\n );\n }\n return;\n }\n\n const variantKey = toVariantKey(search);\n return resource.mutate.call(resource, variantKey, (data: any) => {\n if (data === undefined || data === null) {\n console.warn(\"Mutate function called before the query.\");\n return data;\n }\n\n if (!fn) {\n return data;\n }\n\n return applyUpdate(data, fn);\n });\n };\n}\n","import { loadLazy, type LazyModule } from \"./lazyModule\";\nimport type { FileRPC } from \"./rpc\";\nimport type { UrlParser } from \"./types\";\n\n/**\n * The paths `fetchBlob` and `fetchText` take: the app's file routes\n * (`this.stream(...)` and `this.file(...)`), or any path while `FileRPC` is\n * empty — an app without file routes, or a program without the app's types.\n */\nexport type FilePath = FilePathOf<FileRPC>;\n\n/** `FilePath` over a given table, for tests. @internal */\nexport type FilePathOf<T> = [keyof T] extends [never] ? string : keyof T & string;\n\nexport type FetchFileOptions<P extends string> = {\n /** The path's `:params`, substituted as `useQuery` does. */\n params?: Partial<UrlParser<P>>;\n /** The query string. `null` and `undefined` values are left out. */\n search?:\n | Record<string, string | number | boolean | null | undefined>\n | URLSearchParams;\n /** Aborts the request; the returned promise then rejects with an `AbortError`. */\n signal?: AbortSignal;\n /** Anything else `fetch` takes (headers, `cache`, `credentials`). Always a `GET`. */\n init?: Omit<RequestInit, \"method\" | \"body\" | \"signal\">;\n};\n\n// `options` is required, with `params`, when the path has a param of its own.\n/** @internal */\nexport type FetchFileArgs<P extends string> =\n {} extends UrlParser<P>\n ? [options?: FetchFileOptions<P>]\n : [options: FetchFileOptions<P> & { params: UrlParser<P> }];\n\ninterface Fetched {\n /**\n * The file name the server gave in `Content-Disposition` (`filename*`\n * first, then `filename`), or `null` when it gave none.\n */\n filename: string | null;\n /** The response, for its headers and status. Its body has been read. */\n response: Response;\n}\n\nexport interface FetchedBlob extends Fetched {\n blob: Blob;\n}\n\nexport interface FetchedText extends Fetched {\n text: string;\n}\n\n// The request itself, loaded on the first call (#915): an app's bundler puts\n// whatever `gemi/client` reaches statically in every route's entry chunk.\nconst request: LazyModule<typeof import(\"./fetchFileRequest\")> = {\n current: null,\n load: () => import(\"./fetchFileRequest.js\"),\n};\n\n/**\n * Downloads a file route's body as a `Blob`.\n *\n * ```ts\n * const { blob, filename } = await fetchBlob(\"/pages/:pageId/post/image\", {\n * params: { pageId },\n * search: { format: \"png\" },\n * });\n * ```\n *\n * A non-2xx rejects with a `QueryError` (`status`, the JSON `body` or `null`,\n * `retryAfter`), the error `useQuery` throws, so `mutationErrorList(error)`\n * reads its message. A network failure rejects with the browser's `TypeError`,\n * an abort with its `AbortError`.\n *\n * The request code loads on the first call (#915), so a route that never\n * downloads a file carries none of it; a failed load rejects as a network\n * failure does.\n */\nexport async function fetchBlob<P extends FilePath>(\n path: P,\n ...args: FetchFileArgs<P>\n): Promise<FetchedBlob> {\n return (await loadLazy(request)).fetchFile(path, args[0], \"blob\") as Promise<FetchedBlob>;\n}\n\n/** `fetchBlob`, with the body read as text. */\nexport async function fetchText<P extends FilePath>(\n path: P,\n ...args: FetchFileArgs<P>\n): Promise<FetchedText> {\n return (await loadLazy(request)).fetchFile(path, args[0], \"text\") as Promise<FetchedText>;\n}\n","import { useCallback, useContext, useEffect } from \"react\";\nimport type { ApiRouterHandler } from \"../http/ApiRouter\";\nimport type { NestedPrettify, UnwrapPromise } from \"../utils/type\";\nimport type { RPC } from \"./rpc\";\nimport type { UrlParser } from \"./types\";\nimport { QueryManagerContext } from \"./QueryManagerContext\";\nimport { loadLazy } from \"./lazyModule\";\nimport { mutationExtras, preloadMutationExtras } from \"./mutationModules\";\nimport type { WriteQueryNext } from \"./queryUpdates\";\nimport { useParams } from \"./useParams\";\n\ntype GetRPC = {\n [K in keyof RPC as K extends `GET:${infer P}` ? P : never]: RPC[K];\n};\n\n/** The data a `useQuery` of this path reads. */\ntype QueryData<P extends keyof GetRPC> = NestedPrettify<\n GetRPC[P] extends ApiRouterHandler<any, infer Data, any> ? UnwrapPromise<Data> : never\n>;\n\n/**\n * The cached query a write lands in: the `useMutate` target. `search` is one\n * variant (the one a `useQuery` with that `search` reads), or a predicate\n * over every variant the cache holds for the path. `params` are merged over\n * the current route's, as `useQuery` merges them.\n */\nexport type QueryTarget<P extends keyof GetRPC> = {\n path: P;\n params?: Partial<UrlParser<`${P & string}`>>;\n search?: Record<string, any> | ((search: URLSearchParams) => boolean);\n};\n\n/**\n * One entry of a mutation's `updates`: a query its answer (`T`) is written\n * into, with no refetch. Without `data` the answer is written as is, which\n * only type-checks when it is the path's data. `data` builds the next value\n * from the answer and what is cached, and is skipped for a variant with\n * nothing cached.\n */\nexport type QueryUpdate<T> = {\n [P in keyof GetRPC]: QueryTarget<P> &\n ([T] extends [QueryData<P>]\n ? { data?: (answer: T, current: QueryData<P>) => QueryData<P> }\n : { data: (answer: T, current: QueryData<P>) => QueryData<P> });\n}[keyof GetRPC];\n\n/**\n * Returns a function that writes into any query's cache by path, with no\n * refetch: for data the server already answered with. `useMutate` is the\n * optimistic counterpart, which refetches to reconcile.\n *\n * ```ts\n * const setQueryData = useSetQueryData();\n * setQueryData({ path: \"/pages/:pageId/assets\", params: { pageId } }, assets);\n * setQueryData({ path: \"/todos\", search: () => true }, (todos) => todos.slice(1));\n * ```\n *\n * A value replaces the variant's data, and seeds it when nothing is cached\n * yet. A function updates what is cached and skips a variant with nothing\n * cached. A predicate `search` reaches every cached variant it accepts.\n *\n * The code behind the writes is loaded when the hook mounts. A call made\n * before it has arrived (during the first render, say) is written once it\n * has, in order.\n */\nexport function useSetQueryData() {\n const { getResource } = useContext(QueryManagerContext);\n const routeParams = useParams();\n // The writes are loaded on mount (#915), so by the time a handler calls the\n // setter they are normally there and it writes at once.\n useEffect(preloadMutationExtras, []);\n return useCallback(\n function setQueryData<P extends keyof GetRPC>(\n target: QueryTarget<P>,\n next: QueryData<P> | ((current: QueryData<P>) => QueryData<P>),\n ) {\n const write: WriteQueryNext =\n typeof next === \"function\"\n ? { update: next as (current: any) => unknown }\n : { value: next };\n const writes = mutationExtras.current;\n if (writes) {\n writes.writeQueryData(getResource, routeParams, target, write);\n return;\n }\n // Called before the module arrived: written once it has, in call\n // order. A failed load writes nothing.\n loadLazy(mutationExtras)\n .then((loaded) => loaded.writeQueryData(getResource, routeParams, target, write))\n .catch(() => {});\n },\n [getResource, routeParams],\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\n\nimport type { ChangeFeedEvent } from \"../services/change-feed/ChangeFeedDriver\";\nimport type { ChangeFeedResponse } from \"../services/change-feed/wire\";\nimport { applyParams } from \"../utils/applyParams\";\nimport { loadedModule } from \"./lazyModule\";\nimport type { SubscriptionState } from \"./subscriptionStream\";\nimport type { UrlParser } from \"./types\";\nimport type { Data, GetRPC } from \"./useQuery\";\nimport { useParams } from \"./useParams\";\n\n/** The `data` a route's `ChangeFeed.stream<T>()` publishes, or `unknown`. */\nexport type SubscriptionData<T extends keyof GetRPC> =\n Data<T> extends ChangeFeedResponse<infer D> ? D : unknown;\n\nexport type SubscriptionStatus = \"connecting\" | \"open\" | \"paused\" | \"closed\";\n\nexport type SubscriptionOptions<T extends keyof GetRPC> = {\n params?: Partial<UrlParser<`${T & string}`>>;\n search?: Record<string, string | number | boolean | null>;\n};\n\nexport type SubscriptionConfig<D> = {\n /** Each change, in order. */\n onChange?: (event: Extract<ChangeFeedEvent<D>, { type: \"change\" }>) => void;\n /**\n * The subscription could not be brought up to date change by change (it\n * was away longer than the server keeps changes): read the resource again.\n */\n onReset?: (event: Extract<ChangeFeedEvent<D>, { type: \"reset\" }>) => void;\n /**\n * Where to start, from `ChangeFeed.cursor()` in the view's data, so that a\n * change made between the server rendering the view and the browser\n * connecting is not missed. Default: the channels' heads when connecting.\n */\n cursor?: string | null;\n /** `false` disconnects. Default `true`. */\n enabled?: boolean;\n /**\n * Disconnect while the tab is hidden, and catch up from the cursor once it\n * is shown again. Default `true`.\n */\n pauseWhenHidden?: boolean;\n};\n\n/** `./subscriptionStream`, loaded on first use. Replaceable in tests. */\nexport const streamModule = {\n load: () => import(\"./subscriptionStream.js\"),\n};\n\n/**\n * Follows a route that answers with `ChangeFeed.stream`, as long as the\n * component is mounted: each change reaches `onChange`, in order, exactly\n * once, across dropped connections and hidden tabs.\n *\n * ```tsx\n * const { status } = useSubscription(\n * \"/sites/:siteId/changes\",\n * { params: { siteId } },\n * { cursor: site.cursor, onChange: ({ data }) => apply(data), onReset: () => reload() },\n * );\n * ```\n *\n * It reconnects after a drop with backoff (1 s doubling to 30 s, or the\n * server's `Retry-After`), resuming with `Last-Event-ID` from the last event\n * it saw. A `4xx` other than `408` and `429` stops it, with status `closed`.\n * The callbacks may change between renders without reconnecting.\n */\nexport function useSubscription<T extends keyof GetRPC>(\n url: T,\n options: SubscriptionOptions<T> = {},\n config: SubscriptionConfig<SubscriptionData<T>> = {},\n): { status: SubscriptionStatus; cursor: string | null; error: Error | null } {\n const routeParams = useParams();\n const params = { ...routeParams, ...(options.params as Record<string, string>) };\n const search = new URLSearchParams(\n Object.entries(options.search ?? {})\n .filter(([, value]) => value !== null && value !== undefined)\n .map(([key, value]) => [key, String(value)]),\n );\n search.sort();\n const path = [applyParams(String(url), params), search.toString()].filter(Boolean).join(\"?\");\n const endpoint = `/api${path}`;\n const enabled = config.enabled !== false;\n const pauseWhenHidden = config.pauseWhenHidden !== false;\n\n const callbacks = useRef(config);\n useEffect(() => {\n callbacks.current = config;\n });\n // The cursor survives a change of callbacks, a pause and a reconnect, and\n // starts over only for another endpoint or another starting cursor.\n const cursor = useRef<string | null>(config.cursor ?? null);\n const [state, setState] = useState<SubscriptionState>({\n status: enabled ? \"connecting\" : \"closed\",\n cursor: cursor.current,\n error: null,\n });\n\n useEffect(() => {\n cursor.current = config.cursor ?? null;\n }, [endpoint, config.cursor]);\n\n useEffect(() => {\n if (!enabled) {\n setState((s) => ({ ...s, status: \"closed\" }));\n return;\n }\n // The connection is loaded on first use; see `./subscriptionStream`.\n let stopped = false;\n let stop: (() => void) | null = null;\n streamModule\n .load()\n .then((module) => {\n const { follow } = loadedModule(module);\n if (stopped) return;\n stop = follow({\n endpoint,\n pauseWhenHidden,\n cursor,\n callbacks: callbacks as { current: SubscriptionConfig<unknown> },\n setState,\n });\n })\n .catch((error: unknown) => {\n // A chunk that will not load (usually a deploy; `init`'s chunk-load\n // recovery reloads the page for it) or a module that failed to\n // evaluate: no connection to retry.\n if (!stopped) setState((s) => ({ ...s, status: \"closed\", error: error as Error }));\n });\n return () => {\n stopped = true;\n stop?.();\n };\n }, [endpoint, enabled, pauseWhenHidden, config.cursor]);\n\n return state;\n}\n","import { useContext, useEffect, useRef } from \"react\";\n\nimport { applyParams } from \"../utils/applyParams\";\nimport { toVariantKey } from \"../utils/variantKey\";\nimport { QueryManagerContext } from \"./QueryManagerContext\";\nimport type { ChannelParamValues } from \"./realtime/RealtimeClient\";\nimport {\n useChannelSubscription,\n useCoalesced,\n type ChannelState,\n} from \"./realtime/useChannelSubscription\";\nimport type { BroadcastRPC } from \"./rpc\";\nimport type { GetRPC } from \"./useQuery\";\nimport { useParams } from \"./useParams\";\n\n/** A channel pattern the app's `ChannelRouter` declares (any string without one). */\nexport type ChannelPattern<R = BroadcastRPC> = [keyof R] extends [never]\n ? string\n : keyof R & string;\n\n/** The params a pattern takes, from `BroadcastRPC`. */\nexport type ChannelParamsFor<P extends string, R = BroadcastRPC> = P extends keyof R\n ? R[P] extends { params: infer X }\n ? X\n : ChannelParamValues\n : ChannelParamValues;\n\n/** The events a pattern's channel carries, from `BroadcastRPC`. */\nexport type ChannelEventsFor<P extends string, R = BroadcastRPC> = P extends keyof R\n ? R[P] extends { events: infer E extends Record<string, unknown> }\n ? E\n : Record<string, unknown>\n : Record<string, unknown>;\n\nexport interface UseChannelOptions<P extends string> {\n params?: ChannelParamsFor<P>;\n}\n\nexport interface UseChannelConfig<Events extends Record<string, unknown>> {\n /** A handler per event name, called with the event's payload. */\n on?: { [E in keyof Events]?: (data: Events[E]) => void };\n /**\n * Events may have been missed — after a (re)connect, once the subscription\n * is acknowledged, or on a server `gap`: refetch what this channel\n * describes. Coalesced to one call per 2 s.\n */\n onResync?: () => void;\n /** `false` unsubscribes. Default `true`. */\n enabled?: boolean;\n}\n\nexport type { ChannelState };\nexport type { ChannelStatus } from \"./realtime/RealtimeClient\";\n\nconst warnedWithoutResync = new Set<string>();\n\n/**\n * Subscribes to a broadcast channel while the component is mounted.\n *\n * ```tsx\n * const { status } = useChannel(\"site.:siteId\", { params: { siteId } }, {\n * on: { changed: (d) => mutate({ path: \"/pages/:pageId\", params: { pageId } }) },\n * onResync: () => mutate({ path: \"/pages/:pageId\", params: { pageId } }),\n * });\n * ```\n *\n * Events are hints, delivered at most once: pair `on` with `onResync`, which\n * runs whenever some may have been missed. `useChannelInvalidate` does both\n * for the common case. On the server, and until the effect runs, `status` is\n * `closed`.\n */\nexport function useChannel<P extends ChannelPattern>(\n pattern: P,\n options: UseChannelOptions<P> = {},\n config: UseChannelConfig<ChannelEventsFor<P>> = {},\n): ChannelState {\n const configRef = useRef(config);\n configRef.current = config;\n const hasOn = config.on !== undefined && Object.keys(config.on).length > 0;\n const hasResync = config.onResync !== undefined;\n\n useEffect(() => {\n if (process.env.NODE_ENV === \"production\") return;\n if (!hasOn || hasResync || warnedWithoutResync.has(pattern)) return;\n warnedWithoutResync.add(pattern);\n console.warn(\n `[gemi] useChannel(\"${pattern}\") has \\`on\\` handlers but no \\`onResync\\`. ` +\n `Broadcast events are hints delivered at most once: after a reconnect ` +\n `or a gap the events in between are gone, so refetch in \\`onResync\\` ` +\n `(or use useChannelInvalidate).`,\n );\n }, [pattern, hasOn, hasResync]);\n\n return useChannelSubscription(\n pattern,\n (options.params ?? {}) as ChannelParamValues,\n {\n onEvent: (event, data) => {\n const handler = (configRef.current.on as Record<string, ((d: unknown) => void) | undefined>)?.[\n event\n ];\n handler?.(data);\n },\n onResync: () => configRef.current.onResync?.(),\n },\n config.enabled !== false,\n );\n}\n\ntype GetPath = [keyof GetRPC] extends [never] ? string : keyof GetRPC & string;\n\n/**\n * A query `useChannelInvalidate` refetches: an api path (its `:params`\n * filled from the channel's params, over the route's), or one with its own\n * params and a single search variant.\n */\nexport type InvalidatePath =\n | GetPath\n | {\n path: GetPath;\n params?: Record<string, string | number>;\n /** Only this search variant. Default: every cached variant. */\n search?: Record<string, string | number | boolean | null>;\n };\n\n/**\n * Refetches `paths` on any event on the channel and on every resync. Only\n * the variants being rendered refetch now; the rest are marked stale. Events\n * are coalesced: a burst within 150 ms refetches once.\n *\n * ```tsx\n * useChannelInvalidate(\"page.:pageId\", { pageId }, [\"/pages/:pageId\", \"/pages/:pageId/pictures\"]);\n * ```\n */\nexport function useChannelInvalidate<P extends ChannelPattern>(\n pattern: P,\n params: ChannelParamsFor<P> | undefined,\n paths: readonly InvalidatePath[],\n config: { enabled?: boolean } = {},\n): ChannelState {\n const { getResource } = useContext(QueryManagerContext);\n const routeParams = useParams();\n const channelParams = (params ?? {}) as ChannelParamValues;\n const latest = useRef({ paths, routeParams, channelParams, getResource });\n latest.current = { paths, routeParams, channelParams, getResource };\n\n const invalidate = () => {\n const { paths, routeParams, channelParams, getResource } = latest.current;\n for (const entry of paths) {\n const target = typeof entry === \"string\" ? { path: entry } : entry;\n const resolved = applyParams(target.path, {\n ...routeParams,\n ...channelParams,\n ...target.params,\n });\n const resource = getResource(resolved);\n const keys = target.search ? [toVariantKey(target.search)] : resource.variantKeys();\n for (const key of keys) resource.invalidate(key);\n }\n };\n\n // A burst of events is one refetch; a resync (already coalesced by the\n // socket, and the answer to missed events) refetches at once.\n const onEvent = useCoalesced(invalidate);\n return useChannelSubscription(\n pattern,\n channelParams,\n { onEvent, onResync: invalidate },\n config.enabled !== false,\n );\n}\n\nexport type { LiveChannel } from \"./realtime/live\";\n","import {\n createContext,\n useContext,\n type ComponentProps,\n type Ref,\n useRef,\n useEffect,\n useSyncExternalStore,\n useCallback,\n} from \"react\";\nimport type { RPC } from \"./rpc\";\nimport type { ApiRouterHandler } from \"../http/ApiRouter\";\nimport { useMutation } from \"./useMutation\";\nimport type { UnwrapPromise } from \"../utils/type\";\nimport type { UrlParser } from \"./types\";\nimport { useParams } from \"./useParams\";\nimport { ServerDataContext } from \"./ServerDataProvider\";\nimport { Subject } from \"../utils/Subject\";\nimport {\n isFormError,\n isValidationError,\n type MutationError,\n type WithMutationErrorHelpers,\n} from \"./MutationError\";\n\ntype Any = any;\n\ninterface MutationContextValue {\n isPending: boolean;\n result: null | Any;\n validationErrors: Record<string, string[]>;\n formError: null | string;\n formDataSubject: React.RefObject<Subject<FormData>>;\n}\n\nconst MutationContext = createContext({\n isPending: false,\n result: null,\n} as MutationContextValue);\n\ntype GetResult<T> =\n T extends ApiRouterHandler<Any, infer Result, Any>\n ? UnwrapPromise<Result>\n : never;\n\ntype PostRequests = {\n [K in keyof RPC as K extends `POST:${infer P}` ? P : never]: GetResult<\n RPC[K]\n >;\n};\n\ntype PutRequests = {\n [K in keyof RPC as K extends `PUT:${infer P}` ? P : never]: GetResult<RPC[K]>;\n};\n\ntype DeleteRequests = {\n [K in keyof RPC as K extends `DELETE:${infer P}` ? P : never]: GetResult<\n RPC[K]\n >;\n};\n\ntype PatchRequests = {\n [K in keyof RPC as K extends `PATCH:${infer P}` ? P : never]: GetResult<\n RPC[K]\n >;\n};\n\ntype GetError<T> =\n T extends ApiRouterHandler<Any, Any, Any, infer E> ? E : never;\n\n/** Each route's typed errors (`HttpResponse.error`), by method and path. */\ntype ErrorMethods = {\n [M in keyof Methods]: {\n [K in keyof RPC as K extends `${M}:${infer P}` ? P : never]: GetError<RPC[K]>;\n };\n};\n\ntype Methods = {\n POST: PostRequests;\n PUT: PutRequests;\n DELETE: DeleteRequests;\n PATCH: PatchRequests;\n};\n\n// Whatever `<form onSubmit>` hands its handler under the installed\n// `@types/react` — `SubmitEvent` in current versions, `FormEvent` in older\n// ones — so the caller's handler can be called with it either way.\ntype FormSubmitEvent = Parameters<\n NonNullable<ComponentProps<\"form\">[\"onSubmit\"]>\n>[0];\n\ninterface FormProps<\n M extends keyof Methods,\n K extends keyof Methods[M],\n E = ErrorMethods[M][K & keyof ErrorMethods[M]],\n> extends Omit<ComponentProps<\"form\">, \"action\" | \"onError\"> {\n method?: M;\n action: K;\n onSuccess?: (result: Methods[M][K], form: HTMLFormElement) => void;\n /**\n * Called when the request fails. `error` is a `MutationError`, or one of\n * the route's typed errors (the bodies its handler answers with\n * `HttpResponse.error` / `httpError`); narrow it with `isValidationError`,\n * `isPermissionError`, `isHttpError` and the other guards from\n * `gemi/client`, or read it with `error.list()` / `error.field(name)`.\n * Validation and form errors are already rendered by `<ValidationErrors>`\n * and `<FormError>`.\n */\n // Method syntax, so a handler typed `(error: MutationError, form) => …`\n // still compiles for a route that has typed errors.\n onError?(\n error: WithMutationErrorHelpers<MutationError | E>,\n form: HTMLFormElement,\n ): void;\n /**\n * Called when a submit is about to send its request, with the exact\n * `FormData` that will be sent (after `dynamicInputs`). Return `false` to\n * skip the request. Not called for a submit swallowed because one is\n * already in flight.\n */\n onSubmitStart?: (\n formData: FormData,\n form: HTMLFormElement,\n ) => void | boolean;\n /** Called after `onSuccess` or `onError`, whichever ran. */\n onSettled?: (form: HTMLFormElement) => void;\n params?: Partial<UrlParser<`${K & string}`>>;\n search?: Record<string, string>;\n dynamicInputs?: (formData: FormData) => Record<string, any>;\n}\n\nexport function Form<\n K extends keyof Methods[T],\n T extends keyof Methods = \"POST\",\n E = ErrorMethods[T][K & keyof ErrorMethods[T]],\n>(props: FormProps<T, K, E>) {\n const _params = useParams();\n const {\n method = \"POST\",\n action,\n onSuccess = () => {},\n onError = () => {},\n onSubmitStart,\n onSettled,\n onSubmit,\n ref,\n params,\n search = {},\n className,\n dynamicInputs = () => ({}),\n ...formProps\n } = \"params\" in props\n ? { ...props, params: { ..._params, ...props.params } }\n : { ...props, params: _params };\n const formRef = useRef<HTMLFormElement>(null);\n // Both refs, not one or the other. A `ref` from the caller used to land in\n // the props spread over the `<form>`, which replaced `formRef` and left\n // every submit returning early at `!formRef.current`.\n const setFormRef = useCallback(\n (node: HTMLFormElement | null) => {\n formRef.current = node;\n const cleanup = assignRef(ref, node);\n // Returning a cleanup means React will not call this again with `null`,\n // so the detach happens here — including the caller's own cleanup when\n // their callback ref returned one.\n return () => {\n formRef.current = null;\n if (typeof cleanup === \"function\") {\n cleanup();\n } else {\n assignRef(ref, null);\n }\n };\n },\n [ref],\n );\n const { __csrf } = useContext(ServerDataContext);\n const formDataSubject = useRef(new Subject(new FormData()));\n\n const updateFormData = useCallback(() => {\n formDataSubject.current.next(new FormData(formRef.current));\n }, []);\n\n useEffect(() => {\n if (!formRef.current) return;\n\n formRef.current.addEventListener(\"input\", updateFormData);\n\n const observer = new MutationObserver(() => {\n const formData = new FormData(formRef.current);\n formDataSubject.current.next(formData);\n });\n\n formRef.current.querySelectorAll(\"input\").forEach((input) =>\n observer.observe(input, {\n attributes: true,\n attributeFilter: [\"value\"],\n }),\n );\n\n formRef.current.querySelectorAll(\"select\").forEach((input) =>\n observer.observe(input, {\n attributes: true,\n attributeFilter: [\"value\"],\n }),\n );\n\n formRef.current.querySelectorAll(\"textarea\").forEach((input) =>\n observer.observe(input, {\n attributes: true,\n attributeFilter: [\"value\"],\n }),\n );\n\n return () => {\n observer.disconnect();\n if (formRef.current) {\n formRef.current.removeEventListener(\"input\", updateFormData);\n }\n };\n }, [updateFormData]);\n\n const { trigger, data, error, loading } = useMutation(\n method,\n String(action) as Any,\n {\n params,\n search,\n } as Any,\n {\n onSuccess: (data) => {\n onSuccess(data as Any, formRef.current);\n onSettled?.(formRef.current);\n },\n onError: (error) => {\n onError(error as Any, formRef.current);\n onSettled?.(formRef.current);\n },\n },\n );\n\n const handleSubmit = async (e: FormSubmitEvent) => {\n // Before the guards, not after: returning early without preventing the\n // default let the browser submit the form itself. A second click while a\n // slow submit was still in flight navigated the page away and took the\n // request with it.\n e.preventDefault();\n // The caller's `onSubmit` runs alongside this handler rather than instead\n // of it. It used to be spread over the `<form>` after `onSubmit=\n // {handleSubmit}` and win: no `preventDefault`, so the browser submitted\n // the form itself, and no request. It sees every submit event, like a\n // native handler does, and it cannot cancel the request — the default is\n // already prevented by now, so `defaultPrevented` carries no signal.\n // `onSubmitStart` returning `false` is the way to skip one.\n onSubmit?.(e);\n if (loading) {\n return;\n }\n if (!formRef.current) {\n return;\n }\n const formData = new FormData(formRef.current);\n for (const [key, value] of Object.entries(dynamicInputs(formData))) {\n formData.append(key, value as any);\n }\n if (onSubmitStart?.(formData, formRef.current) === false) {\n return;\n }\n trigger(formData as any);\n };\n\n const validationErrors = isValidationError(error) ? error.messages : {};\n\n const formError = isFormError(error) ? error.message : null;\n\n return (\n <MutationContext.Provider\n value={{\n isPending: loading,\n result: data,\n validationErrors,\n formError,\n formDataSubject,\n }}\n >\n {/* The spread comes first so that nothing in it can replace what\n `<Form>` needs to work; `ref` and `onSubmit` are composed above. */}\n <form\n {...formProps}\n className={[\"group\", className].filter(Boolean).join(\" \")}\n data-loading={loading}\n ref={setFormRef}\n onSubmit={handleSubmit}\n >\n <input type=\"hidden\" name=\"__csrf\" value={__csrf} />\n {props.children}\n </form>\n </MutationContext.Provider>\n );\n}\n\nfunction assignRef<T>(ref: Ref<T> | undefined, value: T | null) {\n if (typeof ref === \"function\") {\n return ref(value);\n }\n if (ref) {\n ref.current = value;\n }\n}\n\nexport function useMutationStatus() {\n const { isPending } = useContext(MutationContext);\n\n return { isPending };\n}\n\nexport function useFormStatus() {\n const { isPending, validationErrors, formError } =\n useContext(MutationContext);\n\n return { isPending, validationErrors, formError };\n}\n\nexport function useFormData() {\n const context = useContext(MutationContext);\n\n const { formDataSubject } = context;\n\n // Unbound on purpose: `Subject` binds in its constructor, so these are\n // stable across renders. The `.bind` calls that used to be here allocated a\n // fresh `subscribe` every render, which made `useSyncExternalStore` drop and\n // re-add this component's subscription on each pass.\n return useSyncExternalStore(\n formDataSubject.current.subscribe,\n formDataSubject.current.getValue,\n formDataSubject.current.getValue,\n );\n}\n\nexport const ValidationErrors = (props: {\n name: string;\n className?: string;\n render?: (props: ComponentProps<\"div\">) => React.JSX.Element;\n}) => {\n const {\n render = (props: ComponentProps<\"div\">) => <div {...props} />,\n name,\n } = props;\n const { validationErrors } = useContext(MutationContext);\n\n const Comp = render;\n\n if (validationErrors[name]?.length > 0) {\n return (\n <>\n {validationErrors[name].map((error) => {\n return (\n <Comp className={props.className} key={error}>\n {error}\n </Comp>\n );\n })}\n </>\n );\n }\n\n return null;\n};\n\nexport const FormFieldContainer = (\n props: ComponentProps<\"div\"> & { name: string },\n) => {\n const { name, children, ...rest } = props;\n const { validationErrors } = useContext(MutationContext);\n const errors = validationErrors[name] || [];\n return (\n <div data-has-error={errors.length > 0} {...rest}>\n {children}\n </div>\n );\n};\n\nexport const FormError = (props: ComponentProps<\"div\">) => {\n const { formError } = useContext(MutationContext);\n\n if (formError) {\n return <div {...props}>{formError}</div>;\n }\n\n return null;\n};\n","import { useContext } from \"react\";\nimport { ServerDataContext } from \"./ServerDataProvider\";\nimport { domainUrl, type DomainTarget } from \"../utils/domainUrl\";\n\n/**\n * The `route.domains` group this page was served under — `params.tenant` on\n * `acme.example.com` — and `url()` for linking to another of the app's hosts.\n * Empty when the app declares no `route.domains`.\n *\n * Hand `url()`'s result to `Link` or `navigate`: a URL on another host is a\n * full page load, not a client-side navigation.\n */\nexport function useDomain() {\n const domain = useContext(ServerDataContext).router?.domain ?? null;\n return {\n host: domain?.host ?? null,\n group: domain?.group ?? null,\n params: domain?.params ?? {},\n custom: domain?.custom ?? false,\n url(target: DomainTarget, path = \"/\") {\n if (!domain?.root) {\n throw new Error(\"`useDomain().url` needs `route.domains` to be configured.\");\n }\n // The origin the server saw, not `window.location`: the two agree, and\n // this one exists during the server render too, so hydration matches.\n return domainUrl({ root: domain.root, origin: domain.origin }, target, path);\n },\n };\n}\n","import { useContext, useSyncExternalStore } from \"react\";\nimport { ClientRouterContext } from \"./ClientRouterContext\";\n\nexport function useIsNavigationPending() {\n const { isNavigatingSubject } = useContext(ClientRouterContext);\n // These read `this`, and `useSyncExternalStore` calls whatever it is handed\n // as a plain function — which used to throw `undefined is not an object\n // (evaluating 'this.value')` on the first render of any component calling\n // this hook. `Subject` now binds in its constructor, so the references are\n // both correct and stable across renders; binding here instead would hand\n // uSES a new `subscribe` every render and churn the subscription.\n const isNavigating = useSyncExternalStore(\n isNavigatingSubject.subscribe,\n isNavigatingSubject.getValue,\n isNavigatingSubject.getValue,\n );\n\n return isNavigating;\n}\n","import { useContext, useEffect, useState } from \"react\";\nimport { ClientRouterContext } from \"./ClientRouterContext\";\n\nexport function useNavigationProgress() {\n const { progressManager } = useContext(ClientRouterContext);\n const [progress, setProgress] = useState(progressManager.state.getValue());\n\n useEffect(() => {\n const unsub = progressManager.state.subscribe((p) => setProgress(p));\n return () => {\n unsub();\n };\n }, [progressManager.state]);\n\n return progress;\n}\n","import { useCallback, useContext } from \"react\";\n\nimport { applyParams } from \"../utils/applyParams\";\nimport { ClientRouterContext } from \"./ClientRouterContext\";\nimport { I18nContext } from \"./I18nContext\";\nimport { useLocation } from \"./useLocation\";\nimport type { IsViewPath, UrlParser, ViewPaths } from \"./types\";\n\ntype Search = Record<string, string | number | boolean | undefined | null>;\n\n/**\n * A prefetch spends the visitor's data on a page they may never open, so it\n * stands down when they have asked for less of that or the connection cannot\n * spare it. `navigator.connection` only exists in Chromium — everywhere else\n * there is nothing to go on and prefetching proceeds.\n */\nfunction connectionRefusesPrefetch() {\n const connection = (navigator as any)?.connection;\n if (!connection) {\n return false;\n }\n if (connection.saveData) {\n return true;\n }\n return [\"slow-2g\", \"2g\"].includes(connection.effectiveType);\n}\n\ntype Options<T extends string> =\n UrlParser<T> extends Record<string, never>\n ? {\n search?: Search;\n locale?: string;\n }\n : {\n search?: Search;\n params: UrlParser<T>;\n locale?: string;\n };\n\n/** The options for a URL built at runtime — see `useNavigate`'s copy. */\ntype RuntimeOptions = {\n search?: Search;\n params?: Record<string, string | number | undefined>;\n locale?: string;\n};\n\n/** Required for a declared route that has params, optional otherwise. See\n * `IsViewPath` — prefetch took `ViewPaths | (string & {})` and so had the\n * same inference fault `useNavigate` did. */\ntype PrefetchArgs<P extends string> = IsViewPath<P> extends true\n ? UrlParser<P> extends Record<string, never>\n ? [options?: Options<P>]\n : [options: Options<P>]\n : [options?: RuntimeOptions];\n\n/**\n * Warms a route ahead of the navigation to it: its page data, its stylesheets\n * and its component chunks. A navigation that lands on a prefetched route\n * renders from the cached payload instead of waiting on a request.\n *\n * The URL is built exactly the way `useNavigate` builds it — the prefetch is\n * only ever used by a navigation that asks for the same one.\n */\nexport function usePrefetch() {\n const { prefetchRoute } = useContext(ClientRouterContext);\n const { defaultLocale } = useContext(I18nContext);\n const location = useLocation();\n\n const currentPathname = location.pathname;\n const currentSearch = location.search;\n const currentLocale = location.locale;\n\n return useCallback(\n async <P extends ViewPaths | (string & {})>(\n path: P,\n ...args: PrefetchArgs<P>\n ) => {\n if (typeof window === \"undefined\" || !prefetchRoute) {\n return;\n }\n\n if (connectionRefusesPrefetch()) {\n return;\n }\n\n const [options = {}] = args;\n const {\n search = {},\n params = {},\n locale = null,\n } = { params: {}, search: {}, locale: null, ...options };\n\n let localeSegment = locale ?? currentLocale;\n if (localeSegment === defaultLocale) {\n localeSegment = \"\";\n }\n\n const pathname = applyParams(path, params) || \"/\";\n // Matches `useNavigate`, which hands the search object straight to\n // `URLSearchParams` — the query string a click produces has to be the one\n // the payload was cached under.\n const queryString = new URLSearchParams(search as any).toString();\n const searchSegment = queryString.length > 0 ? `?${queryString}` : \"\";\n\n // The route already on screen has nothing to warm, and eagerly prefetched\n // links pointing back at it would just replay the current page's queries.\n if (pathname === currentPathname && searchSegment === currentSearch) {\n return;\n }\n\n await prefetchRoute({\n pathname,\n search: searchSegment,\n localeSegment: localeSegment ? `/${localeSegment}` : \"\",\n });\n },\n [\n prefetchRoute,\n defaultLocale,\n currentLocale,\n currentPathname,\n currentSearch,\n ],\n );\n}\n","import { useContext } from \"react\";\nimport { useRoute } from \"./useRoute\";\nimport { ClientRouterContext } from \"./ClientRouterContext\";\n\nexport type Breadcrumb = {\n label: string;\n href: string;\n};\n\nexport function useBreadcrumbs() {\n const { pathname } = useRoute();\n const { getViewPathsFromPathname, breadcrumbsCache } =\n useContext(ClientRouterContext);\n\n let breadcrumbs: Breadcrumb[] = [];\n const viewPaths = getViewPathsFromPathname(pathname);\n for (const viewPath of viewPaths) {\n if (breadcrumbsCache.has(`${viewPath}:${pathname}`)) {\n breadcrumbs.push(breadcrumbsCache.get(`${viewPath}:${pathname}`));\n }\n }\n\n return breadcrumbs.filter((breadcrumb) => breadcrumb?.label.length > 0);\n}\n","import {\n useCallback,\n useContext,\n useEffect,\n useRef,\n memo,\n type ComponentProps,\n type MouseEvent as ReactMouseEvent,\n type ReactElement,\n type SyntheticEvent,\n} from \"react\";\n\nimport { applyParams } from \"../utils/applyParams\";\nimport { isAbsoluteUrl, type AbsoluteUrl } from \"../utils/domainUrl\";\nimport { useLocation } from \"./useLocation\";\nimport type { UrlParser, ViewResult } from \"./types\";\nimport { useNavigate } from \"./useNavigate\";\nimport type { ViewRPC } from \"./rpc\";\nimport type { Prettify } from \"../utils/type\";\nimport { useParams } from \"./useParams\";\nimport { I18nContext } from \"./I18nContext\";\nimport { useRouteTransition } from \"./RouteTransitionProvider\";\nimport { usePrefetch } from \"./usePrefetch\";\n\ntype Views = {\n [K in keyof ViewRPC as K extends `view:${infer P}`\n ? P\n : never]: ViewResult<K>;\n};\n\ntype Search = Record<string, string | number | boolean | undefined | null>;\n\n/**\n * When to warm the target route's data, styles and chunks.\n *\n * - `hover` — the moment the pointer arrives, or on touch or keyboard focus.\n * - `intent` — hover held long enough to read as intent, so a cursor sweeping\n * across a nav bar does not fire a request per link it crosses.\n * - `viewport` — as the link comes into view.\n * - `render` — as soon as the link renders.\n *\n * Several can be combined. The useful pairing is a bulk strategy with an\n * interactive one — `[\"viewport\", \"intent\"]` warms the link on the way past and\n * warms it again on approach if the cached payload has since gone stale.\n * `hover` and `intent` together is just `hover`, since it fires first.\n *\n * Every strategy stands down on metered or very slow connections.\n */\nexport type PrefetchStrategy = \"hover\" | \"intent\" | \"viewport\" | \"render\";\n\n/** How long the pointer has to rest on an `intent` link before it counts. */\nconst INTENT_DELAY = 100;\n\n/** How far ahead of the viewport a `viewport` link starts warming. */\nconst VIEWPORT_MARGIN = \"200px\";\n\ntype LinkBaseProps<T extends keyof Views> = Omit<\n ComponentProps<\"a\">,\n \"href\"\n> & {\n active?: boolean;\n href: T;\n hash?: string;\n /** Off unless set. `false` is accepted so it can be driven by a variable. */\n prefetch?: PrefetchStrategy | readonly PrefetchStrategy[] | false;\n params: UrlParser<T>;\n search?: T extends keyof Views\n ? Views[T][\"input\"] extends Record<string, never>\n ? Search\n : Prettify<Partial<Views[T][\"input\"]> & Search>\n : Search;\n};\n\n/** A link to one of the app's own view routes, handled by the client router. */\nexport type LinkProps<T extends keyof Views, U = UrlParser<T>> = U extends Record<\n string,\n never\n>\n ? Omit<LinkBaseProps<T>, \"params\">\n : LinkBaseProps<T>;\n\nfunction normalizeSearch(search: Search): Record<string, string> {\n return Object.fromEntries(\n Object.entries(search)\n .filter(([_k, v]) => v !== undefined && v !== null)\n .map(([k, v]) => [k, String(v)]),\n ) as Record<string, string>;\n}\n\n/** A link to another host — `useDomain().url(...)` — which the router cannot reach. */\nexport type ExternalLinkProps = Omit<ComponentProps<\"a\">, \"href\"> & {\n href: AbsoluteUrl;\n active?: boolean;\n};\n\n// `ComponentProps<typeof Link>` cannot see through an overloaded generic\n// signature and comes out `{}` — derive prop types from `LinkProps` and\n// `ExternalLinkProps` instead.\ntype LinkComponent = {\n (props: ExternalLinkProps): ReactElement;\n <T extends keyof Views>(props: LinkProps<T>): ReactElement;\n};\n\n/**\n * A path renders an anchor the client router handles; an absolute URL, one on\n * another of the app's hosts, a plain anchor the browser loads in full — the\n * router would otherwise push the path into the current host.\n */\nexport const Link = memo((props: any) => {\n if (isAbsoluteUrl(props.href)) {\n const { active = false, ...rest } = props as ExternalLinkProps;\n return <a data-active={active} {...rest} />;\n }\n const Route = RouteLink as unknown as (props: any) => ReactElement;\n return <Route {...props} />;\n}) as unknown as LinkComponent;\n\n/**\n * Clicks the router must not take over, so the browser does what it would for a\n * plain anchor: a new tab or window for `target=\"_blank\"` and for cmd/ctrl/\n * shift/alt-clicks, the context action for a middle click, a file for\n * `download`, and nothing at all when a handler has already cancelled the click.\n */\nfunction leaveClickToBrowser(event: ReactMouseEvent<HTMLAnchorElement>) {\n if (event.defaultPrevented) {\n return true;\n }\n if (event.button !== 0) {\n return true;\n }\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {\n return true;\n }\n const anchor = event.currentTarget;\n const target = anchor.getAttribute(\"target\");\n if (target && target !== \"_self\") {\n return true;\n }\n return anchor.hasAttribute(\"download\");\n}\n\nconst RouteLink = memo(<T extends keyof Views>(props: LinkProps<T>) => {\n const _params = useParams();\n const { isTransitioning, targetPath } = useRouteTransition();\n const {\n href,\n onClick,\n onMouseEnter,\n onMouseLeave,\n onTouchStart,\n onFocus,\n onBlur,\n ref,\n hash = \"\",\n active = false,\n prefetch,\n params = {},\n search = {},\n ...rest\n } = { params: _params, search: {}, ...props };\n const { defaultLocale } = useContext(I18nContext);\n const { push } = useNavigate();\n const location = useLocation();\n const prefetchRoute = usePrefetch();\n const searchParams = new URLSearchParams(normalizeSearch(search));\n\n const path = applyParams(href, params);\n // `applyParams` drops the trailing slash, so the root route comes back empty\n // where every pathname the router reports says `/`.\n const resolvedPath = path || \"/\";\n let urlLocaleSegment = location.locale;\n if (urlLocaleSegment === defaultLocale) {\n urlLocaleSegment = \"\";\n }\n\n const localeSegment = urlLocaleSegment ? `/${urlLocaleSegment}` : \"\";\n\n const targetHref = [\n [`${localeSegment}${path}`, searchParams.toString()]\n .filter((s) => s.length > 0)\n .join(\"?\"),\n hash,\n ].join(\"\");\n\n const currentHref = [location.pathname, location.search, location.hash]\n .filter((item) => !!item)\n .join(\"\");\n\n // Held in a ref because the prefetch callback is rebuilt on every router\n // render — an effect that depended on it would re-fire on renders that have\n // nothing to do with this link.\n const prefetchRouteRef = useRef(prefetchRoute);\n useEffect(() => {\n prefetchRouteRef.current = prefetchRoute;\n });\n\n // Clicking through to the path we are already on is a shallow navigation —\n // it moves the URL without fetching, so there is nothing to warm.\n const isShallowTarget = resolvedPath === location.pathname;\n\n const strategies = !prefetch\n ? []\n : Array.isArray(prefetch)\n ? prefetch\n : [prefetch];\n const uses = (strategy: PrefetchStrategy) => strategies.includes(strategy);\n // Effects below key off the strategies, which arrive as an array literal with\n // a fresh identity on every render. The names are what actually matters.\n const strategyKey = strategies.join(\",\");\n\n // Repeats are the cache's problem, not this component's: it collapses a\n // hover storm into one request and lets a hover past the TTL refresh a\n // payload that has gone stale.\n const runPrefetch = () => {\n if (strategies.length === 0 || isShallowTarget) {\n return;\n }\n prefetchRouteRef.current(href, { params, search } as never);\n };\n\n useEffect(() => {\n if (uses(\"render\")) {\n runPrefetch();\n }\n }, [strategyKey, targetHref]);\n\n const anchorRef = useRef<HTMLAnchorElement | null>(null);\n // A caller's own `ref` still has to reach them — under React 19 it arrives as\n // a plain prop, and the spread below would otherwise hand the element to one\n // of us and null to the other.\n //\n // Memoised because `Link` re-renders on every navigation in the app: a fresh\n // callback identity would have React detach and reattach the element each\n // time, handing a caller's ref callback a null it never asked for.\n const setAnchorRef = useCallback(\n (node: HTMLAnchorElement | null) => {\n anchorRef.current = node;\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n },\n [ref],\n );\n\n useEffect(() => {\n if (!uses(\"viewport\")) {\n return;\n }\n const element = anchorRef.current;\n if (!element || typeof IntersectionObserver === \"undefined\") {\n return;\n }\n // One shot: a link scrolled past and back is already warm, and if its entry\n // has expired the next hover or click pays for a fresh one.\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n observer.disconnect();\n runPrefetch();\n }\n },\n { rootMargin: VIEWPORT_MARGIN },\n );\n observer.observe(element);\n return () => observer.disconnect();\n }, [strategyKey, targetHref]);\n\n const intentTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const cancelIntent = () => {\n if (intentTimerRef.current !== null) {\n clearTimeout(intentTimerRef.current);\n intentTimerRef.current = null;\n }\n };\n useEffect(() => cancelIntent, []);\n\n /** A pointer arriving — the one signal `intent` waits on before believing. */\n const pointerArrived = () => {\n if (uses(\"hover\")) {\n runPrefetch();\n } else if (uses(\"intent\")) {\n cancelIntent();\n intentTimerRef.current = setTimeout(runPrefetch, INTENT_DELAY);\n }\n };\n\n /** Focus and touch are deliberate, so neither strategy makes them wait. */\n const linkTargeted = () => {\n if (uses(\"hover\") || uses(\"intent\")) {\n runPrefetch();\n }\n };\n\n /** Runs the caller's own handler first, then the prefetch trigger. */\n const prefetchOn =\n <E extends SyntheticEvent>(\n handler: ((event: E) => void) | undefined,\n trigger: () => void,\n ) =>\n (event: E) => {\n handler?.(event);\n trigger();\n };\n\n return (\n <a\n ref={setAnchorRef}\n data-active={active || currentHref === targetHref}\n // The resolved path, not the template: one template can back a whole list\n // of rows, and only the row that was clicked is heading anywhere.\n data-pending={isTransitioning && resolvedPath === targetPath}\n href={targetHref === '' ? '/' : targetHref}\n onClick={(e) => {\n // The caller's handler always runs, and runs first: it may want to\n // log, close a menu, or cancel the navigation with `preventDefault()`.\n onClick?.(e);\n if (leaveClickToBrowser(e)) {\n return;\n }\n if (currentHref === targetHref) {\n e.preventDefault();\n return;\n }\n let currentPath = window.location.pathname.replace(localeSegment, \"\");\n currentPath = currentPath === \"\" ? \"/\" : currentPath;\n\n if (hash === \"\") {\n e.preventDefault();\n }\n push(href, {\n hash,\n search,\n params,\n shallow: path === currentPath,\n } as unknown as never);\n }}\n onMouseEnter={prefetchOn(onMouseEnter, pointerArrived)}\n onMouseLeave={prefetchOn(onMouseLeave, cancelIntent)}\n onTouchStart={prefetchOn(onTouchStart, linkTargeted)}\n onFocus={prefetchOn(onFocus, linkTargeted)}\n onBlur={prefetchOn(onBlur, cancelIntent)}\n {...rest}\n />\n );\n});\n","import { useEffect } from \"react\";\nimport type { LinkProps } from \"./Link\";\nimport type { ViewPaths } from \"./types\";\n\nimport { useNavigate } from \"./useNavigate\";\n\n// Typed against `LinkProps` directly: `ComponentProps<typeof Link>` comes out\n// `{}` now that `Link` is overloaded, which left `action` the only prop.\nexport const Redirect = <T extends ViewPaths>(\n props: LinkProps<T> & { action: \"push\" | \"replace\" },\n) => {\n const {\n href,\n params = {},\n search = {},\n action = \"replace\",\n } = props as LinkProps<T> & {\n action: \"push\" | \"replace\";\n params?: Record<string, unknown>;\n };\n const { push, replace } = useNavigate();\n\n // The destination decides when to navigate again, because none of the parts\n // it is made of keep their identity: `useNavigate` builds `push` and\n // `replace` fresh on every render, and `params` and `search` fall back to\n // new objects each time. Depending on them directly navigated on every\n // render of whatever holds this — with `action=\"push\"`, one history entry\n // per render, which the back button then has to walk back through.\n const target = JSON.stringify([action, href, params, search]);\n\n useEffect(() => {\n if (action === \"replace\") {\n replace(href, { params, search } as any);\n } else {\n push(href, { params, search } as any);\n }\n }, [target]);\n\n return <></>;\n};\n","import type { HtmlAttributes } from \"../http/Metadata\";\n\nexport type { HtmlAttributes };\n\n// Languages written right to left, by their primary subtag.\nconst RTL_LANGUAGES = new Set([\"ar\", \"arc\", \"ckb\", \"dv\", \"fa\", \"he\", \"iw\", \"ks\", \"ps\", \"sd\", \"ug\", \"ur\", \"yi\"]);\n\n/** The direction `lang` is written in: `\"rtl\"` for Arabic, Hebrew and the like, else `\"ltr\"`. */\nexport function textDirection(lang: string | null | undefined): \"ltr\" | \"rtl\" {\n const language = lang?.split(/[-_]/)[0]?.toLowerCase() ?? \"\";\n return RTL_LANGUAGES.has(language) ? \"rtl\" : \"ltr\";\n}\n\n/**\n * The `<html>` attributes a layout receives: what the response set with\n * `Meta.htmlAttributes`, else the request's locale and its direction.\n */\nexport function resolveHtmlAttributes(\n set: HtmlAttributes | null | undefined,\n locale: string | null | undefined,\n): Required<Pick<HtmlAttributes, \"lang\" | \"dir\">> & HtmlAttributes {\n const lang = set?.lang ?? locale ?? \"en\";\n return { ...set, lang, dir: set?.dir ?? textDirection(lang) };\n}\n\n/** The props gemi renders a root layout (or a static view's layout) with. */\nexport interface RootLayoutProps {\n children: React.ReactNode;\n /** The request's locale; empty when the app configures none. */\n locale: string;\n /** For `<html {...htmlAttributes}>`: `lang` and `dir`, see `Meta.htmlAttributes`. */\n htmlAttributes: ReturnType<typeof resolveHtmlAttributes>;\n}\n","/**\n * `Meta.fonts`: the `@font-face` rules and font preloads of one response.\n * Pure, so the server (validation) and `<Head />` (rendering) share it.\n */\n\n/** A font file format, as `@font-face`'s `format()` names it. */\nexport type FontFormat =\n | \"woff2\"\n | \"woff\"\n | \"truetype\"\n | \"opentype\"\n | \"collection\"\n | \"embedded-opentype\"\n | \"svg\";\n\n/** One file of a font; list the preferred format first. */\nexport type FontSource = {\n url: string;\n /** Inferred from the url's extension when left out. */\n format?: FontFormat;\n};\n\n/** One `@font-face`, see `Meta.fonts`. */\nexport type MetaFont = {\n /** The `font-family` name that CSS refers to, e.g. `\"Acme Sans\"`. */\n family: string;\n /** A url, or several files with the preferred one first. */\n src: string | FontSource[];\n /** `font-weight`: `400`, `\"bold\"`, or a range for a variable font, `\"100 900\"`. */\n weight?: string | number;\n /** `font-style`: `\"normal\"`, `\"italic\"`, `\"oblique 10deg\"`. */\n style?: string;\n /** `font-stretch`: `\"condensed\"`, `\"75% 125%\"`. */\n stretch?: string;\n /** `font-display`. Defaults to `\"swap\"`. */\n display?: \"auto\" | \"block\" | \"swap\" | \"fallback\" | \"optional\";\n /** `unicode-range`, e.g. `\"U+0000-00FF, U+0131\"`. */\n unicodeRange?: string;\n /**\n * Preload the first file with `<link rel=\"preload\" as=\"font\" crossorigin>`.\n * Only for fonts the page renders above the fold: a preloaded font that is\n * never used is a wasted download (and a console warning).\n */\n preload?: boolean;\n};\n\n/** A font after `normalizeFonts`: validated, with every source's format resolved. */\nexport type NormalizedFont = {\n family: string;\n src: { url: string; format: FontFormat | null }[];\n weight: string | null;\n style: string | null;\n stretch: string | null;\n display: NonNullable<MetaFont[\"display\"]>;\n unicodeRange: string | null;\n preload: boolean;\n};\n\nexport type FontPreload = { href: string; type: string | null };\n\nconst FORMATS = new Set<FontFormat>([\n \"woff2\",\n \"woff\",\n \"truetype\",\n \"opentype\",\n \"collection\",\n \"embedded-opentype\",\n \"svg\",\n]);\n\nconst FORMAT_BY_EXTENSION: Record<string, FontFormat> = {\n woff2: \"woff2\",\n woff: \"woff\",\n ttf: \"truetype\",\n otf: \"opentype\",\n ttc: \"collection\",\n eot: \"embedded-opentype\",\n svg: \"svg\",\n};\n\nconst MIME_BY_FORMAT: Partial<Record<FontFormat, string>> = {\n woff2: \"font/woff2\",\n woff: \"font/woff\",\n truetype: \"font/ttf\",\n opentype: \"font/otf\",\n collection: \"font/collection\",\n};\n\nconst DISPLAYS = new Set([\"auto\", \"block\", \"swap\", \"fallback\", \"optional\"]);\n\n// Descriptors are written into the CSS as they are, so only keywords, numbers,\n// angles and percentages pass: nothing that can end the declaration or rule.\nconst DESCRIPTOR = /^[a-zA-Z0-9.%+\\- ]+$/;\nconst UNICODE_RANGE = /^[uU]\\+[0-9a-fA-F?]{1,6}(-[0-9a-fA-F]{1,6})?(\\s*,\\s*[uU]\\+[0-9a-fA-F?]{1,6}(-[0-9a-fA-F]{1,6})?)*$/;\n\nfunction invalid(message: string): never {\n throw new TypeError(`Meta.fonts: ${message}`);\n}\n\n/** The format a url's extension implies (`.woff2` → `\"woff2\"`), ignoring query and hash. */\nexport function fontFormatOf(url: string): FontFormat | null {\n const file = (url.split(/[?#]/)[0] ?? \"\").split(\"/\").pop() ?? \"\";\n const dot = file.lastIndexOf(\".\");\n return dot === -1 ? null : (FORMAT_BY_EXTENSION[file.slice(dot + 1).toLowerCase()] ?? null);\n}\n\nfunction descriptor(name: string, value: string | number | undefined): string | null {\n if (value === undefined || value === null) return null;\n const text = String(value).trim();\n if (!text || !DESCRIPTOR.test(text)) {\n invalid(`${name} ${JSON.stringify(value)} is not a valid font-${name} value`);\n }\n return text;\n}\n\n/** Validates what a handler passed; throws a `TypeError` naming the bad value. */\nexport function normalizeFonts(fonts: MetaFont[]): NormalizedFont[] {\n if (!Array.isArray(fonts)) invalid(\"expected an array of fonts\");\n return fonts.map((font) => {\n if (typeof font?.family !== \"string\" || !font.family.trim()) {\n invalid(\"every font needs a family\");\n }\n const sources = typeof font.src === \"string\" ? [{ url: font.src }] : font.src;\n if (!Array.isArray(sources) || sources.length === 0) {\n invalid(`font \"${font.family}\" needs a src`);\n }\n const src = sources.map((source) => {\n if (typeof source?.url !== \"string\" || !source.url.trim()) {\n invalid(`font \"${font.family}\" has a source without a url`);\n }\n if (source.format !== undefined && !FORMATS.has(source.format)) {\n invalid(`font \"${font.family}\" has an unknown format ${JSON.stringify(source.format)}`);\n }\n return { url: source.url.trim(), format: source.format ?? fontFormatOf(source.url) };\n });\n const display = font.display ?? \"swap\";\n if (!DISPLAYS.has(display)) {\n invalid(`display ${JSON.stringify(display)} is not a valid font-display value`);\n }\n const unicodeRange = font.unicodeRange?.trim() || null;\n if (unicodeRange && !UNICODE_RANGE.test(unicodeRange)) {\n invalid(`unicodeRange ${JSON.stringify(font.unicodeRange)} is not a valid unicode-range`);\n }\n return {\n family: font.family.trim(),\n src,\n weight: descriptor(\"weight\", font.weight),\n style: descriptor(\"style\", font.style),\n stretch: descriptor(\"stretch\", font.stretch),\n display,\n unicodeRange,\n preload: font.preload === true,\n };\n });\n}\n\n/**\n * A CSS string literal holding `value`. Quotes, backslashes, control\n * characters and `<` (so `</style>` can't close the element) are escaped.\n */\nexport function cssString(value: string): string {\n // oxlint-disable-next-line no-control-regex -- escaping them is the point\n const escaped = value.replace(/[\\\\\"<>\\u0000-\\u001f\\u007f]/g, (char) =>\n char === \"\\\\\" || char === '\"' ? `\\\\${char}` : `\\\\${char.charCodeAt(0).toString(16)} `,\n );\n return `\"${escaped}\"`;\n}\n\n/** One `@font-face` rule. */\nexport function fontFaceRule(font: NormalizedFont): string {\n const src = font.src\n .map(({ url, format }) => `url(${cssString(url)})${format ? ` format(${cssString(format)})` : \"\"}`)\n .join(\", \");\n const declarations = [\n `font-family: ${cssString(font.family)}`,\n `src: ${src}`,\n font.weight && `font-weight: ${font.weight}`,\n font.style && `font-style: ${font.style}`,\n font.stretch && `font-stretch: ${font.stretch}`,\n `font-display: ${font.display}`,\n font.unicodeRange && `unicode-range: ${font.unicodeRange}`,\n ].filter(Boolean);\n return `@font-face { ${declarations.join(\"; \")}; }`;\n}\n\n/** The `@font-face` rules for `fonts`, an identical font declared twice once. */\nexport function fontFaceRules(fonts: NormalizedFont[] | null | undefined): string[] {\n return [...new Set((fonts ?? []).map(fontFaceRule))];\n}\n\n/** The first file of every font marked `preload`, each url once. */\nexport function fontPreloads(fonts: NormalizedFont[] | null | undefined): FontPreload[] {\n const preloads = new Map<string, FontPreload>();\n for (const font of fonts ?? []) {\n const first = font.preload ? font.src[0] : undefined;\n if (first && !preloads.has(first.url)) {\n preloads.set(first.url, {\n href: first.url,\n type: (first.format && MIME_BY_FORMAT[first.format]) ?? null,\n });\n }\n }\n return [...preloads.values()];\n}\n","import type { AlternateLink } from \"../http/Metadata\";\nimport { type ReactNode, useContext } from \"react\";\nimport { ServerDataContext } from \"./ServerDataProvider\";\nimport { resolveHtmlAttributes } from \"./htmlAttributes\";\nimport { fontFaceRules, fontPreloads } from \"./fonts\";\n\n/** Marks the `<link>`s rendered from metadata, so a navigation can replace them. */\nconst GEMI_META_ATTRIBUTE = \"data-gemi-meta\";\n\ntype MetaLink = { rel: \"canonical\" | \"alternate\"; href: string; hrefLang?: string };\n\nfunction metaLinks(\n canonical: string | null | undefined,\n alternates: AlternateLink[] | null | undefined,\n): MetaLink[] {\n const links: MetaLink[] = [];\n if (canonical) links.push({ rel: \"canonical\", href: canonical });\n for (const { hrefLang, href } of alternates ?? []) {\n links.push({ rel: \"alternate\", href, hrefLang });\n }\n return links;\n}\n\n/** Marks the `<style>`s holding `Meta.fonts`' `@font-face` rules. */\nconst GEMI_FONTS_ATTRIBUTE = \"data-gemi-fonts\";\n\n/**\n * The `@font-face` rules already in the document. A navigation adds the new\n * page's and removes none: a skipped layout's fonts are still in use, and an\n * unused `@font-face` costs nothing (it is only fetched when text uses it).\n */\nconst appliedFontRules = new Set<string>();\n\n/** Whether a navigation has set `<html>` attributes from metadata. */\nlet htmlAttributesApplied = false;\n\nexport function updateMeta(meta: any, locale?: string | null) {\n // A partially rendered response whose segments set no metadata sends none —\n // what is on the page belongs to the segments that were skipped.\n if (!meta) {\n return;\n }\n const { title, description, htmlAttributes, canonical, alternates, fonts } = meta;\n // A page that set `<html>` attributes gets them; after one, a page that set\n // none goes back to its locale's. A layout that never asked keeps its own.\n if (htmlAttributes || htmlAttributesApplied) {\n htmlAttributesApplied = true;\n for (const [name, value] of Object.entries(resolveHtmlAttributes(htmlAttributes, locale))) {\n if (typeof value === \"string\") {\n document.documentElement.setAttribute(name, value);\n }\n }\n }\n // The links `<Head />` rendered from metadata, and only those: a layout's\n // own `<link>`s are left alone.\n document.head\n .querySelectorAll(`link[${GEMI_META_ATTRIBUTE}]`)\n .forEach((link) => link.remove());\n for (const link of metaLinks(canonical, alternates)) {\n const element = document.createElement(\"link\");\n element.setAttribute(\"rel\", link.rel);\n element.setAttribute(\"href\", link.href);\n if (link.hrefLang) element.setAttribute(\"hreflang\", link.hrefLang);\n element.setAttribute(GEMI_META_ATTRIBUTE, \"\");\n document.head.appendChild(element);\n }\n const newFontRules = fontFaceRules(fonts).filter((rule) => !appliedFontRules.has(rule));\n if (newFontRules.length > 0) {\n const style = document.createElement(\"style\");\n style.setAttribute(GEMI_FONTS_ATTRIBUTE, \"\");\n style.textContent = newFontRules.join(\"\\n\");\n document.head.appendChild(style);\n for (const rule of newFontRules) appliedFontRules.add(rule);\n }\n if (title) {\n document.title = title;\n }\n if (description) {\n const desc = document.querySelector(\"meta[name='description']\");\n if (desc) {\n desc.setAttribute(\"content\", description);\n } else {\n const newDesc = document.createElement(\"meta\");\n newDesc.setAttribute(\"name\", \"description\");\n newDesc.setAttribute(\"content\", description);\n document.head.appendChild(newDesc);\n }\n }\n}\n\nconst OpenGraph = (props: {\n title: string;\n type: string;\n url: string;\n image: string;\n description?: string;\n imageAlt?: string;\n imageWidth?: number;\n imageHeight?: number;\n twitterImage?: string;\n twitterImageAlt?: string;\n twitterImageWidth?: number;\n twitterImageHeight?: number;\n}) => {\n const {\n title,\n description,\n type,\n url,\n image,\n imageAlt,\n imageWidth,\n imageHeight,\n twitterImage,\n twitterImageAlt,\n twitterImageWidth,\n twitterImageHeight,\n } = props;\n\n return (\n <>\n <meta property=\"og:title\" content={title} />\n <meta property=\"og:type\" content={type} />\n <meta property=\"og:url\" content={url} />\n <meta property=\"og:image\" content={image} />\n {description && <meta property=\"og:description\" content={description} />}\n {imageAlt && <meta property=\"og:image:alt\" content={imageAlt} />}\n {imageWidth && (\n <meta property=\"og:image:width\" content={String(imageWidth)} />\n )}\n {imageHeight && (\n <meta property=\"og:image:height\" content={String(imageHeight)} />\n )}\n {twitterImage && (\n <>\n <meta name=\"twitter:image\" content={twitterImage} />\n <meta name=\"twitter:card\" content=\"summary_large_image\" />\n </>\n )}\n {twitterImageAlt && (\n <meta name=\"twitter:image:alt\" content={twitterImageAlt} />\n )}\n {twitterImageWidth && (\n <meta name=\"twitter:image:width\" content={String(twitterImageWidth)} />\n )}\n {twitterImageHeight && (\n <meta\n name=\"twitter:image:height\"\n content={String(twitterImageHeight)}\n />\n )}\n </>\n );\n};\n\nexport const Head = ({\n children = null,\n charSet = \"utf-8\",\n}: { children?: ReactNode; charSet?: string }) => {\n const { meta } = useContext(ServerDataContext);\n // The first page set them, so the layout rendered them: a later page that\n // sets none has to go back to its locale's (`updateMeta`). Only ever read\n // in the browser.\n if (meta?.htmlAttributes) {\n htmlAttributesApplied = true;\n }\n const fontRules = fontFaceRules(meta?.fonts);\n // Browser only: on the server the set would be shared by every request.\n if (typeof window !== \"undefined\") {\n for (const rule of fontRules) appliedFontRules.add(rule);\n }\n return (\n <head>\n <meta charSet={charSet} />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n {/*\n Disable browser auto-translation (Chrome/Google Translate). Gemi apps do\n their own i18n, and a translator that rewrites text nodes *before* React\n hydrates mutates the SSR DOM — which React rejects as a hydration\n mismatch (Minified React error #418) and then regenerates the tree,\n dropping the server-injected <style> and leaving the page unstyled.\n Pair this with `translate=\"no\"` on the <html> element in RootLayout.\n */}\n <meta name=\"google\" content=\"notranslate\" />\n <title>{meta?.title}</title>\n {meta?.description && (\n <meta name=\"description\" content={meta.description} />\n )}\n {meta?.openGraph && <OpenGraph {...meta.openGraph} />}\n {metaLinks(meta?.canonical, meta?.alternates).map((link) => (\n <link\n key={`${link.rel}:${link.hrefLang ?? \"\"}:${link.href}`}\n rel={link.rel}\n href={link.href}\n hrefLang={link.hrefLang}\n {...{ [GEMI_META_ATTRIBUTE]: \"\" }}\n />\n ))}\n {fontPreloads(meta?.fonts).map((preload) => (\n <link\n key={`preload:${preload.href}`}\n rel=\"preload\"\n as=\"font\"\n href={preload.href}\n type={preload.type ?? undefined}\n crossOrigin=\"\"\n />\n ))}\n {fontRules.length > 0 && (\n <style\n {...{ [GEMI_FONTS_ATTRIBUTE]: \"\" }}\n // Escaped by `fontFaceRule`: strings are CSS-escaped (`<` included),\n // descriptors are checked by `Meta.fonts`.\n dangerouslySetInnerHTML={{ __html: fontRules.join(\"\\n\") }}\n />\n )}\n {children}\n </head>\n );\n};\n","import { applyParams } from \"./applyParams\";\n\n/**\n * Route the client is currently rendering, sent on `.json` navigations so the\n * server can skip the handlers of the segments that route already has mounted.\n * Value is a locale-less pathname plus search, e.g. `/app/A/chat?tab=2`.\n */\nexport const PARTIAL_RENDER_HEADER = \"x-gemi-from\";\n\n/** What the server reports back about the skip it performed, if any. */\nexport interface PartialRenderInfo {\n /** The `x-gemi-from` value the plan was computed against. */\n from: string;\n /** View paths of the skipped segments, in order. Their data is carried forward. */\n carriedViews: string[];\n}\n\n/**\n * The `x-gemi-from` value for the route the client starts on.\n *\n * On the first render the router's `pathname` is still the route *pattern* the\n * server matched — it only becomes a resolved path once the history listener\n * has run — so this has to apply the params. Sending `/app/:orgId/chat` names\n * no route the server can resolve, and the first navigation after every full\n * page load would skip nothing.\n */\nexport function initialRenderedRoute(route: {\n pathname?: string;\n params?: Record<string, string>;\n search?: string;\n}) {\n // `applyParams` strips the trailing slash, so the root route resolves to the\n // empty string — which the server reads as \"no header\" and renders in full.\n const pathname = applyParams(route.pathname ?? \"/\", route.params ?? {}) || \"/\";\n return `${pathname}${route.search ?? \"\"}`;\n}\n","import type { Breadcrumb } from \"../useBreadcrumbs\";\n\ninterface RouteSnapshot {\n /** Concrete pathname, without the locale segment. */\n pathname: string;\n /** Route pattern the data was produced for — part of every breadcrumb key. */\n routePath: string;\n data: Record<string, any>;\n breadcrumbs: Record<string, Breadcrumb>;\n}\n\n/**\n * A partially rendered response only carries the segments the server actually\n * ran. Everything is keyed by the *new* pathname, so a carried layout would\n * render with empty props unless the data it already had is copied across.\n *\n * Data the server sent always wins: a carried view is only filled in where the\n * response has nothing for it.\n */\nexport function mergeCarriedSegments(\n previous: RouteSnapshot,\n next: RouteSnapshot,\n carriedViews: string[],\n) {\n if (carriedViews.length === 0) {\n return { data: next.data, breadcrumbs: next.breadcrumbs };\n }\n\n // Page data is keyed by the pathname it was fetched for, and a shallow\n // navigation moves the pathname on without fetching — so fall back to the key\n // the data is actually under. The server sends exactly one.\n const previousData = previous.data ?? {};\n const previousViewData =\n previousData[previous.pathname] ?? previousData[Object.keys(previousData)[0]] ?? {};\n const previousBreadcrumbs = previous.breadcrumbs ?? {};\n\n const carriedViewData: Record<string, unknown> = {};\n const carriedBreadcrumbs: Record<string, Breadcrumb> = {};\n\n for (const viewPath of carriedViews) {\n if (viewPath in previousViewData) {\n carriedViewData[viewPath] = previousViewData[viewPath];\n }\n // Breadcrumbs are keyed by route pattern, and that changed even though the\n // segment did not, so they have to be re-keyed rather than copied.\n const previousKey = `${viewPath}:${previous.routePath}`;\n if (previousKey in previousBreadcrumbs) {\n carriedBreadcrumbs[`${viewPath}:${next.routePath}`] = previousBreadcrumbs[previousKey];\n }\n }\n\n // The server sends page data under exactly one key. Take it from the payload\n // rather than recomputing it, so the two never disagree on spelling.\n const [nextKey = next.pathname] = Object.keys(next.data ?? {});\n\n return {\n data: {\n ...next.data,\n [nextKey]: { ...carriedViewData, ...next.data?.[nextKey] },\n },\n breadcrumbs: { ...carriedBreadcrumbs, ...next.breadcrumbs },\n };\n}\n","import {\n PARTIAL_RENDER_HEADER,\n type PartialRenderInfo,\n} from \"../../utils/partialRender\";\nimport { readRoutePayload, type RouteQueryPayload } from \"./readRoutePayload\";\n\ninterface LoadRoutePayloadOptions {\n /** The `.json` URL for the route being navigated to. */\n url: string;\n /** `x-gemi-from` value for the route currently on screen. */\n from: string;\n /** Hands over a payload warmed ahead of this navigation, if there is one. */\n takePrefetched?: (url: string) => Promise<unknown> | null;\n /**\n * The route that is on screen *now*, re-read at the moment a response lands.\n * A navigation that committed while this one was in flight invalidates the\n * partial-render plan the server computed.\n */\n renderedRoute: () => string;\n /**\n * Receives each query result the server streams behind the envelope\n * (#290) — the caller hydrates it into the cache, which settles any\n * segment suspended on that variant.\n */\n onQueryPayload?: (payload: RouteQueryPayload) => void;\n}\n\n/**\n * The page data for a navigation, from whichever source can produce it.\n *\n * A prefetched payload is always a full render, so it can be committed as-is\n * and the `x-gemi-from` round trip skipped entirely. Everything else — no\n * prefetch, a prefetch that failed, a partial response computed against a route\n * that has since been navigated away from — falls through to a request.\n *\n * Returns `null` when nothing usable came back; the caller leaves the current\n * route on screen.\n */\nexport async function loadRoutePayload(\n options: LoadRoutePayloadOptions,\n): Promise<any> {\n const { url, from, takePrefetched, renderedRoute, onQueryPayload } = options;\n\n const prefetched = takePrefetched?.(url);\n if (prefetched) {\n const payload = await prefetched;\n if (payload) {\n return payload;\n }\n }\n\n let response = { ok: false, json: async () => ({}) } as Response;\n try {\n response = await fetch(url, { headers: { [PARTIAL_RENDER_HEADER]: from } });\n } catch (e) {\n console.error(e);\n return null;\n }\n\n if (!response.ok) {\n return null;\n }\n\n // Resolves with the envelope as soon as its line arrives; query results\n // streaming behind it keep draining into `onQueryPayload`.\n const payload = await readRoutePayload(response, onQueryPayload);\n\n // The segments the server carried forward were computed against a route that\n // is no longer on screen. Nothing sound to merge onto — ask for the whole\n // tree instead.\n const claimed: PartialRenderInfo | null = payload?.partial ?? null;\n if (claimed && claimed.from !== renderedRoute()) {\n try {\n const full = await fetch(url);\n if (full.ok) {\n return await readRoutePayload(full, onQueryPayload);\n }\n } catch (e) {\n console.error(e);\n }\n }\n\n return payload;\n}\n","/**\n * The search parameter carrying the page a signed-out visitor was trying to\n * reach. `AuthenticationMiddleware` writes it onto the sign-in redirect —\n * `/auth/sign-in?redirect=%2Finvoices%3Fpage%3D2` — and `Auth.intendedUrl()` /\n * `useIntendedUrl()` read it back after sign-in.\n */\nexport const INTENDED_URL_PARAM = \"redirect\";\n\n// Only ever compared against, never requested.\nconst PROBE_ORIGIN = \"http://gemi.invalid\";\n\n/**\n * `value` if it is a path on this origin, `fallback` otherwise.\n *\n * The intended URL arrives in a query string anybody can write, so reading it\n * back unchecked is an open redirect: `?redirect=https://evil.example` signs\n * the user in and hands them to a look-alike. Only a same-origin path passes:\n * `//evil.example` and `/\\evil.example` are protocol-relative to a browser and\n * are refused, as is anything a browser would strip control characters out of\n * before resolving.\n *\n * Returns path, search and hash — never an origin — so the result is safe to\n * hand to `push`, `Redirect.to` or a `Location` header alike.\n */\nexport function safeRedirectPath(value: unknown, fallback = \"/\"): string {\n if (typeof value !== \"string\" || !value.startsWith(\"/\")) {\n return fallback;\n }\n if (/[\\u0000-\\u001f\\u007f\\\\]/.test(value) || value.startsWith(\"//\")) {\n return fallback;\n }\n try {\n const url = new URL(value, PROBE_ORIGIN);\n if (url.origin !== PROBE_ORIGIN) {\n return fallback;\n }\n // `push` and `Redirect.to` run their path through `applyParams`, which\n // reads `:x` as a route parameter and collapses `//` — both legal in a\n // query (`?next=https://…`) and in a path. Percent-encoded they mean the\n // same to `URLSearchParams` and survive the trip; left raw, `?redirect=/:x`\n // throws in dev and navigates to `/undefined` in production.\n const tail = `${url.search}${url.hash}`.replaceAll(\"/\", \"%2F\");\n const path = `${url.pathname}${tail}`.replaceAll(\":\", \"%3A\");\n // The `//` test above reads the input, but `.` and `..` segments are\n // resolved away by `new URL` afterwards, and resolving them can *produce* a\n // leading `//`: `/..//evil.example` normalizes to `//evil.example`, which is\n // protocol-relative to a browser. Test what actually goes out.\n return path.startsWith(\"//\") ? fallback : path;\n } catch {\n return fallback;\n }\n}\n\n/**\n * Whether the client addressed this request over https — through the proxy in\n * front if there is one, since TLS is nearly always terminated before the app\n * and a forged `X-Forwarded-Proto` only spoils the forger's own cookie.\n *\n * Not `origin.includes(\"localhost\")`: the URL is built from the `Host` header,\n * so `localhost.evil.example` would read as local and drop `Secure`.\n */\nexport function isSecureRequest(request: Request): boolean {\n const forwarded = request.headers.get(\"x-forwarded-proto\")?.split(\",\")[0]?.trim();\n return forwarded ? forwarded === \"https\" : new URL(request.url).protocol === \"https:\";\n}\n\n/**\n * Whether a `Redirect` directive names somewhere outside the router — an\n * absolute http(s) URL or a protocol-relative one — and so has to leave the\n * page rather than be looked up as a route.\n *\n * Only those two shapes. The value goes to `location.replace`, and *any*\n * scheme that parses would include `javascript:`, which runs in this document\n * rather than navigating away from it: an app passing a user-influenced value\n * to `Redirect.external` would be handing out same-origin script execution.\n * Anything else falls through to the router, which cannot leave the origin.\n */\nexport function isExternalRedirect(path: string | null | undefined): boolean {\n return /^(https?:\\/\\/|\\/\\/)/i.test(path ?? \"\");\n}\n","import {\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n StrictMode,\n memo,\n useTransition,\n Suspense,\n useSyncExternalStore,\n} from \"react\";\n\nimport type { PropsWithChildren, ComponentType, lazy } from \"react\";\nimport { ErrorBoundary, type FallbackProps } from \"react-error-boundary\";\n\nimport { ServerDataContext } from \"./ServerDataProvider\";\nimport { ClientRouterContext, ClientRouterProvider } from \"./ClientRouterContext\";\nimport type { ComponentTree } from \"./types\";\nimport {\n ComponentsContext,\n ComponentsProvider,\n loadViewModule,\n subscribeViewModules,\n} from \"./ComponentContext\";\nimport { QueryManagerContext, QueryManagerProvider, type QueryConfig } from \"./QueryManagerContext\";\nimport { I18nProvider } from \"./I18nContext\";\nimport { useNavigate } from \"./useNavigate\";\nimport { type PageData, type RouteState, RouteStateProvider } from \"./RouteStateContext\";\nimport { applyParams } from \"../utils/applyParams\";\nimport { Action } from \"history\";\nimport { useRouteData } from \"./useRouteData\";\nimport { updateMeta } from \"./Head\";\nimport { resolveHtmlAttributes, type RootLayoutProps } from \"./htmlAttributes\";\nimport { RouteTransitionProvider } from \"./RouteTransitionProvider\";\nimport { ThemeProvider } from \"./ThemeProvider\";\nimport { initialRenderedRoute } from \"../utils/partialRender\";\nimport { mergeCarriedSegments } from \"./helpers/mergeCarriedSegments\";\nimport { routeDataUrl } from \"./helpers/routeDataUrl\";\nimport { loadRoutePayload } from \"./helpers/loadRoutePayload\";\nimport { isExternalRedirect } from \"../utils/intendedUrl\";\n\ndeclare global {\n interface Window {\n scrollHistory: Map<string, number>;\n loaders: Record<string, () => void>;\n }\n}\n\nfunction restoreScroll(action: Action | null = null, _pathname = \"no path\") {\n if (action === null) {\n return;\n }\n\n const { pathname, search, hash } = window.location;\n\n const key = [pathname, search, hash].join(\"\");\n const sh = window.scrollHistory;\n\n const scrollPosition = sh?.get(key);\n\n if (action !== Action.Pop) {\n window.scrollTo(0, 0);\n } else {\n // In dev mode the effect runs scroll restoration\n // will be called twice, this if statement prevents\n // scroll to top\n if (!scrollPosition) {\n return;\n }\n window.scrollTo(0, scrollPosition ?? 0);\n }\n\n sh?.delete(key);\n}\n\ninterface RouteProps {\n componentPath: string;\n pathname: string;\n action: Action | null;\n}\n\nconst DefaultQueryErrorFallback = (props: FallbackProps) => {\n return (\n <div role=\"alert\">\n <p>Something went wrong.</p>\n <button type=\"button\" onClick={() => props.resetErrorBoundary()}>\n Try again\n </button>\n </div>\n );\n};\n\nconst Route = memo((props: PropsWithChildren<RouteProps>) => {\n const { componentPath, pathname, action, children } = props;\n const { viewImportMap, getViewModule } = useContext(ComponentsContext);\n const { clearErrors } = useContext(QueryManagerContext);\n const { data } = useRouteData();\n\n // `Loading` / `Error` are optional named exports of the view module,\n // subscribed so a Route that rendered before its chunk arrived re-reads\n // the registry once it lands. On the server `getViewModule` reads the\n // eagerly-loaded modules the http server passed in — a streaming render\n // suspends for real, so the `Loading` fallback it puts in the shell must be\n // the same one the client hydrates.\n const getModule = useCallback(\n () => getViewModule?.(componentPath),\n [getViewModule, componentPath],\n );\n const mod = useSyncExternalStore(subscribeViewModules, getModule, getModule);\n\n const componentData = data?.[pathname]?.[componentPath] ?? {};\n const Component = viewImportMap[componentPath];\n\n useEffect(() => {\n if (!children) {\n restoreScroll(action, componentPath);\n }\n }, [action, children, componentPath]);\n\n if (!Component) {\n const NotFound = viewImportMap[\"404\"];\n return <NotFound />;\n }\n const Loading = mod?.Loading;\n const ErrorFallback = mod?.Error ?? DefaultQueryErrorFallback;\n\n return (\n <ErrorBoundary FallbackComponent={ErrorFallback} resetKeys={[pathname]} onReset={clearErrors}>\n <Suspense fallback={Loading ? <Loading /> : null}>\n {/* Keyed by view path so swapping views remounts the view (fresh\n state), while the boundary above — keyed by tree slot in `Tree` —\n stays revealed across the swap. */}\n <Component key={componentPath} {...componentData}>\n {props.children}\n </Component>\n </Suspense>\n </ErrorBoundary>\n );\n});\n\nexport const Tree = memo(\n (props: {\n action: Action;\n tree: ComponentTree;\n entries: string[];\n pathname: string;\n /** Index into `entries` this level of the tree renders. */\n depth?: number;\n }) => {\n const { entries, tree, pathname, action, depth = 0 } = props;\n\n return (\n <>\n {/* `entries` is the matched route's chain, outermost layout first, so\n each level renders the one view at its own position. Matching on\n membership instead mounted a view twice when it also sat at\n another depth of the tree (#788). */}\n {tree\n .filter(([path]) => path === entries[depth])\n .map((node, slot) => {\n const [path, subtree] = node;\n // Keyed by tree SLOT, not by view path: the Suspense/error\n // boundary inside `Route` must survive a sibling swap (Home →\n // Pricing under the same layout), so React treats it as already\n // revealed and a suspending navigation keeps the previous page on\n // screen. A path key would remount the boundary every navigation,\n // and a brand-new boundary commits its fallback the moment any\n // sibling content (the layout's re-rendered chrome) commits —\n // blanking the outgoing page. The view itself still remounts when\n // the path changes: `Route` keys its Component render.\n if (subtree.length > 0) {\n return (\n <Route\n action={action}\n key={`slot-${slot}`}\n componentPath={path}\n pathname={pathname}\n >\n <Tree\n action={action}\n tree={subtree}\n entries={entries}\n pathname={pathname}\n depth={depth + 1}\n />\n </Route>\n );\n }\n return (\n <Route\n action={action}\n key={`slot-${slot}`}\n componentPath={path}\n pathname={pathname}\n />\n );\n })}\n </>\n );\n },\n);\n\nconst Routes = (props: { componentTree: ComponentTree }) => {\n const { componentTree } = props;\n const [isPending, startTransition] = useTransition();\n const [isFetching, setIsFetching] = useState(false);\n const { routerSubject, fetchRouteCSS, preloadRouteModules, takePrefetched } =\n useContext(ClientRouterContext);\n const { hydrate } = useContext(QueryManagerContext);\n\n const [transitionPath, setTransitionPath] = useState<[string, string]>([\n null,\n routerSubject?.getValue().pathname,\n ]);\n\n const {\n breadcrumbs,\n pageData,\n i18n,\n prefetchedData,\n features,\n appId: currentAppId,\n } = useContext(ServerDataContext);\n\n const [routeState, setRouteState] = useState<RouteState & PageData>({\n params: routerSubject?.getValue().params,\n search: routerSubject?.getValue().search,\n pathname: routerSubject?.getValue().pathname,\n views: routerSubject?.getValue().views,\n action: null,\n hash: routerSubject?.getValue().hash,\n state: routerSubject?.getValue().state,\n routePath: routerSubject?.getValue().routePath,\n locale: routerSubject?.getValue().locale,\n breadcrumbs,\n data: pageData,\n i18n,\n prefetchedData,\n features: features ?? {},\n appId: currentAppId,\n });\n\n const { replace } = useNavigate();\n\n // Adopt what the document was rendered with. Without this the initial payload\n // only ever reaches a component that mounts on the first render, and one that\n // mounts on a later navigation — into a route whose layout has since been\n // carried forward rather than re-run — would fetch it over `/api` instead.\n useEffect(() => {\n hydrate(prefetchedData);\n }, [hydrate, prefetchedData]);\n\n // The route currently on screen, in `x-gemi-from` form. Updated when a\n // response is committed, never when one is merely requested — a navigation\n // that fails must leave the base the server carries segments from intact.\n const renderedRouteRef = useRef(initialRenderedRoute(routeState));\n\n useEffect(() => {\n return routerSubject?.subscribe(async (routerState) => {\n const { pathname, search, state, views } = routerState;\n setTransitionPath((current) => {\n const [, prevTarget] = current;\n return [prevTarget, pathname];\n });\n if (routerState.views.length === 0) {\n // Same reason as the `is404` branch below: the tree about to be mounted\n // carries none of the segments the stale `from` would have the server\n // skip.\n renderedRouteRef.current = \"\";\n setRouteState((routerState) => ({\n ...routerState,\n views: [\"404\"],\n }));\n return;\n }\n\n if (state?.shallow) {\n setRouteState((state) => ({\n ...state,\n ...routerState,\n }));\n return;\n }\n\n const localeSegment = routerState.locale ? `/${routerState.locale}` : \"\";\n\n const url = routeDataUrl({ pathname, search, localeSegment });\n const from = renderedRouteRef.current;\n setIsFetching(true);\n\n // `fetchRouteCSS` keys off the route manifest, so it needs the pattern\n // rather than the concrete path — `/posts/:id`, not `/posts/123`.\n fetchRouteCSS(routerState.routePath).catch((e) => console.error(e));\n // Announced before the imports below start, so each view's own static\n // imports are already in flight rather than discovered one parse at a\n // time once its chunk lands (#352).\n preloadRouteModules(routerState.routePath);\n // Through `loadViewModule` so the module registry — and with it each\n // view's `Loading`/`Error` exports — is populated before the\n // transition commits the new surface.\n //\n // The rejection is handled by the route's `lazy()`, which reaches the\n // same import, and by the chunk recovery inside `loadViewModule`; left\n // unhandled here it was only noise in an error reporter (folio#2117).\n for (const component of views) {\n loadViewModule(component).catch(() => {});\n }\n\n const payload = await loadRoutePayload({\n url,\n from,\n takePrefetched,\n renderedRoute: () => renderedRouteRef.current,\n // Query results streaming behind the envelope (#290): hydrating each\n // settles the segment suspended on it — the same wake path streamed\n // documents use.\n onQueryPayload: ([path, variantKey, data]) => {\n hydrate({ [path]: { [variantKey]: data } });\n },\n });\n\n if (payload) {\n const {\n data,\n i18n,\n prefetchedData,\n breadcrumbs,\n meta,\n directive = {},\n is404 = false,\n appId,\n features,\n } = payload;\n updateMeta(meta, i18n?.currentLocale ?? i18n?.defaultLocale);\n if (directive?.kind === \"Redirect\") {\n // An absolute URL (`Redirect.external`, an off-origin sign-in page)\n // is not a route: the router would prefix a locale and look it up.\n if (isExternalRedirect(directive?.path)) {\n window.location.replace(directive.path);\n } else if (directive?.path) {\n // `directive.path` is a concrete url the server built, not a route\n // pattern, so there is nothing to substitute. It used to need an\n // empty `params` and an `as unknown` to get past the signature —\n // the framework's own copy of the bug apps hit.\n replace(directive.path);\n }\n\n return;\n }\n\n // Returns, rather than falling through. The commit below spreads\n // `routerState`, which carries the *matched* route's views — so without\n // the return this updater's `[\"404\"]` is queued and then overwritten in\n // the same batch, and the route renders its real views with no data.\n //\n // Reachable only since `.feature()`: a path the client cannot match is\n // caught by the `views.length === 0` guard above and never fetched, so\n // `is404` from the server used to imply an empty client `views`. A gated\n // route keeps its manifest entry, which is exactly the case where the\n // server says 404 and the client still knows how to render the page.\n if (is404) {\n // Not `${pathname}${search}`. `x-gemi-from` tells the server which\n // segments are already mounted so it can skip their handlers, and\n // after this commit the mounted tree is `[\"404\"]` — none of the target\n // route's layouts, and none of the previous route's either. The empty\n // string is what the server reads as \"carry nothing\".\n renderedRouteRef.current = \"\";\n startTransition(() => {\n setRouteState((state) => ({\n ...state,\n ...routerState,\n appId,\n i18n,\n features: features ?? state.features,\n // After the spread, deliberately.\n views: [\"404\"],\n }));\n });\n setIsFetching(false);\n return;\n }\n\n const carriedViews: string[] = payload.partial?.carriedViews ?? [];\n renderedRouteRef.current = `${pathname}${search}`;\n\n // Adopt what the server just prefetched before the new surface mounts\n // and its queries read the cache, otherwise they refetch it over /api.\n // Safe here: this callback is async, so we are past the render phase.\n hydrate(prefetchedData);\n\n startTransition(() => {\n setRouteState((state) => ({\n ...routerState,\n appId,\n i18n,\n // `?? state.features` rather than a bare assignment: an error-path\n // or older-server envelope carrying no flags must leave the current\n // values on screen, not blank every flag mid-session.\n features: features ?? state.features,\n prefetchedData,\n ...mergeCarriedSegments(\n state,\n { pathname, routePath: routerState.routePath, data, breadcrumbs },\n carriedViews,\n ),\n }));\n });\n }\n setIsFetching(false);\n });\n }, [routerSubject, fetchRouteCSS, preloadRouteModules, takePrefetched, replace, hydrate]);\n\n return (\n <RouteTransitionProvider\n isPending={isPending}\n isFetching={isFetching}\n transitionPath={transitionPath}\n >\n <RouteStateProvider state={routeState}>\n <Tree\n action={routeState.action}\n // `applyParams` strips the trailing slash, so the root comes back as\n // `\"\"` while the server keys its data under `/` (#819).\n pathname={applyParams(routeState.pathname ?? \"/\", routeState.params) || \"/\"}\n tree={componentTree}\n entries={routeState.pathname ? routeState.views : [\"404\"]}\n />\n </RouteStateProvider>\n </RouteTransitionProvider>\n );\n};\n\nexport const ClientRouter = (props: {\n viewImportMap?: Record<string, ReturnType<typeof lazy>>;\n /** Server only: full view modules for `Loading`/`Error` fallbacks. */\n viewModules?: Record<string, Record<string, any>>;\n RootLayout: ComponentType<RootLayoutProps>;\n /** App-wide `useQuery` defaults; per-call config always wins. */\n queryConfig?: QueryConfig;\n}) => {\n const { RootLayout } = props;\n const {\n routeManifest,\n router,\n componentTree,\n pageData,\n cssManifest,\n modulePreloadManifest,\n assetBase,\n breadcrumbs,\n i18n,\n meta,\n } = useContext(ServerDataContext);\n const htmlAttributes = resolveHtmlAttributes(\n meta?.htmlAttributes,\n i18n.currentLocale ?? i18n.defaultLocale,\n );\n\n return (\n <ThemeProvider>\n <I18nProvider>\n <QueryManagerProvider queryConfig={props.queryConfig}>\n <ComponentsProvider viewImportMap={props.viewImportMap} modules={props.viewModules}>\n <ClientRouterProvider\n cssManifest={cssManifest}\n modulePreloadManifest={modulePreloadManifest}\n assetBase={assetBase}\n searchParams={router.searchParams}\n params={router.params}\n pageData={pageData}\n is404={router.is404}\n is500={false}\n pathname={router.pathname}\n currentPath={router.currentPath}\n routeManifest={routeManifest}\n breadcrumbs={breadcrumbs}\n urlLocaleSegment={router.urlLocaleSegment}\n >\n <StrictMode>\n <RootLayout locale={i18n.currentLocale} htmlAttributes={htmlAttributes}>\n <Routes componentTree={componentTree} />\n </RootLayout>\n </StrictMode>\n </ClientRouterProvider>\n </ComponentsProvider>\n </QueryManagerProvider>\n </I18nProvider>\n </ThemeProvider>\n );\n};\n","import { useEffect, type ComponentType } from \"react\";\nimport { hydrateRoot, createRoot } from \"react-dom/client\";\nimport { ServerDataProvider } from \"./ServerDataProvider\";\nimport { ClientRouter } from \"./ClientRouter\";\nimport type { QueryConfig } from \"./QueryManagerContext\";\nimport { ErrorBoundary } from \"react-error-boundary\";\nimport { initialViewModulesReady } from \"./ComponentContext\";\nimport {\n configureChunkLoadRecovery,\n recoverFromChunkLoadError,\n type ChunkLoadRecoveryOptions,\n} from \"./chunkLoadRecovery\";\nimport { configureRealtime } from \"./realtime/loader\";\nimport type { RealtimeOptions } from \"./realtime/RealtimeClient\";\n\nexport interface InitOptions {\n /**\n * App-wide `useQuery` defaults (per-call config always wins). Mirror the\n * value passed to `createRoot` in the view router's service provider so the\n * server render and hydration agree.\n */\n queryConfig?: QueryConfig;\n /**\n * What happens when a chunk fails to load — usually a page from an earlier\n * release after a deploy. By default gemi reloads the page it was going to\n * once, and not again within 30 seconds. Pass options to report the failure\n * or veto the reload, or `false` to leave every failure to the route's error\n * boundary. See `recoverFromChunkLoadError`.\n */\n chunkLoadRecovery?: ChunkLoadRecoveryOptions | false;\n /**\n * The broadcast socket the channel hooks use: `path` (match\n * `defineBroadcastConfig({ path })`, default `/__gemi/socket`) and\n * `hiddenDisconnectMs` (how long a hidden tab keeps its socket, default\n * 60 000).\n */\n realtime?: RealtimeOptions;\n}\n\n/**\n * Vite's preload helper fires `vite:preloadError` on `window` when a lazy\n * `import()` in app code — a `lazy(() => import(\"./Chart\"))` inside a view —\n * cannot load a dependency. `preventDefault()` stops the helper rethrowing,\n * which is only right when a reload is actually under way.\n */\nfunction installPreloadErrorRecovery() {\n window.addEventListener(\"vite:preloadError\", (event) => {\n const error = (event as Event & { payload?: unknown }).payload;\n if (recoverFromChunkLoadError(error, { source: \"preload\" })) {\n event.preventDefault();\n }\n });\n}\n\nconst StackTrace = () => {\n useEffect(() => {\n window.addEventListener(\"load\", () => {\n const container = document.getElementById(\"overlay\");\n const ErrorOverlay = customElements.get(\"vite-error-overlay\");\n if (ErrorOverlay) {\n const overlay = new ErrorOverlay({\n message: (window as any).error,\n stack: (window as any).stack_trace || \"\",\n });\n container.appendChild(overlay);\n }\n });\n }, []);\n\n return <div id=\"overlay\" />;\n};\n\nexport function init(\n RootLayout: ComponentType<any>,\n options: InitOptions = {},\n) {\n configureChunkLoadRecovery(options.chunkLoadRecovery);\n if (options.realtime) configureRealtime(options.realtime);\n if (typeof window !== \"undefined\" && options.chunkLoadRecovery !== false) {\n installPreloadErrorRecovery();\n }\n if (typeof window !== \"undefined\" && (window as any).render_error) {\n createRoot(document.body).render(<StackTrace />);\n } else {\n // Held until the current route's view chunks are in the registry, so no\n // segment's first registration lands on a boundary that is mid-hydration.\n // See `initialViewModulesReady`.\n //\n // The `.catch` re-throws out of the microtask for the same reason the\n // bootstrap script wraps the entry `import()` that way: hydration used to\n // run inside the entry's evaluation, so a throw from `hydrateRoot` — a\n // `RootLayout` that fails at module scope, a root already attached —\n // reached that handler. Deferring it past a `.then` puts the throw in a\n // rejection no `window.onerror` reporter sees, and the page sits\n // permanently unhydrated with nothing raised.\n void initialViewModulesReady\n .then(() => hydrate(RootLayout, options))\n .catch((e) => {\n setTimeout(() => {\n throw e;\n });\n });\n }\n}\n\nfunction hydrate(RootLayout: ComponentType<any>, options: InitOptions) {\n hydrateRoot(\n document,\n <>\n <></>\n <></>\n <ErrorBoundary fallback={<div />}>\n <ServerDataProvider>\n <ClientRouter\n RootLayout={RootLayout}\n queryConfig={options.queryConfig}\n />\n </ServerDataProvider>\n </ErrorBoundary>\n </>,\n {\n onCaughtError: (error) => {\n console.error(error);\n // @ts-ignore\n if (import.meta.env.DEV) {\n const ErrorOverlay = customElements.get(\"vite-error-overlay\");\n if (ErrorOverlay) {\n const overlay = new ErrorOverlay({\n message: (error as any).message,\n stack: (error as any).stack || \"\",\n });\n document.body.appendChild(overlay);\n }\n }\n },\n },\n );\n}\n\nexport function create(\n RootLayout: ComponentType<any>,\n {\n componentTree,\n loaders,\n routeManifest,\n router,\n i18n,\n auth,\n prefetchedData,\n viewImportMap,\n }: any,\n) {\n (window as any).__GEMI_DATA__ = {\n componentTree,\n loaders,\n routeManifest,\n router,\n i18n,\n auth,\n prefetchedData,\n pageData: {},\n };\n createRoot(document.getElementById(\"root\")).render(\n <ServerDataProvider>\n <ClientRouter viewImportMap={viewImportMap} RootLayout={RootLayout} />\n </ServerDataProvider>,\n );\n}\n","import { createContext } from \"react\";\nimport type { DictionarySink } from \"../i18n/dictionarySink\";\n\n/**\n * The SSR-only collector `useDictionary` reports into. `null` in the browser,\n * where nothing needs collecting — the strings are already there.\n *\n * Mirrors `ServerQueryContext`: a server-supplied per-request object handed to\n * the tree by `createRoot`.\n */\nexport const DictionarySinkContext = createContext<DictionarySink | null>(null);\n","import type { ComponentType } from \"react\";\nimport { ClientRouter } from \"./ClientRouter\";\nimport { DictionarySinkContext } from \"./DictionarySinkContext\";\nimport type { RootLayoutProps } from \"./htmlAttributes\";\nimport type { QueryConfig } from \"./QueryManagerContext\";\nimport { ServerDataProvider } from \"./ServerDataProvider\";\nimport { ServerQueryContext } from \"./ServerQueryContext\";\n\nexport interface CreateRootOptions {\n /**\n * App-wide `useQuery` defaults (per-call config always wins). Set the same\n * value in the client entry's `init` call so hydration matches the server\n * render.\n */\n queryConfig?: QueryConfig;\n}\n\nexport function createRoot(\n RootLayout: ComponentType<RootLayoutProps>,\n options: CreateRootOptions = {},\n) {\n // `serverQueries`, `viewModules` and `dictionarySink` exist only when the view\n // router renders this on the server — the browser mounts with all three absent.\n // So does `rootLayout`: a static view's own document layout\n // (`.static({ layout })`), which replaces the app's for that render only.\n return (props: any) => (\n <ServerDataProvider value={props.data}>\n <ServerQueryContext.Provider value={props.serverQueries ?? null}>\n <DictionarySinkContext.Provider value={props.dictionarySink ?? null}>\n <ClientRouter\n RootLayout={props.rootLayout ?? RootLayout}\n viewImportMap={props.viewImportMap}\n viewModules={props.viewModules}\n queryConfig={options.queryConfig}\n />\n </DictionarySinkContext.Provider>\n </ServerQueryContext.Provider>\n </ServerDataProvider>\n );\n}\n","import type { ComponentProps } from \"react\";\n\nconst defaultScreen = [390, 768, 1024];\nconst defaultContainer = [100, 100, 100, 100];\n\nfunction generateImageProps(\n src: string,\n width: number,\n container = defaultContainer,\n screen = defaultScreen,\n quality = 80,\n) {\n const baseUrl = src;\n\n const widths = [...container.map((c, i) => (screen[i] * c) / 100), width * 2];\n\n return {\n srcSet: [\n ...screen.map((size, i) => {\n return `/api/__gemi__/services/image/resize?url=${baseUrl}&q=${quality}&w=${widths[i]} ${size}${isNaN(Number(size)) ? \"\" : \"w\"}`;\n }),\n `/api/__gemi__/services/image/resize?url=${baseUrl}&q=${quality}&w=${width * 2} 2x`,\n ].join(\", \"),\n sources: [\n ...container.map((c, i) => {\n if (!screen[i]) {\n return `${c}vw`;\n }\n return `(max-width: ${screen[i]}px) ${c}vw`;\n }),\n ].join(\", \"),\n };\n}\n\nfunction fillRestWithLast<T>(arr: T[], length: number): T[] {\n return [\n ...arr,\n ...Array.from({ length: length - arr.length }).fill(arr[arr.length - 1]),\n ] as T[];\n}\n\ninterface ImageProps {\n src: string;\n width: number;\n container?: number[];\n screen?: number[];\n quality?: number;\n}\n\nexport const Image = (props: ComponentProps<\"img\"> & ImageProps) => {\n const {\n screen = defaultScreen,\n container = defaultContainer,\n src,\n width,\n quality = 80,\n srcSet: __,\n ...rest\n } = props;\n\n if (!src) {\n return null;\n }\n\n const srcProps = generateImageProps(\n src,\n width,\n fillRestWithLast(container, 4),\n screen,\n quality,\n );\n\n return <img {...srcProps} width={width} {...rest} />;\n};\n","import { usePost } from \"../useMutation\";\n\ninterface UseForgotPasswordArgs {\n onSuccess: () => void;\n}\n\nconst defaultArgs: UseForgotPasswordArgs = {\n onSuccess: () => {},\n};\n\nexport function useForgotPassword(args: UseForgotPasswordArgs = defaultArgs) {\n return usePost(\n \"/auth/forgot-password\",\n {},\n {\n onSuccess: () => {\n args.onSuccess();\n },\n },\n );\n}\n","import { usePost } from \"../useMutation\";\nimport { useFrameworkQuery } from \"../useQuery\";\nimport { reconnectRealtime } from \"../realtime/loader\";\n\ninterface UseSignInArgs {\n onSuccess?: (data: any) => void;\n}\n\nconst defaultArgs: UseSignInArgs = {\n onSuccess: () => {},\n};\n\nexport function useSignIn(args: UseSignInArgs = defaultArgs) {\n // Only here for `mutate` — `lazy` so the sign-in form neither fetches nor\n // suspends on a user it does not have yet. `useFrameworkQuery` keeps that\n // pinned regardless of the app's `queryConfig`.\n const { mutate } = useFrameworkQuery(\"/auth/me\", {}, { lazy: true });\n return usePost(\n \"/auth/sign-in\",\n {},\n {\n onSuccess: (user) => {\n args.onSuccess(user);\n mutate(user as any);\n // The socket was opened as a guest: authorize its channels as the user.\n reconnectRealtime();\n },\n },\n );\n}\n","import { usePost } from \"../useMutation\";\n\nexport function useSignUp() {\n return usePost(\"/auth/sign-up\");\n}\n","import { useMutate } from \"../useMutate\";\nimport { usePost } from \"../useMutation\";\nimport { reconnectRealtime } from \"../realtime/loader\";\n\ninterface UseSignOutArgs {\n onSuccess?: () => void;\n}\n\nconst defaultArgs: UseSignOutArgs = {\n onSuccess: () => {},\n};\n\nexport function useSignOut(args: UseSignOutArgs = defaultArgs) {\n const mutator = useMutate();\n return usePost(\n \"/auth/sign-out\",\n {},\n {\n onSuccess: () => {\n args.onSuccess();\n mutator({ path: \"/auth/me\" });\n // The socket was opened as the signed-in user.\n reconnectRealtime();\n },\n },\n );\n}\n","import { usePost } from \"../useMutation\";\n\ninterface UseResetPasswordArgs {\n onSuccess: () => void;\n}\n\nconst defaultArgs: UseResetPasswordArgs = {\n onSuccess: () => {},\n};\n\nexport function useResetPassword(args: UseResetPasswordArgs = defaultArgs) {\n return usePost(\n \"/auth/reset-password\",\n {},\n {\n onSuccess: () => {\n args.onSuccess();\n },\n },\n );\n}\n","import { useContext } from \"react\";\nimport { ServerDataContext } from \"../ServerDataProvider\";\nimport { useFrameworkQuery } from \"../useQuery\";\nimport {\n QueryConfigContext,\n USER_QUERY_CONFIG_KEYS,\n pickDefined,\n type UserQueryConfig,\n} from \"../QueryManagerContext\";\n\n/**\n * The signed-in user, or `null`. `config` tunes the `/auth/me` query — its\n * freshness window and retry policy — over the app-wide `queryConfig.user`;\n * the app's general `queryConfig` never applies here.\n */\nexport function useUser(config?: UserQueryConfig) {\n const { auth } = useContext(ServerDataContext);\n const appUserConfig = useContext(QueryConfigContext)?.user;\n const {\n data: user,\n loading,\n error,\n // `useFrameworkQuery`: the semantics below are pinned, so an app-wide\n // `queryConfig` must not leak in. Only the `UserQueryConfig` keys are\n // taken, from `queryConfig.user` and then the call.\n } = useFrameworkQuery(\n \"/auth/me\",\n {},\n {\n ...pickDefined(appUserConfig, USER_QUERY_CONFIG_KEYS),\n ...pickDefined(config, USER_QUERY_CONFIG_KEYS),\n fallbackData: auth?.user ? auth.user : null,\n // An anonymous visitor has no `/auth/me` data and never will — this\n // must resolve to `user: null`, not suspend the page behind a 401. The\n // 401 is not retried (see `retry`), so it is one request, not a poll.\n suspense: false,\n },\n );\n\n if (loading && !user) {\n return { user: null, loading, error };\n }\n\n return { user: user, loading, error };\n}\n","import { useSearchParams } from \"../useSearchParams\";\nimport { INTENDED_URL_PARAM, safeRedirectPath } from \"../../utils/intendedUrl\";\n\n/**\n * The page a signed-out visitor was sent to sign-in from, for the sign-in page\n * to return them to: `AuthenticationMiddleware` puts it on the sign-in URL as\n * `?redirect=`. `fallback` when there is none, or when it is not a path on\n * this origin — the parameter is attacker-writable, and following it\n * unchecked is an open redirect.\n *\n * ```tsx\n * const intended = useIntendedUrl(\"/dashboard\");\n * <Form action=\"/auth/sign-in-v2\" onSuccess={() => push(intended)} />\n * ```\n */\nexport function useIntendedUrl(fallback = \"/\"): string {\n return safeRedirectPath(useSearchParams().get(INTENDED_URL_PARAM), fallback);\n}\n","import { useState } from \"react\";\nimport { usePost } from \"../useMutation\";\nimport { useFrameworkQuery } from \"../useQuery\";\nimport { reconnectRealtime } from \"../realtime/loader\";\n\ninterface UseEmailCodeArgs {\n /** After `verify` signs in. `isNewUser` is true when the account was just created. */\n onSuccess?: (result: { session: any; isNewUser: boolean }) => void;\n}\n\n/**\n * Passwordless sign-up-or-sign-in with a one-time email code, in place — no\n * redirect, so it fits a dialog (#708). Needs `auth.emailCode.enabled`.\n *\n * ```tsx\n * const { request, verify, isPending, error } = useEmailCode();\n * await request(email); // always { ok: true }\n * const r = await verify(email, code); // { session, isNewUser } or undefined\n * ```\n *\n * `error` is the outcome of the latest call, `request` or `verify`: a\n * `validation_error` on `email` or `code` (`invalid_code`,\n * `too_many_attempts`), a 429 `rate_limit`, or `null` once that call succeeds.\n * A failed `verify` followed by \"send a new code\" therefore shows the\n * request's error, or nothing, not the stale `invalid_code` (#724).\n * `requestError` and `verifyError` hold each call's own last error. A\n * successful `verify` refreshes `useUser()`.\n */\nexport function useEmailCode(args: UseEmailCodeArgs = {}) {\n const { mutate } = useFrameworkQuery(\"/auth/me\", {}, { lazy: true });\n const requestMutation = usePost(\"/auth/email-code\");\n const verifyMutation = usePost(\n \"/auth/email-code/verify\",\n {},\n {\n onSuccess: (result: any) => {\n if (result?.session?.user) {\n mutate(result.session.user);\n // The socket was opened as a guest: authorize its channels as the user.\n reconnectRealtime();\n }\n args.onSuccess?.(result);\n },\n },\n );\n\n // Each mutation keeps its error until it runs again, so either one alone\n // can be stale. The latest call decides which one `error` reports.\n const [latest, setLatest] = useState<\"request\" | \"verify\" | null>(null);\n const error =\n latest === \"verify\"\n ? verifyMutation.error\n : latest === \"request\"\n ? requestMutation.error\n : null;\n const isPending = requestMutation.loading || verifyMutation.loading;\n\n return {\n request: (email: string) => {\n setLatest(\"request\");\n return requestMutation.trigger({ email } as any);\n },\n verify: (email: string, code: string, extra: { name?: string } = {}) => {\n setLatest(\"verify\");\n return verifyMutation.trigger({ email, code, ...extra } as any);\n },\n isPending,\n error,\n requestError: requestMutation.error,\n verifyError: verifyMutation.error,\n };\n}\n","import { useContext } from \"react\";\nimport { RouteStateContext } from \"./RouteStateContext\";\nimport type { ClientFeatureKey } from \"./rpc\";\n\n/**\n * Reads a feature evaluated by the server for this request.\n *\n * ```tsx\n * if (useFeature(\"new-checkout\")) {\n * return <NewCheckout />;\n * }\n * ```\n *\n * Keys are typed against `app/features`, so a typo is a compile error rather\n * than a feature that silently reads as off. Features declared\n * `serverOnly: true` are excluded from that set: they are withheld from the\n * payload on purpose, so reading one here could only ever answer `false`. Use\n * the `Features` facade for those.\n *\n * ## It never fetches\n *\n * The value comes from the payload the server already sent — embedded in the\n * document on first load, and replaced by each navigation's envelope after\n * that. So this is a context read: no request, no suspense, no loading state,\n * and no flash of the wrong branch, which is the failure mode that makes\n * client-evaluated features unusable for anything above the fold.\n *\n * The corollary is that switching a feature on reaches an open page on its next\n * navigation, not instantly.\n *\n * ## Reads route state, not server data\n *\n * `RouteStateContext` is what each navigation replaces — the same reason\n * `useLocale` reads it. Reading `ServerDataContext` instead would pin every\n * feature to the values from the initial document for the life of the session.\n */\nexport function useFeature(key: ClientFeatureKey): boolean {\n // `= {}` because several existing tests provide a bare object as page data,\n // and an error-path envelope may carry no features at all.\n const { features = {} } = useContext(RouteStateContext);\n\n if (process.env.NODE_ENV !== \"production\" && !(key in features)) {\n // Both reasons, because the type system only rules out the second one for a\n // caller whose `gemi.d.ts` resolved — and \"declare it\" is actively wrong\n // advice for the app that already did, then marked it `serverOnly`.\n console.warn(\n `[gemi] Feature \"${String(key)}\" is not in the payload the server sent. Either it is not declared in app/features, or it is declared \\`serverOnly: true\\` and never reaches the browser.`,\n );\n }\n\n // An unknown key reads as off rather than throwing: a feature deleted from the\n // declarations, or a payload that predates one, must not white-screen a page\n // that renders it.\n return features[key as string] === true;\n}\n\n/**\n * Every feature the server sent, for a component that needs to branch on\n * several at once or forward them somewhere.\n */\nexport function useFeatures(): Record<string, boolean> {\n const { features = {} } = useContext(RouteStateContext);\n return features;\n}\n","import { createElement, Fragment, isValidElement, type JSX } from \"react\";\n\ntype TemplateParams = Record<\n string,\n string | ((p: unknown) => string | JSX.Element)\n>;\n\nexport function parseTranslation(template: string, params: TemplateParams) {\n // Check if we have any JSX in our parameters\n const hasJSX = Object.values(params).some(\n (value) =>\n typeof value === \"function\" &&\n isValidElement((value as (p: unknown) => unknown)(\"\")),\n );\n\n // Regular expression to match template variables:\n // {{name}} - simple variable\n // {{name:type}} - variable with type casting\n // {{name:[content]}} - variable with interpolated content\n const regex = /{{([^{}]+?)(?::([^{}\\[\\]]+?))?(?:\\[(.*?)\\])?}}/g;\n\n if (!hasJSX) {\n // Simple string replacement\n const result = template.replace(regex, (match, name, type, content) => {\n // Clean the name part by removing any colon if present\n const cleanName = name.includes(\":\") ? name.split(\":\")[0] : name;\n\n const value = params[cleanName];\n if (value === undefined) {\n return match; // Return original match if no parameter found\n }\n\n if (typeof value === \"function\") {\n // If value is a function, call it with the content if available\n const functionParam = content !== undefined ? content : \"\";\n const functionResult = value(functionParam);\n // Check if function returned JSX - this shouldn't happen in the string branch\n if (isValidElement(functionResult)) {\n throw new Error(\"JSX returned in string context\");\n }\n return String(functionResult);\n }\n\n // Handle type casting if specified\n if (type) {\n switch (type.toLowerCase()) {\n case \"number\":\n return Number(value).toString();\n case \"string\":\n return String(value);\n case \"boolean\":\n return Boolean(value).toString();\n default:\n return String(value);\n }\n }\n return String(value);\n });\n return result as any;\n } else {\n // JSX replacement - we'll split the template into parts\n const parts: Array<string | JSX.Element> = [];\n let lastIndex = 0;\n let match: RegExpExecArray | null = null;\n\n while ((match = regex.exec(template)) !== null) {\n const [fullMatch, name, type, content] = match;\n const matchIndex = match.index;\n\n // Clean the name part by removing any colon if present\n const cleanName = name.includes(\":\") ? name.split(\":\")[0] : name;\n\n // Add text before the match\n if (matchIndex > lastIndex) {\n parts.push(template.substring(lastIndex, matchIndex));\n }\n\n const value = params[cleanName];\n if (value === undefined) {\n // Keep original template variable if no parameter found\n parts.push(fullMatch);\n } else if (typeof value === \"function\") {\n // If value is a function, call it with the content if available\n const functionParam = content !== undefined ? content : \"\";\n const functionResult = value(functionParam);\n parts.push(functionResult);\n } else if (type) {\n // Handle type casting if specified\n switch (type.toLowerCase()) {\n case \"number\":\n parts.push(Number(value).toString());\n break;\n case \"string\":\n parts.push(String(value));\n break;\n case \"boolean\":\n parts.push(Boolean(value).toString());\n break;\n default:\n parts.push(String(value));\n }\n } else {\n parts.push(String(value));\n }\n\n lastIndex = matchIndex + fullMatch.length;\n }\n\n // Add any remaining text\n if (lastIndex < template.length) {\n parts.push(template.substring(lastIndex));\n }\n\n // Convert the parts array to JSX\n return createElement(Fragment, {}, ...parts) as any;\n }\n}\n","import type { I18nDictionary } from \"./rpc\";\nimport type { ParseTranslationParams, Prettify } from \"../utils/type\";\nimport type { JSX } from \"react\";\nimport { parseTranslation } from \"../utils/parseTranslation\";\nimport { useRouteData } from \"./useRouteData\";\n\ntype Parser<T extends Record<string, string>> = Prettify<\n {\n [K in keyof T]: ParseTranslationParams<T[K]>;\n }[keyof T]\n>;\n\ntype ParamsOrNever<T> = T extends Record<string, never>\n ? [params?: never]\n : [params: T];\n\n/**\n * @deprecated Use `useDictionary(dict)` with a `defineDictionary` dictionary\n * declared next to the component. This resolves a dictionary by name through\n * the global `I18nDictionary` interface, which needs a `gemi.d.ts`\n * declaration, a central `app/i18n/index.ts`, and a hand-maintained `prefetch`\n * map naming every route's dictionaries — and it ships whatever that map says\n * whether the page reads it or not. Still supported; see `docs/i18n.md`.\n */\nexport function useTranslator<T extends keyof I18nDictionary>(component: T) {\n const { i18n } = useRouteData();\n\n function parse<\n K extends keyof I18nDictionary[T][\"dictionary\"],\n U extends Record<string, string> = I18nDictionary[T][\"dictionary\"][K],\n >(key: K, ...args: ParamsOrNever<Parser<U>>) {\n try {\n const translations = i18n.dictionary[i18n.currentLocale][component];\n const [params = {}] = args;\n return parseTranslation(translations[key as any], params);\n } catch (err) {\n console.error(\n `Unresolved translation Component:${component} key:${String(key)}`,\n );\n return String(key);\n }\n }\n\n parse.jsx = <\n K extends keyof I18nDictionary[T][\"dictionary\"],\n U extends Record<string, string> = I18nDictionary[T][\"dictionary\"][K],\n >(\n key: K,\n ...args: ParamsOrNever<Parser<U>>\n ) => {\n return parse(key, ...(args as any)) as unknown as JSX.Element;\n };\n\n return parse;\n}\n","/**\n * Locale- and time-zone-aware formatting, shared by `useFormatter`, the\n * `format` property of a `useDictionary` result and `Lang.formatter()`.\n *\n * Dependency-free on purpose: components import it, so it must not pull in the\n * server facades.\n *\n * Why the time zone is pinned: a `Date` formatted with no `timeZone` uses the\n * runtime's zone, which is the server's during SSR and the viewer's in the\n * browser. The two disagree for anyone not sitting in the server's zone, so the\n * same instant can print a different hour, or a different day, on each side —\n * a hydration mismatch at best, a wrong date at worst. Every formatter here\n * carries one zone, resolved on the server and shipped with the page, so both\n * sides print the same text.\n */\n\nexport type DateInput = Date | number | string;\n\nexport interface FormatterInit {\n /** BCP 47 locale tag. */\n locale: string;\n /** IANA time zone, such as `UTC` or `Europe/Istanbul`. */\n timeZone: string;\n}\n\nexport interface Formatter {\n readonly locale: string;\n readonly timeZone: string;\n /** A date, `{ dateStyle: \"medium\" }` unless options are given. */\n date(value: DateInput, options?: Intl.DateTimeFormatOptions): string;\n /** A time of day, `{ timeStyle: \"short\" }` unless options are given. */\n time(value: DateInput, options?: Intl.DateTimeFormatOptions): string;\n /** Date and time, `{ dateStyle: \"medium\", timeStyle: \"short\" }` unless options are given. */\n dateTime(value: DateInput, options?: Intl.DateTimeFormatOptions): string;\n number(value: number | bigint, options?: Intl.NumberFormatOptions): string;\n relative(\n value: number,\n unit: Intl.RelativeTimeFormatUnit,\n options?: Intl.RelativeTimeFormatOptions,\n ): string;\n list(values: Iterable<string>, options?: Intl.ListFormatOptions): string;\n /** The CLDR plural category for `count`: `one`, `few`, `other`, … */\n plural(count: number, options?: Intl.PluralRulesOptions): Intl.LDMLPluralRule;\n /**\n * The cached `Intl.DateTimeFormat` behind `date`/`time`/`dateTime`, with the\n * formatter's zone applied. For `formatToParts` or `formatRange`.\n */\n dateTimeFormat(options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat;\n}\n\n/** The zone used when the app configures none. */\nexport const DEFAULT_TIME_ZONE = \"UTC\";\n\n/**\n * Whether `timeZone` is an IANA zone (or offset) this runtime's `Intl` accepts.\n * An unknown zone makes `Intl.DateTimeFormat` throw a `RangeError`, so a zone\n * that comes from a cookie or a user record is checked before it is trusted.\n */\nexport function isValidTimeZone(timeZone: unknown): timeZone is string {\n if (typeof timeZone !== \"string\" || timeZone.length === 0) {\n return false;\n }\n try {\n new Intl.DateTimeFormat(\"en-US\", { timeZone });\n return true;\n } catch {\n return false;\n }\n}\n\n// Constructing an `Intl` formatter is the expensive part — it resolves locale\n// data — so each one is built once per (kind, locale, options). Options are\n// keyed by their JSON; callers pass small literal objects, and a key order\n// difference only costs a duplicate entry, never a wrong result.\nconst cache = new Map<string, unknown>();\nconst CACHE_LIMIT = 500;\n\nfunction cached<T>(key: string, create: () => T): T {\n let value = cache.get(key) as T | undefined;\n if (value === undefined) {\n if (cache.size >= CACHE_LIMIT) {\n // Insertion order: drop the oldest. Unbounded user-driven option objects\n // (a currency per row) must not grow a long-lived server process forever.\n cache.delete(cache.keys().next().value!);\n }\n value = create();\n cache.set(key, value);\n }\n return value;\n}\n\nfunction toDate(value: DateInput): Date {\n return value instanceof Date ? value : new Date(value);\n}\n\nfunction hasDateTimeFields(options: Intl.DateTimeFormatOptions): boolean {\n return (\n options.dateStyle !== undefined ||\n options.timeStyle !== undefined ||\n options.weekday !== undefined ||\n options.era !== undefined ||\n options.year !== undefined ||\n options.month !== undefined ||\n options.day !== undefined ||\n options.dayPeriod !== undefined ||\n options.hour !== undefined ||\n options.minute !== undefined ||\n options.second !== undefined ||\n options.fractionalSecondDigits !== undefined ||\n options.timeZoneName !== undefined\n );\n}\n\nexport function createFormatter(init: FormatterInit): Formatter {\n const { locale, timeZone } = init;\n\n const dateTimeFormat = (options: Intl.DateTimeFormatOptions = {}) => {\n // `??`, not a spread: `{ timeZone: undefined }` would otherwise drop the\n // pinned zone and fall back to the runtime's, which is the bug this exists\n // to prevent.\n const resolved = { ...options, timeZone: options.timeZone ?? timeZone };\n return cached(`dt|${locale}|${JSON.stringify(resolved)}`, () => {\n return new Intl.DateTimeFormat(locale, resolved);\n });\n };\n\n const withDefaults = (\n options: Intl.DateTimeFormatOptions | undefined,\n defaults: Intl.DateTimeFormatOptions,\n ) => {\n if (options && hasDateTimeFields(options)) {\n return options;\n }\n // Options that only tweak (a `timeZone`, `hour12`) still get the default\n // fields; otherwise `{ timeZone }` alone would print a bare numeric date.\n return { ...defaults, ...options };\n };\n\n return {\n locale,\n timeZone,\n date(value, options) {\n return dateTimeFormat(withDefaults(options, { dateStyle: \"medium\" })).format(\n toDate(value),\n );\n },\n time(value, options) {\n return dateTimeFormat(withDefaults(options, { timeStyle: \"short\" })).format(\n toDate(value),\n );\n },\n dateTime(value, options) {\n return dateTimeFormat(\n withDefaults(options, { dateStyle: \"medium\", timeStyle: \"short\" }),\n ).format(toDate(value));\n },\n number(value, options = {}) {\n return cached(\n `n|${locale}|${JSON.stringify(options)}`,\n () => new Intl.NumberFormat(locale, options),\n ).format(value);\n },\n relative(value, unit, options = {}) {\n return cached(\n `r|${locale}|${JSON.stringify(options)}`,\n () => new Intl.RelativeTimeFormat(locale, options),\n ).format(value, unit);\n },\n list(values, options = {}) {\n return cached(\n `l|${locale}|${JSON.stringify(options)}`,\n () => new Intl.ListFormat(locale, options),\n ).format(values);\n },\n plural(count, options = {}) {\n return cached(\n `p|${locale}|${JSON.stringify(options)}`,\n () => new Intl.PluralRules(locale, options),\n ).select(count);\n },\n dateTimeFormat,\n };\n}\n","import { useMemo } from \"react\";\nimport {\n createFormatter,\n DEFAULT_TIME_ZONE,\n isValidTimeZone,\n type Formatter,\n} from \"../i18n/formatter\";\nimport { useRouteData } from \"./useRouteData\";\n\n/**\n * Format dates, numbers, relative times and lists in the active locale and the\n * app's time zone.\n *\n * ```tsx\n * const format = useFormatter();\n * format.date(order.createdAt, { dateStyle: \"long\" });\n * format.number(1199.88, { style: \"currency\", currency: \"USD\" });\n * format.date(order.createdAt, { timeZone: \"Europe/Istanbul\" }); // per call\n * ```\n *\n * The locale and zone both come from the page payload, so the server render\n * and the hydrating browser format with the same ones. Prefer this to\n * `toLocaleDateString()`, which uses the runtime's locale and zone and so\n * differs between the two.\n *\n * Pass `options` to pin a zone for one subtree (`useFormatter({ timeZone })`).\n */\nexport function useFormatter(\n options: { locale?: string; timeZone?: string } = {},\n): Formatter {\n const { i18n } = useRouteData();\n const locale =\n options.locale ?? i18n?.currentLocale ?? i18n?.defaultLocale ?? \"en-US\";\n // An explicit zone is trusted and throws from `Intl` if it is wrong, like a\n // per-call one. The payload's was validated on the server; the check is for\n // a hand-built payload (tests, an older server) that has none.\n const timeZone =\n options.timeZone ??\n (isValidTimeZone(i18n?.timeZone) ? i18n.timeZone : DEFAULT_TIME_ZONE);\n\n return useMemo(\n () => createFormatter({ locale, timeZone }),\n [locale, timeZone],\n );\n}\n","import { use, useContext, type JSX } from \"react\";\nimport type { DictionaryHandle } from \"../i18n/defineDictionary\";\nimport { setActiveLocale } from \"../i18n/dictionaryRegistry\";\nimport type { DictionaryTranslations } from \"../i18n/dictionaryShape\";\nimport { parseTranslation } from \"../utils/parseTranslation\";\nimport type { ParseTranslationParams, Prettify } from \"../utils/type\";\nimport { DictionarySinkContext } from \"./DictionarySinkContext\";\nimport { useFormatter } from \"./useFormatter\";\nimport { useRouteData } from \"./useRouteData\";\n\ntype Parser<T extends Record<string, string>> = Prettify<\n {\n [K in keyof T]: ParseTranslationParams<T[K]>;\n }[keyof T]\n>;\n\ntype ParamsOrNever<T> = T extends Record<string, never>\n ? [params?: never]\n : [params: T];\n\n/**\n * Read a dictionary declared with `defineDictionary`, next to the component\n * that uses it.\n *\n * ```tsx\n * const t = useDictionary(homeDict);\n * t(\"title\", { name });\n * ```\n *\n * Keys and interpolation params come straight from the literal — there is no\n * name string to keep in sync and no `gemi.d.ts` augmentation.\n *\n * Normally this resolves without suspending: the server seeds the strings it\n * rendered with into the hydration payload, and the router warms a view's\n * dictionaries while it is already loading that view's chunks. It falls back to\n * suspending on the locale's chunk when neither happened — a dictionary inside\n * a `lazy()` subtree, or the first render after a locale switch.\n *\n * Replaces `useTranslator`, which is deprecated.\n */\nexport function useDictionary<const T extends DictionaryTranslations>(\n dictionary: DictionaryHandle<T>,\n) {\n const { i18n } = useRouteData();\n const sink = useContext(DictionarySinkContext);\n // An app with i18n switched off still renders dictionaries — fall back to the\n // source language rather than blowing up on an empty `i18n` payload.\n const locale = i18n?.currentLocale ?? dictionary.locales[0];\n // Tells the view loader which locale's chunks to warm on the next\n // navigation. `__GEMI_DATA__` only knows the locale the document loaded in.\n setActiveLocale(locale);\n // Before `use()` below, so the hook order is the same on a replayed render.\n // Same locale the strings resolve in, so `t.format` never disagrees with `t`.\n const format = useFormatter({ locale });\n\n // `loadForRender`, not the plain loader: a rejected locale chunk must not\n // rethrow out of `use()` and take the route down. It degrades to no strings,\n // and the per-key lookup below falls back to the key — what `useTranslator`\n // did. Called on the handle rather than the registry so a dictionary declared\n // at module scope survives the registry being reset under it.\n //\n // `use()` on every thenable a render could have suspended on, including once\n // it has resolved (#494): React replays a component that suspended in `use()`\n // once the thenable resolves, and only `use()` itself puts the mount hook\n // dispatcher back — so a replay that took the synchronous path would run\n // every later hook under the update dispatcher and throw \"Update hook called\n // on initial render\" at the first `useState`.\n //\n // Strings that were already in hand when their thenable was made skip it\n // (#542): no render ever suspended on that thenable, and under `act` even a\n // fulfilled `use()` makes a later thrown suspense (a `useQuery`) park forever.\n const thenable = dictionary.loadForRender(locale);\n const strings = thenable.inHand ?? use(thenable);\n\n // Reported from the render phase, and deliberately so: on the server the\n // strings have to reach the document before the segment that used them is\n // revealed, or hydration would find them missing and refetch. The sink\n // de-duplicates, and it is null in the browser.\n sink?.use(dictionary.id, locale, strings);\n\n // Annotated `string` rather than inferred: `parseTranslation` returns `any`\n // (it hands back a JSX element on the `t.jsx` path), and letting that leak\n // through would silently defeat the key and param checking below — every\n // call site would typecheck against `any`.\n function parse<K extends keyof T & string, U extends T[K] = T[K]>(\n key: K,\n ...args: ParamsOrNever<Parser<U extends Record<string, string> ? U : never>>\n ): string {\n const template = strings[key];\n if (typeof template !== \"string\") {\n console.error(\n `Unresolved translation key:${key} locale:${locale} dictionary:${dictionary.id}`,\n );\n return key;\n }\n const [params = {}] = args;\n return parseTranslation(template, params as any) as string;\n }\n\n parse.jsx = <K extends keyof T & string, U extends T[K] = T[K]>(\n key: K,\n ...args: ParamsOrNever<Parser<U extends Record<string, string> ? U : never>>\n ) => {\n return parse(key, ...(args as any)) as unknown as JSX.Element;\n };\n\n /**\n * Formatting in this dictionary's locale and the app's time zone. See\n * `useFormatter`.\n */\n parse.format = format;\n\n return parse;\n}\n","/**\n * The one implementation of \"what is a dictionary literal, and what is its id\",\n * shared by the runtime (`defineDictionary`) and the Vite plugin.\n *\n * Both sides must agree exactly. A dictionary's id is a hash of its own\n * contents rather than of its file path, so a module that is bundled on one\n * side and evaluated raw on the other still lands on the same id — which is\n * what lets the SSR payload seed the client registry.\n */\n\nexport type DictionaryTranslations = Record<string, Record<string, string>>;\n\nexport type LocaleStrings = Record<string, string>;\n\n/**\n * Locales the dictionary declares, source language first.\n *\n * The order is meaningful: the first locale is the source language, and a key\n * missing from some other locale falls back along this list.\n *\n * `sourceLocale` pins that choice. Without it the source language is whichever\n * locale is seen first while walking the literal, which makes it an emergent\n * property of key order — adding a key at the top of a dictionary whose other\n * keys happen to lack `en-US` would silently re-point every fallback in it. Any\n * dictionary that is not uniformly translated should say which locale it is\n * authored in.\n */\nexport function dictionaryLocales(\n translations: DictionaryTranslations,\n sourceLocale?: string,\n): string[] {\n const locales: string[] = [];\n const seen = new Set<string>();\n if (sourceLocale) {\n seen.add(sourceLocale);\n locales.push(sourceLocale);\n }\n for (const byLocale of Object.values(translations)) {\n for (const locale of Object.keys(byLocale)) {\n if (!seen.has(locale)) {\n seen.add(locale);\n locales.push(locale);\n }\n }\n }\n return locales;\n}\n\n/**\n * Flatten one locale out of a dictionary.\n *\n * A key with no string for `locale` falls back along the declared locale order\n * rather than vanishing, so a half-translated dictionary degrades one string at\n * a time instead of rendering the whole component as raw keys.\n */\nexport function localeStrings(\n translations: DictionaryTranslations,\n locale: string,\n fallbackOrder: string[] = dictionaryLocales(translations),\n): LocaleStrings {\n const out: LocaleStrings = {};\n for (const [key, byLocale] of Object.entries(translations)) {\n let value = byLocale?.[locale];\n if (typeof value !== \"string\") {\n for (const candidate of fallbackOrder) {\n const fallback = byLocale?.[candidate];\n if (typeof fallback === \"string\") {\n value = fallback;\n break;\n }\n }\n }\n if (typeof value === \"string\") {\n out[key] = value;\n }\n }\n return out;\n}\n\nexport interface SourceDisagreement {\n key: string;\n first: string;\n againstKey: string;\n againstFirst: string;\n}\n\n/**\n * Whether the inferred source language survives reordering the literal.\n *\n * `dictionaryLocales` collects locales entry by entry, so `locales[0]` is the\n * first locale of the first entry. That is invariant under key reordering\n * exactly when every entry lists the same locale first — and order-dependent\n * the moment two entries disagree, because then whichever happens to be written\n * first decides what the *whole* dictionary falls back to. Adding one key at\n * the top can flip every other key's fallback language, from a diff that reads\n * as an addition.\n *\n * Returns the disagreement so the build can name both keys; `null` when the\n * inference is stable. `sourceLocale` settles it and makes the question moot.\n */\nexport function findSourceDisagreement(\n translations: DictionaryTranslations,\n): SourceDisagreement | null {\n let againstKey: string | undefined;\n let againstFirst: string | undefined;\n\n for (const [key, byLocale] of Object.entries(translations)) {\n const first = Object.keys(byLocale ?? {})[0];\n // A key with no locales at all is a different problem, reported elsewhere.\n if (first === undefined) continue;\n\n if (againstFirst === undefined) {\n againstFirst = first;\n againstKey = key;\n continue;\n }\n if (first !== againstFirst) {\n return { key, first, againstKey: againstKey!, againstFirst };\n }\n }\n return null;\n}\n\n/**\n * Canonical serialization — key order in the source file must not change the\n * id, or an innocuous reordering would break the payload/registry match.\n */\nexport function canonicalizeDictionary(\n translations: DictionaryTranslations,\n): string {\n const keys = Object.keys(translations).sort();\n const parts = keys.map((key) => {\n const byLocale = translations[key] ?? {};\n const locales = Object.keys(byLocale).sort();\n const inner = locales.map((l) => JSON.stringify([l, byLocale[l]])).join(\",\");\n return `${JSON.stringify(key)}:[${inner}]`;\n });\n return `{${parts.join(\",\")}}`;\n}\n\n/**\n * FNV-1a, run twice with different offsets for a 64-bit-wide id. No crypto\n * import, and it has to work identically in the browser bundle, under Bun on\n * the server, and inside the Vite plugin.\n */\nexport function dictionaryId(translations: DictionaryTranslations): string {\n const input = canonicalizeDictionary(translations);\n let a = 0x811c9dc5;\n let b = 0x01000193;\n for (let i = 0; i < input.length; i++) {\n const c = input.charCodeAt(i);\n a = Math.imul(a ^ c, 0x01000193);\n b = Math.imul(b ^ c, 0x811c9dc5);\n }\n const hex = (n: number) => (n >>> 0).toString(16).padStart(8, \"0\");\n return `d_${hex(a)}${hex(b)}`;\n}\n","import {\n dictionaryId,\n dictionaryLocales,\n localeStrings,\n type DictionaryTranslations,\n type LocaleStrings,\n} from \"./dictionaryShape\";\nimport {\n loadDictionary,\n loadDictionaryForRender,\n registerDictionary,\n type RenderThenable,\n} from \"./dictionaryRegistry\";\n\ndeclare const brand: unique symbol;\n\nexport interface DictionaryHandle<\n T extends DictionaryTranslations = DictionaryTranslations,\n> {\n readonly id: string;\n /** Locales this dictionary declares, source language first. */\n readonly locales: readonly string[];\n /**\n * Strings for `locale`. Synchronous when they are already in memory —\n * always, for an unbundled dictionary; after a preload or the SSR seed, for a\n * bundled one.\n */\n load(locale: string): LocaleStrings | Promise<LocaleStrings>;\n /**\n * `load`, but as the exact thing React's `use()` wants: never rejecting, so\n * a failed locale chunk degrades the component to rendering keys instead of\n * unmounting it into an error boundary; and always a thenable, even when the\n * strings are already in memory. The caller skips `use()` only for a\n * thenable built from strings already in hand, which carries them as\n * `inHand`; every thenable a render could have suspended on still goes\n * through it. `loadDictionaryForRender` has the whole reasoning.\n */\n loadForRender(locale: string): RenderThenable;\n get(locale: string): LocaleStrings | undefined;\n /** Type-only: carries the literal's shape through to `useDictionary`. */\n readonly [brand]?: T;\n}\n\n/**\n * Declare the strings a component needs, next to the component.\n *\n * ```ts\n * export const homeDict = defineDictionary({\n * title: { \"en-US\": \"Welcome {{name}}\", \"tr-TR\": \"Hoş geldin {{name}}\" },\n * });\n * ```\n *\n * As written this holds every locale. Under gemi's Vite plugin the call is\n * rewritten so each locale becomes its own chunk and a page downloads only the\n * one it renders in — but the plugin is strictly an optimization, and the\n * behaviour is identical without it (in `bun test`, and in server code that\n * does not go through the bundler).\n *\n * The first locale in the literal is the source language: a key missing from\n * another locale falls back to it rather than rendering as its own key.\n */\nexport interface DefineDictionaryOptions {\n /**\n * The locale this dictionary is authored in. Keys missing from another locale\n * fall back to it, and it is what renders when the app has no locale\n * configured.\n *\n * Optional, but worth setting on any dictionary that is not uniformly\n * translated: without it the source language is whichever locale appears\n * first in the literal, so adding a key at the top can re-point every\n * fallback in the dictionary.\n */\n sourceLocale?: string;\n}\n\nexport function defineDictionary<const T extends DictionaryTranslations>(\n translations: T,\n options: DefineDictionaryOptions = {},\n): DictionaryHandle<T> {\n const locales = dictionaryLocales(translations, options.sourceLocale);\n return createHandle(dictionaryId(translations), locales, (locale) =>\n localeStrings(translations, locale, locales),\n );\n}\n\n/**\n * The rewritten form of a `defineDictionary` call — emitted by\n * `packages/gemi/vite/dictionaryPlugin.ts`, never written by hand. `loaders`\n * holds one dynamic import per locale so the bundler emits one chunk per\n * locale and the untaken ones never reach the browser.\n */\nexport function __gemi_dict__<\n const T extends DictionaryTranslations = DictionaryTranslations,\n>(\n id: string,\n loaders: Record<string, () => Promise<{ default: LocaleStrings }>>,\n): DictionaryHandle<T> {\n const locales = Object.keys(loaders);\n return createHandle(id, locales, (locale) => {\n // An unknown locale falls back to the source language, matching what\n // `localeStrings` does per key on the unbundled path.\n const load = loaders[locale] ?? loaders[locales[0]];\n if (!load) {\n return {};\n }\n return load().then((mod) => mod.default);\n });\n}\n\nfunction createHandle<T extends DictionaryTranslations>(\n id: string,\n locales: string[],\n load: (locale: string) => LocaleStrings | Promise<LocaleStrings>,\n): DictionaryHandle<T> {\n const entry = { id, locales, load };\n registerDictionary(entry);\n\n // Re-asserted on every read rather than only at construction. A handle is\n // created once, at module scope, but the registry it delegates to can be\n // emptied under it — a test's `afterEach` reset, an HMR boundary — and the\n // handle would then be permanently orphaned, throwing \"Unknown dictionary\"\n // for a dictionary the caller is holding. `registerDictionary` is a no-op\n // when the id is already there, so this costs one Map lookup.\n const ensure = () => registerDictionary(entry);\n\n return {\n id,\n locales,\n // Routed through the registry rather than calling `load` directly so\n // concurrent readers share one in-flight import and results are cached.\n load: (locale: string) => {\n ensure();\n return loadDictionary(id, locale);\n },\n loadForRender: (locale: string) => {\n ensure();\n return loadDictionaryForRender(id, locale);\n },\n get: (locale: string) => {\n ensure();\n const strings = loadDictionary(id, locale);\n if (strings instanceof Promise) {\n // Nothing downstream awaits this one — `get` is the synchronous peek,\n // and the caller is about to discard it. An unattached rejection (a\n // locale chunk that 404s mid-deploy) would surface as an\n // `unhandledRejection`, which under Node's default handler takes the\n // process down over one missing translation file. The load itself is\n // still cached and still retried through `loadDictionary`.\n strings.catch(() => {});\n return undefined;\n }\n return strings;\n },\n };\n}\n\n","import { useLocation } from \"./useLocation\";\nimport { useNavigate } from \"./useNavigate\";\nimport { useParams } from \"./useParams\";\nimport { useRouteData } from \"./useRouteData\";\n\nconst LOCALE_COOKIE = \"i18n-locale\";\nconst LOCALE_COOKIE_MAX_AGE = 60 * 60 * 24 * 365;\n\n/**\n * The active locale lives in two places: the URL segment `setLocale` navigates\n * to, and the `i18n-locale` cookie the server falls back to when the URL has no\n * segment — which is exactly the case for the default locale. Both have to be in\n * place *before* the navigation asks for route data, or `Translator.detectLocale`\n * answers the request with a redirect back to the locale the cookie still names.\n *\n * Hence a synchronous `document.cookie` write rather than an awaited one. The\n * previous implementation awaited `cookieStore.set()` and hung the navigation off\n * its `.then()`; that promise is reported to never settle on iOS Safari, so the\n * `.then()` never ran and changing the language became a silent no-op — no\n * rejection, nothing for an error reporter to pick up. A synchronous write cannot\n * hang and cannot fail asynchronously, so nothing is left to gate navigation on.\n */\nfunction persistLocale(locale: string) {\n if (typeof document === \"undefined\") {\n return;\n }\n try {\n document.cookie = [\n // Encoded, not interpolated: `cookieStore.set()` rejected malformed\n // values, a raw string write does not. A locale carrying `;` would\n // otherwise write cookie *attributes* — `Domain`, `Path` — from whatever\n // the app happens to feed the switcher.\n `${LOCALE_COOKIE}=${encodeURIComponent(locale)}`,\n `Max-Age=${LOCALE_COOKIE_MAX_AGE}`,\n \"SameSite=Strict\",\n \"Path=/\",\n ].join(\"; \");\n } catch {\n // A sandboxed iframe with no storage access throws here. The navigation\n // still carries the locale in its URL, so it is better to switch without\n // remembering the choice than to not switch at all.\n }\n}\n\n/**\n * `onLocaleChange` is a server-side hook, so it takes a request to fire it. The\n * switch must not wait on that round trip, nor be cancelled by one that fails —\n * including one that fails *synchronously*: `fetch` is absent in some old\n * WebViews, and an unguarded call would throw before the navigation ran, which\n * is the same silent no-op this hook exists to prevent through another door.\n */\nfunction notifyLocaleChange(locale: string) {\n try {\n void fetch(\n `/api/__gemi__/services/i18n/set-locale/${encodeURIComponent(locale)}`,\n ).catch(() => {});\n } catch {\n // `fetch` itself is unavailable. The locale is already persisted and the\n // navigation still runs; only the server-side hook misses this switch.\n }\n}\n\nexport function useLocale() {\n const { i18n } = useRouteData();\n const { pathname, search } = useLocation();\n const { replace } = useNavigate();\n const params = useParams();\n\n const setLocale = async (locale: string) => {\n persistLocale(locale);\n notifyLocaleChange(locale);\n\n const urlSearchParams = new URLSearchParams(search);\n await replace(pathname, {\n locale,\n // TODO: fix: this conversion is wrong, because there can be multiple\n // search params with the same name\n search: Object.fromEntries(urlSearchParams.entries()),\n params,\n } as any);\n };\n\n return [i18n.currentLocale, setLocale] as const;\n}\n","import { createElement, Fragment, type ReactNode } from \"react\";\nimport type { SatoriOptions } from \"satori\";\n\ntype Font = Omit<SatoriOptions[\"fonts\"][number], \"data\">;\ntype Options = Omit<SatoriOptions, \"fonts\"> & {\n fonts: Font[];\n} & { width: number; height: number };\n\nexport const OpenGraphImage = ({\n children,\n ...satoriOptions\n}: Options & { children: ReactNode }) => {\n return (\n <>\n {(() => {\n throw {\n jsx: createElement(Fragment, { children }),\n satoriOptions,\n };\n })()}\n </>\n );\n};\n","import { useContext } from \"react\";\nimport { ServerDataContext } from \"./ServerDataProvider\";\nimport { RouteStateContext } from \"./RouteStateContext\";\n\nexport function useAppIdMissmatch() {\n const { appId: next } = useContext(RouteStateContext);\n const { appId: current } = useContext(ServerDataContext);\n\n return current !== next;\n}\n","import {\n type ComponentType,\n type Context,\n type ReactElement,\n type ReactNode,\n Fragment,\n createContext,\n createElement,\n lazy,\n use,\n useContext,\n} from \"react\";\n\n/**\n * When an island's code is fetched and hydrated, per marker.\n *\n * - `\"eager\"` (default): as soon as the page has parsed. The island's chunks\n * and React are `modulepreload`ed from the head, so they are usually in\n * cache by then.\n * - `\"idle\"`: on `requestIdleCallback` (a timeout where unsupported).\n * - `\"visible\"`: when the island's content first scrolls into view. Suits a\n * heavy island far down the page, like a canvas or a map.\n */\nexport type IslandLoad = \"eager\" | \"idle\" | \"visible\";\n\nexport interface IslandOptions {\n /** When the island hydrates on a static page. Defaults to `\"eager\"`. */\n load?: IslandLoad;\n /** Which export of the module is the component. Defaults to `\"default\"`. */\n export?: string;\n}\n\n/**\n * `() => import(\"./Counter\")`, the argument `island()` takes. gemi's Vite\n * plugin adds the module's build key and the module itself, so the server can\n * render it synchronously in a hydrated view and point a static page at its\n * built chunk.\n */\nexport type IslandLoader<M = any> = (() => Promise<M>) & {\n /** @internal The module's path from the project root, the client manifest's key. */\n gemiIsland?: string;\n /** @internal The module, statically imported by the plugin. */\n gemiModule?: M;\n};\n\n/** @internal One island module a static page uses: an entry of the page's island table. */\nexport interface IslandEntry {\n /** The module's build key, or `undefined` when the plugin did not run. */\n module: string | undefined;\n export: string;\n load: IslandLoad;\n}\n\ninterface IslandInstance {\n html: Promise<string>;\n index: number;\n uid: string;\n props: string | undefined;\n}\n\n/**\n * @internal Provided by the view router around a static view's render; `null`\n * everywhere else, which is how `island()` knows to render a plain component.\n */\nexport interface StaticRenderCollector {\n /** The page's island table: what the loader imports, by marker index. */\n islands: IslandEntry[];\n /**\n * Renders one island as its own React root, settled, to HTML. Supplied by\n * the server, so this module never imports `react-dom/server`.\n */\n render: (element: ReactElement, identifierPrefix: string) => Promise<string>;\n /** Per-instance render state, keyed by the island's props object. */\n instances: WeakMap<object, IslandInstance>;\n /** Instances rendered so far, for each one's `identifierPrefix`. */\n count: number;\n}\n\n/** @internal */\nexport function createStaticRenderCollector(\n render: StaticRenderCollector[\"render\"],\n): StaticRenderCollector {\n return { islands: [], render, instances: new WeakMap(), count: 0 };\n}\n\n/** @internal The element an island's static children land in. */\nexport const ISLAND_SLOT_TAG = \"gemi-slot\";\n/** @internal On the empty slot an island's own render leaves for its children. */\nexport const ISLAND_SLOT_ATTRIBUTE = \"data-slot\";\n/** @internal On the template holding the children the page tree rendered. */\nexport const ISLAND_SLOT_TEMPLATE_ATTRIBUTE = \"data-gemi-slot\";\n\n/** The property gemi's Vite plugin attaches to an island's loader. */\nexport const ISLAND_MODULE_KEY = \"gemiIsland\";\n\nconst CONTEXT_KEY = Symbol.for(\"gemi.staticRender\");\n\n/**\n * @internal On `globalThis` rather than a module-level `createContext`: the\n * published package bundles `gemi/client` and the server side separately, so a\n * plain module singleton would give the provider and the islands two different\n * context objects.\n */\nexport const StaticRenderContext: Context<StaticRenderCollector | null> = ((\n globalThis as Record<symbol, unknown>\n)[CONTEXT_KEY] ??= createContext<StaticRenderCollector | null>(null)) as Context<\n StaticRenderCollector | null\n>;\n\nconst isProduction = () =>\n typeof process !== \"undefined\" && process.env?.NODE_ENV === \"production\";\n\n/**\n * Throws when `value` would not survive `JSON.stringify` and `JSON.parse`\n * unchanged, naming the prop. An island's props cross from the server to the\n * browser as JSON: a function would vanish and a `Date` would arrive as a\n * string, so the island would hydrate with other props than it rendered with.\n */\nexport function assertSerialisableProps(value: unknown, island: string): void {\n const seen = new Set<object>();\n const fail = (path: string, what: string): never => {\n throw new Error(\n `${island}: the prop \\`${path}\\` is ${what}. An island's props are sent to the browser ` +\n `as JSON, so they must be plain data: strings, finite numbers, booleans, null, ` +\n `arrays and plain objects. Pass static markup as children instead.`,\n );\n };\n const walk = (v: unknown, path: string, inArray: boolean): void => {\n switch (typeof v) {\n case \"string\":\n case \"boolean\":\n return;\n case \"number\":\n if (!Number.isFinite(v)) fail(path, String(v));\n return;\n case \"undefined\":\n // Dropped from an object, which reads back the same; not in an array.\n if (inArray) fail(path, \"undefined (it would arrive as null)\");\n return;\n case \"function\":\n fail(path, \"a function\");\n return;\n case \"symbol\":\n case \"bigint\":\n fail(path, `a ${typeof v}`);\n return;\n }\n if (v === null) return;\n const object = v as Record<string, unknown>;\n if (seen.has(object)) fail(path, \"a circular reference\");\n if (\"$$typeof\" in object) fail(path, \"a React element\");\n seen.add(object);\n if (Array.isArray(object)) {\n object.forEach((item, i) => walk(item, `${path}[${i}]`, true));\n } else {\n const proto = Object.getPrototypeOf(object);\n if (proto !== Object.prototype && proto !== null) {\n fail(path, `an instance of ${proto?.constructor?.name || \"a class\"}`);\n }\n for (const [key, item] of Object.entries(object)) {\n walk(item, path ? `${path}.${key}` : key, false);\n }\n }\n seen.delete(object);\n };\n walk(value, \"\", false);\n}\n\nconst hasChildren = (children: unknown) =>\n children !== undefined && children !== null && typeof children !== \"boolean\";\n\ntype AnyComponent = ComponentType<any>;\n\n/**\n * Makes a component an island: hydrated on its own on a static page, an\n * ordinary component everywhere else.\n *\n * ```tsx\n * // app/views/site/Counter.tsx: a plain React component\n * export default function Counter({ start }: { start: number }) {\n * const [n, setN] = useState(start);\n * return <button onClick={() => setN(n + 1)}>{n}</button>;\n * }\n *\n * // where it is used\n * const Counter = island(() => import(\"./Counter\"), { load: \"visible\" });\n * <Counter start={3} />\n * ```\n *\n * - In a **static** view (`this.view(...).static()`), it server-renders the\n * component as its own React root inside a `<gemi-island>` marker and\n * serialises its props. The page gets a tiny loader that, on the island's\n * `load` trigger, imports React (one chunk shared by every island) and the\n * component's chunk and calls `hydrateRoot` on the marker.\n * - In a **hydrated** view, it is the component itself: rendered inline, with\n * the page's context, and nothing extra to load.\n *\n * Write the loader exactly as `() => import(\"./path\")` inside the `island(`\n * call: gemi's Vite plugin finds that call, builds the module as its own\n * client entry and imports it statically for the server.\n *\n * Props must be plain data (checked in dev). `children` are rendered on the\n * server as static HTML and passed through untouched. On a static page the\n * island is a separate React root, so context from the page does not reach it.\n */\nexport function island<M extends { default: AnyComponent }>(\n loader: () => Promise<M>,\n options?: IslandOptions & { export?: \"default\" },\n): M[\"default\"];\nexport function island<M, K extends keyof M & string>(\n loader: () => Promise<M>,\n options: IslandOptions & { export: K },\n): M[K];\nexport function island(loader: IslandLoader, options: IslandOptions = {}): AnyComponent {\n if (typeof loader !== \"function\") {\n throw new Error(\n 'island() takes `() => import(\"./Component\")` and options since gemi 0.110. ' +\n 'The island(\"name\", Component, () => import(\"./x.island\")) form was removed: see UPGRADE.md.',\n );\n }\n const exportName = options.export ?? \"default\";\n const load: IslandLoad = options.load ?? \"eager\";\n const key = loader[ISLAND_MODULE_KEY];\n const label = `island(${key ?? \"() => import(…)\"}${exportName === \"default\" ? \"\" : `#${exportName}`})`;\n\n const pick = (mod: Record<string, unknown>): AnyComponent => {\n const component = mod?.[exportName];\n if (typeof component !== \"function\" && (typeof component !== \"object\" || component === null)) {\n throw new Error(`${label}: the module has no component export \\`${exportName}\\`.`);\n }\n return component as AnyComponent;\n };\n\n // A hydrated view renders the component in place. The plugin imported the\n // module statically; without it (a test that doesn't run the plugin) the\n // component loads lazily and suspends once.\n let inline: AnyComponent | undefined;\n const inlineComponent = (): AnyComponent =>\n (inline ??= loader.gemiModule\n ? pick(loader.gemiModule)\n : lazy(() => loader().then((mod) => ({ default: pick(mod) }))));\n\n const register = (collector: StaticRenderCollector): number => {\n const known = collector.islands.findIndex(\n (entry) =>\n key !== undefined && entry.module === key && entry.export === exportName && entry.load === load,\n );\n return known !== -1 ? known : collector.islands.push({ module: key, export: exportName, load }) - 1;\n };\n\n const start = (collector: StaticRenderCollector, props: Record<string, unknown>): IslandInstance => {\n const { children, ...rest } = props;\n if (!isProduction()) {\n assertSerialisableProps(rest, label);\n }\n const uid = `i${collector.count++}-`;\n const component = loader.gemiModule\n ? Promise.resolve(pick(loader.gemiModule))\n : loader().then(pick);\n // The island's own render is a root of its own, as it will be in the\n // browser: islands nested in it are plain components of that root. Its\n // children are not rendered here: they belong to the page (and its\n // context), so the page tree renders them next to the marker and\n // `spliceIslandSlots` moves their HTML into this empty slot.\n const html = component.then((Component) =>\n collector.render(\n createElement(\n StaticRenderContext.Provider,\n { value: null },\n hasChildren(children)\n ? createElement(\n Component,\n rest,\n createElement(ISLAND_SLOT_TAG, { [ISLAND_SLOT_ATTRIBUTE]: uid, style: { display: \"contents\" } }),\n )\n : createElement(Component, rest),\n ),\n uid,\n ),\n );\n // A rejection surfaces through `use`; this keeps it from also being\n // reported as unhandled.\n html.catch(() => {});\n const json = JSON.stringify(rest);\n return { html, index: register(collector), uid, props: json === \"{}\" ? undefined : json };\n };\n\n function Island(props: Record<string, unknown>): ReactNode {\n const collector = useContext(StaticRenderContext);\n if (!collector) {\n return createElement(inlineComponent(), props);\n }\n\n // Suspending on `use` re-renders this component with the same props\n // object, so the render it started is found again rather than restarted.\n let instance = collector.instances.get(props);\n if (!instance) {\n instance = start(collector, props);\n collector.instances.set(props, instance);\n }\n\n const marker = createElement(\"gemi-island\", {\n \"data-island\": instance.index,\n \"data-uid\": instance.uid,\n // React escapes attribute values, so the JSON needs (and must get) no\n // escaping of its own.\n \"data-props\": instance.props,\n style: { display: \"contents\" },\n dangerouslySetInnerHTML: { __html: use(instance.html) },\n });\n if (!hasChildren(props.children)) {\n return marker;\n }\n // The children, rendered here in the page tree with the page's context\n // (islands among them are islands of their own), in a template the\n // static document splices into the island's slot before it is sent.\n return createElement(\n Fragment,\n null,\n marker,\n createElement(\"template\", { [ISLAND_SLOT_TEMPLATE_ATTRIBUTE]: instance.uid }, props.children as ReactNode),\n );\n }\n\n Island.displayName = label;\n return Island;\n}\n","/** What `onStaticNavigate` and the `gemi:page-load` event report. */\nexport interface StaticPageLoad {\n /** The page's URL, `#hash` included. */\n url: string;\n /** Its `document.title`. */\n title: string;\n /** `true` for the page the browser loaded, `false` after a client navigation. */\n initial: boolean;\n}\n\n/** The state the navigation runtime keeps on `window` (see `internal/staticNavigation`). */\ntype RuntimeState = { p?: StaticPageLoad } | undefined;\n\n/**\n * Calls `callback` for every page a static view's navigation runtime shows\n * (`.static({ navigation })`): right away for the current page, then after\n * every client-side navigation. Returns a function that stops it.\n *\n * Meant for analytics and the like from an island:\n *\n * ```tsx\n * useEffect(() => onStaticNavigate(({ url }) => track(url)), []);\n * ```\n *\n * Without the runtime (a hydrated page, a static page without `navigation`,\n * the server), it does nothing. The same notice is the `gemi:page-load` event\n * on `document`, for code that is not an island.\n */\nexport function onStaticNavigate(callback: (page: StaticPageLoad) => void): () => void {\n if (typeof document === \"undefined\") return () => {};\n const listener = (event: Event) => callback((event as CustomEvent<StaticPageLoad>).detail);\n document.addEventListener(\"gemi:page-load\", listener);\n const current = (window as unknown as { __gemi_nav?: RuntimeState }).__gemi_nav?.p;\n if (current) callback(current);\n return () => document.removeEventListener(\"gemi:page-load\", listener);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../client/ServerQueryContext.tsx","../../client/useRouteData.ts","../../client/isPlainObject.ts","../../client/useQuery.ts","../../client/useInfiniteQuery.ts","../../services/broadcast/socketHeader.ts","../../client/mutationModules.ts","../../client/useMutation.ts","../../client/useMutate.ts","../../client/fetchFile.ts","../../client/useSetQueryData.ts","../../client/useSubscription.ts","../../client/useChannel.ts","../../client/Mutation.tsx","../../client/useDomain.ts","../../client/useIsNavigationPending.ts","../../client/useNavigationProgress.ts","../../client/usePrefetch.ts","../../client/useBreadcrumbs.ts","../../client/Link.tsx","../../client/Redirect.tsx","../../client/htmlAttributes.ts","../../client/fonts.ts","../../client/Head.tsx","../../utils/partialRender.ts","../../client/helpers/mergeCarriedSegments.ts","../../client/helpers/loadRoutePayload.ts","../../utils/intendedUrl.ts","../../client/ClientRouter.tsx","../../client/init.tsx","../../client/DictionarySinkContext.ts","../../client/createRoot.tsx","../../client/Image.tsx","../../client/auth/useForgotPassword.ts","../../client/auth/useSignIn.tsx","../../client/auth/useSignUp.ts","../../client/auth/useSignOut.ts","../../client/auth/useResetPassword.ts","../../client/auth/useUser.ts","../../client/auth/useIntendedUrl.ts","../../client/auth/useEmailCode.ts","../../client/useFeature.ts","../../utils/parseTranslation.tsx","../../client/useTranslator.ts","../../i18n/formatter.ts","../../client/useFormatter.ts","../../client/useDictionary.ts","../../i18n/dictionaryShape.ts","../../i18n/defineDictionary.ts","../../client/useLocale.ts","../../client/OpenGraphImage.tsx","../../client/useAppIdMissmatch.ts","../../client/islands.tsx","../../client/staticNavigation.ts"],"sourcesContent":["import { createContext } from \"react\";\n\n/**\n * The structural slice of the server's `ServerQueryStore` that `useQuery`\n * needs during a streaming server render. Declared here — not imported from\n * `services/router` — because this file ships in the browser bundle; only the\n * shape crosses over, never the implementation.\n */\nexport interface ServerQueryEntryLike {\n status: \"pending\" | \"resolved\" | \"rejected\";\n data?: any;\n error?: any;\n promise: Promise<void>;\n}\n\nexport interface ServerQueriesLike {\n ensure(\n path: string,\n options?: {\n params?: Record<string, any>;\n search?: Record<string, string | number | boolean | null>;\n },\n source?: \"prefetch\" | \"render\",\n ): ServerQueryEntryLike;\n}\n\n/**\n * Populated only during a streaming server render (`createRoot` threads the\n * request's store through); always `null` in the browser, where suspension\n * runs on `QueryResource` instead.\n */\nexport const ServerQueryContext = createContext<ServerQueriesLike | null>(null);\n","import { useContext } from \"react\";\nimport { RouteStateContext } from \"./RouteStateContext\";\n\nexport function useRouteData() {\n const { data, i18n, prefetchedData, breadcrumbs } =\n useContext(RouteStateContext);\n\n return { data, i18n, prefetchedData, breadcrumbs };\n}\n","export function isPlainObject(\n value: unknown,\n): value is Record<string, unknown> {\n return (\n value !== null &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n Object.getPrototypeOf(value) === Object.prototype\n );\n}\n","import {\n useCallback,\n useContext,\n useDeferredValue,\n useEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport type { RPC } from \"./rpc\";\nimport type { NestedPrettify } from \"../utils/type\";\n\nimport type { ApiRouterHandler } from \"../http/ApiRouter\";\nimport type { UnwrapPromise } from \"../utils/type\";\nimport { QueryConfigContext, QueryManagerContext } from \"./QueryManagerContext\";\nimport { ServerQueryContext } from \"./ServerQueryContext\";\nimport { DEFAULT_STALE_TIME } from \"./QueryResource\";\nimport { applyParams } from \"../utils/applyParams\";\nimport type { UrlParser } from \"./types\";\nimport { toVariantKey } from \"../utils/variantKey\";\nimport { useParams } from \"./useParams\";\nimport { useRouteData } from \"./useRouteData\";\nimport { isPlainObject } from \"./isPlainObject\";\nimport {\n DEFAULT_RETRY,\n retryDelayFor,\n shouldRetryQuery,\n type QueryFailure,\n type RetryDelayOption,\n type RetryOption,\n} from \"./retryPolicy\";\nimport type { LiveChannel } from \"./realtime/live\";\nimport { followLive } from \"./realtime/loader\";\nimport { RealtimeContext } from \"./realtime/RealtimeContext\";\n\n/**\n * A DOM event or React's synthetic one. Never a plain object, so a cached\n * value that happens to have a `nativeEvent` key is not mistaken for one.\n */\nfunction isEventLike(value: unknown): boolean {\n if (typeof value !== \"object\" || value === null || isPlainObject(value)) {\n return false;\n }\n if (typeof Event !== \"undefined\" && value instanceof Event) return true;\n return (\n \"nativeEvent\" in value &&\n typeof (value as { preventDefault?: unknown }).preventDefault === \"function\"\n );\n}\n\nexport interface Config<T> {\n fallbackData?: T;\n /**\n * When true (the default), a variant change keeps rendering the previous\n * variant's data while the new one loads. Under suspense this reads through\n * a deferred variant key, so changing `search`/`params` never flashes the\n * segment fallback and needs no `startTransition` at the call site — the\n * pending window is exposed as `loading: true`. Set to `false` to get the\n * suspend-on-variant-change semantics back (e.g. tab-like switches where\n * stale rows would mislead). First mount always suspends either way.\n */\n keepPreviousData?: boolean;\n /**\n * Background retries for a failed `suspense: false` query (under suspense\n * the error goes to the error boundary instead). Default `3`: network\n * failures, 408, 429 and 5xx are retried up to three times in a row with\n * exponential backoff; any other 4xx (401, 403, 404, 422, …) is returned\n * once and never retried, because sending the same request again gets the\n * same answer. `false` turns retries off, `true` removes the cap, and a\n * function `(failureCount, error) => boolean` decides alone.\n */\n retry?: RetryOption;\n /**\n * The wait before each retry, in ms, or `(failureCount, error) => ms`.\n * Default: `1000 * 2^(failureCount - 1)` capped at 30s — 1s, 2s, 4s. A\n * `Retry-After` header on the failed response (a 429 or 503) wins.\n */\n retryDelay?: RetryDelayOption;\n /**\n * @deprecated Use `retryDelay`. Kept as the base of the default backoff:\n * the first retry waits this long, each next one twice as long.\n */\n retryIntervalOnError?: number;\n refreshInterval?: number;\n /**\n * When true, the query revalidates whenever the tab comes back to the\n * foreground. Off by default. `staleTime` still gates it, so a quick\n * tab-out-and-back costs nothing and only data that has actually aged goes\n * back to the wire — silently, keeping what's on screen rendered.\n */\n revalidateOnFocus?: boolean;\n /**\n * Minimum gap between two `revalidateOnFocus` revalidations of the same\n * query, in ms (default 5000). `focus` fires on far more than tab returns —\n * dismissing a file picker, closing a popup, clicking in and out of an\n * embedded iframe — and `staleTime: 0` would otherwise turn each of those\n * into a request per mounted query.\n */\n focusThrottleInterval?: number;\n /** How long cached data stays fresh before a read revalidates it, in ms. */\n staleTime?: number;\n debug?: boolean;\n lazy?: boolean;\n /**\n * When true (the default), a query with no cached data suspends the nearest\n * `Suspense` boundary instead of returning `loading: true`, and an HTTP\n * failure throws into the nearest error boundary. `lazy: true` implies\n * `suspense: false`.\n */\n suspense?: boolean;\n /**\n * Polls while it returns a delay in ms: after data lands, the query refetches\n * that long later; `0` stops. `duration` is the delay it returned last (`0`\n * at first), for backoff. It is read from the current render after every\n * commit, so it can depend on props and state too\n * (`(d) => (d.active || building ? 2000 : 0)`): a stopped poll restarts as\n * soon as it returns a delay again, and a pending one is cancelled when it\n * returns `0`. Keep it pure and cheap.\n */\n refetchUntil?: (data: T, duration: number) => number;\n /**\n * A broadcast channel that keeps this query fresh: its events and resyncs\n * refetch the query (every cached variant; the rendered ones now). While\n * the channel is open, `refetchUntil` and `refreshInterval` are paused;\n * while it is not (connecting, denied, offline, on the server), they run\n * as the fallback.\n *\n * ```ts\n * useQuery(\"/site-imports/:importId\", { params }, { refetchUntil: (d) => (d.active ? 2000 : 0), live: \"user\" });\n * ```\n */\n live?: LiveChannel;\n}\n\ntype WithOptionalValues<T> = {\n [K in keyof T]: T[K] | null;\n};\n\nconst defaultConfig: Config<any> = {\n fallbackData: null,\n keepPreviousData: true,\n retry: DEFAULT_RETRY,\n refreshInterval: 999999,\n revalidateOnFocus: false,\n focusThrottleInterval: 5000,\n staleTime: DEFAULT_STALE_TIME,\n debug: false,\n lazy: false,\n suspense: true,\n};\n\nexport type GetRPC = {\n [K in keyof RPC as K extends `GET:${infer P}` ? P : never]: RPC[K];\n};\n\nexport type Data<T extends keyof GetRPC> =\n GetRPC[T] extends ApiRouterHandler<any, infer Data, any>\n ? UnwrapPromise<Data>\n : never;\n\ntype Input<T extends keyof GetRPC> =\n GetRPC[T] extends ApiRouterHandler<infer I, any, any> ? I : never;\n\ntype QueryOptions<T extends keyof GetRPC> = {\n search?: Partial<WithOptionalValues<Input<T>>>;\n};\n\ntype Error = Record<string, unknown>;\n\nconst defaultOptions: QueryOptions<any> & { params?: Record<string, any> } = {\n params: {} as Record<string, string>,\n search: {} as Record<string, string>,\n};\n\nexport type QueryResult<T extends keyof GetRPC> = NestedPrettify<Data<T> & {}>;\n\nexport type Options<T extends keyof GetRPC> = {\n search?: Record<string, string | number | boolean | null>;\n params?: Partial<UrlParser<`${T & string}`>>;\n};\n\ninterface QueryReturn<T extends keyof GetRPC, D> {\n data: D;\n loading: boolean;\n error: Error;\n mutate: {\n (fn?: NestedPrettify<Data<T>>): void;\n (fn?: (data: NestedPrettify<Data<T>>) => NestedPrettify<Data<T>>): void;\n };\n trigger: () => void;\n prefetch: () => void;\n refetch: () => void;\n version: number;\n}\n\n/**\n * A suspense-enabled query never renders without data, so `data` is\n * non-nullable. Opting out — `suspense: false` or `lazy: true` — brings back\n * the `loading` flag and with it a `data` that can be `undefined`.\n */\ninterface SuspenseConfig<T> extends Omit<Config<T>, \"suspense\" | \"lazy\"> {\n suspense?: true;\n lazy?: false;\n}\n\n/** A per-call `suspense: true` opt-in — wins over an app-wide `suspense: false`. */\ninterface ExplicitSuspenseConfig<T> extends Omit<\n Config<T>,\n \"suspense\" | \"lazy\"\n> {\n suspense: true;\n lazy?: false;\n}\n\n/**\n * The type-level mirror of a provider-level `queryConfig: { suspense: false }`.\n * The `useQuery` overloads reflect the call site only — they cannot see the\n * value threaded through `createRoot` — so an app that turns suspense off\n * app-wide flips the default `data` nullability with the same\n * module-augmentation switch RPC types use:\n *\n * ```ts\n * declare module \"gemi/client\" {\n * interface GemiQueryDefaults {\n * suspense: false;\n * }\n * }\n * ```\n *\n * A per-call `suspense: true` still narrows `data` back to non-nullable.\n */\nexport interface GemiQueryDefaults {}\n\ntype DefaultData<T extends keyof GetRPC> = GemiQueryDefaults extends {\n suspense: false;\n}\n ? NestedPrettify<Data<T>> | undefined\n : NestedPrettify<Data<T>>;\n\nexport function useQuery<T extends keyof GetRPC>(\n url: T,\n options: Options<T> | undefined,\n config: ExplicitSuspenseConfig<Data<T>>,\n): QueryReturn<T, NestedPrettify<Data<T>>>;\nexport function useQuery<T extends keyof GetRPC>(\n url: T,\n options?: Options<T>,\n config?: SuspenseConfig<Data<T>>,\n): QueryReturn<T, DefaultData<T>>;\nexport function useQuery<T extends keyof GetRPC>(\n url: T,\n options?: Options<T>,\n config?: Config<Data<T>>,\n): QueryReturn<T, NestedPrettify<Data<T>> | undefined>;\nexport function useQuery<T extends keyof GetRPC>(\n url: T,\n ...args: [options?: Options<T>, config?: Config<Data<T>>]\n) {\n const [options, config] = args;\n // Resolution order: per-call config → provider `queryConfig` → framework\n // defaults. The first two merge here; `useFrameworkQuery` applies the last.\n // Only *defined* per-call keys participate: a key explicitly set to\n // `undefined` (`{ suspense: cond ? true : undefined }`, forwarding an\n // optional prop) must fall through to the provider default, not clobber it\n // — a plain spread would copy the `undefined` over it. The provider value\n // is already sanitized at the provider (see `QueryManagerProvider`).\n // `user` is `useUser`'s own section, not a query default.\n const { user: _user, ...queryConfig } = useContext(QueryConfigContext) ?? {};\n const merged: Config<Data<T>> = { ...queryConfig };\n if (config) {\n for (const key of Object.keys(config) as Array<keyof Config<Data<T>>>) {\n if (config[key] !== undefined) {\n (merged as Record<string, unknown>)[key] = config[key];\n }\n }\n }\n return useFrameworkQuery(url, options, merged);\n}\n\n/**\n * `useQuery` minus the app's provider-level `queryConfig`: per-call config\n * resolves straight against the framework defaults. Framework-internal hooks\n * (`useUser`'s `suspense: false`, `useSignIn`'s `lazy`) build on this so an\n * app-wide `queryConfig` can never change their semantics. Deliberately not\n * exported from the package root.\n */\nexport function useFrameworkQuery<T extends keyof GetRPC>(\n url: T,\n ...args: [options?: Options<T>, config?: Config<Data<T>>]\n): QueryReturn<T, NestedPrettify<Data<T>> | undefined> {\n const _params = useParams();\n const [_options = defaultOptions, _config = defaultConfig] = args;\n const options = { ...defaultOptions, ..._options };\n const config = { ...defaultConfig, ..._config };\n const suspense = config.suspense !== false && !config.lazy;\n const params =\n \"params\" in options ? { ..._params, ...options.params } : _params;\n const search = \"search\" in options ? (options.search ?? {}) : {};\n const { getResource } = useContext(QueryManagerContext);\n const serverQueries = useContext(ServerQueryContext);\n const currentPath = applyParams(url, params);\n const currentVariantKey = toVariantKey(search);\n // `keepPreviousData` under suspense: read through deferred keys so a\n // variant change never suspends the committed tree. The urgent render keeps\n // showing the previous variant's data; React re-renders in the background\n // with the new keys, suspends *that* attempt only (no fallback flash), and\n // commits when the data lands — no `startTransition` needed at the call\n // site. First mount is unchanged: deferred and current keys are equal, so\n // an uncached query suspends into the segment fallback as today. Both hooks\n // run unconditionally (hook order); the values are only *used* when\n // deferring applies.\n //\n // Deliberate: during the pending window the imperative callbacks\n // (`mutate`/`refetch`/`trigger`/`prefetch`) and the revalidation effects\n // close over the deferred — i.e. *visible* — variant and resource, so they\n // act on the data the user is looking at, not the variant still loading in\n // the background. The window ends when the deferred render commits, at\n // which point they re-bind to the new keys.\n const deferredPath = useDeferredValue(currentPath);\n const deferredVariantKey = useDeferredValue(currentVariantKey);\n const deferVariant = suspense && config.keepPreviousData;\n const normalPath = deferVariant ? deferredPath : currentPath;\n const variantKey = deferVariant ? deferredVariantKey : currentVariantKey;\n // The pending signal for pager UI: true while the visible data belongs to\n // the previous variant and the new one is still loading in the background.\n const isDeferred =\n normalPath !== currentPath || variantKey !== currentVariantKey;\n const { prefetchedData } = useRouteData();\n // `fallbackData` is a single variant's value, so it seeds under this\n // query's variant key; `prefetchedData[normalPath]` is already the full\n // `{ [variantKey]: data }` map the server produced.\n const seed =\n config.fallbackData != null\n ? { [variantKey]: config.fallbackData }\n : prefetchedData?.[normalPath];\n // A memoized map lookup on the provider's ref: stable and cheap, so the\n // resource is derived every render — a params change swaps it in the same\n // render pass instead of flashing through an effect.\n const resource = getResource(normalPath, seed ?? undefined);\n const lazy = config.lazy;\n\n const configRef = useRef(config);\n configRef.current = config;\n\n // `live`: the channel's events and resyncs refetch every cached variant of\n // this path (the rendered ones now), and polling pauses while it is open.\n // `followLive` loads the subscription on first use (#891), so a page whose\n // queries are not live carries none of it. Keyed on the option's value: an\n // inline `live` object is a new one every render.\n const realtime = useContext(RealtimeContext);\n const [liveOpen, setLiveOpen] = useState(false);\n const liveResourceRef = useRef(resource);\n liveResourceRef.current = resource;\n const liveKey = config.live ? JSON.stringify(config.live) : null;\n useEffect(() => {\n if (liveKey === null) return;\n return followLive(realtime, JSON.parse(liveKey), () => liveResourceRef.current, setLiveOpen);\n }, [realtime, liveKey]);\n\n const refreshIntervalRef = useRef<ReturnType<typeof setInterval> | null>(\n null,\n );\n const fetchedRef = useRef(!lazy);\n // `refetchUntil`'s poll: the pending timer, the last delay it returned\n // (handed back as `duration`), the snapshot/variant it was last evaluated\n // against, and whether a poll's refetch is on the wire.\n const pollRef = useRef<{\n timer: ReturnType<typeof setTimeout> | null;\n duration: number;\n snapshot: unknown;\n resource: unknown;\n variantKey: string | null;\n awaiting: boolean;\n }>({\n timer: null,\n duration: 0,\n snapshot: undefined,\n resource: null,\n variantKey: null,\n awaiting: false,\n });\n const prefetchedRef = useRef(false);\n // Focus revalidation eligibility, deliberately *not* `fetchedRef`: that one\n // is flipped by `prefetch()` too, and a hover prefetch is documented as\n // \"fetch once\" for data the user may never look at — enrolling it in focus\n // revalidation would keep re-requesting it for the life of the component.\n // Only the reads that put data on screen (`trigger`, `refetch`, `mutate`,\n // or simply not being lazy) count.\n const focusEligibleRef = useRef(!lazy);\n // The away latch: `focus` fires for things that never left the page —\n // dismissing an `alert`, returning from devtools — so a revalidation is only\n // owed when the window actually lost focus or the tab was hidden first.\n const wasAwayRef = useRef(false);\n const lastFocusRevalidationRef = useRef(0);\n\n // Subscribing also retains the variant, so an `invalidate` across search\n // variants knows this one is on screen and refetches it now.\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n const release = resource.retain(variantKey);\n const unsubscribe = resource.store.subscribe(onStoreChange);\n return () => {\n unsubscribe();\n release();\n };\n },\n [resource, variantKey],\n );\n // `peek` hands back the object stored in the map — its identity only\n // changes on a real write, so the snapshot is stable across render\n // attempts. Also the server snapshot: SSR renders whatever the prefetch\n // payload seeded, and never fetches.\n //\n // uSES and transitions: store updates are always urgent, so a write landing\n // mid-transition restarts the pending transition — wasted work, never wrong\n // UI. Exposure is kept small by design: render-phase reads never write the\n // store synchronously (fetches are silent), and a suspended component has no\n // subscription — it is woken by its thrown promise, not the store. The\n // navigation-shaped consequences are pinned in `useQuery.transition.test.tsx`.\n const getSnapshot = useCallback(\n () => resource.peek(variantKey),\n [resource, variantKey],\n );\n const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n // `keepPreviousData`: remember the last snapshot that had data, and show it\n // whenever the current one is loading without data (e.g. a variant change\n // with `suspense: false`). Presence is `hasData`, never `data`'s truthiness\n // — `null`/`0`/`false`/`\"\"` are legitimate response bodies.\n const lastDataRef = useRef(snapshot?.hasData ? snapshot : null);\n useEffect(() => {\n if (snapshot?.hasData) {\n lastDataRef.current = snapshot;\n }\n }, [snapshot]);\n\n let state = snapshot;\n if (\n config.keepPreviousData &&\n !snapshot?.hasData &&\n snapshot?.loading &&\n lastDataRef.current\n ) {\n state = { ...lastDataRef.current, loading: true };\n }\n\n // The render-phase read for the suspense path. Only when there is nothing\n // to show — data in hand always renders, and revalidation stays where it\n // was (the mount effect below). Both reads dedupe across the render\n // attempts React discards, so this is safe to hit on every attempt.\n //\n // On a streaming server render the read goes to the request's\n // `ServerQueryStore` instead of the client resource: a prefetched query is\n // already in flight there and is joined, an undiscovered one starts now\n // (the store logs the late-discovery hint when that cost something).\n let readPromise: Promise<void> | undefined;\n let serverError: unknown;\n if (suspense && !state?.hasData && !state?.error) {\n if (typeof window === \"undefined\") {\n if (serverQueries) {\n const entry = serverQueries.ensure(url, { params, search });\n if (entry.status === \"resolved\") {\n state = {\n loading: false,\n data: entry.data,\n hasData: true,\n error: null,\n version: 0,\n };\n } else if (entry.status === \"rejected\") {\n serverError = entry.error;\n } else {\n readPromise = entry.promise;\n }\n }\n } else {\n readPromise = resource.read(variantKey, config.staleTime).promise;\n }\n }\n\n if (\n suspense &&\n typeof window === \"undefined\" &&\n !serverQueries &&\n !state?.hasData &&\n process.env.NODE_ENV !== \"production\"\n ) {\n const searchHint = variantKey\n ? `, { search: ${JSON.stringify(\n Object.fromEntries(new URLSearchParams(variantKey)),\n )} }`\n : \"\";\n console.warn(\n `[gemi] useQuery(\"${url}\") rendered on the server without data. ` +\n `The server never fetches, so this page ships without it and the ` +\n `client suspends after hydration. Add ` +\n `\\`Query.prefetch(\"${url}\"${searchHint})\\` to the route's view handler.`,\n );\n }\n\n // While a `keepPreviousData` variant change is pending, the variant loading\n // in the background has no subscription yet — only the visible one does.\n // Hold it too, so that when `search`/`params` change again before it lands,\n // letting go of it aborts its request (#659) instead of leaving it to run\n // to completion for nobody. Seeded like the render-path lookup, since this\n // may be the first `getResource` for the new path.\n useEffect(() => {\n if (!isDeferred) return;\n const targetSeed =\n configRef.current.fallbackData != null\n ? { [currentVariantKey]: configRef.current.fallbackData }\n : prefetchedData?.[currentPath];\n return getResource(currentPath, targetSeed ?? undefined).retain(\n currentVariantKey,\n );\n }, [isDeferred, getResource, currentPath, currentVariantKey, prefetchedData]);\n\n // Mount / variant-change revalidation — unchanged semantics: `getVariant`\n // fetches when the variant is missing or stale, and now joins an in-flight\n // render-initiated read instead of racing it.\n useEffect(() => {\n if (fetchedRef.current) {\n resource.getVariant(variantKey, configRef.current.staleTime);\n }\n }, [variantKey, resource]);\n\n // With `suspense: false` an error is returned and, when the retry policy\n // allows, retried in the background; under suspense it throws below\n // instead. The resource owns the timer — one per variant however many\n // readers render it — and drops it once none of them is mounted.\n useEffect(() => {\n if (suspense || !snapshot?.error || snapshot.loading) return;\n const cfg = configRef.current;\n const error = snapshot.error as QueryFailure;\n const failureCount = Math.max(1, resource.failureCount(variantKey));\n if (!shouldRetryQuery(failureCount, error, cfg.retry)) return;\n const delay = retryDelayFor(\n failureCount,\n error,\n cfg.retryDelay,\n cfg.retryIntervalOnError,\n );\n if (cfg.debug) console.log(\"retrying\", variantKey, \"in\", delay);\n resource.scheduleRetry(variantKey, delay);\n }, [snapshot, suspense, resource, variantKey]);\n\n // Coming back online retries a query that failed in a way another attempt\n // might fix — e.g. one that ran out of retries while offline — as long as\n // its retry policy would retry that error at all. Silent, and it starts a\n // fresh run of failures.\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const onOnline = () => {\n const state = resource.peek(variantKey);\n if (!state?.error) return;\n if (!shouldRetryQuery(1, state.error, configRef.current.retry)) return;\n resource.retryNow(variantKey);\n };\n window.addEventListener(\"online\", onOnline);\n return () => window.removeEventListener(\"online\", onOnline);\n }, [resource, variantKey]);\n\n // `refetchUntil` runs after every commit, not only when the data changes,\n // so the predicate always sees the current render's closure: one that also\n // reads props or state (`d.active || building`) restarts a stopped poll, or\n // cancels a pending one, as soon as that state changes. New data clears the\n // pending timer and asks the predicate again, as before. On a plain\n // re-render a pending timer is kept, so frequent renders never push the\n // next refetch back.\n useEffect(() => {\n const poll = pollRef.current;\n const clear = () => {\n if (poll.timer) clearTimeout(poll.timer);\n poll.timer = null;\n };\n if (\n poll.snapshot !== snapshot ||\n poll.resource !== resource ||\n poll.variantKey !== variantKey\n ) {\n clear();\n poll.awaiting = false;\n poll.snapshot = snapshot;\n poll.resource = resource;\n poll.variantKey = variantKey;\n }\n const refetchUntil = configRef.current.refetchUntil;\n if (\n !refetchUntil ||\n liveOpen ||\n !snapshot ||\n snapshot.loading ||\n !snapshot.hasData ||\n snapshot.error\n ) {\n clear();\n return;\n }\n // The poll's own refetch is on the wire; its answer re-runs this.\n if (poll.awaiting) return;\n const nextDuration = refetchUntil(snapshot.data, poll.duration);\n if (!(nextDuration > 0)) {\n clear();\n poll.duration = 0;\n return;\n }\n if (poll.timer) return;\n poll.duration = nextDuration;\n poll.timer = setTimeout(() => {\n poll.timer = null;\n poll.awaiting = true;\n resource.refetch(variantKey);\n }, nextDuration);\n });\n\n useEffect(\n () => () => {\n const poll = pollRef.current;\n if (poll.timer) clearTimeout(poll.timer);\n poll.timer = null;\n // A StrictMode remount re-runs the effect above with the same snapshot.\n poll.snapshot = undefined;\n poll.awaiting = false;\n },\n [],\n );\n\n const handleReload = useCallback(() => {\n if (configRef.current.debug) {\n console.log(\"Reloading query for\", variantKey);\n }\n const data = resource.getVariant(\n variantKey,\n configRef.current.staleTime,\n ).data;\n resource.mutate(variantKey, () => data);\n }, [variantKey, resource]);\n\n useEffect(() => {\n if (!fetchedRef.current || liveOpen) return;\n refreshIntervalRef.current = setInterval(() => {\n handleReload();\n }, config.refreshInterval);\n\n return () => {\n if (refreshIntervalRef.current) {\n clearInterval(refreshIntervalRef.current);\n }\n };\n }, [config.refreshInterval, handleReload, liveOpen]);\n\n // Revalidate when the tab comes back to the foreground — opt-in via\n // `revalidateOnFocus` (per call or app-wide). `resource.revalidate` applies\n // `staleTime` like the mount effect does, but always fetches silently, so\n // data still inside its freshness window is left alone and anything older\n // is refreshed without what's on screen ever flashing a loading state.\n //\n // Three guards decide whether a return to the foreground is owed a request,\n // because `focus` alone is a poor proxy for one:\n // - eligibility — an untriggered lazy query has nothing on screen;\n // - the away latch — `focus` also fires for a dismissed `alert` or a\n // closed devtools pane, neither of which is a return from anywhere;\n // - the throttle — clicking in and out of an embedded iframe (a payment\n // form, a video) blurs and focuses the window every time, and `focus`\n // runs this for *every* mounted query, so a dashboard would otherwise\n // fire a dozen requests per interaction under `staleTime: 0`.\n //\n // Both events are listened for because neither covers the other: switching\n // between windows fires `focus` while the document stays visible, and\n // switching tabs (or unlocking the device) fires `visibilitychange` without\n // necessarily firing `focus`. They land on one guarded call, so the overlap\n // costs nothing — the latch is already spent by the time the second fires.\n useEffect(() => {\n if (!config.revalidateOnFocus) return;\n const markAway = () => {\n wasAwayRef.current = true;\n };\n const revalidate = () => {\n if (!focusEligibleRef.current) return;\n if (document.visibilityState === \"hidden\") return;\n if (!wasAwayRef.current) return;\n const now = Date.now();\n // Throttled: leave the latch armed so the next return, once the\n // interval has passed, still revalidates.\n if (\n now - lastFocusRevalidationRef.current <\n configRef.current.focusThrottleInterval\n ) {\n return;\n }\n wasAwayRef.current = false;\n lastFocusRevalidationRef.current = now;\n resource.revalidate(variantKey, configRef.current.staleTime);\n };\n const onVisibilityChange = () => {\n if (document.visibilityState === \"hidden\") {\n markAway();\n } else {\n revalidate();\n }\n };\n window.addEventListener(\"blur\", markAway);\n window.addEventListener(\"focus\", revalidate);\n document.addEventListener(\"visibilitychange\", onVisibilityChange);\n return () => {\n window.removeEventListener(\"blur\", markAway);\n window.removeEventListener(\"focus\", revalidate);\n document.removeEventListener(\"visibilitychange\", onVisibilityChange);\n };\n }, [config.revalidateOnFocus, resource, variantKey]);\n\n useEffect(() => {\n // Feature-checked per method: vitest's `import.meta.hot` shim has `on`\n // but not `off`.\n // @ts-ignore\n if (typeof import.meta.hot?.on === \"function\") {\n // @ts-ignore\n import.meta.hot.on(\"http-reload\", handleReload);\n }\n return () => {\n // @ts-ignore\n if (typeof import.meta.hot?.off === \"function\") {\n // @ts-ignore\n import.meta.hot.off(\"http-reload\", handleReload);\n }\n };\n }, [handleReload]);\n\n const trigger = useCallback(() => {\n fetchedRef.current = true;\n focusEligibleRef.current = true;\n const store = resource.store.getValue();\n const variant = store.get(variantKey);\n if (!variant || (!variant.loading && !variant.hasData)) {\n resource.refetch(variantKey);\n }\n }, [resource, variantKey]);\n\n const prefetch = useCallback(() => {\n if (prefetchedRef.current) return;\n prefetchedRef.current = true;\n fetchedRef.current = true;\n // `read`, not `refetch`: a suspending read that follows joins this\n // request instead of racing it, and fresh data is a no-op.\n resource.read(variantKey, configRef.current.staleTime);\n }, [resource, variantKey]);\n\n const refetch = useCallback(() => {\n fetchedRef.current = true;\n focusEligibleRef.current = true;\n resource.refetch(variantKey);\n }, [resource, variantKey]);\n\n function mutate(fn?: NestedPrettify<Data<T>>): void;\n function mutate(\n fn?: (data: NestedPrettify<Data<T>>) => NestedPrettify<Data<T>>,\n ): void;\n function mutate(fn?: any) {\n // `onClick={mutate}` hands React's event to `mutate` as if it were the\n // new data. It is not a plain object, so the shape check below threw —\n // and where the data is untyped nothing caught it at compile time. An\n // event carries no data to write, so it means what a bare `mutate()`\n // means: refetch.\n if (isEventLike(fn)) fn = undefined;\n // Either form ends in a fetch whose result the component renders, so a\n // lazy query mutated by hand is as focus-eligible as a triggered one.\n focusEligibleRef.current = true;\n if (!fn) {\n fetchedRef.current = true;\n resource.refetch(variantKey);\n return;\n }\n return resource.mutate(variantKey, (data: any) => {\n // `null` is a legitimate cached body; only `undefined` means the query\n // hasn't produced anything (and `mutate` refetches instead of calling\n // this in that case).\n if (data === undefined) {\n console.warn(\"Mutate function called before the query.\");\n return data;\n }\n\n // The callback's return value *replaces* the cached data. The type checks\n // below only ensure the shape matches so a stray value can't corrupt the\n // cache; they do not merge or append.\n const updatedData = typeof fn === \"function\" ? fn(data) : fn;\n\n if (isPlainObject(data)) {\n if (isPlainObject(updatedData)) {\n return updatedData;\n }\n throw new Error(\n \"Mutate function must return an object when the current data is an object.\",\n );\n }\n\n if (Array.isArray(data)) {\n if (Array.isArray(updatedData)) {\n return updatedData;\n }\n throw new Error(\n \"Mutate function must return an array when the current data is an array.\",\n );\n }\n\n if (typeof data !== typeof updatedData) {\n throw new Error(\n \"Mutate function must return the same type as the current data.\",\n );\n }\n\n return updatedData;\n });\n }\n\n // Suspend last, after every hook has run: the attempt React discards ran\n // them all, and the retry re-runs them identically. The promise is *thrown*\n // rather than passed to `use()` — the thenable-throw protocol is what\n // React's ping-and-retry machinery is built around (React.lazy, SWR, React\n // Query), whereas `use()` on a client-created promise is documented as\n // unsupported outside a Suspense-compatible framework and React never\n // retries it. A streaming server render takes the same paths: a pending\n // entry suspends (React streams the fallback and resumes on settle), and a\n // rejected one throws so the segment falls back to client rendering, where\n // the browser's own fetch surfaces the error into the boundary.\n if (suspense) {\n if (serverError) {\n throw serverError;\n }\n if (state?.error && !state?.hasData) {\n throw state.error;\n }\n if (!state?.hasData && readPromise) {\n throw readPromise;\n }\n }\n\n return {\n data: state?.data as NestedPrettify<Data<T>>,\n loading: isDeferred || (state?.loading ?? !lazy),\n error: state?.error as Error,\n mutate,\n trigger,\n prefetch,\n refetch,\n version: state?.version as number,\n };\n}\n","import {\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\n\nimport type { NestedPrettify } from \"../utils/type\";\nimport { applyParams } from \"../utils/applyParams\";\nimport { toVariantKey } from \"../utils/variantKey\";\nimport { QueryConfigContext, QueryManagerContext } from \"./QueryManagerContext\";\nimport type { QueryResource } from \"./QueryResource\";\nimport { useParams } from \"./useParams\";\nimport { useRouteData } from \"./useRouteData\";\nimport {\n useQuery,\n type Config,\n type Data,\n type GetRPC,\n type Options,\n} from \"./useQuery\";\n\ntype Page<T extends keyof GetRPC> = NestedPrettify<Data<T>>;\n\n/** What a page's `getNextPage` points at: a page number or a cursor. */\ntype PageCursor = string | number;\n\n/** A page that is an array is its own list of items. */\ntype DefaultItem<P> = P extends readonly (infer U)[] ? U : never;\n\nexport interface InfiniteQueryConfig<P, Item> extends Omit<\n Config<P>,\n \"lazy\" | \"refetchUntil\" | \"fallbackData\"\n> {\n /**\n * The next page's cursor, read off the pages loaded so far — usually a page\n * number, e.g. `(last, pages) => last.length === 48 ? pages.length + 1 :\n * null`. `null`/`undefined`/`false` means there is no next page, which is\n * what `hasMore` reports.\n */\n getNextPage: (\n lastPage: P,\n pages: P[],\n ) => PageCursor | null | undefined | false;\n /**\n * The search key the cursor is sent under (default `\"page\"`). The first\n * page is requested *without* it, so it is the same cached variant a plain\n * `useQuery` — and a `Query.prefetch` — with the same `search` reads.\n */\n pageParam?: string;\n /** A page's rows. Defaults to the page itself when it is an array. */\n getItems?: (page: P) => readonly Item[];\n /**\n * An item's identity. With it, a row that shifts into the next page (an\n * insert or delete between two offset-based fetches) is kept at its first\n * position instead of being rendered twice.\n */\n getKey?: (item: Item) => unknown;\n}\n\nexport interface InfiniteQueryReturn<P, Item> {\n /** Every loaded page, in order. Empty until the first page has data. */\n pages: P[];\n /** The pages' rows flattened, de-duplicated by `getKey` when given. */\n items: Item[];\n /** Whether `getNextPage` points past the last loaded page. */\n hasMore: boolean;\n /**\n * Load the next page. A no-op while one is loading or when there is none;\n * when the last requested page failed, it retries that page.\n */\n fetchNextPage: () => void;\n isFetchingNextPage: boolean;\n /** The first page's `loading` — see `useQuery`. */\n loading: boolean;\n error: Record<string, unknown> | null;\n /** Refetch every loaded page. */\n refetch: () => void;\n}\n\ntype VariantState = ReturnType<QueryResource[\"peek\"]>;\n\n/**\n * Follows the cursor chain through the cache: the first page, then\n * `getNextPage` of it, and so on, up to `count` pages. Stops at the first page\n * that has no data yet — that one is loading (or failed).\n */\nfunction walkPages(\n resource: QueryResource,\n firstKey: string,\n search: Record<string, unknown>,\n pageParam: string,\n count: number,\n getNextPage: (\n last: any,\n pages: any[],\n ) => PageCursor | null | undefined | false,\n) {\n const keys = [firstKey];\n const states: VariantState[] = [resource.peek(firstKey)];\n const pages: any[] = [];\n let next: PageCursor | null | undefined | false = null;\n for (let i = 0; i < count; i++) {\n const state = states[i];\n if (!state?.hasData) break;\n pages.push(state.data);\n next = getNextPage(state.data, pages.slice());\n if (next === null || next === undefined || next === false) break;\n if (i + 1 === count) break;\n const key = toVariantKey({ ...search, [pageParam]: next });\n keys.push(key);\n states.push(resource.peek(key));\n }\n return { keys, states, pages, next };\n}\n\n/**\n * A paged list whose pages live in the query cache: page 1 is a plain\n * `useQuery` (so it suspends, SSR-renders and `Query.prefetch`es exactly like\n * one), and each further page is the same path with `pageParam` added to the\n * search — its own cached variant, which `useMutate` updates and invalidates\n * like any other. Changing `params` or `search` starts over from page 1.\n */\nexport function useInfiniteQuery<\n T extends keyof GetRPC,\n Item = DefaultItem<Page<T>>,\n>(\n url: T,\n options: Options<T> | undefined,\n config: InfiniteQueryConfig<Page<T>, Item>,\n): InfiniteQueryReturn<Page<T>, Item> {\n const {\n getNextPage,\n pageParam = \"page\",\n getItems,\n getKey,\n ...queryConfig\n } = config;\n\n const first = useQuery(url, options, queryConfig as Config<Data<T>>);\n\n const routeParams = useParams();\n const params =\n options && \"params\" in options\n ? { ...routeParams, ...options.params }\n : routeParams;\n const search: Record<string, unknown> = options?.search ?? {};\n const path = applyParams(url, params);\n const firstKey = toVariantKey(search);\n const listKey = `${path}?${firstKey}`;\n const { getResource } = useContext(QueryManagerContext);\n const appConfig = useContext(QueryConfigContext);\n const { prefetchedData } = useRouteData();\n // Seeded the way `useQuery` seeds it: during a params change `useQuery` is\n // still reading the previous path, so this may be the first `getResource`\n // for the new one, and the prefetch payload must not be lost to it.\n const resource = getResource(path, prefetchedData?.[path] ?? undefined);\n\n // How many pages this list has asked for. Keyed by the list, so a\n // params/search change drops it back to one page in the same render.\n const [requested, setRequested] = useState({ listKey, count: 1 });\n const count = requested.listKey === listKey ? requested.count : 1;\n\n const getNextPageRef = useRef(getNextPage);\n getNextPageRef.current = getNextPage;\n\n // The snapshot is the tuple of variant states along the chain; it keeps its\n // identity until one of them is written, as `useSyncExternalStore` needs.\n const snapshotRef = useRef<ReturnType<typeof walkPages> | null>(null);\n const getSnapshot = useCallback(() => {\n const walked = walkPages(\n resource,\n firstKey,\n search,\n pageParam,\n count,\n getNextPageRef.current,\n );\n const previous = snapshotRef.current;\n if (\n previous &&\n previous.keys.length === walked.keys.length &&\n previous.keys.every((key, i) => key === walked.keys[i]) &&\n previous.states.every((state, i) => state === walked.states[i])\n ) {\n return previous;\n }\n snapshotRef.current = walked;\n return walked;\n // `search` is captured through `firstKey`, its serialization.\n }, [resource, firstKey, pageParam, count]);\n const chain = useSyncExternalStore(\n resource.store.subscribe,\n getSnapshot,\n getSnapshot,\n );\n\n // Pages past the first: `useQuery` owns page 1. Retained while on screen so\n // an invalidation refetches them now, and fetched when missing or stale.\n const laterKeys = chain.keys.slice(1);\n const laterKeysId = laterKeys.join(\"\\n\");\n const staleTime = queryConfig.staleTime ?? appConfig?.staleTime;\n const staleTimeRef = useRef(staleTime);\n staleTimeRef.current = staleTime;\n // Each page is read once when it joins the list — fetched when missing,\n // revalidated when stale — not again on every later `fetchNextPage`. A new\n // list (params/search change) starts a new record, so returning to a filter\n // revalidates its pages again as they are loaded.\n const ensuredRef = useRef({ listKey, keys: new Set<string>() });\n useEffect(() => {\n if (!laterKeysId) return;\n if (ensuredRef.current.listKey !== listKey) {\n ensuredRef.current = { listKey, keys: new Set() };\n }\n const ensured = ensuredRef.current.keys;\n const keys = laterKeysId.split(\"\\n\");\n const releases = keys.map((key) => resource.retain(key));\n for (const key of keys) {\n if (ensured.has(key)) continue;\n ensured.add(key);\n resource.getVariant(key, staleTimeRef.current);\n }\n return () => releases.forEach((release) => release());\n }, [resource, listKey, laterKeysId]);\n\n // Until this list's page 1 is cached, show what `useQuery` shows. During a\n // variant change under `keepPreviousData` that is the previous list's\n // data, so every page of the previous list stays on screen rather than\n // collapsing to its first; otherwise (the server render) it is page 1.\n const ownFirstPage = chain.states[0]?.hasData === true;\n const fallbackPage = ownFirstPage ? undefined : first.data;\n const keepingPrevious =\n !ownFirstPage && fallbackPage !== undefined && first.loading;\n const shownRef = useRef<Page<T>[] | null>(null);\n const pages = useMemo<Page<T>[]>(\n () =>\n ownFirstPage\n ? chain.pages\n : keepingPrevious && shownRef.current\n ? shownRef.current\n : fallbackPage !== undefined\n ? [fallbackPage as Page<T>]\n : [],\n [ownFirstPage, chain, keepingPrevious, fallbackPage],\n );\n useEffect(() => {\n if (ownFirstPage) shownRef.current = pages;\n }, [ownFirstPage, pages]);\n\n const pending = chain.states[chain.pages.length];\n const allLoaded = ownFirstPage && chain.pages.length === chain.keys.length;\n const hasMore =\n allLoaded &&\n chain.next !== null &&\n chain.next !== undefined &&\n chain.next !== false;\n const isFetchingNextPage =\n ownFirstPage && chain.pages.length < chain.keys.length && !pending?.error;\n const pageError =\n ownFirstPage && chain.pages.length < chain.keys.length\n ? (pending?.error ?? null)\n : null;\n\n const items = useMemo(() => {\n const out: Item[] = [];\n const seen = new Set<unknown>();\n for (const page of pages) {\n const rows = getItems\n ? getItems(page)\n : Array.isArray(page)\n ? (page as unknown as Item[])\n : [];\n for (const row of rows) {\n if (getKey) {\n const key = getKey(row);\n if (seen.has(key)) continue;\n seen.add(key);\n }\n out.push(row);\n }\n }\n return out;\n }, [pages, getItems, getKey]);\n\n const fetchNextPage = useCallback(() => {\n if (pageError) {\n resource.refetch(chain.keys[chain.keys.length - 1]);\n return;\n }\n if (!hasMore) return;\n setRequested((current) => ({\n listKey,\n count: (current.listKey === listKey ? current.count : 1) + 1,\n }));\n }, [pageError, hasMore, resource, chain, listKey]);\n\n const refetch = useCallback(() => {\n for (const key of chain.keys) {\n resource.refetch(key);\n }\n }, [resource, chain]);\n\n return {\n pages,\n items,\n hasMore,\n fetchNextPage,\n isFetchingNextPage,\n loading: first.loading,\n error: first.error ?? pageError,\n refetch,\n };\n}\n","/**\n * The request header a client sends its socket id in, for `toOthers`.\n *\n * A module of its own, re-exported by `./protocol`: every mutation in the\n * browser reads it, and anything else in `./protocol` it pulled along would\n * land in every route's entry chunk instead of the lazily loaded socket's.\n */\nexport const SOCKET_ID_HEADER = \"x-gemi-socket\";\n","import { loadLazy, type LazyModule } from \"./lazyModule\";\n\n/**\n * `./mutationExtras`, which a page only needs once it mutates: loaded when the\n * first mutation hook, or `useSetQueryData()`, mounts (#915), so no route's\n * entry chunk carries it. By the time a request settles it is normally there;\n * one that settles first waits for it.\n *\n * Keep this module out of `gemi/testing`'s imports. Shared with that entry, it\n * moves into the chunk both entries import, and there an app's bundler can\n * emit `./mutationExtras` even for an app that never mutates, which splits the\n * app's entry chunk (\"needs no chunk besides the entry to start\" in\n * `packaging.test.ts`).\n */\nexport const mutationExtras: LazyModule<typeof import(\"./mutationExtras\")> = {\n current: null,\n load: () => import(\"./mutationExtras.js\"),\n};\n\n/** Starts loading `./mutationExtras`: the hooks' mount effect. */\nexport function preloadMutationExtras() {\n loadLazy(mutationExtras).catch(() => {});\n}\n","import { useContext, useEffect, useRef, useState } from \"react\";\nimport type { RPC } from \"./rpc\";\nimport type { ApiRouterHandler } from \"../http/ApiRouter\";\nimport type { UnwrapPromise } from \"../utils/type\";\nimport type { UrlParser } from \"./types\";\nimport { useParams } from \"./useParams\";\nimport { ClientRouterContext } from \"./ClientRouterContext\";\nimport {\n isObject,\n mutationErrorFromBody,\n type MutationError,\n type WithMutationErrorHelpers,\n} from \"./MutationError\";\nimport { realtime } from \"./realtime/loader\";\nimport { SOCKET_ID_HEADER } from \"../services/broadcast/socketHeader\";\nimport { QueryManagerContext } from \"./QueryManagerContext\";\nimport type { QueryUpdate } from \"./useSetQueryData\";\nimport { loadLazy } from \"./lazyModule\";\nimport { mutationExtras, preloadMutationExtras } from \"./mutationModules\";\n\ntype Methods = {\n POST: {\n [K in keyof RPC as K extends `POST:${infer P}` ? P : never]: RPC[K];\n };\n PUT: {\n [K in keyof RPC as K extends `PUT:${infer P}` ? P : never]: RPC[K];\n };\n PATCH: {\n [K in keyof RPC as K extends `PATCH:${infer P}` ? P : never]: RPC[K];\n };\n DELETE: {\n [K in keyof RPC as K extends `DELETE:${infer P}` ? P : never]: RPC[K];\n };\n};\n\nfunction applyParams(url: string, params: Record<string, any> = {}) {\n let out = url;\n\n for (const [key, value] of Object.entries(params)) {\n out = out.replace(`:${key}?`, value).replace(`:${key}`, value);\n }\n return out;\n}\n\n/**\n * How a hook treats a `trigger` that starts while another is in flight.\n *\n * - `\"latest\"` (the default): the newest request wins. An older request that\n * settles afterwards is dropped: its callbacks don't run, it writes no state\n * and its `trigger` resolves `undefined`. Right for forms and edits, where a\n * newer submit supersedes the older one.\n * - `\"parallel\"`: every request stands on its own. Each one runs its callbacks\n * and resolves its own `trigger`, whatever else is in flight (issue #719).\n *\n * Neither mode aborts the older request; only `cancel()` does.\n */\nexport type MutationConcurrency = \"latest\" | \"parallel\";\n\ntype Config<T, E = never> = {\n autoInvalidate?: boolean;\n onSuccess: (data: T) => void;\n /**\n * A `MutationError`, or one of the route's typed errors (`E`): the bodies\n * its handler answers with `HttpResponse.error` / `httpError`.\n *\n * It carries `error.list()` and `error.field(name)`.\n *\n * Method syntax, so a handler written as `(error: MutationError) => …`\n * before the route had typed errors still compiles.\n */\n onError(error: WithMutationErrorHelpers<MutationError | E>): void;\n onCanceled?: () => void;\n concurrency?: MutationConcurrency;\n /**\n * Queries the answer is written into on success, before `onSuccess`, with\n * no refetch: `{ path, params?, search?, data? }`. Without `data` the\n * answer is written as is; `data(answer, current)` builds the next value\n * from it and what is cached (#897).\n */\n updates?: ReadonlyArray<QueryUpdate<T>>;\n};\n\n/**\n * Callbacks for one `trigger` call. They run after the hook's own, and only\n * when the hook's would: in `\"latest\"` mode a superseded call runs neither.\n */\nexport type MutationCallConfig<T, E = never> = {\n onSuccess?: (data: T) => void;\n onError?(error: WithMutationErrorHelpers<MutationError | E>): void;\n};\n\nconst defaultOptions: Config<any> = {\n autoInvalidate: false,\n onSuccess: () => {},\n onError: (_: MutationError) => {},\n onCanceled: () => {},\n};\n\ntype Data<\n M extends keyof Methods,\n K extends keyof Methods[M],\n> = Methods[M][K] extends ApiRouterHandler<any, infer T, any>\n ? UnwrapPromise<T>\n : never;\n\ntype Body<\n M extends keyof Methods,\n K extends keyof Methods[M],\n> = Methods[M][K] extends ApiRouterHandler<infer T, any, any> ? T : never;\n\n/**\n * The route's typed errors: what its handler answers with `HttpResponse.error`\n * or `httpError`, as `onError` receives them. `never` when it has none.\n */\ntype ErrorOf<\n M extends keyof Methods,\n K extends keyof Methods[M],\n> = Methods[M][K] extends ApiRouterHandler<any, any, any, infer E> ? E : never;\n\ntype ParseParams<T> = UrlParser<`${T & string}`>;\n\ntype State<T, E = never> = {\n data: T | null;\n // With `list()` and `field(name)`.\n error: WithMutationErrorHelpers<MutationError | E> | null;\n loading: boolean;\n // Requests on the wire, superseded ones included.\n pending: number;\n};\n\nexport function useMutation<\n M extends keyof Methods,\n K extends keyof Methods[M],\n T = Data<M, K>,\n U = Body<M, K>,\n E = ErrorOf<M, K>,\n>(\n method: M,\n url: K,\n ...args: [\n options?: { params?: Partial<ParseParams<K>>, search?: Record<string, string> },\n config?: Partial<Config<T, E>>,\n ]\n) {\n const _params = useParams();\n // A write may have moved the data behind any page warmed ahead of a click,\n // and a prefetched payload is committed wholesale — into the query cache too.\n const { clearPrefetchCache } = useContext(ClientRouterContext);\n const { getResource } = useContext(QueryManagerContext);\n const [state, setState] = useState<State<T, E>>({\n data: null,\n error: null,\n loading: false,\n pending: 0,\n });\n\n // A controller per request, held in a ref rather than state. Swapping it\n // through `setState` only took effect on the next render, so a `cancel()`\n // and a `trigger()` in one tick reused the signal `cancel()` had just\n // aborted and the new request never left the ground.\n const abortController = useRef(new AbortController());\n\n // Only the newest request may write state. Nothing tied a response to the\n // request that asked for it, so two submits in flight resolved in whatever\n // order the network returned them — and a slow first submit's validation\n // error could land after the corrected second one had already succeeded,\n // putting the message back and wiping the result.\n const latestRequest = useRef(0);\n\n // Every request still on the wire in `\"parallel\"` mode, so `cancel()` can\n // abort all of them rather than only the newest.\n const inFlight = useRef(new Set<AbortController>());\n\n const formData = useRef(new FormData());\n\n // `Partial<Config<T>>` means a caller may name only the callbacks it wants,\n // and the framework's own `useSignIn`/`useSignOut` name only `onSuccess`.\n // Taking the config as given left the rest undefined, so a success called\n // `options.onSuccess(data)` on `undefined` and reported its own `TypeError`\n // through `onError`.\n const [inputs = {}, config] = args ?? [];\n const options = { ...defaultOptions, ...config } as Config<T, E>;\n\n // Resolves `undefined` rather than rejecting whenever there is no result to\n // hand back: a non-2xx response or a network failure (both already reported\n // through `onError` and `error`), a `cancel()`, and a request superseded by a\n // newer `trigger`. It was typed `Promise<T>`, so `const r = await trigger()`\n // read `r.id` off `undefined` with nothing in the types to say it could.\n // Rejecting instead would turn every `onClick={() => trigger()}` — and\n // `<Form>`'s own submit — into an unhandled rejection, so the type changed\n // and the behaviour did not (issue #623).\n //\n // In `\"parallel\"` mode no call is superseded: each one resolves to its own\n // body and runs its own callbacks, and `data`/`error` hold the outcome of\n // whichever call settled last.\n const parallel = options.concurrency === \"parallel\";\n useEffect(preloadMutationExtras, []);\n\n async function trigger(\n input?: U,\n call: MutationCallConfig<T, E> = {},\n ): Promise<T | undefined> {\n const controller = new AbortController();\n abortController.current = controller;\n if (parallel) inFlight.current.add(controller);\n const requestId = ++latestRequest.current;\n const isSuperseded = () =>\n !parallel && latestRequest.current !== requestId;\n\n // The last response's error is about the last submit. Left in place, a\n // corrected resubmit shows the old validation message until it returns.\n // In parallel mode it belongs to another call, which is still the last\n // one to have settled.\n setState((prev) => ({\n data: prev.data,\n error: parallel ? prev.error : null,\n loading: true,\n pending: prev.pending + 1,\n }));\n // One request off the wire. `update` gives the state it leaves; `loading`\n // is `pending > 0` in parallel mode, while in latest mode it follows the\n // newest request alone, as it always has, so a superseded one settling\n // leaves it as it is.\n //\n // A call leaves `pending` once: an `onError` that throws lands in the\n // `catch` and settles the call a second time.\n let left = false;\n const settle = (\n update: (prev: State<T, E>) => Pick<State<T, E>, \"data\" | \"error\">,\n superseded = false,\n ) => {\n inFlight.current.delete(controller);\n const leaving = !left;\n left = true;\n setState((prev) => {\n const pending = leaving ? prev.pending - 1 : prev.pending;\n return {\n ...update(prev),\n pending,\n loading: parallel ? pending > 0 : superseded ? prev.loading : false,\n };\n });\n };\n // The accumulator this call sent, so a parallel call settling doesn't\n // empty fields gathered since for the next one.\n const sentFormData = typeof input === \"undefined\" ? formData.current : null;\n const resetFormData = () => {\n if (!parallel || formData.current === sentFormData) {\n formData.current = new FormData();\n }\n };\n const params =\n \"params\" in inputs ? { ..._params, ...inputs.params } : _params;\n const search = \"search\" in inputs ? inputs.search : {};\n const searchParams = new URLSearchParams(search);\n const finalUrl = [applyParams(String(url).replace(`${method}:`, \"\"), params), searchParams.toString()].filter(Boolean).join(\"?\");\n\n let body = null;\n\n const contentType =\n typeof input === \"undefined\" || input instanceof FormData\n ? {}\n : { \"Content-Type\": \"application/json\" };\n\n if (input instanceof FormData) {\n body = input;\n } else if (typeof input === \"undefined\") {\n body = formData.current;\n } else if (input) {\n body = JSON.stringify(input);\n }\n\n const socketId = realtime.client?.socketId;\n try {\n const response = await fetch(`/api${finalUrl}`, {\n method,\n headers: {\n ...contentType,\n // This tab's broadcast socket, while one is open, so a controller's\n // `Broadcast.toOthers(req)` skips the tab that made the change.\n ...(socketId ? { [SOCKET_ID_HEADER]: socketId } : {}),\n },\n ...(body ? { body } : {}),\n signal: controller.signal,\n });\n\n const data = await response.json();\n // `data.error` rather than the envelope around it: `onError` is typed\n // `(error: MutationError) => void`, and the envelope has no `kind` to\n // branch on. A body without one — an app's own `HttpResponse.json` —\n // is handed over whole.\n const error = response.ok\n ? null\n : await withErrorHelpers<MutationError | E>(mutationErrorFromBody(data, response.status));\n // Loaded before the check below, so a request superseded while it waits\n // for the module writes nothing.\n const extras = response.ok && options.updates ? await loadOrNull() : null;\n\n // A superseded request has nothing left to say: a newer submit is what\n // the user is waiting on, and its state is the state on screen.\n if (isSuperseded()) {\n settle((prev) => prev, true);\n return;\n }\n\n resetFormData();\n\n if (!response.ok) {\n // `data` is the last result the caller was given, and a rejected\n // submit did not replace it — the same reason the pending state above\n // keeps it.\n settle((prev) => ({ data: prev.data, error }));\n\n options.onError(error!);\n call.onError?.(error!);\n return;\n }\n\n clearPrefetchCache?.();\n extras?.applyQueryUpdates(getResource, _params, options.updates, data);\n options.onSuccess(data);\n call.onSuccess?.(data);\n\n settle(() => ({ data, error: null }));\n\n return data as T;\n } catch (thrown) {\n const error = await withErrorHelpers(thrown as MutationError);\n if (isSuperseded()) {\n settle((prev) => prev, true);\n return;\n }\n\n resetFormData();\n // `cancel()` aborts the request, so the fetch rejects here. A cancelled\n // submit is not a failed one: `onCanceled` has already reported it, and\n // a DOMException carries no `kind` for `<Form>` to read, so leaving it\n // in `error` only puts a value there that nothing can act on.\n if ((error as Error)?.name === \"AbortError\") {\n settle((prev) => prev);\n return;\n }\n // A `TypeError` from `fetch` (no answer) or a `SyntaxError` from\n // `response.json()` (an answer that was not JSON) — both `Error`s.\n options.onError(error);\n call.onError?.(error);\n // A parallel call's failure doesn't take back another call's result.\n settle((prev) => ({\n data: parallel ? prev.data : null,\n error,\n }));\n }\n }\n\n trigger.formData = (formData: FormData) => {\n return trigger(formData as U);\n };\n\n return {\n data: state.data as T,\n error: state.error,\n loading: state.loading,\n // How many requests are on the wire. In parallel mode `loading` is\n // `pending > 0`.\n pending: state.pending,\n formData: formData.current,\n // Aborts the newest request, or in parallel mode every one in flight.\n cancel: () => {\n if (parallel) {\n // Each aborted call takes itself off `pending` as it settles, and\n // `loading` follows.\n for (const controller of inFlight.current) controller.abort();\n } else {\n abortController.current.abort();\n setState((prev) => ({ ...prev, loading: false }));\n }\n\n formData.current = new FormData();\n options.onCanceled?.();\n },\n trigger,\n };\n}\n\nexport function usePost<\n K extends keyof Methods[\"POST\"],\n T = Data<\"POST\", K>,\n E = ErrorOf<\"POST\", K>,\n>(\n url: K,\n ...args: [\n options?: { params?: Partial<ParseParams<K>> },\n config?: Partial<Config<T, E>>,\n ]\n) {\n return useMutation(\"POST\", url, ...(args as any));\n}\n\nexport function usePut<\n K extends keyof Methods[\"PUT\"],\n T = Data<\"PUT\", K>,\n E = ErrorOf<\"PUT\", K>,\n>(\n url: K,\n ...args: [\n options?: { params?: Partial<ParseParams<K>> },\n config?: Partial<Config<T, E>>,\n ]\n) {\n return useMutation(\"PUT\", url, ...(args as any));\n}\n\nexport function usePatch<\n K extends keyof Methods[\"PATCH\"],\n T = Data<\"PATCH\", K>,\n E = ErrorOf<\"PATCH\", K>,\n>(\n url: K,\n ...args: [\n options?: { params?: Partial<ParseParams<K>> },\n config?: Partial<Config<T, E>>,\n ]\n) {\n return useMutation(\"PATCH\", url, ...(args as any));\n}\n\nexport function useDelete<\n K extends keyof Methods[\"DELETE\"],\n T = Data<\"DELETE\", K>,\n E = ErrorOf<\"DELETE\", K>,\n>(\n url: K,\n ...args: [\n options?: { params?: Partial<ParseParams<K>> },\n config?: Partial<Config<T, E>>,\n ]\n) {\n return useMutation(\"DELETE\", url, ...(args as any));\n}\n\nexport function useUpload<\n K extends keyof Methods[\"POST\"],\n T = Data<\"POST\", K>,\n E = ErrorOf<\"POST\", K>,\n>(\n url: K,\n ...args: [\n options?: { params?: Partial<ParseParams<K>> },\n config?: Partial<Omit<Config<T, E>, \"concurrency\">>,\n ]\n) {\n const [state, setState] = useState<\"idle\" | \"uploading\" | \"done\" | \"error\">(\n \"idle\",\n );\n const [progress, setProgress] = useState(0);\n const _params = useParams();\n const { clearPrefetchCache } = useContext(ClientRouterContext);\n const { getResource } = useContext(QueryManagerContext);\n const abortRef = useRef<VoidFunction | null>(null);\n\n const [inputs = {}, options = defaultOptions] = args ?? [];\n useEffect(preloadMutationExtras, []);\n\n // Clears the ref so a `cancel()` after the upload has settled does nothing:\n // it used to abort a finished request and report `onCanceled` for it.\n const cancel = () => {\n const abort = abortRef.current;\n if (!abort) return;\n abortRef.current = null;\n abort();\n options.onCanceled?.();\n setState(\"idle\");\n setProgress(0);\n };\n\n // `undefined` for no file, a failed upload (reported through `onError`), a\n // network error or a `cancel()`, the same contract as `useMutation`'s\n // `trigger`. A cancel is not an error: `onCanceled` reports it and `onError`\n // does not run.\n //\n // It settles on the request's `load`/`error`/`timeout`/`abort` events. It\n // used to settle on `readyState` 4 by wrapping the answer in a `Response`,\n // which throws for the status 0 an abort or a dropped connection leaves —\n // inside an async handler, so the throw was an unhandled rejection and a\n // cancelled upload's `trigger` never settled (issue #671).\n const trigger = async (\n fileList: FileList | null | File,\n ): Promise<T | undefined> => {\n if (!fileList) {\n return;\n }\n const params =\n \"params\" in inputs ? { ..._params, ...inputs.params } : _params;\n const finalUrl = applyParams(String(url).replace(\"POST:\", \"\"), params);\n\n const method = \"POST\";\n const action = `/api${finalUrl}`;\n const data = new FormData();\n if (fileList instanceof FileList) {\n for (const file of Array.from(fileList)) {\n data.append(\"file\", file);\n }\n } else {\n data.append(\"file\", fileList);\n }\n const xhr = new XMLHttpRequest();\n const abort = () => xhr.abort();\n abortRef.current = abort;\n // A newer `trigger` owns the ref once it has replaced it.\n const release = () => {\n if (abortRef.current === abort) abortRef.current = null;\n };\n\n setState(\"uploading\");\n setProgress(0);\n\n try {\n const outcome = await new Promise<\n | { type: \"load\"; status: number; statusText: string; body: string }\n | { type: \"abort\" }\n >((resolve, reject) => {\n xhr.addEventListener(\"load\", () => {\n resolve({\n type: \"load\",\n status: xhr.status,\n statusText: xhr.statusText,\n body: xhr.responseText,\n });\n });\n xhr.addEventListener(\"abort\", () => resolve({ type: \"abort\" }));\n xhr.addEventListener(\"error\", () => {\n reject(new TypeError(\"Failed to fetch\"));\n });\n xhr.addEventListener(\"timeout\", () => {\n reject(new TypeError(\"Failed to fetch\"));\n });\n\n xhr.upload.addEventListener(\"loadstart\", () => {\n setProgress(0);\n });\n // `load`, not `loadend`: `loadend` follows an abort too, and put the\n // progress of a cancelled upload back to 1.\n xhr.upload.addEventListener(\"load\", () => {\n setProgress(1);\n });\n xhr.upload.addEventListener(\"progress\", (event) => {\n // A total the browser cannot tell is 0, and the ratio was `NaN`.\n if (event.lengthComputable && event.total > 0) {\n setProgress(event.loaded / event.total);\n }\n });\n\n xhr.open(method, action, true);\n xhr.send(data);\n });\n release();\n\n // `cancel()` has already reported it and put the state back to idle.\n if (outcome.type === \"abort\") {\n return;\n }\n\n if (outcome.status < 200 || outcome.status > 299) {\n let error: MutationError | E = {\n kind: \"server_error\",\n message: outcome.statusText,\n status: outcome.status,\n };\n try {\n error = mutationErrorFromBody(\n JSON.parse(outcome.body),\n outcome.status,\n );\n } catch {\n // Not JSON: a proxy's error page, say.\n }\n const failure = await withErrorHelpers(error);\n setState(\"error\");\n options?.onError?.(failure);\n return;\n }\n const json = JSON.parse(outcome.body);\n clearPrefetchCache?.();\n if (options.updates) {\n (await loadOrNull())?.applyQueryUpdates(getResource, _params, options.updates, json);\n }\n options?.onSuccess?.(json);\n setState(\"done\");\n return json;\n } catch (error) {\n release();\n const failure = await withErrorHelpers(error as MutationError);\n setState(\"error\");\n options?.onError?.(failure);\n return;\n }\n };\n\n return {\n state,\n progress,\n trigger,\n cancel,\n };\n}\n\n\n// `./mutationExtras`, or `null` when it could not be loaded (a chunk gone\n// after a deploy, no network).\nfunction loadOrNull() {\n return loadLazy(mutationExtras).catch(() => null);\n}\n\n// `error.list()` and `error.field(name)` on what the hooks hand over. If\n// their module could not be loaded, stand-ins that only know the fallback\n// keep `error.list()` in a render from throwing.\nasync function withErrorHelpers<T>(error: T): Promise<WithMutationErrorHelpers<T>> {\n const extras = await loadOrNull();\n if (extras) return extras.withMutationErrorHelpers(error);\n if (isObject(error) && Object.isExtensible(error) && !(\"list\" in error)) {\n Object.defineProperties(error, {\n list: { value: (fallback = \"Something went wrong. Try again.\") => [fallback] },\n field: { value: () => [] },\n });\n }\n return error as WithMutationErrorHelpers<T>;\n}\n","import { useContext } from \"react\";\nimport type { ApiRouterHandler } from \"../http/ApiRouter\";\nimport type { NestedPrettify, UnwrapPromise } from \"../utils/type\";\nimport { isPlainObject } from \"./isPlainObject\";\n\nimport type { RPC } from \"./rpc\";\nimport { QueryManagerContext } from \"./QueryManagerContext\";\nimport type { UrlParser } from \"./types\";\nimport { applyParams } from \"../utils/applyParams\";\nimport { toVariantKey } from \"../utils/variantKey\";\ntype GetRPC = {\n [K in keyof RPC as K extends `GET:${infer P}` ? P : never]: RPC[K];\n};\n\ntype Data<T extends keyof GetRPC> =\n GetRPC[T] extends ApiRouterHandler<any, infer Data, any>\n ? UnwrapPromise<Data>\n : never;\n\n/**\n * Which cached search variants of the path a call updates: one search object\n * (the variant a `useQuery` with that `search` reads), or a predicate over\n * every variant the cache holds for the path.\n */\ntype SearchTarget =\n | Record<string, any>\n | ((search: URLSearchParams) => boolean);\n\n/**\n * The shape guard both `mutate` forms apply: the callback's return value\n * *replaces* the cached data, so it has to keep the data's shape — a stray\n * value must not corrupt the cache. It does not merge or append.\n */\nfunction applyUpdate(data: any, fn: unknown) {\n const updatedData = typeof fn === \"function\" ? fn(data) : fn;\n\n if (isPlainObject(data)) {\n if (isPlainObject(updatedData)) {\n return updatedData;\n }\n throw new Error(\n \"Mutate function must return an object when the current data is an object.\",\n );\n }\n\n if (Array.isArray(data)) {\n if (Array.isArray(updatedData)) {\n return updatedData;\n }\n throw new Error(\n \"Mutate function must return an array when the current data is an array.\",\n );\n }\n\n if (typeof data !== typeof updatedData) {\n throw new Error(\n \"Mutate function must return the same type as the current data.\",\n );\n }\n\n return updatedData;\n}\n\nexport function useMutate() {\n const { getResource } = useContext(QueryManagerContext);\n return function mutate<T extends keyof GetRPC>(\n options: {\n path: T;\n params?: UrlParser<`${T & string}`>;\n search?: SearchTarget;\n },\n fn?:\n | ((data: NestedPrettify<Data<T>>) => NestedPrettify<Data<T>>)\n | NestedPrettify<Data<T>>,\n ) {\n const { path, params = {}, search = {} } = options ?? {};\n const normalPath = applyParams(path, params);\n const resource = getResource(normalPath);\n\n if (typeof search === \"function\") {\n // Every cached variant the predicate accepts — e.g. `() => true` for\n // all of them, pages of a `useInfiniteQuery` included. Variants on\n // screen refetch now; the rest are marked stale and revalidate when\n // next read, so a path with many cached searches doesn't burst.\n for (const variantKey of resource.variantKeys()) {\n if (!search(new URLSearchParams(variantKey))) continue;\n resource.invalidate(\n variantKey,\n fn === undefined\n ? undefined\n : (data: any) => (data === null ? data : applyUpdate(data, fn)),\n );\n }\n return;\n }\n\n const variantKey = toVariantKey(search);\n return resource.mutate.call(resource, variantKey, (data: any) => {\n if (data === undefined || data === null) {\n console.warn(\"Mutate function called before the query.\");\n return data;\n }\n\n if (!fn) {\n return data;\n }\n\n return applyUpdate(data, fn);\n });\n };\n}\n","import { loadLazy, type LazyModule } from \"./lazyModule\";\nimport type { FileRPC } from \"./rpc\";\nimport type { UrlParser } from \"./types\";\n\n/**\n * The paths `fetchBlob` and `fetchText` take: the app's file routes\n * (`this.stream(...)` and `this.file(...)`), or any path while `FileRPC` is\n * empty — an app without file routes, or a program without the app's types.\n */\nexport type FilePath = FilePathOf<FileRPC>;\n\n/** `FilePath` over a given table, for tests. @internal */\nexport type FilePathOf<T> = [keyof T] extends [never] ? string : keyof T & string;\n\nexport type FetchFileOptions<P extends string> = {\n /** The path's `:params`, substituted as `useQuery` does. */\n params?: Partial<UrlParser<P>>;\n /** The query string. `null` and `undefined` values are left out. */\n search?:\n | Record<string, string | number | boolean | null | undefined>\n | URLSearchParams;\n /** Aborts the request; the returned promise then rejects with an `AbortError`. */\n signal?: AbortSignal;\n /** Anything else `fetch` takes (headers, `cache`, `credentials`). Always a `GET`. */\n init?: Omit<RequestInit, \"method\" | \"body\" | \"signal\">;\n};\n\n// `options` is required, with `params`, when the path has a param of its own.\n/** @internal */\nexport type FetchFileArgs<P extends string> =\n {} extends UrlParser<P>\n ? [options?: FetchFileOptions<P>]\n : [options: FetchFileOptions<P> & { params: UrlParser<P> }];\n\ninterface Fetched {\n /**\n * The file name the server gave in `Content-Disposition` (`filename*`\n * first, then `filename`), or `null` when it gave none.\n */\n filename: string | null;\n /** The response, for its headers and status. Its body has been read. */\n response: Response;\n}\n\nexport interface FetchedBlob extends Fetched {\n blob: Blob;\n}\n\nexport interface FetchedText extends Fetched {\n text: string;\n}\n\n// The request itself, loaded on the first call (#915): an app's bundler puts\n// whatever `gemi/client` reaches statically in every route's entry chunk.\nconst request: LazyModule<typeof import(\"./fetchFileRequest\")> = {\n current: null,\n load: () => import(\"./fetchFileRequest.js\"),\n};\n\n/**\n * Downloads a file route's body as a `Blob`.\n *\n * ```ts\n * const { blob, filename } = await fetchBlob(\"/pages/:pageId/post/image\", {\n * params: { pageId },\n * search: { format: \"png\" },\n * });\n * ```\n *\n * A non-2xx rejects with a `QueryError` (`status`, the JSON `body` or `null`,\n * `retryAfter`), the error `useQuery` throws, so `mutationErrorList(error)`\n * reads its message. A network failure rejects with the browser's `TypeError`,\n * an abort with its `AbortError`.\n *\n * The request code loads on the first call (#915), so a route that never\n * downloads a file carries none of it; a failed load rejects as a network\n * failure does.\n */\nexport async function fetchBlob<P extends FilePath>(\n path: P,\n ...args: FetchFileArgs<P>\n): Promise<FetchedBlob> {\n return (await loadLazy(request)).fetchFile(path, args[0], \"blob\") as Promise<FetchedBlob>;\n}\n\n/** `fetchBlob`, with the body read as text. */\nexport async function fetchText<P extends FilePath>(\n path: P,\n ...args: FetchFileArgs<P>\n): Promise<FetchedText> {\n return (await loadLazy(request)).fetchFile(path, args[0], \"text\") as Promise<FetchedText>;\n}\n","import { useCallback, useContext, useEffect } from \"react\";\nimport type { ApiRouterHandler } from \"../http/ApiRouter\";\nimport type { NestedPrettify, UnwrapPromise } from \"../utils/type\";\nimport type { RPC } from \"./rpc\";\nimport type { UrlParser } from \"./types\";\nimport { QueryManagerContext } from \"./QueryManagerContext\";\nimport { loadLazy } from \"./lazyModule\";\nimport { mutationExtras, preloadMutationExtras } from \"./mutationModules\";\nimport type { WriteQueryNext } from \"./queryUpdates\";\nimport { useParams } from \"./useParams\";\n\ntype GetRPC = {\n [K in keyof RPC as K extends `GET:${infer P}` ? P : never]: RPC[K];\n};\n\n/** The data a `useQuery` of this path reads. */\ntype QueryData<P extends keyof GetRPC> = NestedPrettify<\n GetRPC[P] extends ApiRouterHandler<any, infer Data, any> ? UnwrapPromise<Data> : never\n>;\n\n/**\n * The cached query a write lands in: the `useMutate` target. `search` is one\n * variant (the one a `useQuery` with that `search` reads), or a predicate\n * over every variant the cache holds for the path. `params` are merged over\n * the current route's, as `useQuery` merges them.\n */\nexport type QueryTarget<P extends keyof GetRPC> = {\n path: P;\n params?: Partial<UrlParser<`${P & string}`>>;\n search?: Record<string, any> | ((search: URLSearchParams) => boolean);\n};\n\n/**\n * One entry of a mutation's `updates`: a query its answer (`T`) is written\n * into, with no refetch. Without `data` the answer is written as is, which\n * only type-checks when it is the path's data. `data` builds the next value\n * from the answer and what is cached, and is skipped for a variant with\n * nothing cached.\n */\nexport type QueryUpdate<T> = {\n [P in keyof GetRPC]: QueryTarget<P> &\n ([T] extends [QueryData<P>]\n ? { data?: (answer: T, current: QueryData<P>) => QueryData<P> }\n : { data: (answer: T, current: QueryData<P>) => QueryData<P> });\n}[keyof GetRPC];\n\n/**\n * Returns a function that writes into any query's cache by path, with no\n * refetch: for data the server already answered with. `useMutate` is the\n * optimistic counterpart, which refetches to reconcile.\n *\n * ```ts\n * const setQueryData = useSetQueryData();\n * setQueryData({ path: \"/pages/:pageId/assets\", params: { pageId } }, assets);\n * setQueryData({ path: \"/todos\", search: () => true }, (todos) => todos.slice(1));\n * ```\n *\n * A value replaces the variant's data, and seeds it when nothing is cached\n * yet. A function updates what is cached and skips a variant with nothing\n * cached. A predicate `search` reaches every cached variant it accepts.\n *\n * The code behind the writes is loaded when the hook mounts. A call made\n * before it has arrived (during the first render, say) is written once it\n * has, in order.\n */\nexport function useSetQueryData() {\n const { getResource } = useContext(QueryManagerContext);\n const routeParams = useParams();\n // The writes are loaded on mount (#915), so by the time a handler calls the\n // setter they are normally there and it writes at once.\n useEffect(preloadMutationExtras, []);\n return useCallback(\n function setQueryData<P extends keyof GetRPC>(\n target: QueryTarget<P>,\n next: QueryData<P> | ((current: QueryData<P>) => QueryData<P>),\n ) {\n const write: WriteQueryNext =\n typeof next === \"function\"\n ? { update: next as (current: any) => unknown }\n : { value: next };\n const writes = mutationExtras.current;\n if (writes) {\n writes.writeQueryData(getResource, routeParams, target, write);\n return;\n }\n // Called before the module arrived: written once it has, in call\n // order. A failed load writes nothing.\n loadLazy(mutationExtras)\n .then((loaded) => loaded.writeQueryData(getResource, routeParams, target, write))\n .catch(() => {});\n },\n [getResource, routeParams],\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\n\nimport type { ChangeFeedEvent } from \"../services/change-feed/ChangeFeedDriver\";\nimport type { ChangeFeedResponse } from \"../services/change-feed/wire\";\nimport { applyParams } from \"../utils/applyParams\";\nimport { loadedModule } from \"./lazyModule\";\nimport type { SubscriptionState } from \"./subscriptionStream\";\nimport type { UrlParser } from \"./types\";\nimport type { Data, GetRPC } from \"./useQuery\";\nimport { useParams } from \"./useParams\";\n\n/** The `data` a route's `ChangeFeed.stream<T>()` publishes, or `unknown`. */\nexport type SubscriptionData<T extends keyof GetRPC> =\n Data<T> extends ChangeFeedResponse<infer D> ? D : unknown;\n\nexport type SubscriptionStatus = \"connecting\" | \"open\" | \"paused\" | \"closed\";\n\nexport type SubscriptionOptions<T extends keyof GetRPC> = {\n params?: Partial<UrlParser<`${T & string}`>>;\n search?: Record<string, string | number | boolean | null>;\n};\n\nexport type SubscriptionConfig<D> = {\n /** Each change, in order. */\n onChange?: (event: Extract<ChangeFeedEvent<D>, { type: \"change\" }>) => void;\n /**\n * The subscription could not be brought up to date change by change (it\n * was away longer than the server keeps changes): read the resource again.\n */\n onReset?: (event: Extract<ChangeFeedEvent<D>, { type: \"reset\" }>) => void;\n /**\n * Where to start, from `ChangeFeed.cursor()` in the view's data, so that a\n * change made between the server rendering the view and the browser\n * connecting is not missed. Default: the channels' heads when connecting.\n */\n cursor?: string | null;\n /** `false` disconnects. Default `true`. */\n enabled?: boolean;\n /**\n * Disconnect while the tab is hidden, and catch up from the cursor once it\n * is shown again. Default `true`.\n */\n pauseWhenHidden?: boolean;\n};\n\n/** `./subscriptionStream`, loaded on first use. Replaceable in tests. */\nexport const streamModule = {\n load: () => import(\"./subscriptionStream.js\"),\n};\n\n/**\n * Follows a route that answers with `ChangeFeed.stream`, as long as the\n * component is mounted: each change reaches `onChange`, in order, exactly\n * once, across dropped connections and hidden tabs.\n *\n * ```tsx\n * const { status } = useSubscription(\n * \"/sites/:siteId/changes\",\n * { params: { siteId } },\n * { cursor: site.cursor, onChange: ({ data }) => apply(data), onReset: () => reload() },\n * );\n * ```\n *\n * It reconnects after a drop with backoff (1 s doubling to 30 s, or the\n * server's `Retry-After`), resuming with `Last-Event-ID` from the last event\n * it saw. A `4xx` other than `408` and `429` stops it, with status `closed`.\n * The callbacks may change between renders without reconnecting.\n */\nexport function useSubscription<T extends keyof GetRPC>(\n url: T,\n options: SubscriptionOptions<T> = {},\n config: SubscriptionConfig<SubscriptionData<T>> = {},\n): { status: SubscriptionStatus; cursor: string | null; error: Error | null } {\n const routeParams = useParams();\n const params = { ...routeParams, ...(options.params as Record<string, string>) };\n const search = new URLSearchParams(\n Object.entries(options.search ?? {})\n .filter(([, value]) => value !== null && value !== undefined)\n .map(([key, value]) => [key, String(value)]),\n );\n search.sort();\n const path = [applyParams(String(url), params), search.toString()].filter(Boolean).join(\"?\");\n const endpoint = `/api${path}`;\n const enabled = config.enabled !== false;\n const pauseWhenHidden = config.pauseWhenHidden !== false;\n\n const callbacks = useRef(config);\n useEffect(() => {\n callbacks.current = config;\n });\n // The cursor survives a change of callbacks, a pause and a reconnect, and\n // starts over only for another endpoint or another starting cursor.\n const cursor = useRef<string | null>(config.cursor ?? null);\n const [state, setState] = useState<SubscriptionState>({\n status: enabled ? \"connecting\" : \"closed\",\n cursor: cursor.current,\n error: null,\n });\n\n useEffect(() => {\n cursor.current = config.cursor ?? null;\n }, [endpoint, config.cursor]);\n\n useEffect(() => {\n if (!enabled) {\n setState((s) => ({ ...s, status: \"closed\" }));\n return;\n }\n // The connection is loaded on first use; see `./subscriptionStream`.\n let stopped = false;\n let stop: (() => void) | null = null;\n streamModule\n .load()\n .then((module) => {\n const { follow } = loadedModule(module);\n if (stopped) return;\n stop = follow({\n endpoint,\n pauseWhenHidden,\n cursor,\n callbacks: callbacks as { current: SubscriptionConfig<unknown> },\n setState,\n });\n })\n .catch((error: unknown) => {\n // A chunk that will not load (usually a deploy; `init`'s chunk-load\n // recovery reloads the page for it) or a module that failed to\n // evaluate: no connection to retry.\n if (!stopped) setState((s) => ({ ...s, status: \"closed\", error: error as Error }));\n });\n return () => {\n stopped = true;\n stop?.();\n };\n }, [endpoint, enabled, pauseWhenHidden, config.cursor]);\n\n return state;\n}\n","import { useContext, useEffect, useRef } from \"react\";\n\nimport { applyParams } from \"../utils/applyParams\";\nimport { toVariantKey } from \"../utils/variantKey\";\nimport { QueryManagerContext } from \"./QueryManagerContext\";\nimport type { ChannelParamValues } from \"./realtime/RealtimeClient\";\nimport {\n useChannelSubscription,\n useCoalesced,\n type ChannelState,\n} from \"./realtime/useChannelSubscription\";\nimport type { BroadcastRPC } from \"./rpc\";\nimport type { GetRPC } from \"./useQuery\";\nimport { useParams } from \"./useParams\";\n\n/** A channel pattern the app's `ChannelRouter` declares (any string without one). */\nexport type ChannelPattern<R = BroadcastRPC> = [keyof R] extends [never]\n ? string\n : keyof R & string;\n\n/** The params a pattern takes, from `BroadcastRPC`. */\nexport type ChannelParamsFor<P extends string, R = BroadcastRPC> = P extends keyof R\n ? R[P] extends { params: infer X }\n ? X\n : ChannelParamValues\n : ChannelParamValues;\n\n/** The events a pattern's channel carries, from `BroadcastRPC`. */\nexport type ChannelEventsFor<P extends string, R = BroadcastRPC> = P extends keyof R\n ? R[P] extends { events: infer E extends Record<string, unknown> }\n ? E\n : Record<string, unknown>\n : Record<string, unknown>;\n\nexport interface UseChannelOptions<P extends string> {\n params?: ChannelParamsFor<P>;\n}\n\nexport interface UseChannelConfig<Events extends Record<string, unknown>> {\n /** A handler per event name, called with the event's payload. */\n on?: { [E in keyof Events]?: (data: Events[E]) => void };\n /**\n * Events may have been missed — after a (re)connect, once the subscription\n * is acknowledged, or on a server `gap`: refetch what this channel\n * describes. Coalesced to one call per 2 s.\n */\n onResync?: () => void;\n /** `false` unsubscribes. Default `true`. */\n enabled?: boolean;\n}\n\nexport type { ChannelState };\nexport type { ChannelStatus } from \"./realtime/RealtimeClient\";\n\nconst warnedWithoutResync = new Set<string>();\n\n/**\n * Subscribes to a broadcast channel while the component is mounted.\n *\n * ```tsx\n * const { status } = useChannel(\"site.:siteId\", { params: { siteId } }, {\n * on: { changed: (d) => mutate({ path: \"/pages/:pageId\", params: { pageId } }) },\n * onResync: () => mutate({ path: \"/pages/:pageId\", params: { pageId } }),\n * });\n * ```\n *\n * Events are hints, delivered at most once: pair `on` with `onResync`, which\n * runs whenever some may have been missed. `useChannelInvalidate` does both\n * for the common case. On the server, and until the effect runs, `status` is\n * `closed`.\n */\nexport function useChannel<P extends ChannelPattern>(\n pattern: P,\n options: UseChannelOptions<P> = {},\n config: UseChannelConfig<ChannelEventsFor<P>> = {},\n): ChannelState {\n const configRef = useRef(config);\n configRef.current = config;\n const hasOn = config.on !== undefined && Object.keys(config.on).length > 0;\n const hasResync = config.onResync !== undefined;\n\n useEffect(() => {\n if (process.env.NODE_ENV === \"production\") return;\n if (!hasOn || hasResync || warnedWithoutResync.has(pattern)) return;\n warnedWithoutResync.add(pattern);\n console.warn(\n `[gemi] useChannel(\"${pattern}\") has \\`on\\` handlers but no \\`onResync\\`. ` +\n `Broadcast events are hints delivered at most once: after a reconnect ` +\n `or a gap the events in between are gone, so refetch in \\`onResync\\` ` +\n `(or use useChannelInvalidate).`,\n );\n }, [pattern, hasOn, hasResync]);\n\n return useChannelSubscription(\n pattern,\n (options.params ?? {}) as ChannelParamValues,\n {\n onEvent: (event, data) => {\n const handler = (configRef.current.on as Record<string, ((d: unknown) => void) | undefined>)?.[\n event\n ];\n handler?.(data);\n },\n onResync: () => configRef.current.onResync?.(),\n },\n config.enabled !== false,\n );\n}\n\ntype GetPath = [keyof GetRPC] extends [never] ? string : keyof GetRPC & string;\n\n/**\n * A query `useChannelInvalidate` refetches: an api path (its `:params`\n * filled from the channel's params, over the route's), or one with its own\n * params and a single search variant.\n */\nexport type InvalidatePath =\n | GetPath\n | {\n path: GetPath;\n params?: Record<string, string | number>;\n /** Only this search variant. Default: every cached variant. */\n search?: Record<string, string | number | boolean | null>;\n };\n\n/**\n * Refetches `paths` on any event on the channel and on every resync. Only\n * the variants being rendered refetch now; the rest are marked stale. Events\n * are coalesced: a burst within 150 ms refetches once.\n *\n * ```tsx\n * useChannelInvalidate(\"page.:pageId\", { pageId }, [\"/pages/:pageId\", \"/pages/:pageId/pictures\"]);\n * ```\n */\nexport function useChannelInvalidate<P extends ChannelPattern>(\n pattern: P,\n params: ChannelParamsFor<P> | undefined,\n paths: readonly InvalidatePath[],\n config: { enabled?: boolean } = {},\n): ChannelState {\n const { getResource } = useContext(QueryManagerContext);\n const routeParams = useParams();\n const channelParams = (params ?? {}) as ChannelParamValues;\n const latest = useRef({ paths, routeParams, channelParams, getResource });\n latest.current = { paths, routeParams, channelParams, getResource };\n\n const invalidate = () => {\n const { paths, routeParams, channelParams, getResource } = latest.current;\n for (const entry of paths) {\n const target = typeof entry === \"string\" ? { path: entry } : entry;\n const resolved = applyParams(target.path, {\n ...routeParams,\n ...channelParams,\n ...target.params,\n });\n const resource = getResource(resolved);\n const keys = target.search ? [toVariantKey(target.search)] : resource.variantKeys();\n for (const key of keys) resource.invalidate(key);\n }\n };\n\n // A burst of events is one refetch; a resync (already coalesced by the\n // socket, and the answer to missed events) refetches at once.\n const onEvent = useCoalesced(invalidate);\n return useChannelSubscription(\n pattern,\n channelParams,\n { onEvent, onResync: invalidate },\n config.enabled !== false,\n );\n}\n\nexport type { LiveChannel } from \"./realtime/live\";\n","import {\n createContext,\n useContext,\n type ComponentProps,\n type Ref,\n useRef,\n useEffect,\n useSyncExternalStore,\n useCallback,\n} from \"react\";\nimport type { RPC } from \"./rpc\";\nimport type { ApiRouterHandler } from \"../http/ApiRouter\";\nimport { useMutation } from \"./useMutation\";\nimport type { UnwrapPromise } from \"../utils/type\";\nimport type { UrlParser } from \"./types\";\nimport { useParams } from \"./useParams\";\nimport { ServerDataContext } from \"./ServerDataProvider\";\nimport { Subject } from \"../utils/Subject\";\nimport {\n isFormError,\n isValidationError,\n type MutationError,\n type WithMutationErrorHelpers,\n} from \"./MutationError\";\n\ntype Any = any;\n\ninterface MutationContextValue {\n isPending: boolean;\n result: null | Any;\n validationErrors: Record<string, string[]>;\n formError: null | string;\n formDataSubject: React.RefObject<Subject<FormData>>;\n}\n\nconst MutationContext = createContext({\n isPending: false,\n result: null,\n} as MutationContextValue);\n\ntype GetResult<T> =\n T extends ApiRouterHandler<Any, infer Result, Any>\n ? UnwrapPromise<Result>\n : never;\n\ntype PostRequests = {\n [K in keyof RPC as K extends `POST:${infer P}` ? P : never]: GetResult<\n RPC[K]\n >;\n};\n\ntype PutRequests = {\n [K in keyof RPC as K extends `PUT:${infer P}` ? P : never]: GetResult<RPC[K]>;\n};\n\ntype DeleteRequests = {\n [K in keyof RPC as K extends `DELETE:${infer P}` ? P : never]: GetResult<\n RPC[K]\n >;\n};\n\ntype PatchRequests = {\n [K in keyof RPC as K extends `PATCH:${infer P}` ? P : never]: GetResult<\n RPC[K]\n >;\n};\n\ntype GetError<T> =\n T extends ApiRouterHandler<Any, Any, Any, infer E> ? E : never;\n\n/** Each route's typed errors (`HttpResponse.error`), by method and path. */\ntype ErrorMethods = {\n [M in keyof Methods]: {\n [K in keyof RPC as K extends `${M}:${infer P}` ? P : never]: GetError<RPC[K]>;\n };\n};\n\ntype Methods = {\n POST: PostRequests;\n PUT: PutRequests;\n DELETE: DeleteRequests;\n PATCH: PatchRequests;\n};\n\n// Whatever `<form onSubmit>` hands its handler under the installed\n// `@types/react` — `SubmitEvent` in current versions, `FormEvent` in older\n// ones — so the caller's handler can be called with it either way.\ntype FormSubmitEvent = Parameters<\n NonNullable<ComponentProps<\"form\">[\"onSubmit\"]>\n>[0];\n\ninterface FormProps<\n M extends keyof Methods,\n K extends keyof Methods[M],\n E = ErrorMethods[M][K & keyof ErrorMethods[M]],\n> extends Omit<ComponentProps<\"form\">, \"action\" | \"onError\"> {\n method?: M;\n action: K;\n onSuccess?: (result: Methods[M][K], form: HTMLFormElement) => void;\n /**\n * Called when the request fails. `error` is a `MutationError`, or one of\n * the route's typed errors (the bodies its handler answers with\n * `HttpResponse.error` / `httpError`); narrow it with `isValidationError`,\n * `isPermissionError`, `isHttpError` and the other guards from\n * `gemi/client`, or read it with `error.list()` / `error.field(name)`.\n * Validation and form errors are already rendered by `<ValidationErrors>`\n * and `<FormError>`.\n */\n // Method syntax, so a handler typed `(error: MutationError, form) => …`\n // still compiles for a route that has typed errors.\n onError?(\n error: WithMutationErrorHelpers<MutationError | E>,\n form: HTMLFormElement,\n ): void;\n /**\n * Called when a submit is about to send its request, with the exact\n * `FormData` that will be sent (after `dynamicInputs`). Return `false` to\n * skip the request. Not called for a submit swallowed because one is\n * already in flight.\n */\n onSubmitStart?: (\n formData: FormData,\n form: HTMLFormElement,\n ) => void | boolean;\n /** Called after `onSuccess` or `onError`, whichever ran. */\n onSettled?: (form: HTMLFormElement) => void;\n params?: Partial<UrlParser<`${K & string}`>>;\n search?: Record<string, string>;\n dynamicInputs?: (formData: FormData) => Record<string, any>;\n}\n\nexport function Form<\n K extends keyof Methods[T],\n T extends keyof Methods = \"POST\",\n E = ErrorMethods[T][K & keyof ErrorMethods[T]],\n>(props: FormProps<T, K, E>) {\n const _params = useParams();\n const {\n method = \"POST\",\n action,\n onSuccess = () => {},\n onError = () => {},\n onSubmitStart,\n onSettled,\n onSubmit,\n ref,\n params,\n search = {},\n className,\n dynamicInputs = () => ({}),\n ...formProps\n } = \"params\" in props\n ? { ...props, params: { ..._params, ...props.params } }\n : { ...props, params: _params };\n const formRef = useRef<HTMLFormElement>(null);\n // Both refs, not one or the other. A `ref` from the caller used to land in\n // the props spread over the `<form>`, which replaced `formRef` and left\n // every submit returning early at `!formRef.current`.\n const setFormRef = useCallback(\n (node: HTMLFormElement | null) => {\n formRef.current = node;\n const cleanup = assignRef(ref, node);\n // Returning a cleanup means React will not call this again with `null`,\n // so the detach happens here — including the caller's own cleanup when\n // their callback ref returned one.\n return () => {\n formRef.current = null;\n if (typeof cleanup === \"function\") {\n cleanup();\n } else {\n assignRef(ref, null);\n }\n };\n },\n [ref],\n );\n const { __csrf } = useContext(ServerDataContext);\n const formDataSubject = useRef(new Subject(new FormData()));\n\n const updateFormData = useCallback(() => {\n formDataSubject.current.next(new FormData(formRef.current));\n }, []);\n\n useEffect(() => {\n if (!formRef.current) return;\n\n formRef.current.addEventListener(\"input\", updateFormData);\n\n const observer = new MutationObserver(() => {\n const formData = new FormData(formRef.current);\n formDataSubject.current.next(formData);\n });\n\n formRef.current.querySelectorAll(\"input\").forEach((input) =>\n observer.observe(input, {\n attributes: true,\n attributeFilter: [\"value\"],\n }),\n );\n\n formRef.current.querySelectorAll(\"select\").forEach((input) =>\n observer.observe(input, {\n attributes: true,\n attributeFilter: [\"value\"],\n }),\n );\n\n formRef.current.querySelectorAll(\"textarea\").forEach((input) =>\n observer.observe(input, {\n attributes: true,\n attributeFilter: [\"value\"],\n }),\n );\n\n return () => {\n observer.disconnect();\n if (formRef.current) {\n formRef.current.removeEventListener(\"input\", updateFormData);\n }\n };\n }, [updateFormData]);\n\n const { trigger, data, error, loading } = useMutation(\n method,\n String(action) as Any,\n {\n params,\n search,\n } as Any,\n {\n onSuccess: (data) => {\n onSuccess(data as Any, formRef.current);\n onSettled?.(formRef.current);\n },\n onError: (error) => {\n onError(error as Any, formRef.current);\n onSettled?.(formRef.current);\n },\n },\n );\n\n const handleSubmit = async (e: FormSubmitEvent) => {\n // Before the guards, not after: returning early without preventing the\n // default let the browser submit the form itself. A second click while a\n // slow submit was still in flight navigated the page away and took the\n // request with it.\n e.preventDefault();\n // The caller's `onSubmit` runs alongside this handler rather than instead\n // of it. It used to be spread over the `<form>` after `onSubmit=\n // {handleSubmit}` and win: no `preventDefault`, so the browser submitted\n // the form itself, and no request. It sees every submit event, like a\n // native handler does, and it cannot cancel the request — the default is\n // already prevented by now, so `defaultPrevented` carries no signal.\n // `onSubmitStart` returning `false` is the way to skip one.\n onSubmit?.(e);\n if (loading) {\n return;\n }\n if (!formRef.current) {\n return;\n }\n const formData = new FormData(formRef.current);\n for (const [key, value] of Object.entries(dynamicInputs(formData))) {\n formData.append(key, value as any);\n }\n if (onSubmitStart?.(formData, formRef.current) === false) {\n return;\n }\n trigger(formData as any);\n };\n\n const validationErrors = isValidationError(error) ? error.messages : {};\n\n const formError = isFormError(error) ? error.message : null;\n\n return (\n <MutationContext.Provider\n value={{\n isPending: loading,\n result: data,\n validationErrors,\n formError,\n formDataSubject,\n }}\n >\n {/* The spread comes first so that nothing in it can replace what\n `<Form>` needs to work; `ref` and `onSubmit` are composed above. */}\n <form\n {...formProps}\n className={[\"group\", className].filter(Boolean).join(\" \")}\n data-loading={loading}\n ref={setFormRef}\n onSubmit={handleSubmit}\n >\n <input type=\"hidden\" name=\"__csrf\" value={__csrf} />\n {props.children}\n </form>\n </MutationContext.Provider>\n );\n}\n\nfunction assignRef<T>(ref: Ref<T> | undefined, value: T | null) {\n if (typeof ref === \"function\") {\n return ref(value);\n }\n if (ref) {\n ref.current = value;\n }\n}\n\nexport function useMutationStatus() {\n const { isPending } = useContext(MutationContext);\n\n return { isPending };\n}\n\nexport function useFormStatus() {\n const { isPending, validationErrors, formError } =\n useContext(MutationContext);\n\n return { isPending, validationErrors, formError };\n}\n\nexport function useFormData() {\n const context = useContext(MutationContext);\n\n const { formDataSubject } = context;\n\n // Unbound on purpose: `Subject` binds in its constructor, so these are\n // stable across renders. The `.bind` calls that used to be here allocated a\n // fresh `subscribe` every render, which made `useSyncExternalStore` drop and\n // re-add this component's subscription on each pass.\n return useSyncExternalStore(\n formDataSubject.current.subscribe,\n formDataSubject.current.getValue,\n formDataSubject.current.getValue,\n );\n}\n\nexport const ValidationErrors = (props: {\n name: string;\n className?: string;\n render?: (props: ComponentProps<\"div\">) => React.JSX.Element;\n}) => {\n const {\n render = (props: ComponentProps<\"div\">) => <div {...props} />,\n name,\n } = props;\n const { validationErrors } = useContext(MutationContext);\n\n const Comp = render;\n\n if (validationErrors[name]?.length > 0) {\n return (\n <>\n {validationErrors[name].map((error) => {\n return (\n <Comp className={props.className} key={error}>\n {error}\n </Comp>\n );\n })}\n </>\n );\n }\n\n return null;\n};\n\nexport const FormFieldContainer = (\n props: ComponentProps<\"div\"> & { name: string },\n) => {\n const { name, children, ...rest } = props;\n const { validationErrors } = useContext(MutationContext);\n const errors = validationErrors[name] || [];\n return (\n <div data-has-error={errors.length > 0} {...rest}>\n {children}\n </div>\n );\n};\n\nexport const FormError = (props: ComponentProps<\"div\">) => {\n const { formError } = useContext(MutationContext);\n\n if (formError) {\n return <div {...props}>{formError}</div>;\n }\n\n return null;\n};\n","import { useContext } from \"react\";\nimport { ServerDataContext } from \"./ServerDataProvider\";\nimport { domainUrl, type DomainTarget } from \"../utils/domainUrl\";\n\n/**\n * The `route.domains` group this page was served under — `params.tenant` on\n * `acme.example.com` — and `url()` for linking to another of the app's hosts.\n * Empty when the app declares no `route.domains`.\n *\n * Hand `url()`'s result to `Link` or `navigate`: a URL on another host is a\n * full page load, not a client-side navigation.\n */\nexport function useDomain() {\n const domain = useContext(ServerDataContext).router?.domain ?? null;\n return {\n host: domain?.host ?? null,\n group: domain?.group ?? null,\n params: domain?.params ?? {},\n custom: domain?.custom ?? false,\n url(target: DomainTarget, path = \"/\") {\n if (!domain?.root) {\n throw new Error(\"`useDomain().url` needs `route.domains` to be configured.\");\n }\n // The origin the server saw, not `window.location`: the two agree, and\n // this one exists during the server render too, so hydration matches.\n return domainUrl({ root: domain.root, origin: domain.origin }, target, path);\n },\n };\n}\n","import { useContext, useSyncExternalStore } from \"react\";\nimport { ClientRouterContext } from \"./ClientRouterContext\";\n\nexport function useIsNavigationPending() {\n const { isNavigatingSubject } = useContext(ClientRouterContext);\n // These read `this`, and `useSyncExternalStore` calls whatever it is handed\n // as a plain function — which used to throw `undefined is not an object\n // (evaluating 'this.value')` on the first render of any component calling\n // this hook. `Subject` now binds in its constructor, so the references are\n // both correct and stable across renders; binding here instead would hand\n // uSES a new `subscribe` every render and churn the subscription.\n const isNavigating = useSyncExternalStore(\n isNavigatingSubject.subscribe,\n isNavigatingSubject.getValue,\n isNavigatingSubject.getValue,\n );\n\n return isNavigating;\n}\n","import { useContext, useEffect, useState } from \"react\";\nimport { ClientRouterContext } from \"./ClientRouterContext\";\n\nexport function useNavigationProgress() {\n const { progressManager } = useContext(ClientRouterContext);\n const [progress, setProgress] = useState(progressManager.state.getValue());\n\n useEffect(() => {\n const unsub = progressManager.state.subscribe((p) => setProgress(p));\n return () => {\n unsub();\n };\n }, [progressManager.state]);\n\n return progress;\n}\n","import { useCallback, useContext } from \"react\";\n\nimport { applyParams } from \"../utils/applyParams\";\nimport { ClientRouterContext } from \"./ClientRouterContext\";\nimport { I18nContext } from \"./I18nContext\";\nimport { useLocation } from \"./useLocation\";\nimport type { IsViewPath, UrlParser, ViewPaths } from \"./types\";\n\ntype Search = Record<string, string | number | boolean | undefined | null>;\n\n/**\n * A prefetch spends the visitor's data on a page they may never open, so it\n * stands down when they have asked for less of that or the connection cannot\n * spare it. `navigator.connection` only exists in Chromium — everywhere else\n * there is nothing to go on and prefetching proceeds.\n */\nfunction connectionRefusesPrefetch() {\n const connection = (navigator as any)?.connection;\n if (!connection) {\n return false;\n }\n if (connection.saveData) {\n return true;\n }\n return [\"slow-2g\", \"2g\"].includes(connection.effectiveType);\n}\n\ntype Options<T extends string> =\n UrlParser<T> extends Record<string, never>\n ? {\n search?: Search;\n locale?: string;\n }\n : {\n search?: Search;\n params: UrlParser<T>;\n locale?: string;\n };\n\n/** The options for a URL built at runtime — see `useNavigate`'s copy. */\ntype RuntimeOptions = {\n search?: Search;\n params?: Record<string, string | number | undefined>;\n locale?: string;\n};\n\n/** Required for a declared route that has params, optional otherwise. See\n * `IsViewPath` — prefetch took `ViewPaths | (string & {})` and so had the\n * same inference fault `useNavigate` did. */\ntype PrefetchArgs<P extends string> = IsViewPath<P> extends true\n ? UrlParser<P> extends Record<string, never>\n ? [options?: Options<P>]\n : [options: Options<P>]\n : [options?: RuntimeOptions];\n\n/**\n * Warms a route ahead of the navigation to it: its page data, its stylesheets\n * and its component chunks. A navigation that lands on a prefetched route\n * renders from the cached payload instead of waiting on a request.\n *\n * The URL is built exactly the way `useNavigate` builds it — the prefetch is\n * only ever used by a navigation that asks for the same one.\n */\nexport function usePrefetch() {\n const { prefetchRoute } = useContext(ClientRouterContext);\n const { defaultLocale } = useContext(I18nContext);\n const location = useLocation();\n\n const currentPathname = location.pathname;\n const currentSearch = location.search;\n const currentLocale = location.locale;\n\n return useCallback(\n async <P extends ViewPaths | (string & {})>(\n path: P,\n ...args: PrefetchArgs<P>\n ) => {\n if (typeof window === \"undefined\" || !prefetchRoute) {\n return;\n }\n\n if (connectionRefusesPrefetch()) {\n return;\n }\n\n const [options = {}] = args;\n const {\n search = {},\n params = {},\n locale = null,\n } = { params: {}, search: {}, locale: null, ...options };\n\n let localeSegment = locale ?? currentLocale;\n if (localeSegment === defaultLocale) {\n localeSegment = \"\";\n }\n\n const pathname = applyParams(path, params) || \"/\";\n // Matches `useNavigate`, which hands the search object straight to\n // `URLSearchParams` — the query string a click produces has to be the one\n // the payload was cached under.\n const queryString = new URLSearchParams(search as any).toString();\n const searchSegment = queryString.length > 0 ? `?${queryString}` : \"\";\n\n // The route already on screen has nothing to warm, and eagerly prefetched\n // links pointing back at it would just replay the current page's queries.\n if (pathname === currentPathname && searchSegment === currentSearch) {\n return;\n }\n\n await prefetchRoute({\n pathname,\n search: searchSegment,\n localeSegment: localeSegment ? `/${localeSegment}` : \"\",\n });\n },\n [\n prefetchRoute,\n defaultLocale,\n currentLocale,\n currentPathname,\n currentSearch,\n ],\n );\n}\n","import { useContext } from \"react\";\nimport { useRoute } from \"./useRoute\";\nimport { ClientRouterContext } from \"./ClientRouterContext\";\n\nexport type Breadcrumb = {\n label: string;\n href: string;\n};\n\nexport function useBreadcrumbs() {\n const { pathname } = useRoute();\n const { getViewPathsFromPathname, breadcrumbsCache } =\n useContext(ClientRouterContext);\n\n let breadcrumbs: Breadcrumb[] = [];\n const viewPaths = getViewPathsFromPathname(pathname);\n for (const viewPath of viewPaths) {\n if (breadcrumbsCache.has(`${viewPath}:${pathname}`)) {\n breadcrumbs.push(breadcrumbsCache.get(`${viewPath}:${pathname}`));\n }\n }\n\n return breadcrumbs.filter((breadcrumb) => breadcrumb?.label.length > 0);\n}\n","import {\n useCallback,\n useContext,\n useEffect,\n useRef,\n memo,\n type ComponentProps,\n type MouseEvent as ReactMouseEvent,\n type ReactElement,\n type SyntheticEvent,\n} from \"react\";\n\nimport { applyParams } from \"../utils/applyParams\";\nimport { isAbsoluteUrl, type AbsoluteUrl } from \"../utils/domainUrl\";\nimport { useLocation } from \"./useLocation\";\nimport type { UrlParser, ViewResult } from \"./types\";\nimport { useNavigate } from \"./useNavigate\";\nimport type { ViewRPC } from \"./rpc\";\nimport type { Prettify } from \"../utils/type\";\nimport { useParams } from \"./useParams\";\nimport { I18nContext } from \"./I18nContext\";\nimport { useRouteTransition } from \"./RouteTransitionProvider\";\nimport { usePrefetch } from \"./usePrefetch\";\n\ntype Views = {\n [K in keyof ViewRPC as K extends `view:${infer P}`\n ? P\n : never]: ViewResult<K>;\n};\n\ntype Search = Record<string, string | number | boolean | undefined | null>;\n\n/**\n * When to warm the target route's data, styles and chunks.\n *\n * - `hover` — the moment the pointer arrives, or on touch or keyboard focus.\n * - `intent` — hover held long enough to read as intent, so a cursor sweeping\n * across a nav bar does not fire a request per link it crosses.\n * - `viewport` — as the link comes into view.\n * - `render` — as soon as the link renders.\n *\n * Several can be combined. The useful pairing is a bulk strategy with an\n * interactive one — `[\"viewport\", \"intent\"]` warms the link on the way past and\n * warms it again on approach if the cached payload has since gone stale.\n * `hover` and `intent` together is just `hover`, since it fires first.\n *\n * Every strategy stands down on metered or very slow connections.\n */\nexport type PrefetchStrategy = \"hover\" | \"intent\" | \"viewport\" | \"render\";\n\n/** How long the pointer has to rest on an `intent` link before it counts. */\nconst INTENT_DELAY = 100;\n\n/** How far ahead of the viewport a `viewport` link starts warming. */\nconst VIEWPORT_MARGIN = \"200px\";\n\ntype LinkBaseProps<T extends keyof Views> = Omit<\n ComponentProps<\"a\">,\n \"href\"\n> & {\n active?: boolean;\n href: T;\n hash?: string;\n /** Off unless set. `false` is accepted so it can be driven by a variable. */\n prefetch?: PrefetchStrategy | readonly PrefetchStrategy[] | false;\n params: UrlParser<T>;\n search?: T extends keyof Views\n ? Views[T][\"input\"] extends Record<string, never>\n ? Search\n : Prettify<Partial<Views[T][\"input\"]> & Search>\n : Search;\n};\n\n/** A link to one of the app's own view routes, handled by the client router. */\nexport type LinkProps<T extends keyof Views, U = UrlParser<T>> = U extends Record<\n string,\n never\n>\n ? Omit<LinkBaseProps<T>, \"params\">\n : LinkBaseProps<T>;\n\nfunction normalizeSearch(search: Search): Record<string, string> {\n return Object.fromEntries(\n Object.entries(search)\n .filter(([_k, v]) => v !== undefined && v !== null)\n .map(([k, v]) => [k, String(v)]),\n ) as Record<string, string>;\n}\n\n/** A link to another host — `useDomain().url(...)` — which the router cannot reach. */\nexport type ExternalLinkProps = Omit<ComponentProps<\"a\">, \"href\"> & {\n href: AbsoluteUrl;\n active?: boolean;\n};\n\n// `ComponentProps<typeof Link>` cannot see through an overloaded generic\n// signature and comes out `{}` — derive prop types from `LinkProps` and\n// `ExternalLinkProps` instead.\ntype LinkComponent = {\n (props: ExternalLinkProps): ReactElement;\n <T extends keyof Views>(props: LinkProps<T>): ReactElement;\n};\n\n/**\n * A path renders an anchor the client router handles; an absolute URL, one on\n * another of the app's hosts, a plain anchor the browser loads in full — the\n * router would otherwise push the path into the current host.\n */\nexport const Link = memo((props: any) => {\n if (isAbsoluteUrl(props.href)) {\n const { active = false, ...rest } = props as ExternalLinkProps;\n return <a data-active={active} {...rest} />;\n }\n const Route = RouteLink as unknown as (props: any) => ReactElement;\n return <Route {...props} />;\n}) as unknown as LinkComponent;\n\n/**\n * Clicks the router must not take over, so the browser does what it would for a\n * plain anchor: a new tab or window for `target=\"_blank\"` and for cmd/ctrl/\n * shift/alt-clicks, the context action for a middle click, a file for\n * `download`, and nothing at all when a handler has already cancelled the click.\n */\nfunction leaveClickToBrowser(event: ReactMouseEvent<HTMLAnchorElement>) {\n if (event.defaultPrevented) {\n return true;\n }\n if (event.button !== 0) {\n return true;\n }\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {\n return true;\n }\n const anchor = event.currentTarget;\n const target = anchor.getAttribute(\"target\");\n if (target && target !== \"_self\") {\n return true;\n }\n return anchor.hasAttribute(\"download\");\n}\n\nconst RouteLink = memo(<T extends keyof Views>(props: LinkProps<T>) => {\n const _params = useParams();\n const { isTransitioning, targetPath } = useRouteTransition();\n const {\n href,\n onClick,\n onMouseEnter,\n onMouseLeave,\n onTouchStart,\n onFocus,\n onBlur,\n ref,\n hash = \"\",\n active = false,\n prefetch,\n params = {},\n search = {},\n ...rest\n } = { params: _params, search: {}, ...props };\n const { defaultLocale } = useContext(I18nContext);\n const { push } = useNavigate();\n const location = useLocation();\n const prefetchRoute = usePrefetch();\n const searchParams = new URLSearchParams(normalizeSearch(search));\n\n const path = applyParams(href, params);\n // `applyParams` drops the trailing slash, so the root route comes back empty\n // where every pathname the router reports says `/`.\n const resolvedPath = path || \"/\";\n let urlLocaleSegment = location.locale;\n if (urlLocaleSegment === defaultLocale) {\n urlLocaleSegment = \"\";\n }\n\n const localeSegment = urlLocaleSegment ? `/${urlLocaleSegment}` : \"\";\n\n const targetHref = [\n [`${localeSegment}${path}`, searchParams.toString()]\n .filter((s) => s.length > 0)\n .join(\"?\"),\n hash,\n ].join(\"\");\n\n const currentHref = [location.pathname, location.search, location.hash]\n .filter((item) => !!item)\n .join(\"\");\n\n // Held in a ref because the prefetch callback is rebuilt on every router\n // render — an effect that depended on it would re-fire on renders that have\n // nothing to do with this link.\n const prefetchRouteRef = useRef(prefetchRoute);\n useEffect(() => {\n prefetchRouteRef.current = prefetchRoute;\n });\n\n // Clicking through to the path we are already on is a shallow navigation —\n // it moves the URL without fetching, so there is nothing to warm.\n const isShallowTarget = resolvedPath === location.pathname;\n\n const strategies = !prefetch\n ? []\n : Array.isArray(prefetch)\n ? prefetch\n : [prefetch];\n const uses = (strategy: PrefetchStrategy) => strategies.includes(strategy);\n // Effects below key off the strategies, which arrive as an array literal with\n // a fresh identity on every render. The names are what actually matters.\n const strategyKey = strategies.join(\",\");\n\n // Repeats are the cache's problem, not this component's: it collapses a\n // hover storm into one request and lets a hover past the TTL refresh a\n // payload that has gone stale.\n const runPrefetch = () => {\n if (strategies.length === 0 || isShallowTarget) {\n return;\n }\n prefetchRouteRef.current(href, { params, search } as never);\n };\n\n useEffect(() => {\n if (uses(\"render\")) {\n runPrefetch();\n }\n }, [strategyKey, targetHref]);\n\n const anchorRef = useRef<HTMLAnchorElement | null>(null);\n // A caller's own `ref` still has to reach them — under React 19 it arrives as\n // a plain prop, and the spread below would otherwise hand the element to one\n // of us and null to the other.\n //\n // Memoised because `Link` re-renders on every navigation in the app: a fresh\n // callback identity would have React detach and reattach the element each\n // time, handing a caller's ref callback a null it never asked for.\n const setAnchorRef = useCallback(\n (node: HTMLAnchorElement | null) => {\n anchorRef.current = node;\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n },\n [ref],\n );\n\n useEffect(() => {\n if (!uses(\"viewport\")) {\n return;\n }\n const element = anchorRef.current;\n if (!element || typeof IntersectionObserver === \"undefined\") {\n return;\n }\n // One shot: a link scrolled past and back is already warm, and if its entry\n // has expired the next hover or click pays for a fresh one.\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n observer.disconnect();\n runPrefetch();\n }\n },\n { rootMargin: VIEWPORT_MARGIN },\n );\n observer.observe(element);\n return () => observer.disconnect();\n }, [strategyKey, targetHref]);\n\n const intentTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const cancelIntent = () => {\n if (intentTimerRef.current !== null) {\n clearTimeout(intentTimerRef.current);\n intentTimerRef.current = null;\n }\n };\n useEffect(() => cancelIntent, []);\n\n /** A pointer arriving — the one signal `intent` waits on before believing. */\n const pointerArrived = () => {\n if (uses(\"hover\")) {\n runPrefetch();\n } else if (uses(\"intent\")) {\n cancelIntent();\n intentTimerRef.current = setTimeout(runPrefetch, INTENT_DELAY);\n }\n };\n\n /** Focus and touch are deliberate, so neither strategy makes them wait. */\n const linkTargeted = () => {\n if (uses(\"hover\") || uses(\"intent\")) {\n runPrefetch();\n }\n };\n\n /** Runs the caller's own handler first, then the prefetch trigger. */\n const prefetchOn =\n <E extends SyntheticEvent>(\n handler: ((event: E) => void) | undefined,\n trigger: () => void,\n ) =>\n (event: E) => {\n handler?.(event);\n trigger();\n };\n\n return (\n <a\n ref={setAnchorRef}\n data-active={active || currentHref === targetHref}\n // The resolved path, not the template: one template can back a whole list\n // of rows, and only the row that was clicked is heading anywhere.\n data-pending={isTransitioning && resolvedPath === targetPath}\n href={targetHref === '' ? '/' : targetHref}\n onClick={(e) => {\n // The caller's handler always runs, and runs first: it may want to\n // log, close a menu, or cancel the navigation with `preventDefault()`.\n onClick?.(e);\n if (leaveClickToBrowser(e)) {\n return;\n }\n if (currentHref === targetHref) {\n e.preventDefault();\n return;\n }\n let currentPath = window.location.pathname.replace(localeSegment, \"\");\n currentPath = currentPath === \"\" ? \"/\" : currentPath;\n\n if (hash === \"\") {\n e.preventDefault();\n }\n push(href, {\n hash,\n search,\n params,\n shallow: path === currentPath,\n } as unknown as never);\n }}\n onMouseEnter={prefetchOn(onMouseEnter, pointerArrived)}\n onMouseLeave={prefetchOn(onMouseLeave, cancelIntent)}\n onTouchStart={prefetchOn(onTouchStart, linkTargeted)}\n onFocus={prefetchOn(onFocus, linkTargeted)}\n onBlur={prefetchOn(onBlur, cancelIntent)}\n {...rest}\n />\n );\n});\n","import { useEffect } from \"react\";\nimport type { LinkProps } from \"./Link\";\nimport type { ViewPaths } from \"./types\";\n\nimport { useNavigate } from \"./useNavigate\";\n\n// Typed against `LinkProps` directly: `ComponentProps<typeof Link>` comes out\n// `{}` now that `Link` is overloaded, which left `action` the only prop.\nexport const Redirect = <T extends ViewPaths>(\n props: LinkProps<T> & { action: \"push\" | \"replace\" },\n) => {\n const {\n href,\n params = {},\n search = {},\n action = \"replace\",\n } = props as LinkProps<T> & {\n action: \"push\" | \"replace\";\n params?: Record<string, unknown>;\n };\n const { push, replace } = useNavigate();\n\n // The destination decides when to navigate again, because none of the parts\n // it is made of keep their identity: `useNavigate` builds `push` and\n // `replace` fresh on every render, and `params` and `search` fall back to\n // new objects each time. Depending on them directly navigated on every\n // render of whatever holds this — with `action=\"push\"`, one history entry\n // per render, which the back button then has to walk back through.\n const target = JSON.stringify([action, href, params, search]);\n\n useEffect(() => {\n if (action === \"replace\") {\n replace(href, { params, search } as any);\n } else {\n push(href, { params, search } as any);\n }\n }, [target]);\n\n return <></>;\n};\n","import type { HtmlAttributes } from \"../http/Metadata\";\n\nexport type { HtmlAttributes };\n\n// Languages written right to left, by their primary subtag.\nconst RTL_LANGUAGES = new Set([\"ar\", \"arc\", \"ckb\", \"dv\", \"fa\", \"he\", \"iw\", \"ks\", \"ps\", \"sd\", \"ug\", \"ur\", \"yi\"]);\n\n/** The direction `lang` is written in: `\"rtl\"` for Arabic, Hebrew and the like, else `\"ltr\"`. */\nexport function textDirection(lang: string | null | undefined): \"ltr\" | \"rtl\" {\n const language = lang?.split(/[-_]/)[0]?.toLowerCase() ?? \"\";\n return RTL_LANGUAGES.has(language) ? \"rtl\" : \"ltr\";\n}\n\n/**\n * The `<html>` attributes a layout receives: what the response set with\n * `Meta.htmlAttributes`, else the request's locale and its direction.\n */\nexport function resolveHtmlAttributes(\n set: HtmlAttributes | null | undefined,\n locale: string | null | undefined,\n): Required<Pick<HtmlAttributes, \"lang\" | \"dir\">> & HtmlAttributes {\n const lang = set?.lang ?? locale ?? \"en\";\n return { ...set, lang, dir: set?.dir ?? textDirection(lang) };\n}\n\n/** The props gemi renders a root layout (or a static view's layout) with. */\nexport interface RootLayoutProps {\n children: React.ReactNode;\n /** The request's locale; empty when the app configures none. */\n locale: string;\n /** For `<html {...htmlAttributes}>`: `lang` and `dir`, see `Meta.htmlAttributes`. */\n htmlAttributes: ReturnType<typeof resolveHtmlAttributes>;\n}\n","/**\n * `Meta.fonts`: the `@font-face` rules and font preloads of one response.\n * Pure, so the server (validation) and `<Head />` (rendering) share it.\n */\n\n/** A font file format, as `@font-face`'s `format()` names it. */\nexport type FontFormat =\n | \"woff2\"\n | \"woff\"\n | \"truetype\"\n | \"opentype\"\n | \"collection\"\n | \"embedded-opentype\"\n | \"svg\";\n\n/** One file of a font; list the preferred format first. */\nexport type FontSource = {\n url: string;\n /** Inferred from the url's extension when left out. */\n format?: FontFormat;\n};\n\n/** One `@font-face`, see `Meta.fonts`. */\nexport type MetaFont = {\n /** The `font-family` name that CSS refers to, e.g. `\"Acme Sans\"`. */\n family: string;\n /** A url, or several files with the preferred one first. */\n src: string | FontSource[];\n /** `font-weight`: `400`, `\"bold\"`, or a range for a variable font, `\"100 900\"`. */\n weight?: string | number;\n /** `font-style`: `\"normal\"`, `\"italic\"`, `\"oblique 10deg\"`. */\n style?: string;\n /** `font-stretch`: `\"condensed\"`, `\"75% 125%\"`. */\n stretch?: string;\n /** `font-display`. Defaults to `\"swap\"`. */\n display?: \"auto\" | \"block\" | \"swap\" | \"fallback\" | \"optional\";\n /** `unicode-range`, e.g. `\"U+0000-00FF, U+0131\"`. */\n unicodeRange?: string;\n /**\n * Preload the first file with `<link rel=\"preload\" as=\"font\" crossorigin>`.\n * Only for fonts the page renders above the fold: a preloaded font that is\n * never used is a wasted download (and a console warning).\n */\n preload?: boolean;\n};\n\n/** A font after `normalizeFonts`: validated, with every source's format resolved. */\nexport type NormalizedFont = {\n family: string;\n src: { url: string; format: FontFormat | null }[];\n weight: string | null;\n style: string | null;\n stretch: string | null;\n display: NonNullable<MetaFont[\"display\"]>;\n unicodeRange: string | null;\n preload: boolean;\n};\n\nexport type FontPreload = { href: string; type: string | null };\n\nconst FORMATS = new Set<FontFormat>([\n \"woff2\",\n \"woff\",\n \"truetype\",\n \"opentype\",\n \"collection\",\n \"embedded-opentype\",\n \"svg\",\n]);\n\nconst FORMAT_BY_EXTENSION: Record<string, FontFormat> = {\n woff2: \"woff2\",\n woff: \"woff\",\n ttf: \"truetype\",\n otf: \"opentype\",\n ttc: \"collection\",\n eot: \"embedded-opentype\",\n svg: \"svg\",\n};\n\nconst MIME_BY_FORMAT: Partial<Record<FontFormat, string>> = {\n woff2: \"font/woff2\",\n woff: \"font/woff\",\n truetype: \"font/ttf\",\n opentype: \"font/otf\",\n collection: \"font/collection\",\n};\n\nconst DISPLAYS = new Set([\"auto\", \"block\", \"swap\", \"fallback\", \"optional\"]);\n\n// Descriptors are written into the CSS as they are, so only keywords, numbers,\n// angles and percentages pass: nothing that can end the declaration or rule.\nconst DESCRIPTOR = /^[a-zA-Z0-9.%+\\- ]+$/;\nconst UNICODE_RANGE = /^[uU]\\+[0-9a-fA-F?]{1,6}(-[0-9a-fA-F]{1,6})?(\\s*,\\s*[uU]\\+[0-9a-fA-F?]{1,6}(-[0-9a-fA-F]{1,6})?)*$/;\n\nfunction invalid(message: string): never {\n throw new TypeError(`Meta.fonts: ${message}`);\n}\n\n/** The format a url's extension implies (`.woff2` → `\"woff2\"`), ignoring query and hash. */\nexport function fontFormatOf(url: string): FontFormat | null {\n const file = (url.split(/[?#]/)[0] ?? \"\").split(\"/\").pop() ?? \"\";\n const dot = file.lastIndexOf(\".\");\n return dot === -1 ? null : (FORMAT_BY_EXTENSION[file.slice(dot + 1).toLowerCase()] ?? null);\n}\n\nfunction descriptor(name: string, value: string | number | undefined): string | null {\n if (value === undefined || value === null) return null;\n const text = String(value).trim();\n if (!text || !DESCRIPTOR.test(text)) {\n invalid(`${name} ${JSON.stringify(value)} is not a valid font-${name} value`);\n }\n return text;\n}\n\n/** Validates what a handler passed; throws a `TypeError` naming the bad value. */\nexport function normalizeFonts(fonts: MetaFont[]): NormalizedFont[] {\n if (!Array.isArray(fonts)) invalid(\"expected an array of fonts\");\n return fonts.map((font) => {\n if (typeof font?.family !== \"string\" || !font.family.trim()) {\n invalid(\"every font needs a family\");\n }\n const sources = typeof font.src === \"string\" ? [{ url: font.src }] : font.src;\n if (!Array.isArray(sources) || sources.length === 0) {\n invalid(`font \"${font.family}\" needs a src`);\n }\n const src = sources.map((source) => {\n if (typeof source?.url !== \"string\" || !source.url.trim()) {\n invalid(`font \"${font.family}\" has a source without a url`);\n }\n if (source.format !== undefined && !FORMATS.has(source.format)) {\n invalid(`font \"${font.family}\" has an unknown format ${JSON.stringify(source.format)}`);\n }\n return { url: source.url.trim(), format: source.format ?? fontFormatOf(source.url) };\n });\n const display = font.display ?? \"swap\";\n if (!DISPLAYS.has(display)) {\n invalid(`display ${JSON.stringify(display)} is not a valid font-display value`);\n }\n const unicodeRange = font.unicodeRange?.trim() || null;\n if (unicodeRange && !UNICODE_RANGE.test(unicodeRange)) {\n invalid(`unicodeRange ${JSON.stringify(font.unicodeRange)} is not a valid unicode-range`);\n }\n return {\n family: font.family.trim(),\n src,\n weight: descriptor(\"weight\", font.weight),\n style: descriptor(\"style\", font.style),\n stretch: descriptor(\"stretch\", font.stretch),\n display,\n unicodeRange,\n preload: font.preload === true,\n };\n });\n}\n\n/**\n * A CSS string literal holding `value`. Quotes, backslashes, control\n * characters and `<` (so `</style>` can't close the element) are escaped.\n */\nexport function cssString(value: string): string {\n // oxlint-disable-next-line no-control-regex -- escaping them is the point\n const escaped = value.replace(/[\\\\\"<>\\u0000-\\u001f\\u007f]/g, (char) =>\n char === \"\\\\\" || char === '\"' ? `\\\\${char}` : `\\\\${char.charCodeAt(0).toString(16)} `,\n );\n return `\"${escaped}\"`;\n}\n\n/** One `@font-face` rule. */\nexport function fontFaceRule(font: NormalizedFont): string {\n const src = font.src\n .map(({ url, format }) => `url(${cssString(url)})${format ? ` format(${cssString(format)})` : \"\"}`)\n .join(\", \");\n const declarations = [\n `font-family: ${cssString(font.family)}`,\n `src: ${src}`,\n font.weight && `font-weight: ${font.weight}`,\n font.style && `font-style: ${font.style}`,\n font.stretch && `font-stretch: ${font.stretch}`,\n `font-display: ${font.display}`,\n font.unicodeRange && `unicode-range: ${font.unicodeRange}`,\n ].filter(Boolean);\n return `@font-face { ${declarations.join(\"; \")}; }`;\n}\n\n/** The `@font-face` rules for `fonts`, an identical font declared twice once. */\nexport function fontFaceRules(fonts: NormalizedFont[] | null | undefined): string[] {\n return [...new Set((fonts ?? []).map(fontFaceRule))];\n}\n\n/** The first file of every font marked `preload`, each url once. */\nexport function fontPreloads(fonts: NormalizedFont[] | null | undefined): FontPreload[] {\n const preloads = new Map<string, FontPreload>();\n for (const font of fonts ?? []) {\n const first = font.preload ? font.src[0] : undefined;\n if (first && !preloads.has(first.url)) {\n preloads.set(first.url, {\n href: first.url,\n type: (first.format && MIME_BY_FORMAT[first.format]) ?? null,\n });\n }\n }\n return [...preloads.values()];\n}\n","import type { AlternateLink } from \"../http/Metadata\";\nimport { type ReactNode, useContext } from \"react\";\nimport { ServerDataContext } from \"./ServerDataProvider\";\nimport { resolveHtmlAttributes } from \"./htmlAttributes\";\nimport { fontFaceRules, fontPreloads } from \"./fonts\";\n\n/** Marks the `<link>`s rendered from metadata, so a navigation can replace them. */\nconst GEMI_META_ATTRIBUTE = \"data-gemi-meta\";\n\ntype MetaLink = { rel: \"canonical\" | \"alternate\"; href: string; hrefLang?: string };\n\nfunction metaLinks(\n canonical: string | null | undefined,\n alternates: AlternateLink[] | null | undefined,\n): MetaLink[] {\n const links: MetaLink[] = [];\n if (canonical) links.push({ rel: \"canonical\", href: canonical });\n for (const { hrefLang, href } of alternates ?? []) {\n links.push({ rel: \"alternate\", href, hrefLang });\n }\n return links;\n}\n\n/** Marks the `<style>`s holding `Meta.fonts`' `@font-face` rules. */\nconst GEMI_FONTS_ATTRIBUTE = \"data-gemi-fonts\";\n\n/**\n * The `@font-face` rules already in the document. A navigation adds the new\n * page's and removes none: a skipped layout's fonts are still in use, and an\n * unused `@font-face` costs nothing (it is only fetched when text uses it).\n */\nconst appliedFontRules = new Set<string>();\n\n/** Whether a navigation has set `<html>` attributes from metadata. */\nlet htmlAttributesApplied = false;\n\nexport function updateMeta(meta: any, locale?: string | null) {\n // A partially rendered response whose segments set no metadata sends none —\n // what is on the page belongs to the segments that were skipped.\n if (!meta) {\n return;\n }\n const { title, description, htmlAttributes, canonical, alternates, fonts } = meta;\n // A page that set `<html>` attributes gets them; after one, a page that set\n // none goes back to its locale's. A layout that never asked keeps its own.\n if (htmlAttributes || htmlAttributesApplied) {\n htmlAttributesApplied = true;\n for (const [name, value] of Object.entries(resolveHtmlAttributes(htmlAttributes, locale))) {\n if (typeof value === \"string\") {\n document.documentElement.setAttribute(name, value);\n }\n }\n }\n // The links `<Head />` rendered from metadata, and only those: a layout's\n // own `<link>`s are left alone.\n document.head\n .querySelectorAll(`link[${GEMI_META_ATTRIBUTE}]`)\n .forEach((link) => link.remove());\n for (const link of metaLinks(canonical, alternates)) {\n const element = document.createElement(\"link\");\n element.setAttribute(\"rel\", link.rel);\n element.setAttribute(\"href\", link.href);\n if (link.hrefLang) element.setAttribute(\"hreflang\", link.hrefLang);\n element.setAttribute(GEMI_META_ATTRIBUTE, \"\");\n document.head.appendChild(element);\n }\n const newFontRules = fontFaceRules(fonts).filter((rule) => !appliedFontRules.has(rule));\n if (newFontRules.length > 0) {\n const style = document.createElement(\"style\");\n style.setAttribute(GEMI_FONTS_ATTRIBUTE, \"\");\n style.textContent = newFontRules.join(\"\\n\");\n document.head.appendChild(style);\n for (const rule of newFontRules) appliedFontRules.add(rule);\n }\n if (title) {\n document.title = title;\n }\n if (description) {\n const desc = document.querySelector(\"meta[name='description']\");\n if (desc) {\n desc.setAttribute(\"content\", description);\n } else {\n const newDesc = document.createElement(\"meta\");\n newDesc.setAttribute(\"name\", \"description\");\n newDesc.setAttribute(\"content\", description);\n document.head.appendChild(newDesc);\n }\n }\n}\n\nconst OpenGraph = (props: {\n title: string;\n type: string;\n url: string;\n image: string;\n description?: string;\n imageAlt?: string;\n imageWidth?: number;\n imageHeight?: number;\n twitterImage?: string;\n twitterImageAlt?: string;\n twitterImageWidth?: number;\n twitterImageHeight?: number;\n}) => {\n const {\n title,\n description,\n type,\n url,\n image,\n imageAlt,\n imageWidth,\n imageHeight,\n twitterImage,\n twitterImageAlt,\n twitterImageWidth,\n twitterImageHeight,\n } = props;\n\n return (\n <>\n <meta property=\"og:title\" content={title} />\n <meta property=\"og:type\" content={type} />\n <meta property=\"og:url\" content={url} />\n <meta property=\"og:image\" content={image} />\n {description && <meta property=\"og:description\" content={description} />}\n {imageAlt && <meta property=\"og:image:alt\" content={imageAlt} />}\n {imageWidth && (\n <meta property=\"og:image:width\" content={String(imageWidth)} />\n )}\n {imageHeight && (\n <meta property=\"og:image:height\" content={String(imageHeight)} />\n )}\n {twitterImage && (\n <>\n <meta name=\"twitter:image\" content={twitterImage} />\n <meta name=\"twitter:card\" content=\"summary_large_image\" />\n </>\n )}\n {twitterImageAlt && (\n <meta name=\"twitter:image:alt\" content={twitterImageAlt} />\n )}\n {twitterImageWidth && (\n <meta name=\"twitter:image:width\" content={String(twitterImageWidth)} />\n )}\n {twitterImageHeight && (\n <meta\n name=\"twitter:image:height\"\n content={String(twitterImageHeight)}\n />\n )}\n </>\n );\n};\n\nexport const Head = ({\n children = null,\n charSet = \"utf-8\",\n}: { children?: ReactNode; charSet?: string }) => {\n const { meta } = useContext(ServerDataContext);\n // The first page set them, so the layout rendered them: a later page that\n // sets none has to go back to its locale's (`updateMeta`). Only ever read\n // in the browser.\n if (meta?.htmlAttributes) {\n htmlAttributesApplied = true;\n }\n const fontRules = fontFaceRules(meta?.fonts);\n // Browser only: on the server the set would be shared by every request.\n if (typeof window !== \"undefined\") {\n for (const rule of fontRules) appliedFontRules.add(rule);\n }\n return (\n <head>\n <meta charSet={charSet} />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n {/*\n Disable browser auto-translation (Chrome/Google Translate). Gemi apps do\n their own i18n, and a translator that rewrites text nodes *before* React\n hydrates mutates the SSR DOM — which React rejects as a hydration\n mismatch (Minified React error #418) and then regenerates the tree,\n dropping the server-injected <style> and leaving the page unstyled.\n Pair this with `translate=\"no\"` on the <html> element in RootLayout.\n */}\n <meta name=\"google\" content=\"notranslate\" />\n <title>{meta?.title}</title>\n {meta?.description && (\n <meta name=\"description\" content={meta.description} />\n )}\n {meta?.openGraph && <OpenGraph {...meta.openGraph} />}\n {metaLinks(meta?.canonical, meta?.alternates).map((link) => (\n <link\n key={`${link.rel}:${link.hrefLang ?? \"\"}:${link.href}`}\n rel={link.rel}\n href={link.href}\n hrefLang={link.hrefLang}\n {...{ [GEMI_META_ATTRIBUTE]: \"\" }}\n />\n ))}\n {fontPreloads(meta?.fonts).map((preload) => (\n <link\n key={`preload:${preload.href}`}\n rel=\"preload\"\n as=\"font\"\n href={preload.href}\n type={preload.type ?? undefined}\n crossOrigin=\"\"\n />\n ))}\n {fontRules.length > 0 && (\n <style\n {...{ [GEMI_FONTS_ATTRIBUTE]: \"\" }}\n // Escaped by `fontFaceRule`: strings are CSS-escaped (`<` included),\n // descriptors are checked by `Meta.fonts`.\n dangerouslySetInnerHTML={{ __html: fontRules.join(\"\\n\") }}\n />\n )}\n {children}\n </head>\n );\n};\n","import { applyParams } from \"./applyParams\";\n\n/**\n * Route the client is currently rendering, sent on `.json` navigations so the\n * server can skip the handlers of the segments that route already has mounted.\n * Value is a locale-less pathname plus search, e.g. `/app/A/chat?tab=2`.\n */\nexport const PARTIAL_RENDER_HEADER = \"x-gemi-from\";\n\n/** What the server reports back about the skip it performed, if any. */\nexport interface PartialRenderInfo {\n /** The `x-gemi-from` value the plan was computed against. */\n from: string;\n /** View paths of the skipped segments, in order. Their data is carried forward. */\n carriedViews: string[];\n}\n\n/**\n * The `x-gemi-from` value for the route the client starts on.\n *\n * On the first render the router's `pathname` is still the route *pattern* the\n * server matched — it only becomes a resolved path once the history listener\n * has run — so this has to apply the params. Sending `/app/:orgId/chat` names\n * no route the server can resolve, and the first navigation after every full\n * page load would skip nothing.\n */\nexport function initialRenderedRoute(route: {\n pathname?: string;\n params?: Record<string, string>;\n search?: string;\n}) {\n // `applyParams` strips the trailing slash, so the root route resolves to the\n // empty string — which the server reads as \"no header\" and renders in full.\n const pathname = applyParams(route.pathname ?? \"/\", route.params ?? {}) || \"/\";\n return `${pathname}${route.search ?? \"\"}`;\n}\n","import type { Breadcrumb } from \"../useBreadcrumbs\";\n\ninterface RouteSnapshot {\n /** Concrete pathname, without the locale segment. */\n pathname: string;\n /** Route pattern the data was produced for — part of every breadcrumb key. */\n routePath: string;\n data: Record<string, any>;\n breadcrumbs: Record<string, Breadcrumb>;\n}\n\n/**\n * A partially rendered response only carries the segments the server actually\n * ran. Everything is keyed by the *new* pathname, so a carried layout would\n * render with empty props unless the data it already had is copied across.\n *\n * Data the server sent always wins: a carried view is only filled in where the\n * response has nothing for it.\n */\nexport function mergeCarriedSegments(\n previous: RouteSnapshot,\n next: RouteSnapshot,\n carriedViews: string[],\n) {\n if (carriedViews.length === 0) {\n return { data: next.data, breadcrumbs: next.breadcrumbs };\n }\n\n // Page data is keyed by the pathname it was fetched for, and a shallow\n // navigation moves the pathname on without fetching — so fall back to the key\n // the data is actually under. The server sends exactly one.\n const previousData = previous.data ?? {};\n const previousViewData =\n previousData[previous.pathname] ?? previousData[Object.keys(previousData)[0]] ?? {};\n const previousBreadcrumbs = previous.breadcrumbs ?? {};\n\n const carriedViewData: Record<string, unknown> = {};\n const carriedBreadcrumbs: Record<string, Breadcrumb> = {};\n\n for (const viewPath of carriedViews) {\n if (viewPath in previousViewData) {\n carriedViewData[viewPath] = previousViewData[viewPath];\n }\n // Breadcrumbs are keyed by route pattern, and that changed even though the\n // segment did not, so they have to be re-keyed rather than copied.\n const previousKey = `${viewPath}:${previous.routePath}`;\n if (previousKey in previousBreadcrumbs) {\n carriedBreadcrumbs[`${viewPath}:${next.routePath}`] = previousBreadcrumbs[previousKey];\n }\n }\n\n // The server sends page data under exactly one key. Take it from the payload\n // rather than recomputing it, so the two never disagree on spelling.\n const [nextKey = next.pathname] = Object.keys(next.data ?? {});\n\n return {\n data: {\n ...next.data,\n [nextKey]: { ...carriedViewData, ...next.data?.[nextKey] },\n },\n breadcrumbs: { ...carriedBreadcrumbs, ...next.breadcrumbs },\n };\n}\n","import {\n PARTIAL_RENDER_HEADER,\n type PartialRenderInfo,\n} from \"../../utils/partialRender\";\nimport { readRoutePayload, type RouteQueryPayload } from \"./readRoutePayload\";\n\ninterface LoadRoutePayloadOptions {\n /** The `.json` URL for the route being navigated to. */\n url: string;\n /** `x-gemi-from` value for the route currently on screen. */\n from: string;\n /** Hands over a payload warmed ahead of this navigation, if there is one. */\n takePrefetched?: (url: string) => Promise<unknown> | null;\n /**\n * The route that is on screen *now*, re-read at the moment a response lands.\n * A navigation that committed while this one was in flight invalidates the\n * partial-render plan the server computed.\n */\n renderedRoute: () => string;\n /**\n * Receives each query result the server streams behind the envelope\n * (#290) — the caller hydrates it into the cache, which settles any\n * segment suspended on that variant.\n */\n onQueryPayload?: (payload: RouteQueryPayload) => void;\n}\n\n/**\n * The page data for a navigation, from whichever source can produce it.\n *\n * A prefetched payload is always a full render, so it can be committed as-is\n * and the `x-gemi-from` round trip skipped entirely. Everything else — no\n * prefetch, a prefetch that failed, a partial response computed against a route\n * that has since been navigated away from — falls through to a request.\n *\n * Returns `null` when nothing usable came back; the caller leaves the current\n * route on screen.\n */\nexport async function loadRoutePayload(\n options: LoadRoutePayloadOptions,\n): Promise<any> {\n const { url, from, takePrefetched, renderedRoute, onQueryPayload } = options;\n\n const prefetched = takePrefetched?.(url);\n if (prefetched) {\n const payload = await prefetched;\n if (payload) {\n return payload;\n }\n }\n\n let response = { ok: false, json: async () => ({}) } as Response;\n try {\n response = await fetch(url, { headers: { [PARTIAL_RENDER_HEADER]: from } });\n } catch (e) {\n console.error(e);\n return null;\n }\n\n if (!response.ok) {\n return null;\n }\n\n // Resolves with the envelope as soon as its line arrives; query results\n // streaming behind it keep draining into `onQueryPayload`.\n const payload = await readRoutePayload(response, onQueryPayload);\n\n // The segments the server carried forward were computed against a route that\n // is no longer on screen. Nothing sound to merge onto — ask for the whole\n // tree instead.\n const claimed: PartialRenderInfo | null = payload?.partial ?? null;\n if (claimed && claimed.from !== renderedRoute()) {\n try {\n const full = await fetch(url);\n if (full.ok) {\n return await readRoutePayload(full, onQueryPayload);\n }\n } catch (e) {\n console.error(e);\n }\n }\n\n return payload;\n}\n","/**\n * The search parameter carrying the page a signed-out visitor was trying to\n * reach. `AuthenticationMiddleware` writes it onto the sign-in redirect —\n * `/auth/sign-in?redirect=%2Finvoices%3Fpage%3D2` — and `Auth.intendedUrl()` /\n * `useIntendedUrl()` read it back after sign-in.\n */\nexport const INTENDED_URL_PARAM = \"redirect\";\n\n// Only ever compared against, never requested.\nconst PROBE_ORIGIN = \"http://gemi.invalid\";\n\n/**\n * `value` if it is a path on this origin, `fallback` otherwise.\n *\n * The intended URL arrives in a query string anybody can write, so reading it\n * back unchecked is an open redirect: `?redirect=https://evil.example` signs\n * the user in and hands them to a look-alike. Only a same-origin path passes:\n * `//evil.example` and `/\\evil.example` are protocol-relative to a browser and\n * are refused, as is anything a browser would strip control characters out of\n * before resolving.\n *\n * Returns path, search and hash — never an origin — so the result is safe to\n * hand to `push`, `Redirect.to` or a `Location` header alike.\n */\nexport function safeRedirectPath(value: unknown, fallback = \"/\"): string {\n if (typeof value !== \"string\" || !value.startsWith(\"/\")) {\n return fallback;\n }\n if (/[\\u0000-\\u001f\\u007f\\\\]/.test(value) || value.startsWith(\"//\")) {\n return fallback;\n }\n try {\n const url = new URL(value, PROBE_ORIGIN);\n if (url.origin !== PROBE_ORIGIN) {\n return fallback;\n }\n // `push` and `Redirect.to` run their path through `applyParams`, which\n // reads `:x` as a route parameter and collapses `//` — both legal in a\n // query (`?next=https://…`) and in a path. Percent-encoded they mean the\n // same to `URLSearchParams` and survive the trip; left raw, `?redirect=/:x`\n // throws in dev and navigates to `/undefined` in production.\n const tail = `${url.search}${url.hash}`.replaceAll(\"/\", \"%2F\");\n const path = `${url.pathname}${tail}`.replaceAll(\":\", \"%3A\");\n // The `//` test above reads the input, but `.` and `..` segments are\n // resolved away by `new URL` afterwards, and resolving them can *produce* a\n // leading `//`: `/..//evil.example` normalizes to `//evil.example`, which is\n // protocol-relative to a browser. Test what actually goes out.\n return path.startsWith(\"//\") ? fallback : path;\n } catch {\n return fallback;\n }\n}\n\n/**\n * Whether the client addressed this request over https — through the proxy in\n * front if there is one, since TLS is nearly always terminated before the app\n * and a forged `X-Forwarded-Proto` only spoils the forger's own cookie.\n *\n * Not `origin.includes(\"localhost\")`: the URL is built from the `Host` header,\n * so `localhost.evil.example` would read as local and drop `Secure`.\n */\nexport function isSecureRequest(request: Request): boolean {\n const forwarded = request.headers.get(\"x-forwarded-proto\")?.split(\",\")[0]?.trim();\n return forwarded ? forwarded === \"https\" : new URL(request.url).protocol === \"https:\";\n}\n\n/**\n * Whether a `Redirect` directive names somewhere outside the router — an\n * absolute http(s) URL or a protocol-relative one — and so has to leave the\n * page rather than be looked up as a route.\n *\n * Only those two shapes. The value goes to `location.replace`, and *any*\n * scheme that parses would include `javascript:`, which runs in this document\n * rather than navigating away from it: an app passing a user-influenced value\n * to `Redirect.external` would be handing out same-origin script execution.\n * Anything else falls through to the router, which cannot leave the origin.\n */\nexport function isExternalRedirect(path: string | null | undefined): boolean {\n return /^(https?:\\/\\/|\\/\\/)/i.test(path ?? \"\");\n}\n","import {\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n StrictMode,\n memo,\n useTransition,\n Suspense,\n useSyncExternalStore,\n} from \"react\";\n\nimport type { PropsWithChildren, ComponentType, lazy } from \"react\";\nimport { ErrorBoundary, type FallbackProps } from \"react-error-boundary\";\n\nimport { ServerDataContext } from \"./ServerDataProvider\";\nimport { ClientRouterContext, ClientRouterProvider } from \"./ClientRouterContext\";\nimport type { ComponentTree } from \"./types\";\nimport {\n ComponentsContext,\n ComponentsProvider,\n loadViewModule,\n subscribeViewModules,\n} from \"./ComponentContext\";\nimport { QueryManagerContext, QueryManagerProvider, type QueryConfig } from \"./QueryManagerContext\";\nimport { I18nProvider } from \"./I18nContext\";\nimport { useNavigate } from \"./useNavigate\";\nimport { type PageData, type RouteState, RouteStateProvider } from \"./RouteStateContext\";\nimport { applyParams } from \"../utils/applyParams\";\nimport { Action } from \"history\";\nimport { useRouteData } from \"./useRouteData\";\nimport { updateMeta } from \"./Head\";\nimport { resolveHtmlAttributes, type RootLayoutProps } from \"./htmlAttributes\";\nimport { RouteTransitionProvider } from \"./RouteTransitionProvider\";\nimport { ThemeProvider } from \"./ThemeProvider\";\nimport { initialRenderedRoute } from \"../utils/partialRender\";\nimport { mergeCarriedSegments } from \"./helpers/mergeCarriedSegments\";\nimport { routeDataUrl } from \"./helpers/routeDataUrl\";\nimport { loadRoutePayload } from \"./helpers/loadRoutePayload\";\nimport { isExternalRedirect } from \"../utils/intendedUrl\";\n\ndeclare global {\n interface Window {\n scrollHistory: Map<string, number>;\n loaders: Record<string, () => void>;\n }\n}\n\nfunction restoreScroll(action: Action | null = null, _pathname = \"no path\") {\n if (action === null) {\n return;\n }\n\n const { pathname, search, hash } = window.location;\n\n const key = [pathname, search, hash].join(\"\");\n const sh = window.scrollHistory;\n\n const scrollPosition = sh?.get(key);\n\n if (action !== Action.Pop) {\n window.scrollTo(0, 0);\n } else {\n // In dev mode the effect runs scroll restoration\n // will be called twice, this if statement prevents\n // scroll to top\n if (!scrollPosition) {\n return;\n }\n window.scrollTo(0, scrollPosition ?? 0);\n }\n\n sh?.delete(key);\n}\n\ninterface RouteProps {\n componentPath: string;\n pathname: string;\n action: Action | null;\n}\n\nconst DefaultQueryErrorFallback = (props: FallbackProps) => {\n return (\n <div role=\"alert\">\n <p>Something went wrong.</p>\n <button type=\"button\" onClick={() => props.resetErrorBoundary()}>\n Try again\n </button>\n </div>\n );\n};\n\nconst Route = memo((props: PropsWithChildren<RouteProps>) => {\n const { componentPath, pathname, action, children } = props;\n const { viewImportMap, getViewModule } = useContext(ComponentsContext);\n const { clearErrors } = useContext(QueryManagerContext);\n const { data } = useRouteData();\n\n // `Loading` / `Error` are optional named exports of the view module,\n // subscribed so a Route that rendered before its chunk arrived re-reads\n // the registry once it lands. On the server `getViewModule` reads the\n // eagerly-loaded modules the http server passed in — a streaming render\n // suspends for real, so the `Loading` fallback it puts in the shell must be\n // the same one the client hydrates.\n const getModule = useCallback(\n () => getViewModule?.(componentPath),\n [getViewModule, componentPath],\n );\n const mod = useSyncExternalStore(subscribeViewModules, getModule, getModule);\n\n const componentData = data?.[pathname]?.[componentPath] ?? {};\n const Component = viewImportMap[componentPath];\n\n useEffect(() => {\n if (!children) {\n restoreScroll(action, componentPath);\n }\n }, [action, children, componentPath]);\n\n if (!Component) {\n const NotFound = viewImportMap[\"404\"];\n return <NotFound />;\n }\n const Loading = mod?.Loading;\n const ErrorFallback = mod?.Error ?? DefaultQueryErrorFallback;\n\n return (\n <ErrorBoundary FallbackComponent={ErrorFallback} resetKeys={[pathname]} onReset={clearErrors}>\n <Suspense fallback={Loading ? <Loading /> : null}>\n {/* Keyed by view path so swapping views remounts the view (fresh\n state), while the boundary above — keyed by tree slot in `Tree` —\n stays revealed across the swap. */}\n <Component key={componentPath} {...componentData}>\n {props.children}\n </Component>\n </Suspense>\n </ErrorBoundary>\n );\n});\n\nexport const Tree = memo(\n (props: {\n action: Action;\n tree: ComponentTree;\n entries: string[];\n pathname: string;\n /** Index into `entries` this level of the tree renders. */\n depth?: number;\n }) => {\n const { entries, tree, pathname, action, depth = 0 } = props;\n\n return (\n <>\n {/* `entries` is the matched route's chain, outermost layout first, so\n each level renders the one view at its own position. Matching on\n membership instead mounted a view twice when it also sat at\n another depth of the tree (#788). */}\n {tree\n .filter(([path]) => path === entries[depth])\n .map((node, slot) => {\n const [path, subtree] = node;\n // Keyed by tree SLOT, not by view path: the Suspense/error\n // boundary inside `Route` must survive a sibling swap (Home →\n // Pricing under the same layout), so React treats it as already\n // revealed and a suspending navigation keeps the previous page on\n // screen. A path key would remount the boundary every navigation,\n // and a brand-new boundary commits its fallback the moment any\n // sibling content (the layout's re-rendered chrome) commits —\n // blanking the outgoing page. The view itself still remounts when\n // the path changes: `Route` keys its Component render.\n if (subtree.length > 0) {\n return (\n <Route\n action={action}\n key={`slot-${slot}`}\n componentPath={path}\n pathname={pathname}\n >\n <Tree\n action={action}\n tree={subtree}\n entries={entries}\n pathname={pathname}\n depth={depth + 1}\n />\n </Route>\n );\n }\n return (\n <Route\n action={action}\n key={`slot-${slot}`}\n componentPath={path}\n pathname={pathname}\n />\n );\n })}\n </>\n );\n },\n);\n\nconst Routes = (props: { componentTree: ComponentTree }) => {\n const { componentTree } = props;\n const [isPending, startTransition] = useTransition();\n const [isFetching, setIsFetching] = useState(false);\n const { routerSubject, fetchRouteCSS, preloadRouteModules, takePrefetched } =\n useContext(ClientRouterContext);\n const { hydrate } = useContext(QueryManagerContext);\n\n const [transitionPath, setTransitionPath] = useState<[string, string]>([\n null,\n routerSubject?.getValue().pathname,\n ]);\n\n const {\n breadcrumbs,\n pageData,\n i18n,\n prefetchedData,\n features,\n appId: currentAppId,\n } = useContext(ServerDataContext);\n\n const [routeState, setRouteState] = useState<RouteState & PageData>({\n params: routerSubject?.getValue().params,\n search: routerSubject?.getValue().search,\n pathname: routerSubject?.getValue().pathname,\n views: routerSubject?.getValue().views,\n action: null,\n hash: routerSubject?.getValue().hash,\n state: routerSubject?.getValue().state,\n routePath: routerSubject?.getValue().routePath,\n locale: routerSubject?.getValue().locale,\n breadcrumbs,\n data: pageData,\n i18n,\n prefetchedData,\n features: features ?? {},\n appId: currentAppId,\n });\n\n const { replace } = useNavigate();\n\n // Adopt what the document was rendered with. Without this the initial payload\n // only ever reaches a component that mounts on the first render, and one that\n // mounts on a later navigation — into a route whose layout has since been\n // carried forward rather than re-run — would fetch it over `/api` instead.\n useEffect(() => {\n hydrate(prefetchedData);\n }, [hydrate, prefetchedData]);\n\n // The route currently on screen, in `x-gemi-from` form. Updated when a\n // response is committed, never when one is merely requested — a navigation\n // that fails must leave the base the server carries segments from intact.\n const renderedRouteRef = useRef(initialRenderedRoute(routeState));\n\n useEffect(() => {\n return routerSubject?.subscribe(async (routerState) => {\n const { pathname, search, state, views } = routerState;\n setTransitionPath((current) => {\n const [, prevTarget] = current;\n return [prevTarget, pathname];\n });\n if (routerState.views.length === 0) {\n // Same reason as the `is404` branch below: the tree about to be mounted\n // carries none of the segments the stale `from` would have the server\n // skip.\n renderedRouteRef.current = \"\";\n setRouteState((routerState) => ({\n ...routerState,\n views: [\"404\"],\n }));\n return;\n }\n\n if (state?.shallow) {\n setRouteState((state) => ({\n ...state,\n ...routerState,\n }));\n return;\n }\n\n const localeSegment = routerState.locale ? `/${routerState.locale}` : \"\";\n\n const url = routeDataUrl({ pathname, search, localeSegment });\n const from = renderedRouteRef.current;\n setIsFetching(true);\n\n // `fetchRouteCSS` keys off the route manifest, so it needs the pattern\n // rather than the concrete path — `/posts/:id`, not `/posts/123`.\n fetchRouteCSS(routerState.routePath).catch((e) => console.error(e));\n // Announced before the imports below start, so each view's own static\n // imports are already in flight rather than discovered one parse at a\n // time once its chunk lands (#352).\n preloadRouteModules(routerState.routePath);\n // Through `loadViewModule` so the module registry — and with it each\n // view's `Loading`/`Error` exports — is populated before the\n // transition commits the new surface.\n //\n // The rejection is handled by the route's `lazy()`, which reaches the\n // same import, and by the chunk recovery inside `loadViewModule`; left\n // unhandled here it was only noise in an error reporter (folio#2117).\n for (const component of views) {\n loadViewModule(component).catch(() => {});\n }\n\n const payload = await loadRoutePayload({\n url,\n from,\n takePrefetched,\n renderedRoute: () => renderedRouteRef.current,\n // Query results streaming behind the envelope (#290): hydrating each\n // settles the segment suspended on it — the same wake path streamed\n // documents use.\n onQueryPayload: ([path, variantKey, data]) => {\n hydrate({ [path]: { [variantKey]: data } });\n },\n });\n\n if (payload) {\n const {\n data,\n i18n,\n prefetchedData,\n breadcrumbs,\n meta,\n directive = {},\n is404 = false,\n appId,\n features,\n } = payload;\n updateMeta(meta, i18n?.currentLocale ?? i18n?.defaultLocale);\n if (directive?.kind === \"Redirect\") {\n // An absolute URL (`Redirect.external`, an off-origin sign-in page)\n // is not a route: the router would prefix a locale and look it up.\n if (isExternalRedirect(directive?.path)) {\n window.location.replace(directive.path);\n } else if (directive?.path) {\n // `directive.path` is a concrete url the server built, not a route\n // pattern, so there is nothing to substitute. It used to need an\n // empty `params` and an `as unknown` to get past the signature —\n // the framework's own copy of the bug apps hit.\n replace(directive.path);\n }\n\n return;\n }\n\n // Returns, rather than falling through. The commit below spreads\n // `routerState`, which carries the *matched* route's views — so without\n // the return this updater's `[\"404\"]` is queued and then overwritten in\n // the same batch, and the route renders its real views with no data.\n //\n // Reachable only since `.feature()`: a path the client cannot match is\n // caught by the `views.length === 0` guard above and never fetched, so\n // `is404` from the server used to imply an empty client `views`. A gated\n // route keeps its manifest entry, which is exactly the case where the\n // server says 404 and the client still knows how to render the page.\n if (is404) {\n // Not `${pathname}${search}`. `x-gemi-from` tells the server which\n // segments are already mounted so it can skip their handlers, and\n // after this commit the mounted tree is `[\"404\"]` — none of the target\n // route's layouts, and none of the previous route's either. The empty\n // string is what the server reads as \"carry nothing\".\n renderedRouteRef.current = \"\";\n startTransition(() => {\n setRouteState((state) => ({\n ...state,\n ...routerState,\n appId,\n i18n,\n features: features ?? state.features,\n // After the spread, deliberately.\n views: [\"404\"],\n }));\n });\n setIsFetching(false);\n return;\n }\n\n const carriedViews: string[] = payload.partial?.carriedViews ?? [];\n renderedRouteRef.current = `${pathname}${search}`;\n\n // Adopt what the server just prefetched before the new surface mounts\n // and its queries read the cache, otherwise they refetch it over /api.\n // Safe here: this callback is async, so we are past the render phase.\n hydrate(prefetchedData);\n\n startTransition(() => {\n setRouteState((state) => ({\n ...routerState,\n appId,\n i18n,\n // `?? state.features` rather than a bare assignment: an error-path\n // or older-server envelope carrying no flags must leave the current\n // values on screen, not blank every flag mid-session.\n features: features ?? state.features,\n prefetchedData,\n ...mergeCarriedSegments(\n state,\n { pathname, routePath: routerState.routePath, data, breadcrumbs },\n carriedViews,\n ),\n }));\n });\n }\n setIsFetching(false);\n });\n }, [routerSubject, fetchRouteCSS, preloadRouteModules, takePrefetched, replace, hydrate]);\n\n return (\n <RouteTransitionProvider\n isPending={isPending}\n isFetching={isFetching}\n transitionPath={transitionPath}\n >\n <RouteStateProvider state={routeState}>\n <Tree\n action={routeState.action}\n // `applyParams` strips the trailing slash, so the root comes back as\n // `\"\"` while the server keys its data under `/` (#819).\n pathname={applyParams(routeState.pathname ?? \"/\", routeState.params) || \"/\"}\n tree={componentTree}\n entries={routeState.pathname ? routeState.views : [\"404\"]}\n />\n </RouteStateProvider>\n </RouteTransitionProvider>\n );\n};\n\nexport const ClientRouter = (props: {\n viewImportMap?: Record<string, ReturnType<typeof lazy>>;\n /** Server only: full view modules for `Loading`/`Error` fallbacks. */\n viewModules?: Record<string, Record<string, any>>;\n RootLayout: ComponentType<RootLayoutProps>;\n /** App-wide `useQuery` defaults; per-call config always wins. */\n queryConfig?: QueryConfig;\n}) => {\n const { RootLayout } = props;\n const {\n routeManifest,\n router,\n componentTree,\n pageData,\n cssManifest,\n modulePreloadManifest,\n assetBase,\n breadcrumbs,\n i18n,\n meta,\n } = useContext(ServerDataContext);\n const htmlAttributes = resolveHtmlAttributes(\n meta?.htmlAttributes,\n i18n.currentLocale ?? i18n.defaultLocale,\n );\n\n return (\n <ThemeProvider>\n <I18nProvider>\n <QueryManagerProvider queryConfig={props.queryConfig}>\n <ComponentsProvider viewImportMap={props.viewImportMap} modules={props.viewModules}>\n <ClientRouterProvider\n cssManifest={cssManifest}\n modulePreloadManifest={modulePreloadManifest}\n assetBase={assetBase}\n searchParams={router.searchParams}\n params={router.params}\n pageData={pageData}\n is404={router.is404}\n is500={false}\n pathname={router.pathname}\n currentPath={router.currentPath}\n routeManifest={routeManifest}\n breadcrumbs={breadcrumbs}\n urlLocaleSegment={router.urlLocaleSegment}\n >\n <StrictMode>\n <RootLayout locale={i18n.currentLocale} htmlAttributes={htmlAttributes}>\n <Routes componentTree={componentTree} />\n </RootLayout>\n </StrictMode>\n </ClientRouterProvider>\n </ComponentsProvider>\n </QueryManagerProvider>\n </I18nProvider>\n </ThemeProvider>\n );\n};\n","import { useEffect, type ComponentType } from \"react\";\nimport { hydrateRoot, createRoot } from \"react-dom/client\";\nimport { ServerDataProvider } from \"./ServerDataProvider\";\nimport { ClientRouter } from \"./ClientRouter\";\nimport type { QueryConfig } from \"./QueryManagerContext\";\nimport { ErrorBoundary } from \"react-error-boundary\";\nimport { initialViewModulesReady } from \"./ComponentContext\";\nimport {\n configureChunkLoadRecovery,\n recoverFromChunkLoadError,\n type ChunkLoadRecoveryOptions,\n} from \"./chunkLoadRecovery\";\nimport { configureRealtime } from \"./realtime/loader\";\nimport type { RealtimeOptions } from \"./realtime/RealtimeClient\";\n\nexport interface InitOptions {\n /**\n * App-wide `useQuery` defaults (per-call config always wins). Mirror the\n * value passed to `createRoot` in the view router's service provider so the\n * server render and hydration agree.\n */\n queryConfig?: QueryConfig;\n /**\n * What happens when a chunk fails to load — usually a page from an earlier\n * release after a deploy. By default gemi reloads the page it was going to\n * once, and not again within 30 seconds. Pass options to report the failure\n * or veto the reload, or `false` to leave every failure to the route's error\n * boundary. See `recoverFromChunkLoadError`.\n */\n chunkLoadRecovery?: ChunkLoadRecoveryOptions | false;\n /**\n * The broadcast socket the channel hooks use: `path` (match\n * `defineBroadcastConfig({ path })`, default `/__gemi/socket`) and\n * `hiddenDisconnectMs` (how long a hidden tab keeps its socket, default\n * 60 000).\n */\n realtime?: RealtimeOptions;\n}\n\n/**\n * Vite's preload helper fires `vite:preloadError` on `window` when a lazy\n * `import()` in app code — a `lazy(() => import(\"./Chart\"))` inside a view —\n * cannot load a dependency. `preventDefault()` stops the helper rethrowing,\n * which is only right when a reload is actually under way.\n */\nfunction installPreloadErrorRecovery() {\n window.addEventListener(\"vite:preloadError\", (event) => {\n const error = (event as Event & { payload?: unknown }).payload;\n if (recoverFromChunkLoadError(error, { source: \"preload\" })) {\n event.preventDefault();\n }\n });\n}\n\nconst StackTrace = () => {\n useEffect(() => {\n window.addEventListener(\"load\", () => {\n const container = document.getElementById(\"overlay\");\n const ErrorOverlay = customElements.get(\"vite-error-overlay\");\n if (ErrorOverlay) {\n const overlay = new ErrorOverlay({\n message: (window as any).error,\n stack: (window as any).stack_trace || \"\",\n });\n container.appendChild(overlay);\n }\n });\n }, []);\n\n return <div id=\"overlay\" />;\n};\n\nexport function init(\n RootLayout: ComponentType<any>,\n options: InitOptions = {},\n) {\n configureChunkLoadRecovery(options.chunkLoadRecovery);\n if (options.realtime) configureRealtime(options.realtime);\n if (typeof window !== \"undefined\" && options.chunkLoadRecovery !== false) {\n installPreloadErrorRecovery();\n }\n if (typeof window !== \"undefined\" && (window as any).render_error) {\n createRoot(document.body).render(<StackTrace />);\n } else {\n // Held until the current route's view chunks are in the registry, so no\n // segment's first registration lands on a boundary that is mid-hydration.\n // See `initialViewModulesReady`.\n //\n // The `.catch` re-throws out of the microtask for the same reason the\n // bootstrap script wraps the entry `import()` that way: hydration used to\n // run inside the entry's evaluation, so a throw from `hydrateRoot` — a\n // `RootLayout` that fails at module scope, a root already attached —\n // reached that handler. Deferring it past a `.then` puts the throw in a\n // rejection no `window.onerror` reporter sees, and the page sits\n // permanently unhydrated with nothing raised.\n void initialViewModulesReady\n .then(() => hydrate(RootLayout, options))\n .catch((e) => {\n setTimeout(() => {\n throw e;\n });\n });\n }\n}\n\nfunction hydrate(RootLayout: ComponentType<any>, options: InitOptions) {\n hydrateRoot(\n document,\n <>\n <></>\n <></>\n <ErrorBoundary fallback={<div />}>\n <ServerDataProvider>\n <ClientRouter\n RootLayout={RootLayout}\n queryConfig={options.queryConfig}\n />\n </ServerDataProvider>\n </ErrorBoundary>\n </>,\n {\n onCaughtError: (error) => {\n console.error(error);\n // @ts-ignore\n if (import.meta.env.DEV) {\n const ErrorOverlay = customElements.get(\"vite-error-overlay\");\n if (ErrorOverlay) {\n const overlay = new ErrorOverlay({\n message: (error as any).message,\n stack: (error as any).stack || \"\",\n });\n document.body.appendChild(overlay);\n }\n }\n },\n },\n );\n}\n\nexport function create(\n RootLayout: ComponentType<any>,\n {\n componentTree,\n loaders,\n routeManifest,\n router,\n i18n,\n auth,\n prefetchedData,\n viewImportMap,\n }: any,\n) {\n (window as any).__GEMI_DATA__ = {\n componentTree,\n loaders,\n routeManifest,\n router,\n i18n,\n auth,\n prefetchedData,\n pageData: {},\n };\n createRoot(document.getElementById(\"root\")).render(\n <ServerDataProvider>\n <ClientRouter viewImportMap={viewImportMap} RootLayout={RootLayout} />\n </ServerDataProvider>,\n );\n}\n","import { createContext } from \"react\";\nimport type { DictionarySink } from \"../i18n/dictionarySink\";\n\n/**\n * The SSR-only collector `useDictionary` reports into. `null` in the browser,\n * where nothing needs collecting — the strings are already there.\n *\n * Mirrors `ServerQueryContext`: a server-supplied per-request object handed to\n * the tree by `createRoot`.\n */\nexport const DictionarySinkContext = createContext<DictionarySink | null>(null);\n","import type { ComponentType } from \"react\";\nimport { ClientRouter } from \"./ClientRouter\";\nimport { DictionarySinkContext } from \"./DictionarySinkContext\";\nimport type { RootLayoutProps } from \"./htmlAttributes\";\nimport type { QueryConfig } from \"./QueryManagerContext\";\nimport { ServerDataProvider } from \"./ServerDataProvider\";\nimport { ServerQueryContext } from \"./ServerQueryContext\";\n\nexport interface CreateRootOptions {\n /**\n * App-wide `useQuery` defaults (per-call config always wins). Set the same\n * value in the client entry's `init` call so hydration matches the server\n * render.\n */\n queryConfig?: QueryConfig;\n}\n\nexport function createRoot(\n RootLayout: ComponentType<RootLayoutProps>,\n options: CreateRootOptions = {},\n) {\n // `serverQueries`, `viewModules` and `dictionarySink` exist only when the view\n // router renders this on the server — the browser mounts with all three absent.\n // So does `rootLayout`: a static view's own document layout\n // (`.static({ layout })`), which replaces the app's for that render only.\n return (props: any) => (\n <ServerDataProvider value={props.data}>\n <ServerQueryContext.Provider value={props.serverQueries ?? null}>\n <DictionarySinkContext.Provider value={props.dictionarySink ?? null}>\n <ClientRouter\n RootLayout={props.rootLayout ?? RootLayout}\n viewImportMap={props.viewImportMap}\n viewModules={props.viewModules}\n queryConfig={options.queryConfig}\n />\n </DictionarySinkContext.Provider>\n </ServerQueryContext.Provider>\n </ServerDataProvider>\n );\n}\n","import type { ComponentProps } from \"react\";\n\nconst defaultScreen = [390, 768, 1024];\nconst defaultContainer = [100, 100, 100, 100];\n\nfunction generateImageProps(\n src: string,\n width: number,\n container = defaultContainer,\n screen = defaultScreen,\n quality = 80,\n) {\n const baseUrl = src;\n\n const widths = [...container.map((c, i) => (screen[i] * c) / 100), width * 2];\n\n return {\n srcSet: [\n ...screen.map((size, i) => {\n return `/api/__gemi__/services/image/resize?url=${baseUrl}&q=${quality}&w=${widths[i]} ${size}${isNaN(Number(size)) ? \"\" : \"w\"}`;\n }),\n `/api/__gemi__/services/image/resize?url=${baseUrl}&q=${quality}&w=${width * 2} 2x`,\n ].join(\", \"),\n sources: [\n ...container.map((c, i) => {\n if (!screen[i]) {\n return `${c}vw`;\n }\n return `(max-width: ${screen[i]}px) ${c}vw`;\n }),\n ].join(\", \"),\n };\n}\n\nfunction fillRestWithLast<T>(arr: T[], length: number): T[] {\n return [\n ...arr,\n ...Array.from({ length: length - arr.length }).fill(arr[arr.length - 1]),\n ] as T[];\n}\n\ninterface ImageProps {\n src: string;\n width: number;\n container?: number[];\n screen?: number[];\n quality?: number;\n}\n\nexport const Image = (props: ComponentProps<\"img\"> & ImageProps) => {\n const {\n screen = defaultScreen,\n container = defaultContainer,\n src,\n width,\n quality = 80,\n srcSet: __,\n ...rest\n } = props;\n\n if (!src) {\n return null;\n }\n\n const srcProps = generateImageProps(\n src,\n width,\n fillRestWithLast(container, 4),\n screen,\n quality,\n );\n\n return <img {...srcProps} width={width} {...rest} />;\n};\n","import { usePost } from \"../useMutation\";\n\ninterface UseForgotPasswordArgs {\n onSuccess: () => void;\n}\n\nconst defaultArgs: UseForgotPasswordArgs = {\n onSuccess: () => {},\n};\n\nexport function useForgotPassword(args: UseForgotPasswordArgs = defaultArgs) {\n return usePost(\n \"/auth/forgot-password\",\n {},\n {\n onSuccess: () => {\n args.onSuccess();\n },\n },\n );\n}\n","import { usePost } from \"../useMutation\";\nimport { useFrameworkQuery } from \"../useQuery\";\nimport { reconnectRealtime } from \"../realtime/loader\";\n\ninterface UseSignInArgs {\n onSuccess?: (data: any) => void;\n}\n\nconst defaultArgs: UseSignInArgs = {\n onSuccess: () => {},\n};\n\nexport function useSignIn(args: UseSignInArgs = defaultArgs) {\n // Only here for `mutate` — `lazy` so the sign-in form neither fetches nor\n // suspends on a user it does not have yet. `useFrameworkQuery` keeps that\n // pinned regardless of the app's `queryConfig`.\n const { mutate } = useFrameworkQuery(\"/auth/me\", {}, { lazy: true });\n return usePost(\n \"/auth/sign-in\",\n {},\n {\n onSuccess: (user) => {\n args.onSuccess(user);\n mutate(user as any);\n // The socket was opened as a guest: authorize its channels as the user.\n reconnectRealtime();\n },\n },\n );\n}\n","import { usePost } from \"../useMutation\";\n\nexport function useSignUp() {\n return usePost(\"/auth/sign-up\");\n}\n","import { useMutate } from \"../useMutate\";\nimport { usePost } from \"../useMutation\";\nimport { reconnectRealtime } from \"../realtime/loader\";\n\ninterface UseSignOutArgs {\n onSuccess?: () => void;\n}\n\nconst defaultArgs: UseSignOutArgs = {\n onSuccess: () => {},\n};\n\nexport function useSignOut(args: UseSignOutArgs = defaultArgs) {\n const mutator = useMutate();\n return usePost(\n \"/auth/sign-out\",\n {},\n {\n onSuccess: () => {\n args.onSuccess();\n mutator({ path: \"/auth/me\" });\n // The socket was opened as the signed-in user.\n reconnectRealtime();\n },\n },\n );\n}\n","import { usePost } from \"../useMutation\";\n\ninterface UseResetPasswordArgs {\n onSuccess: () => void;\n}\n\nconst defaultArgs: UseResetPasswordArgs = {\n onSuccess: () => {},\n};\n\nexport function useResetPassword(args: UseResetPasswordArgs = defaultArgs) {\n return usePost(\n \"/auth/reset-password\",\n {},\n {\n onSuccess: () => {\n args.onSuccess();\n },\n },\n );\n}\n","import { useContext } from \"react\";\nimport { ServerDataContext } from \"../ServerDataProvider\";\nimport { useFrameworkQuery } from \"../useQuery\";\nimport {\n QueryConfigContext,\n USER_QUERY_CONFIG_KEYS,\n pickDefined,\n type UserQueryConfig,\n} from \"../QueryManagerContext\";\n\n/**\n * The signed-in user, or `null`. `config` tunes the `/auth/me` query — its\n * freshness window and retry policy — over the app-wide `queryConfig.user`;\n * the app's general `queryConfig` never applies here.\n */\nexport function useUser(config?: UserQueryConfig) {\n const { auth } = useContext(ServerDataContext);\n const appUserConfig = useContext(QueryConfigContext)?.user;\n const {\n data: user,\n loading,\n error,\n // `useFrameworkQuery`: the semantics below are pinned, so an app-wide\n // `queryConfig` must not leak in. Only the `UserQueryConfig` keys are\n // taken, from `queryConfig.user` and then the call.\n } = useFrameworkQuery(\n \"/auth/me\",\n {},\n {\n ...pickDefined(appUserConfig, USER_QUERY_CONFIG_KEYS),\n ...pickDefined(config, USER_QUERY_CONFIG_KEYS),\n fallbackData: auth?.user ? auth.user : null,\n // An anonymous visitor has no `/auth/me` data and never will — this\n // must resolve to `user: null`, not suspend the page behind a 401. The\n // 401 is not retried (see `retry`), so it is one request, not a poll.\n suspense: false,\n },\n );\n\n if (loading && !user) {\n return { user: null, loading, error };\n }\n\n return { user: user, loading, error };\n}\n","import { useSearchParams } from \"../useSearchParams\";\nimport { INTENDED_URL_PARAM, safeRedirectPath } from \"../../utils/intendedUrl\";\n\n/**\n * The page a signed-out visitor was sent to sign-in from, for the sign-in page\n * to return them to: `AuthenticationMiddleware` puts it on the sign-in URL as\n * `?redirect=`. `fallback` when there is none, or when it is not a path on\n * this origin — the parameter is attacker-writable, and following it\n * unchecked is an open redirect.\n *\n * ```tsx\n * const intended = useIntendedUrl(\"/dashboard\");\n * <Form action=\"/auth/sign-in-v2\" onSuccess={() => push(intended)} />\n * ```\n */\nexport function useIntendedUrl(fallback = \"/\"): string {\n return safeRedirectPath(useSearchParams().get(INTENDED_URL_PARAM), fallback);\n}\n","import { useState } from \"react\";\nimport { usePost } from \"../useMutation\";\nimport { useFrameworkQuery } from \"../useQuery\";\nimport { reconnectRealtime } from \"../realtime/loader\";\n\ninterface UseEmailCodeArgs {\n /** After `verify` signs in. `isNewUser` is true when the account was just created. */\n onSuccess?: (result: { session: any; isNewUser: boolean }) => void;\n}\n\n/**\n * Passwordless sign-up-or-sign-in with a one-time email code, in place — no\n * redirect, so it fits a dialog (#708). Needs `auth.emailCode.enabled`.\n *\n * ```tsx\n * const { request, verify, isPending, error } = useEmailCode();\n * await request(email); // always { ok: true }\n * const r = await verify(email, code); // { session, isNewUser } or undefined\n * ```\n *\n * `error` is the outcome of the latest call, `request` or `verify`: a\n * `validation_error` on `email` or `code` (`invalid_code`,\n * `too_many_attempts`), a 429 `rate_limit`, or `null` once that call succeeds.\n * A failed `verify` followed by \"send a new code\" therefore shows the\n * request's error, or nothing, not the stale `invalid_code` (#724).\n * `requestError` and `verifyError` hold each call's own last error. A\n * successful `verify` refreshes `useUser()`.\n */\nexport function useEmailCode(args: UseEmailCodeArgs = {}) {\n const { mutate } = useFrameworkQuery(\"/auth/me\", {}, { lazy: true });\n const requestMutation = usePost(\"/auth/email-code\");\n const verifyMutation = usePost(\n \"/auth/email-code/verify\",\n {},\n {\n onSuccess: (result: any) => {\n if (result?.session?.user) {\n mutate(result.session.user);\n // The socket was opened as a guest: authorize its channels as the user.\n reconnectRealtime();\n }\n args.onSuccess?.(result);\n },\n },\n );\n\n // Each mutation keeps its error until it runs again, so either one alone\n // can be stale. The latest call decides which one `error` reports.\n const [latest, setLatest] = useState<\"request\" | \"verify\" | null>(null);\n const error =\n latest === \"verify\"\n ? verifyMutation.error\n : latest === \"request\"\n ? requestMutation.error\n : null;\n const isPending = requestMutation.loading || verifyMutation.loading;\n\n return {\n request: (email: string) => {\n setLatest(\"request\");\n return requestMutation.trigger({ email } as any);\n },\n verify: (email: string, code: string, extra: { name?: string } = {}) => {\n setLatest(\"verify\");\n return verifyMutation.trigger({ email, code, ...extra } as any);\n },\n isPending,\n error,\n requestError: requestMutation.error,\n verifyError: verifyMutation.error,\n };\n}\n","import { useContext } from \"react\";\nimport { RouteStateContext } from \"./RouteStateContext\";\nimport type { ClientFeatureKey } from \"./rpc\";\n\n/**\n * Reads a feature evaluated by the server for this request.\n *\n * ```tsx\n * if (useFeature(\"new-checkout\")) {\n * return <NewCheckout />;\n * }\n * ```\n *\n * Keys are typed against `app/features`, so a typo is a compile error rather\n * than a feature that silently reads as off. Features declared\n * `serverOnly: true` are excluded from that set: they are withheld from the\n * payload on purpose, so reading one here could only ever answer `false`. Use\n * the `Features` facade for those.\n *\n * ## It never fetches\n *\n * The value comes from the payload the server already sent — embedded in the\n * document on first load, and replaced by each navigation's envelope after\n * that. So this is a context read: no request, no suspense, no loading state,\n * and no flash of the wrong branch, which is the failure mode that makes\n * client-evaluated features unusable for anything above the fold.\n *\n * The corollary is that switching a feature on reaches an open page on its next\n * navigation, not instantly.\n *\n * ## Reads route state, not server data\n *\n * `RouteStateContext` is what each navigation replaces — the same reason\n * `useLocale` reads it. Reading `ServerDataContext` instead would pin every\n * feature to the values from the initial document for the life of the session.\n */\nexport function useFeature(key: ClientFeatureKey): boolean {\n // `= {}` because several existing tests provide a bare object as page data,\n // and an error-path envelope may carry no features at all.\n const { features = {} } = useContext(RouteStateContext);\n\n if (process.env.NODE_ENV !== \"production\" && !(key in features)) {\n // Both reasons, because the type system only rules out the second one for a\n // caller whose `gemi.d.ts` resolved — and \"declare it\" is actively wrong\n // advice for the app that already did, then marked it `serverOnly`.\n console.warn(\n `[gemi] Feature \"${String(key)}\" is not in the payload the server sent. Either it is not declared in app/features, or it is declared \\`serverOnly: true\\` and never reaches the browser.`,\n );\n }\n\n // An unknown key reads as off rather than throwing: a feature deleted from the\n // declarations, or a payload that predates one, must not white-screen a page\n // that renders it.\n return features[key as string] === true;\n}\n\n/**\n * Every feature the server sent, for a component that needs to branch on\n * several at once or forward them somewhere.\n */\nexport function useFeatures(): Record<string, boolean> {\n const { features = {} } = useContext(RouteStateContext);\n return features;\n}\n","import { createElement, Fragment, isValidElement, type JSX } from \"react\";\n\ntype TemplateParams = Record<\n string,\n string | ((p: unknown) => string | JSX.Element)\n>;\n\nexport function parseTranslation(template: string, params: TemplateParams) {\n // Check if we have any JSX in our parameters\n const hasJSX = Object.values(params).some(\n (value) =>\n typeof value === \"function\" &&\n isValidElement((value as (p: unknown) => unknown)(\"\")),\n );\n\n // Regular expression to match template variables:\n // {{name}} - simple variable\n // {{name:type}} - variable with type casting\n // {{name:[content]}} - variable with interpolated content\n const regex = /{{([^{}]+?)(?::([^{}\\[\\]]+?))?(?:\\[(.*?)\\])?}}/g;\n\n if (!hasJSX) {\n // Simple string replacement\n const result = template.replace(regex, (match, name, type, content) => {\n // Clean the name part by removing any colon if present\n const cleanName = name.includes(\":\") ? name.split(\":\")[0] : name;\n\n const value = params[cleanName];\n if (value === undefined) {\n return match; // Return original match if no parameter found\n }\n\n if (typeof value === \"function\") {\n // If value is a function, call it with the content if available\n const functionParam = content !== undefined ? content : \"\";\n const functionResult = value(functionParam);\n // Check if function returned JSX - this shouldn't happen in the string branch\n if (isValidElement(functionResult)) {\n throw new Error(\"JSX returned in string context\");\n }\n return String(functionResult);\n }\n\n // Handle type casting if specified\n if (type) {\n switch (type.toLowerCase()) {\n case \"number\":\n return Number(value).toString();\n case \"string\":\n return String(value);\n case \"boolean\":\n return Boolean(value).toString();\n default:\n return String(value);\n }\n }\n return String(value);\n });\n return result as any;\n } else {\n // JSX replacement - we'll split the template into parts\n const parts: Array<string | JSX.Element> = [];\n let lastIndex = 0;\n let match: RegExpExecArray | null = null;\n\n while ((match = regex.exec(template)) !== null) {\n const [fullMatch, name, type, content] = match;\n const matchIndex = match.index;\n\n // Clean the name part by removing any colon if present\n const cleanName = name.includes(\":\") ? name.split(\":\")[0] : name;\n\n // Add text before the match\n if (matchIndex > lastIndex) {\n parts.push(template.substring(lastIndex, matchIndex));\n }\n\n const value = params[cleanName];\n if (value === undefined) {\n // Keep original template variable if no parameter found\n parts.push(fullMatch);\n } else if (typeof value === \"function\") {\n // If value is a function, call it with the content if available\n const functionParam = content !== undefined ? content : \"\";\n const functionResult = value(functionParam);\n parts.push(functionResult);\n } else if (type) {\n // Handle type casting if specified\n switch (type.toLowerCase()) {\n case \"number\":\n parts.push(Number(value).toString());\n break;\n case \"string\":\n parts.push(String(value));\n break;\n case \"boolean\":\n parts.push(Boolean(value).toString());\n break;\n default:\n parts.push(String(value));\n }\n } else {\n parts.push(String(value));\n }\n\n lastIndex = matchIndex + fullMatch.length;\n }\n\n // Add any remaining text\n if (lastIndex < template.length) {\n parts.push(template.substring(lastIndex));\n }\n\n // Convert the parts array to JSX\n return createElement(Fragment, {}, ...parts) as any;\n }\n}\n","import type { I18nDictionary } from \"./rpc\";\nimport type { ParseTranslationParams, Prettify } from \"../utils/type\";\nimport type { JSX } from \"react\";\nimport { parseTranslation } from \"../utils/parseTranslation\";\nimport { useRouteData } from \"./useRouteData\";\n\ntype Parser<T extends Record<string, string>> = Prettify<\n {\n [K in keyof T]: ParseTranslationParams<T[K]>;\n }[keyof T]\n>;\n\ntype ParamsOrNever<T> = T extends Record<string, never>\n ? [params?: never]\n : [params: T];\n\n/**\n * @deprecated Use `useDictionary(dict)` with a `defineDictionary` dictionary\n * declared next to the component. This resolves a dictionary by name through\n * the global `I18nDictionary` interface, which needs a `gemi.d.ts`\n * declaration, a central `app/i18n/index.ts`, and a hand-maintained `prefetch`\n * map naming every route's dictionaries — and it ships whatever that map says\n * whether the page reads it or not. Still supported; see `docs/i18n.md`.\n */\nexport function useTranslator<T extends keyof I18nDictionary>(component: T) {\n const { i18n } = useRouteData();\n\n function parse<\n K extends keyof I18nDictionary[T][\"dictionary\"],\n U extends Record<string, string> = I18nDictionary[T][\"dictionary\"][K],\n >(key: K, ...args: ParamsOrNever<Parser<U>>) {\n try {\n const translations = i18n.dictionary[i18n.currentLocale][component];\n const [params = {}] = args;\n return parseTranslation(translations[key as any], params);\n } catch (err) {\n console.error(\n `Unresolved translation Component:${component} key:${String(key)}`,\n );\n return String(key);\n }\n }\n\n parse.jsx = <\n K extends keyof I18nDictionary[T][\"dictionary\"],\n U extends Record<string, string> = I18nDictionary[T][\"dictionary\"][K],\n >(\n key: K,\n ...args: ParamsOrNever<Parser<U>>\n ) => {\n return parse(key, ...(args as any)) as unknown as JSX.Element;\n };\n\n return parse;\n}\n","/**\n * Locale- and time-zone-aware formatting, shared by `useFormatter`, the\n * `format` property of a `useDictionary` result and `Lang.formatter()`.\n *\n * Dependency-free on purpose: components import it, so it must not pull in the\n * server facades.\n *\n * Why the time zone is pinned: a `Date` formatted with no `timeZone` uses the\n * runtime's zone, which is the server's during SSR and the viewer's in the\n * browser. The two disagree for anyone not sitting in the server's zone, so the\n * same instant can print a different hour, or a different day, on each side —\n * a hydration mismatch at best, a wrong date at worst. Every formatter here\n * carries one zone, resolved on the server and shipped with the page, so both\n * sides print the same text.\n */\n\nexport type DateInput = Date | number | string;\n\nexport interface FormatterInit {\n /** BCP 47 locale tag. */\n locale: string;\n /** IANA time zone, such as `UTC` or `Europe/Istanbul`. */\n timeZone: string;\n}\n\nexport interface Formatter {\n readonly locale: string;\n readonly timeZone: string;\n /** A date, `{ dateStyle: \"medium\" }` unless options are given. */\n date(value: DateInput, options?: Intl.DateTimeFormatOptions): string;\n /** A time of day, `{ timeStyle: \"short\" }` unless options are given. */\n time(value: DateInput, options?: Intl.DateTimeFormatOptions): string;\n /** Date and time, `{ dateStyle: \"medium\", timeStyle: \"short\" }` unless options are given. */\n dateTime(value: DateInput, options?: Intl.DateTimeFormatOptions): string;\n number(value: number | bigint, options?: Intl.NumberFormatOptions): string;\n relative(\n value: number,\n unit: Intl.RelativeTimeFormatUnit,\n options?: Intl.RelativeTimeFormatOptions,\n ): string;\n list(values: Iterable<string>, options?: Intl.ListFormatOptions): string;\n /** The CLDR plural category for `count`: `one`, `few`, `other`, … */\n plural(count: number, options?: Intl.PluralRulesOptions): Intl.LDMLPluralRule;\n /**\n * The cached `Intl.DateTimeFormat` behind `date`/`time`/`dateTime`, with the\n * formatter's zone applied. For `formatToParts` or `formatRange`.\n */\n dateTimeFormat(options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat;\n}\n\n/** The zone used when the app configures none. */\nexport const DEFAULT_TIME_ZONE = \"UTC\";\n\n/**\n * Whether `timeZone` is an IANA zone (or offset) this runtime's `Intl` accepts.\n * An unknown zone makes `Intl.DateTimeFormat` throw a `RangeError`, so a zone\n * that comes from a cookie or a user record is checked before it is trusted.\n */\nexport function isValidTimeZone(timeZone: unknown): timeZone is string {\n if (typeof timeZone !== \"string\" || timeZone.length === 0) {\n return false;\n }\n try {\n new Intl.DateTimeFormat(\"en-US\", { timeZone });\n return true;\n } catch {\n return false;\n }\n}\n\n// Constructing an `Intl` formatter is the expensive part — it resolves locale\n// data — so each one is built once per (kind, locale, options). Options are\n// keyed by their JSON; callers pass small literal objects, and a key order\n// difference only costs a duplicate entry, never a wrong result.\nconst cache = new Map<string, unknown>();\nconst CACHE_LIMIT = 500;\n\nfunction cached<T>(key: string, create: () => T): T {\n let value = cache.get(key) as T | undefined;\n if (value === undefined) {\n if (cache.size >= CACHE_LIMIT) {\n // Insertion order: drop the oldest. Unbounded user-driven option objects\n // (a currency per row) must not grow a long-lived server process forever.\n cache.delete(cache.keys().next().value!);\n }\n value = create();\n cache.set(key, value);\n }\n return value;\n}\n\nfunction toDate(value: DateInput): Date {\n return value instanceof Date ? value : new Date(value);\n}\n\nfunction hasDateTimeFields(options: Intl.DateTimeFormatOptions): boolean {\n return (\n options.dateStyle !== undefined ||\n options.timeStyle !== undefined ||\n options.weekday !== undefined ||\n options.era !== undefined ||\n options.year !== undefined ||\n options.month !== undefined ||\n options.day !== undefined ||\n options.dayPeriod !== undefined ||\n options.hour !== undefined ||\n options.minute !== undefined ||\n options.second !== undefined ||\n options.fractionalSecondDigits !== undefined ||\n options.timeZoneName !== undefined\n );\n}\n\nexport function createFormatter(init: FormatterInit): Formatter {\n const { locale, timeZone } = init;\n\n const dateTimeFormat = (options: Intl.DateTimeFormatOptions = {}) => {\n // `??`, not a spread: `{ timeZone: undefined }` would otherwise drop the\n // pinned zone and fall back to the runtime's, which is the bug this exists\n // to prevent.\n const resolved = { ...options, timeZone: options.timeZone ?? timeZone };\n return cached(`dt|${locale}|${JSON.stringify(resolved)}`, () => {\n return new Intl.DateTimeFormat(locale, resolved);\n });\n };\n\n const withDefaults = (\n options: Intl.DateTimeFormatOptions | undefined,\n defaults: Intl.DateTimeFormatOptions,\n ) => {\n if (options && hasDateTimeFields(options)) {\n return options;\n }\n // Options that only tweak (a `timeZone`, `hour12`) still get the default\n // fields; otherwise `{ timeZone }` alone would print a bare numeric date.\n return { ...defaults, ...options };\n };\n\n return {\n locale,\n timeZone,\n date(value, options) {\n return dateTimeFormat(withDefaults(options, { dateStyle: \"medium\" })).format(\n toDate(value),\n );\n },\n time(value, options) {\n return dateTimeFormat(withDefaults(options, { timeStyle: \"short\" })).format(\n toDate(value),\n );\n },\n dateTime(value, options) {\n return dateTimeFormat(\n withDefaults(options, { dateStyle: \"medium\", timeStyle: \"short\" }),\n ).format(toDate(value));\n },\n number(value, options = {}) {\n return cached(\n `n|${locale}|${JSON.stringify(options)}`,\n () => new Intl.NumberFormat(locale, options),\n ).format(value);\n },\n relative(value, unit, options = {}) {\n return cached(\n `r|${locale}|${JSON.stringify(options)}`,\n () => new Intl.RelativeTimeFormat(locale, options),\n ).format(value, unit);\n },\n list(values, options = {}) {\n return cached(\n `l|${locale}|${JSON.stringify(options)}`,\n () => new Intl.ListFormat(locale, options),\n ).format(values);\n },\n plural(count, options = {}) {\n return cached(\n `p|${locale}|${JSON.stringify(options)}`,\n () => new Intl.PluralRules(locale, options),\n ).select(count);\n },\n dateTimeFormat,\n };\n}\n","import { useMemo } from \"react\";\nimport {\n createFormatter,\n DEFAULT_TIME_ZONE,\n isValidTimeZone,\n type Formatter,\n} from \"../i18n/formatter\";\nimport { useRouteData } from \"./useRouteData\";\n\n/**\n * Format dates, numbers, relative times and lists in the active locale and the\n * app's time zone.\n *\n * ```tsx\n * const format = useFormatter();\n * format.date(order.createdAt, { dateStyle: \"long\" });\n * format.number(1199.88, { style: \"currency\", currency: \"USD\" });\n * format.date(order.createdAt, { timeZone: \"Europe/Istanbul\" }); // per call\n * ```\n *\n * The locale and zone both come from the page payload, so the server render\n * and the hydrating browser format with the same ones. Prefer this to\n * `toLocaleDateString()`, which uses the runtime's locale and zone and so\n * differs between the two.\n *\n * Pass `options` to pin a zone for one subtree (`useFormatter({ timeZone })`).\n */\nexport function useFormatter(\n options: { locale?: string; timeZone?: string } = {},\n): Formatter {\n const { i18n } = useRouteData();\n const locale =\n options.locale ?? i18n?.currentLocale ?? i18n?.defaultLocale ?? \"en-US\";\n // An explicit zone is trusted and throws from `Intl` if it is wrong, like a\n // per-call one. The payload's was validated on the server; the check is for\n // a hand-built payload (tests, an older server) that has none.\n const timeZone =\n options.timeZone ??\n (isValidTimeZone(i18n?.timeZone) ? i18n.timeZone : DEFAULT_TIME_ZONE);\n\n return useMemo(\n () => createFormatter({ locale, timeZone }),\n [locale, timeZone],\n );\n}\n","import { use, useContext, type JSX } from \"react\";\nimport type { DictionaryHandle } from \"../i18n/defineDictionary\";\nimport { setActiveLocale } from \"../i18n/dictionaryRegistry\";\nimport type { DictionaryTranslations } from \"../i18n/dictionaryShape\";\nimport { parseTranslation } from \"../utils/parseTranslation\";\nimport type { ParseTranslationParams, Prettify } from \"../utils/type\";\nimport { DictionarySinkContext } from \"./DictionarySinkContext\";\nimport { useFormatter } from \"./useFormatter\";\nimport { useRouteData } from \"./useRouteData\";\n\ntype Parser<T extends Record<string, string>> = Prettify<\n {\n [K in keyof T]: ParseTranslationParams<T[K]>;\n }[keyof T]\n>;\n\ntype ParamsOrNever<T> = T extends Record<string, never>\n ? [params?: never]\n : [params: T];\n\n/**\n * Read a dictionary declared with `defineDictionary`, next to the component\n * that uses it.\n *\n * ```tsx\n * const t = useDictionary(homeDict);\n * t(\"title\", { name });\n * ```\n *\n * Keys and interpolation params come straight from the literal — there is no\n * name string to keep in sync and no `gemi.d.ts` augmentation.\n *\n * Normally this resolves without suspending: the server seeds the strings it\n * rendered with into the hydration payload, and the router warms a view's\n * dictionaries while it is already loading that view's chunks. It falls back to\n * suspending on the locale's chunk when neither happened — a dictionary inside\n * a `lazy()` subtree, or the first render after a locale switch.\n *\n * Replaces `useTranslator`, which is deprecated.\n */\nexport function useDictionary<const T extends DictionaryTranslations>(\n dictionary: DictionaryHandle<T>,\n) {\n const { i18n } = useRouteData();\n const sink = useContext(DictionarySinkContext);\n // An app with i18n switched off still renders dictionaries — fall back to the\n // source language rather than blowing up on an empty `i18n` payload.\n const locale = i18n?.currentLocale ?? dictionary.locales[0];\n // Tells the view loader which locale's chunks to warm on the next\n // navigation. `__GEMI_DATA__` only knows the locale the document loaded in.\n setActiveLocale(locale);\n // Before `use()` below, so the hook order is the same on a replayed render.\n // Same locale the strings resolve in, so `t.format` never disagrees with `t`.\n const format = useFormatter({ locale });\n\n // `loadForRender`, not the plain loader: a rejected locale chunk must not\n // rethrow out of `use()` and take the route down. It degrades to no strings,\n // and the per-key lookup below falls back to the key — what `useTranslator`\n // did. Called on the handle rather than the registry so a dictionary declared\n // at module scope survives the registry being reset under it.\n //\n // `use()` on every thenable a render could have suspended on, including once\n // it has resolved (#494): React replays a component that suspended in `use()`\n // once the thenable resolves, and only `use()` itself puts the mount hook\n // dispatcher back — so a replay that took the synchronous path would run\n // every later hook under the update dispatcher and throw \"Update hook called\n // on initial render\" at the first `useState`.\n //\n // Strings that were already in hand when their thenable was made skip it\n // (#542): no render ever suspended on that thenable, and under `act` even a\n // fulfilled `use()` makes a later thrown suspense (a `useQuery`) park forever.\n const thenable = dictionary.loadForRender(locale);\n const strings = thenable.inHand ?? use(thenable);\n\n // Reported from the render phase, and deliberately so: on the server the\n // strings have to reach the document before the segment that used them is\n // revealed, or hydration would find them missing and refetch. The sink\n // de-duplicates, and it is null in the browser.\n sink?.use(dictionary.id, locale, strings);\n\n // Annotated `string` rather than inferred: `parseTranslation` returns `any`\n // (it hands back a JSX element on the `t.jsx` path), and letting that leak\n // through would silently defeat the key and param checking below — every\n // call site would typecheck against `any`.\n function parse<K extends keyof T & string, U extends T[K] = T[K]>(\n key: K,\n ...args: ParamsOrNever<Parser<U extends Record<string, string> ? U : never>>\n ): string {\n const template = strings[key];\n if (typeof template !== \"string\") {\n console.error(\n `Unresolved translation key:${key} locale:${locale} dictionary:${dictionary.id}`,\n );\n return key;\n }\n const [params = {}] = args;\n return parseTranslation(template, params as any) as string;\n }\n\n parse.jsx = <K extends keyof T & string, U extends T[K] = T[K]>(\n key: K,\n ...args: ParamsOrNever<Parser<U extends Record<string, string> ? U : never>>\n ) => {\n return parse(key, ...(args as any)) as unknown as JSX.Element;\n };\n\n /**\n * Formatting in this dictionary's locale and the app's time zone. See\n * `useFormatter`.\n */\n parse.format = format;\n\n return parse;\n}\n","/**\n * The one implementation of \"what is a dictionary literal, and what is its id\",\n * shared by the runtime (`defineDictionary`) and the Vite plugin.\n *\n * Both sides must agree exactly. A dictionary's id is a hash of its own\n * contents rather than of its file path, so a module that is bundled on one\n * side and evaluated raw on the other still lands on the same id — which is\n * what lets the SSR payload seed the client registry.\n */\n\nexport type DictionaryTranslations = Record<string, Record<string, string>>;\n\nexport type LocaleStrings = Record<string, string>;\n\n/**\n * Locales the dictionary declares, source language first.\n *\n * The order is meaningful: the first locale is the source language, and a key\n * missing from some other locale falls back along this list.\n *\n * `sourceLocale` pins that choice. Without it the source language is whichever\n * locale is seen first while walking the literal, which makes it an emergent\n * property of key order — adding a key at the top of a dictionary whose other\n * keys happen to lack `en-US` would silently re-point every fallback in it. Any\n * dictionary that is not uniformly translated should say which locale it is\n * authored in.\n */\nexport function dictionaryLocales(\n translations: DictionaryTranslations,\n sourceLocale?: string,\n): string[] {\n const locales: string[] = [];\n const seen = new Set<string>();\n if (sourceLocale) {\n seen.add(sourceLocale);\n locales.push(sourceLocale);\n }\n for (const byLocale of Object.values(translations)) {\n for (const locale of Object.keys(byLocale)) {\n if (!seen.has(locale)) {\n seen.add(locale);\n locales.push(locale);\n }\n }\n }\n return locales;\n}\n\n/**\n * Flatten one locale out of a dictionary.\n *\n * A key with no string for `locale` falls back along the declared locale order\n * rather than vanishing, so a half-translated dictionary degrades one string at\n * a time instead of rendering the whole component as raw keys.\n */\nexport function localeStrings(\n translations: DictionaryTranslations,\n locale: string,\n fallbackOrder: string[] = dictionaryLocales(translations),\n): LocaleStrings {\n const out: LocaleStrings = {};\n for (const [key, byLocale] of Object.entries(translations)) {\n let value = byLocale?.[locale];\n if (typeof value !== \"string\") {\n for (const candidate of fallbackOrder) {\n const fallback = byLocale?.[candidate];\n if (typeof fallback === \"string\") {\n value = fallback;\n break;\n }\n }\n }\n if (typeof value === \"string\") {\n out[key] = value;\n }\n }\n return out;\n}\n\nexport interface SourceDisagreement {\n key: string;\n first: string;\n againstKey: string;\n againstFirst: string;\n}\n\n/**\n * Whether the inferred source language survives reordering the literal.\n *\n * `dictionaryLocales` collects locales entry by entry, so `locales[0]` is the\n * first locale of the first entry. That is invariant under key reordering\n * exactly when every entry lists the same locale first — and order-dependent\n * the moment two entries disagree, because then whichever happens to be written\n * first decides what the *whole* dictionary falls back to. Adding one key at\n * the top can flip every other key's fallback language, from a diff that reads\n * as an addition.\n *\n * Returns the disagreement so the build can name both keys; `null` when the\n * inference is stable. `sourceLocale` settles it and makes the question moot.\n */\nexport function findSourceDisagreement(\n translations: DictionaryTranslations,\n): SourceDisagreement | null {\n let againstKey: string | undefined;\n let againstFirst: string | undefined;\n\n for (const [key, byLocale] of Object.entries(translations)) {\n const first = Object.keys(byLocale ?? {})[0];\n // A key with no locales at all is a different problem, reported elsewhere.\n if (first === undefined) continue;\n\n if (againstFirst === undefined) {\n againstFirst = first;\n againstKey = key;\n continue;\n }\n if (first !== againstFirst) {\n return { key, first, againstKey: againstKey!, againstFirst };\n }\n }\n return null;\n}\n\n/**\n * Canonical serialization — key order in the source file must not change the\n * id, or an innocuous reordering would break the payload/registry match.\n */\nexport function canonicalizeDictionary(\n translations: DictionaryTranslations,\n): string {\n const keys = Object.keys(translations).sort();\n const parts = keys.map((key) => {\n const byLocale = translations[key] ?? {};\n const locales = Object.keys(byLocale).sort();\n const inner = locales.map((l) => JSON.stringify([l, byLocale[l]])).join(\",\");\n return `${JSON.stringify(key)}:[${inner}]`;\n });\n return `{${parts.join(\",\")}}`;\n}\n\n/**\n * FNV-1a, run twice with different offsets for a 64-bit-wide id. No crypto\n * import, and it has to work identically in the browser bundle, under Bun on\n * the server, and inside the Vite plugin.\n */\nexport function dictionaryId(translations: DictionaryTranslations): string {\n const input = canonicalizeDictionary(translations);\n let a = 0x811c9dc5;\n let b = 0x01000193;\n for (let i = 0; i < input.length; i++) {\n const c = input.charCodeAt(i);\n a = Math.imul(a ^ c, 0x01000193);\n b = Math.imul(b ^ c, 0x811c9dc5);\n }\n const hex = (n: number) => (n >>> 0).toString(16).padStart(8, \"0\");\n return `d_${hex(a)}${hex(b)}`;\n}\n","import {\n dictionaryId,\n dictionaryLocales,\n localeStrings,\n type DictionaryTranslations,\n type LocaleStrings,\n} from \"./dictionaryShape\";\nimport {\n loadDictionary,\n loadDictionaryForRender,\n registerDictionary,\n type RenderThenable,\n} from \"./dictionaryRegistry\";\n\ndeclare const brand: unique symbol;\n\nexport interface DictionaryHandle<\n T extends DictionaryTranslations = DictionaryTranslations,\n> {\n readonly id: string;\n /** Locales this dictionary declares, source language first. */\n readonly locales: readonly string[];\n /**\n * Strings for `locale`. Synchronous when they are already in memory —\n * always, for an unbundled dictionary; after a preload or the SSR seed, for a\n * bundled one.\n */\n load(locale: string): LocaleStrings | Promise<LocaleStrings>;\n /**\n * `load`, but as the exact thing React's `use()` wants: never rejecting, so\n * a failed locale chunk degrades the component to rendering keys instead of\n * unmounting it into an error boundary; and always a thenable, even when the\n * strings are already in memory. The caller skips `use()` only for a\n * thenable built from strings already in hand, which carries them as\n * `inHand`; every thenable a render could have suspended on still goes\n * through it. `loadDictionaryForRender` has the whole reasoning.\n */\n loadForRender(locale: string): RenderThenable;\n get(locale: string): LocaleStrings | undefined;\n /** Type-only: carries the literal's shape through to `useDictionary`. */\n readonly [brand]?: T;\n}\n\n/**\n * Declare the strings a component needs, next to the component.\n *\n * ```ts\n * export const homeDict = defineDictionary({\n * title: { \"en-US\": \"Welcome {{name}}\", \"tr-TR\": \"Hoş geldin {{name}}\" },\n * });\n * ```\n *\n * As written this holds every locale. Under gemi's Vite plugin the call is\n * rewritten so each locale becomes its own chunk and a page downloads only the\n * one it renders in — but the plugin is strictly an optimization, and the\n * behaviour is identical without it (in `bun test`, and in server code that\n * does not go through the bundler).\n *\n * The first locale in the literal is the source language: a key missing from\n * another locale falls back to it rather than rendering as its own key.\n */\nexport interface DefineDictionaryOptions {\n /**\n * The locale this dictionary is authored in. Keys missing from another locale\n * fall back to it, and it is what renders when the app has no locale\n * configured.\n *\n * Optional, but worth setting on any dictionary that is not uniformly\n * translated: without it the source language is whichever locale appears\n * first in the literal, so adding a key at the top can re-point every\n * fallback in the dictionary.\n */\n sourceLocale?: string;\n}\n\nexport function defineDictionary<const T extends DictionaryTranslations>(\n translations: T,\n options: DefineDictionaryOptions = {},\n): DictionaryHandle<T> {\n const locales = dictionaryLocales(translations, options.sourceLocale);\n return createHandle(dictionaryId(translations), locales, (locale) =>\n localeStrings(translations, locale, locales),\n );\n}\n\n/**\n * The rewritten form of a `defineDictionary` call — emitted by\n * `packages/gemi/vite/dictionaryPlugin.ts`, never written by hand. `loaders`\n * holds one dynamic import per locale so the bundler emits one chunk per\n * locale and the untaken ones never reach the browser.\n */\nexport function __gemi_dict__<\n const T extends DictionaryTranslations = DictionaryTranslations,\n>(\n id: string,\n loaders: Record<string, () => Promise<{ default: LocaleStrings }>>,\n): DictionaryHandle<T> {\n const locales = Object.keys(loaders);\n return createHandle(id, locales, (locale) => {\n // An unknown locale falls back to the source language, matching what\n // `localeStrings` does per key on the unbundled path.\n const load = loaders[locale] ?? loaders[locales[0]];\n if (!load) {\n return {};\n }\n return load().then((mod) => mod.default);\n });\n}\n\nfunction createHandle<T extends DictionaryTranslations>(\n id: string,\n locales: string[],\n load: (locale: string) => LocaleStrings | Promise<LocaleStrings>,\n): DictionaryHandle<T> {\n const entry = { id, locales, load };\n registerDictionary(entry);\n\n // Re-asserted on every read rather than only at construction. A handle is\n // created once, at module scope, but the registry it delegates to can be\n // emptied under it — a test's `afterEach` reset, an HMR boundary — and the\n // handle would then be permanently orphaned, throwing \"Unknown dictionary\"\n // for a dictionary the caller is holding. `registerDictionary` is a no-op\n // when the id is already there, so this costs one Map lookup.\n const ensure = () => registerDictionary(entry);\n\n return {\n id,\n locales,\n // Routed through the registry rather than calling `load` directly so\n // concurrent readers share one in-flight import and results are cached.\n load: (locale: string) => {\n ensure();\n return loadDictionary(id, locale);\n },\n loadForRender: (locale: string) => {\n ensure();\n return loadDictionaryForRender(id, locale);\n },\n get: (locale: string) => {\n ensure();\n const strings = loadDictionary(id, locale);\n if (strings instanceof Promise) {\n // Nothing downstream awaits this one — `get` is the synchronous peek,\n // and the caller is about to discard it. An unattached rejection (a\n // locale chunk that 404s mid-deploy) would surface as an\n // `unhandledRejection`, which under Node's default handler takes the\n // process down over one missing translation file. The load itself is\n // still cached and still retried through `loadDictionary`.\n strings.catch(() => {});\n return undefined;\n }\n return strings;\n },\n };\n}\n\n","import { useLocation } from \"./useLocation\";\nimport { useNavigate } from \"./useNavigate\";\nimport { useParams } from \"./useParams\";\nimport { useRouteData } from \"./useRouteData\";\n\nconst LOCALE_COOKIE = \"i18n-locale\";\nconst LOCALE_COOKIE_MAX_AGE = 60 * 60 * 24 * 365;\n\n/**\n * The active locale lives in two places: the URL segment `setLocale` navigates\n * to, and the `i18n-locale` cookie the server falls back to when the URL has no\n * segment — which is exactly the case for the default locale. Both have to be in\n * place *before* the navigation asks for route data, or `Translator.detectLocale`\n * answers the request with a redirect back to the locale the cookie still names.\n *\n * Hence a synchronous `document.cookie` write rather than an awaited one. The\n * previous implementation awaited `cookieStore.set()` and hung the navigation off\n * its `.then()`; that promise is reported to never settle on iOS Safari, so the\n * `.then()` never ran and changing the language became a silent no-op — no\n * rejection, nothing for an error reporter to pick up. A synchronous write cannot\n * hang and cannot fail asynchronously, so nothing is left to gate navigation on.\n */\nfunction persistLocale(locale: string) {\n if (typeof document === \"undefined\") {\n return;\n }\n try {\n document.cookie = [\n // Encoded, not interpolated: `cookieStore.set()` rejected malformed\n // values, a raw string write does not. A locale carrying `;` would\n // otherwise write cookie *attributes* — `Domain`, `Path` — from whatever\n // the app happens to feed the switcher.\n `${LOCALE_COOKIE}=${encodeURIComponent(locale)}`,\n `Max-Age=${LOCALE_COOKIE_MAX_AGE}`,\n \"SameSite=Strict\",\n \"Path=/\",\n ].join(\"; \");\n } catch {\n // A sandboxed iframe with no storage access throws here. The navigation\n // still carries the locale in its URL, so it is better to switch without\n // remembering the choice than to not switch at all.\n }\n}\n\n/**\n * `onLocaleChange` is a server-side hook, so it takes a request to fire it. The\n * switch must not wait on that round trip, nor be cancelled by one that fails —\n * including one that fails *synchronously*: `fetch` is absent in some old\n * WebViews, and an unguarded call would throw before the navigation ran, which\n * is the same silent no-op this hook exists to prevent through another door.\n */\nfunction notifyLocaleChange(locale: string) {\n try {\n void fetch(\n `/api/__gemi__/services/i18n/set-locale/${encodeURIComponent(locale)}`,\n ).catch(() => {});\n } catch {\n // `fetch` itself is unavailable. The locale is already persisted and the\n // navigation still runs; only the server-side hook misses this switch.\n }\n}\n\nexport function useLocale() {\n const { i18n } = useRouteData();\n const { pathname, search } = useLocation();\n const { replace } = useNavigate();\n const params = useParams();\n\n const setLocale = async (locale: string) => {\n persistLocale(locale);\n notifyLocaleChange(locale);\n\n const urlSearchParams = new URLSearchParams(search);\n await replace(pathname, {\n locale,\n // TODO: fix: this conversion is wrong, because there can be multiple\n // search params with the same name\n search: Object.fromEntries(urlSearchParams.entries()),\n params,\n } as any);\n };\n\n return [i18n.currentLocale, setLocale] as const;\n}\n","import { createElement, Fragment, type ReactNode } from \"react\";\nimport type { SatoriOptions } from \"satori\";\n\ntype Font = Omit<SatoriOptions[\"fonts\"][number], \"data\">;\ntype Options = Omit<SatoriOptions, \"fonts\"> & {\n fonts: Font[];\n} & { width: number; height: number };\n\nexport const OpenGraphImage = ({\n children,\n ...satoriOptions\n}: Options & { children: ReactNode }) => {\n return (\n <>\n {(() => {\n throw {\n jsx: createElement(Fragment, { children }),\n satoriOptions,\n };\n })()}\n </>\n );\n};\n","import { useContext } from \"react\";\nimport { ServerDataContext } from \"./ServerDataProvider\";\nimport { RouteStateContext } from \"./RouteStateContext\";\n\nexport function useAppIdMissmatch() {\n const { appId: next } = useContext(RouteStateContext);\n const { appId: current } = useContext(ServerDataContext);\n\n return current !== next;\n}\n","import {\n type ComponentType,\n type Context,\n type ReactElement,\n type ReactNode,\n Fragment,\n createContext,\n createElement,\n lazy,\n use,\n useContext,\n} from \"react\";\n\n/**\n * When an island's code is fetched and hydrated, per marker.\n *\n * - `\"eager\"` (default): as soon as the page has parsed. The island's chunks\n * and React are `modulepreload`ed from the head, so they are usually in\n * cache by then.\n * - `\"idle\"`: on `requestIdleCallback` (a timeout where unsupported).\n * - `\"visible\"`: when the island's content first scrolls into view. Suits a\n * heavy island far down the page, like a canvas or a map.\n */\nexport type IslandLoad = \"eager\" | \"idle\" | \"visible\";\n\nexport interface IslandOptions {\n /** When the island hydrates on a static page. Defaults to `\"eager\"`. */\n load?: IslandLoad;\n /** Which export of the module is the component. Defaults to `\"default\"`. */\n export?: string;\n /**\n * Also `modulepreload` the chunks the island's code loads with `import()`,\n * on static pages that render it, so a lazy piece it needs right after\n * hydrating (an animation runtime, say) arrives with it instead of one\n * round trip later. Applies to `\"eager\"` islands only; hydrated views are\n * unaffected. Defaults to `false`.\n */\n preloadDynamic?: boolean;\n}\n\n/**\n * `() => import(\"./Counter\")`, the argument `island()` takes. gemi's Vite\n * plugin adds the module's build key and the module itself, so the server can\n * render it synchronously in a hydrated view and point a static page at its\n * built chunk.\n */\nexport type IslandLoader<M = any> = (() => Promise<M>) & {\n /** @internal The module's path from the project root, the client manifest's key. */\n gemiIsland?: string;\n /** @internal The module, statically imported by the plugin. */\n gemiModule?: M;\n};\n\n/** @internal One island module a static page uses: an entry of the page's island table. */\nexport interface IslandEntry {\n /** The module's build key, or `undefined` when the plugin did not run. */\n module: string | undefined;\n export: string;\n load: IslandLoad;\n /** Preload the entry's dynamic imports too: set when any island() call sharing this entry asks. */\n preloadDynamic?: boolean;\n}\n\ninterface IslandInstance {\n html: Promise<string>;\n index: number;\n uid: string;\n props: string | undefined;\n}\n\n/**\n * @internal Provided by the view router around a static view's render; `null`\n * everywhere else, which is how `island()` knows to render a plain component.\n */\nexport interface StaticRenderCollector {\n /** The page's island table: what the loader imports, by marker index. */\n islands: IslandEntry[];\n /**\n * Renders one island as its own React root, settled, to HTML. Supplied by\n * the server, so this module never imports `react-dom/server`.\n */\n render: (element: ReactElement, identifierPrefix: string) => Promise<string>;\n /** Per-instance render state, keyed by the island's props object. */\n instances: WeakMap<object, IslandInstance>;\n /** Instances rendered so far, for each one's `identifierPrefix`. */\n count: number;\n}\n\n/** @internal */\nexport function createStaticRenderCollector(\n render: StaticRenderCollector[\"render\"],\n): StaticRenderCollector {\n return { islands: [], render, instances: new WeakMap(), count: 0 };\n}\n\n/** @internal The element an island's static children land in. */\nexport const ISLAND_SLOT_TAG = \"gemi-slot\";\n/** @internal On the empty slot an island's own render leaves for its children. */\nexport const ISLAND_SLOT_ATTRIBUTE = \"data-slot\";\n/** @internal On the template holding the children the page tree rendered. */\nexport const ISLAND_SLOT_TEMPLATE_ATTRIBUTE = \"data-gemi-slot\";\n\n/** The property gemi's Vite plugin attaches to an island's loader. */\nexport const ISLAND_MODULE_KEY = \"gemiIsland\";\n\nconst CONTEXT_KEY = Symbol.for(\"gemi.staticRender\");\n\n/**\n * @internal On `globalThis` rather than a module-level `createContext`: the\n * published package bundles `gemi/client` and the server side separately, so a\n * plain module singleton would give the provider and the islands two different\n * context objects.\n */\nexport const StaticRenderContext: Context<StaticRenderCollector | null> = ((\n globalThis as Record<symbol, unknown>\n)[CONTEXT_KEY] ??= createContext<StaticRenderCollector | null>(null)) as Context<\n StaticRenderCollector | null\n>;\n\nconst isProduction = () =>\n typeof process !== \"undefined\" && process.env?.NODE_ENV === \"production\";\n\n/**\n * Throws when `value` would not survive `JSON.stringify` and `JSON.parse`\n * unchanged, naming the prop. An island's props cross from the server to the\n * browser as JSON: a function would vanish and a `Date` would arrive as a\n * string, so the island would hydrate with other props than it rendered with.\n */\nexport function assertSerialisableProps(value: unknown, island: string): void {\n const seen = new Set<object>();\n const fail = (path: string, what: string): never => {\n throw new Error(\n `${island}: the prop \\`${path}\\` is ${what}. An island's props are sent to the browser ` +\n `as JSON, so they must be plain data: strings, finite numbers, booleans, null, ` +\n `arrays and plain objects. Pass static markup as children instead.`,\n );\n };\n const walk = (v: unknown, path: string, inArray: boolean): void => {\n switch (typeof v) {\n case \"string\":\n case \"boolean\":\n return;\n case \"number\":\n if (!Number.isFinite(v)) fail(path, String(v));\n return;\n case \"undefined\":\n // Dropped from an object, which reads back the same; not in an array.\n if (inArray) fail(path, \"undefined (it would arrive as null)\");\n return;\n case \"function\":\n fail(path, \"a function\");\n return;\n case \"symbol\":\n case \"bigint\":\n fail(path, `a ${typeof v}`);\n return;\n }\n if (v === null) return;\n const object = v as Record<string, unknown>;\n if (seen.has(object)) fail(path, \"a circular reference\");\n if (\"$$typeof\" in object) fail(path, \"a React element\");\n seen.add(object);\n if (Array.isArray(object)) {\n object.forEach((item, i) => walk(item, `${path}[${i}]`, true));\n } else {\n const proto = Object.getPrototypeOf(object);\n if (proto !== Object.prototype && proto !== null) {\n fail(path, `an instance of ${proto?.constructor?.name || \"a class\"}`);\n }\n for (const [key, item] of Object.entries(object)) {\n walk(item, path ? `${path}.${key}` : key, false);\n }\n }\n seen.delete(object);\n };\n walk(value, \"\", false);\n}\n\nconst hasChildren = (children: unknown) =>\n children !== undefined && children !== null && typeof children !== \"boolean\";\n\ntype AnyComponent = ComponentType<any>;\n\n/**\n * Makes a component an island: hydrated on its own on a static page, an\n * ordinary component everywhere else.\n *\n * ```tsx\n * // app/views/site/Counter.tsx: a plain React component\n * export default function Counter({ start }: { start: number }) {\n * const [n, setN] = useState(start);\n * return <button onClick={() => setN(n + 1)}>{n}</button>;\n * }\n *\n * // where it is used\n * const Counter = island(() => import(\"./Counter\"), { load: \"visible\" });\n * <Counter start={3} />\n * ```\n *\n * - In a **static** view (`this.view(...).static()`), it server-renders the\n * component as its own React root inside a `<gemi-island>` marker and\n * serialises its props. The page gets a tiny loader that, on the island's\n * `load` trigger, imports React (one chunk shared by every island) and the\n * component's chunk and calls `hydrateRoot` on the marker.\n * - In a **hydrated** view, it is the component itself: rendered inline, with\n * the page's context, and nothing extra to load.\n *\n * Write the loader exactly as `() => import(\"./path\")` inside the `island(`\n * call: gemi's Vite plugin finds that call, builds the module as its own\n * client entry and imports it statically for the server.\n *\n * Props must be plain data (checked in dev). `children` are rendered on the\n * server as static HTML and passed through untouched. On a static page the\n * island is a separate React root, so context from the page does not reach it.\n */\nexport function island<M extends { default: AnyComponent }>(\n loader: () => Promise<M>,\n options?: IslandOptions & { export?: \"default\" },\n): M[\"default\"];\nexport function island<M, K extends keyof M & string>(\n loader: () => Promise<M>,\n options: IslandOptions & { export: K },\n): M[K];\nexport function island(loader: IslandLoader, options: IslandOptions = {}): AnyComponent {\n if (typeof loader !== \"function\") {\n throw new Error(\n 'island() takes `() => import(\"./Component\")` and options since gemi 0.110. ' +\n 'The island(\"name\", Component, () => import(\"./x.island\")) form was removed: see UPGRADE.md.',\n );\n }\n const exportName = options.export ?? \"default\";\n const load: IslandLoad = options.load ?? \"eager\";\n const preloadDynamic = options.preloadDynamic === true ? true : undefined;\n const key = loader[ISLAND_MODULE_KEY];\n const label = `island(${key ?? \"() => import(…)\"}${exportName === \"default\" ? \"\" : `#${exportName}`})`;\n\n const pick = (mod: Record<string, unknown>): AnyComponent => {\n const component = mod?.[exportName];\n if (typeof component !== \"function\" && (typeof component !== \"object\" || component === null)) {\n throw new Error(`${label}: the module has no component export \\`${exportName}\\`.`);\n }\n return component as AnyComponent;\n };\n\n // A hydrated view renders the component in place. The plugin imported the\n // module statically; without it (a test that doesn't run the plugin) the\n // component loads lazily and suspends once.\n let inline: AnyComponent | undefined;\n const inlineComponent = (): AnyComponent =>\n (inline ??= loader.gemiModule\n ? pick(loader.gemiModule)\n : lazy(() => loader().then((mod) => ({ default: pick(mod) }))));\n\n const register = (collector: StaticRenderCollector): number => {\n const known = collector.islands.findIndex(\n (entry) =>\n key !== undefined && entry.module === key && entry.export === exportName && entry.load === load,\n );\n if (known !== -1) {\n // Another island() call with the same entry may be the one asking.\n if (preloadDynamic) collector.islands[known].preloadDynamic = true;\n return known;\n }\n return collector.islands.push({ module: key, export: exportName, load, preloadDynamic }) - 1;\n };\n\n const start = (collector: StaticRenderCollector, props: Record<string, unknown>): IslandInstance => {\n const { children, ...rest } = props;\n if (!isProduction()) {\n assertSerialisableProps(rest, label);\n }\n const uid = `i${collector.count++}-`;\n const component = loader.gemiModule\n ? Promise.resolve(pick(loader.gemiModule))\n : loader().then(pick);\n // The island's own render is a root of its own, as it will be in the\n // browser: islands nested in it are plain components of that root. Its\n // children are not rendered here: they belong to the page (and its\n // context), so the page tree renders them next to the marker and\n // `spliceIslandSlots` moves their HTML into this empty slot.\n const html = component.then((Component) =>\n collector.render(\n createElement(\n StaticRenderContext.Provider,\n { value: null },\n hasChildren(children)\n ? createElement(\n Component,\n rest,\n createElement(ISLAND_SLOT_TAG, { [ISLAND_SLOT_ATTRIBUTE]: uid, style: { display: \"contents\" } }),\n )\n : createElement(Component, rest),\n ),\n uid,\n ),\n );\n // A rejection surfaces through `use`; this keeps it from also being\n // reported as unhandled.\n html.catch(() => {});\n const json = JSON.stringify(rest);\n return { html, index: register(collector), uid, props: json === \"{}\" ? undefined : json };\n };\n\n function Island(props: Record<string, unknown>): ReactNode {\n const collector = useContext(StaticRenderContext);\n if (!collector) {\n return createElement(inlineComponent(), props);\n }\n\n // Suspending on `use` re-renders this component with the same props\n // object, so the render it started is found again rather than restarted.\n let instance = collector.instances.get(props);\n if (!instance) {\n instance = start(collector, props);\n collector.instances.set(props, instance);\n }\n\n const marker = createElement(\"gemi-island\", {\n \"data-island\": instance.index,\n \"data-uid\": instance.uid,\n // React escapes attribute values, so the JSON needs (and must get) no\n // escaping of its own.\n \"data-props\": instance.props,\n style: { display: \"contents\" },\n dangerouslySetInnerHTML: { __html: use(instance.html) },\n });\n if (!hasChildren(props.children)) {\n return marker;\n }\n // The children, rendered here in the page tree with the page's context\n // (islands among them are islands of their own), in a template the\n // static document splices into the island's slot before it is sent.\n return createElement(\n Fragment,\n null,\n marker,\n createElement(\"template\", { [ISLAND_SLOT_TEMPLATE_ATTRIBUTE]: instance.uid }, props.children as ReactNode),\n );\n }\n\n Island.displayName = label;\n return Island;\n}\n","/** What `onStaticNavigate` and the `gemi:page-load` event report. */\nexport interface StaticPageLoad {\n /** The page's URL, `#hash` included. */\n url: string;\n /** Its `document.title`. */\n title: string;\n /** `true` for the page the browser loaded, `false` after a client navigation. */\n initial: boolean;\n}\n\n/** The state the navigation runtime keeps on `window` (see `internal/staticNavigation`). */\ntype RuntimeState = { p?: StaticPageLoad } | undefined;\n\n/**\n * Calls `callback` for every page a static view's navigation runtime shows\n * (`.static({ navigation })`): right away for the current page, then after\n * every client-side navigation. Returns a function that stops it.\n *\n * Meant for analytics and the like from an island:\n *\n * ```tsx\n * useEffect(() => onStaticNavigate(({ url }) => track(url)), []);\n * ```\n *\n * Without the runtime (a hydrated page, a static page without `navigation`,\n * the server), it does nothing. The same notice is the `gemi:page-load` event\n * on `document`, for code that is not an island.\n */\nexport function onStaticNavigate(callback: (page: StaticPageLoad) => void): () => void {\n if (typeof document === \"undefined\") return () => {};\n const listener = (event: Event) => callback((event as CustomEvent<StaticPageLoad>).detail);\n document.addEventListener(\"gemi:page-load\", listener);\n const current = (window as unknown as { __gemi_nav?: RuntimeState }).__gemi_nav?.p;\n if (current) callback(current);\n return () => document.removeEventListener(\"gemi:page-load\", listener);\n}\n"],"mappings":"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"}
|