/** * rsc-router/loader (RSC/server version) * * Server-side createLoader implementation with full loader functionality. * Only used in react-server context via export conditions. * * For non-fetchable loaders: returns a loader definition with fn included * For fetchable loaders: stores fn in registry and returns a serializable loader * * The $$id is injected by the Vite exposeInternalIds plugin as a hidden parameter. * Users don't need to pass any name - IDs are auto-generated from file path. */ import type { FetchableLoaderOptions, LoaderDefinition, LoaderFn, } from "./types.js"; import type { MiddlewareFn } from "./router/middleware.js"; import { registerFetchableLoader, getFetchableLoader, } from "./server/fetchable-loader-store.js"; export { getFetchableLoader }; // Overload 1: With function only (not fetchable) export function createLoader( fn: LoaderFn, any>, ): LoaderDefinition, Record>; // Overload 2: Fetchable with `true` (no middleware) export function createLoader( fn: LoaderFn, any>, fetchable: true, ): LoaderDefinition, Record>; // Overload 3: Fetchable with middleware options export function createLoader( fn: LoaderFn, any>, options: FetchableLoaderOptions, ): LoaderDefinition, Record>; // Implementation - the $$id parameter is injected by Vite plugin, not user-provided export function createLoader( fn: LoaderFn, any>, fetchable?: true | FetchableLoaderOptions, // Hidden parameter injected by Vite exposeInternalIds plugin __injectedId?: string, ): LoaderDefinition, Record> { // The $$id will be set on the returned object by Vite plugin // For fetchable loaders, __injectedId is also passed as a parameter const loaderId = __injectedId || ""; if (!loaderId && process.env.NODE_ENV === "development") { throw new Error( "[rango] Loader is missing $$id. " + "Make sure the exposeInternalIds Vite plugin is enabled and " + "the loader is exported with: export const MyLoader = createLoader(...)", ); } // If not fetchable, store fn in registry (for SSR ctx.use() resolution) // but mark fetchable=false so the _rsc_loader endpoint rejects it. if (fetchable === undefined) { if (fn && loaderId) { registerFetchableLoader(loaderId, fn, [], false); } return { __brand: "loader", $$id: loaderId, }; } // Fetchable loader - store fn in registry and return a serializable object const middleware: MiddlewareFn[] = fetchable === true ? [] : fetchable?.middleware || []; // Register the function in the internal registry by $$id (server-side only) // The loader fetch handler looks it up by $$id when load() is called from the client. if (fn && loaderId) { registerFetchableLoader(loaderId, fn, middleware, true); } return { __brand: "loader", $$id: loaderId, }; }