Socket
Book a DemoSign in
Socket

@tanstack/start-server-core

Package Overview
Dependencies
Maintainers
4
Versions
403
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tanstack/start-server-core - npm Package Compare versions

Comparing version
1.141.8
to
1.142.1
+3
-1
dist/esm/createSsrRpc.d.ts
import { TSS_SERVER_FUNCTION } from '@tanstack/start-client-core';
export declare const createSsrRpc: (functionId: string) => ((...args: Array<any>) => Promise<any>) & {
import { ServerFn } from '#tanstack-start-server-fn-manifest';
export type SsrRpcImporter = () => Promise<ServerFn>;
export declare const createSsrRpc: (functionId: string, importer?: SsrRpcImporter) => ((...args: Array<any>) => Promise<any>) & {
url: string;

@@ -4,0 +6,0 @@ functionId: string;

import { TSS_SERVER_FUNCTION } from "@tanstack/start-client-core";
import { getServerFnById } from "#tanstack-start-server-fn-manifest";
const createSsrRpc = (functionId) => {
const createSsrRpc = (functionId, importer) => {
const url = process.env.TSS_SERVER_FN_BASE + functionId;
const fn = async (...args) => {
const serverFn = await getServerFnById(functionId);
const serverFn = importer ? await importer() : await getServerFnById(functionId);
return serverFn(...args);

@@ -8,0 +8,0 @@ };

@@ -1,1 +0,1 @@

{"version":3,"file":"createSsrRpc.js","sources":["../../src/createSsrRpc.ts"],"sourcesContent":["import { TSS_SERVER_FUNCTION } from '@tanstack/start-client-core'\nimport { getServerFnById } from './getServerFnById'\n\nexport const createSsrRpc = (functionId: string) => {\n const url = process.env.TSS_SERVER_FN_BASE + functionId\n const fn = async (...args: Array<any>): Promise<any> => {\n const serverFn = await getServerFnById(functionId)\n return serverFn(...args)\n }\n\n return Object.assign(fn, {\n url,\n functionId,\n [TSS_SERVER_FUNCTION]: true,\n })\n}\n"],"names":[],"mappings":";;AAGO,MAAM,eAAe,CAAC,eAAuB;AAClD,QAAM,MAAM,QAAQ,IAAI,qBAAqB;AAC7C,QAAM,KAAK,UAAU,SAAmC;AACtD,UAAM,WAAW,MAAM,gBAAgB,UAAU;AACjD,WAAO,SAAS,GAAG,IAAI;AAAA,EACzB;AAEA,SAAO,OAAO,OAAO,IAAI;AAAA,IACvB;AAAA,IACA;AAAA,IACA,CAAC,mBAAmB,GAAG;AAAA,EAAA,CACxB;AACH;"}
{"version":3,"file":"createSsrRpc.js","sources":["../../src/createSsrRpc.ts"],"sourcesContent":["import { TSS_SERVER_FUNCTION } from '@tanstack/start-client-core'\nimport { getServerFnById } from './getServerFnById'\nimport type { ServerFn } from '#tanstack-start-server-fn-manifest'\n\nexport type SsrRpcImporter = () => Promise<ServerFn>\n\nexport const createSsrRpc = (functionId: string, importer?: SsrRpcImporter) => {\n const url = process.env.TSS_SERVER_FN_BASE + functionId\n const fn = async (...args: Array<any>): Promise<any> => {\n // If an importer is provided, use it directly (server-to-server call within the SSR environment)\n // Otherwise, fall back to manifest lookup (client-to-server call, server functions that are only referenced on the server or if the provider environment is not SSR)\n const serverFn = importer\n ? await importer()\n : await getServerFnById(functionId)\n return serverFn(...args)\n }\n\n return Object.assign(fn, {\n url,\n functionId,\n [TSS_SERVER_FUNCTION]: true,\n })\n}\n"],"names":[],"mappings":";;AAMO,MAAM,eAAe,CAAC,YAAoB,aAA8B;AAC7E,QAAM,MAAM,QAAQ,IAAI,qBAAqB;AAC7C,QAAM,KAAK,UAAU,SAAmC;AAGtD,UAAM,WAAW,WACb,MAAM,aACN,MAAM,gBAAgB,UAAU;AACpC,WAAO,SAAS,GAAG,IAAI;AAAA,EACzB;AAEA,SAAO,OAAO,OAAO,IAAI;AAAA,IACvB;AAAA,IACA;AAAA,IACA,CAAC,mBAAmB,GAAG;AAAA,EAAA,CACxB;AACH;"}

@@ -118,8 +118,3 @@ import { RequestHeaderMap, RequestHeaderName, ResponseHeaderMap, ResponseHeaderName, TypedHeaders } from 'fetchdts';

export declare function clearSession(config: Partial<SessionConfig>): Promise<void>;
export declare function getResponse(): {
status?: number;
statusText?: string;
_headers?: Headers;
get headers(): Headers;
} | undefined;
export declare function getResponse(): any;
export declare function getValidatedQuery<TSchema extends StandardSchemaV1>(schema: StandardSchemaV1): Promise<StandardSchemaV1.InferOutput<TSchema>>;
import { AsyncLocalStorage } from "node:async_hooks";
import { H3Event, toResponse, getRequestIP as getRequestIP$1, getRequestHost as getRequestHost$1, getRequestURL, getRequestProtocol as getRequestProtocol$1, sanitizeStatusCode, sanitizeStatusMessage, parseCookies, setCookie as setCookie$1, deleteCookie as deleteCookie$1, useSession as useSession$1, getSession as getSession$1, updateSession as updateSession$1, sealSession as sealSession$1, unsealSession as unsealSession$1, clearSession as clearSession$1, getValidatedQuery as getValidatedQuery$1 } from "h3-v2";
const eventStorage = new AsyncLocalStorage();
const GLOBAL_EVENT_STORAGE_KEY = Symbol.for("tanstack-start:event-storage");
const globalObj = globalThis;
if (!globalObj[GLOBAL_EVENT_STORAGE_KEY]) {
globalObj[GLOBAL_EVENT_STORAGE_KEY] = new AsyncLocalStorage();
}
const eventStorage = globalObj[GLOBAL_EVENT_STORAGE_KEY];
function requestHandler(handler) {

@@ -145,3 +150,3 @@ return (request, requestOpts) => {

const event = getH3Event();
return event._res;
return event[Symbol.for("h3.internal.event.res")];
}

@@ -148,0 +153,0 @@ function getValidatedQuery(schema) {

@@ -1,1 +0,1 @@

{"version":3,"file":"request-response.js","sources":["../../src/request-response.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\n\nimport {\n H3Event,\n clearSession as h3_clearSession,\n deleteCookie as h3_deleteCookie,\n getRequestHost as h3_getRequestHost,\n getRequestIP as h3_getRequestIP,\n getRequestProtocol as h3_getRequestProtocol,\n getRequestURL as h3_getRequestURL,\n getSession as h3_getSession,\n getValidatedQuery as h3_getValidatedQuery,\n parseCookies as h3_parseCookies,\n sanitizeStatusCode as h3_sanitizeStatusCode,\n sanitizeStatusMessage as h3_sanitizeStatusMessage,\n sealSession as h3_sealSession,\n setCookie as h3_setCookie,\n toResponse as h3_toResponse,\n unsealSession as h3_unsealSession,\n updateSession as h3_updateSession,\n useSession as h3_useSession,\n} from 'h3-v2'\nimport type {\n RequestHeaderMap,\n RequestHeaderName,\n ResponseHeaderMap,\n ResponseHeaderName,\n TypedHeaders,\n} from 'fetchdts'\n\nimport type { CookieSerializeOptions } from 'cookie-es'\nimport type {\n Session,\n SessionConfig,\n SessionData,\n SessionManager,\n SessionUpdate,\n} from './session'\nimport type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type { RequestHandler } from './request-handler'\n\ninterface StartEvent {\n h3Event: H3Event\n}\nconst eventStorage = new AsyncLocalStorage<StartEvent>()\n\nexport type { ResponseHeaderName, RequestHeaderName }\n\nexport function requestHandler<TRegister = unknown>(\n handler: RequestHandler<TRegister>,\n) {\n return (request: Request, requestOpts: any): Promise<Response> | Response => {\n const h3Event = new H3Event(request)\n\n const response = eventStorage.run({ h3Event }, () =>\n handler(request, requestOpts),\n )\n return h3_toResponse(response, h3Event)\n }\n}\n\nfunction getH3Event() {\n const event = eventStorage.getStore()\n if (!event) {\n throw new Error(\n `No StartEvent found in AsyncLocalStorage. Make sure you are using the function within the server runtime.`,\n )\n }\n return event.h3Event\n}\n\nexport function getRequest(): Request {\n const event = getH3Event()\n return event.req\n}\n\nexport function getRequestHeaders(): TypedHeaders<RequestHeaderMap> {\n // TODO `as any` not needed when fetchdts is updated\n return getH3Event().req.headers as any\n}\n\nexport function getRequestHeader(name: RequestHeaderName): string | undefined {\n return getRequestHeaders().get(name) || undefined\n}\n\nexport function getRequestIP(opts?: {\n /**\n * Use the X-Forwarded-For HTTP header set by proxies.\n *\n * Note: Make sure that this header can be trusted (your application running behind a CDN or reverse proxy) before enabling.\n */\n xForwardedFor?: boolean\n}) {\n return h3_getRequestIP(getH3Event(), opts)\n}\n\n/**\n * Get the request hostname.\n *\n * If `xForwardedHost` is `true`, it will use the `x-forwarded-host` header if it exists.\n *\n * If no host header is found, it will default to \"localhost\".\n */\nexport function getRequestHost(opts?: { xForwardedHost?: boolean }) {\n return h3_getRequestHost(getH3Event(), opts)\n}\n\n/**\n * Get the full incoming request URL.\n *\n * If `xForwardedHost` is `true`, it will use the `x-forwarded-host` header if it exists.\n *\n * If `xForwardedProto` is `false`, it will not use the `x-forwarded-proto` header.\n */\nexport function getRequestUrl(opts?: {\n xForwardedHost?: boolean\n xForwardedProto?: boolean\n}) {\n return h3_getRequestURL(getH3Event(), opts)\n}\n\n/**\n * Get the request protocol.\n *\n * If `x-forwarded-proto` header is set to \"https\", it will return \"https\". You can disable this behavior by setting `xForwardedProto` to `false`.\n *\n * If protocol cannot be determined, it will default to \"http\".\n */\nexport function getRequestProtocol(opts?: {\n xForwardedProto?: boolean\n}): 'http' | 'https' | (string & {}) {\n return h3_getRequestProtocol(getH3Event(), opts)\n}\n\nexport function setResponseHeaders(\n headers: TypedHeaders<ResponseHeaderMap>,\n): void {\n const event = getH3Event()\n for (const [name, value] of Object.entries(headers)) {\n event.res.headers.set(name, value)\n }\n}\n\nexport function getResponseHeaders(): TypedHeaders<ResponseHeaderMap> {\n const event = getH3Event()\n return event.res.headers\n}\n\nexport function getResponseHeader(\n name: ResponseHeaderName,\n): string | undefined {\n const event = getH3Event()\n return event.res.headers.get(name) || undefined\n}\n\nexport function setResponseHeader(\n name: ResponseHeaderName,\n value: string | Array<string>,\n): void {\n const event = getH3Event()\n if (Array.isArray(value)) {\n event.res.headers.delete(name)\n for (const valueItem of value) {\n event.res.headers.append(name, valueItem)\n }\n } else {\n event.res.headers.set(name, value)\n }\n}\nexport function removeResponseHeader(name: ResponseHeaderName): void {\n const event = getH3Event()\n event.res.headers.delete(name)\n}\n\nexport function clearResponseHeaders(\n headerNames?: Array<ResponseHeaderName>,\n): void {\n const event = getH3Event()\n // If headerNames is provided, clear only those headers\n if (headerNames && headerNames.length > 0) {\n for (const name of headerNames) {\n event.res.headers.delete(name)\n }\n // Otherwise, clear all headers\n } else {\n for (const name of event.res.headers.keys()) {\n event.res.headers.delete(name)\n }\n }\n}\n\nexport function getResponseStatus(): number {\n return getH3Event().res.status || 200\n}\n\nexport function setResponseStatus(code?: number, text?: string): void {\n const event = getH3Event()\n if (code) {\n event.res.status = h3_sanitizeStatusCode(code, event.res.status)\n }\n if (text) {\n event.res.statusText = h3_sanitizeStatusMessage(text)\n }\n}\n\n/**\n * Parse the request to get HTTP Cookie header string and return an object of all cookie name-value pairs.\n * @returns Object of cookie name-value pairs\n * ```ts\n * const cookies = getCookies()\n * ```\n */\nexport function getCookies(): Record<string, string> {\n const event = getH3Event()\n return h3_parseCookies(event)\n}\n\n/**\n * Get a cookie value by name.\n * @param name Name of the cookie to get\n * @returns {*} Value of the cookie (String or undefined)\n * ```ts\n * const authorization = getCookie('Authorization')\n * ```\n */\nexport function getCookie(name: string): string | undefined {\n return getCookies()[name] || undefined\n}\n\n/**\n * Set a cookie value by name.\n * @param name Name of the cookie to set\n * @param value Value of the cookie to set\n * @param options {CookieSerializeOptions} Options for serializing the cookie\n * ```ts\n * setCookie('Authorization', '1234567')\n * ```\n */\nexport function setCookie(\n name: string,\n value: string,\n options?: CookieSerializeOptions,\n): void {\n const event = getH3Event()\n h3_setCookie(event, name, value, options)\n}\n\n/**\n * Remove a cookie by name.\n * @param name Name of the cookie to delete\n * @param serializeOptions {CookieSerializeOptions} Cookie options\n * ```ts\n * deleteCookie('SessionId')\n * ```\n */\nexport function deleteCookie(\n name: string,\n options?: CookieSerializeOptions,\n): void {\n const event = getH3Event()\n h3_deleteCookie(event, name, options)\n}\n\nfunction getDefaultSessionConfig(config: SessionConfig): SessionConfig {\n return {\n name: 'start',\n ...config,\n }\n}\n\n/**\n * Create a session manager for the current request.\n */\nexport function useSession<TSessionData extends SessionData = SessionData>(\n config: SessionConfig,\n): Promise<SessionManager<TSessionData>> {\n const event = getH3Event()\n return h3_useSession(event, getDefaultSessionConfig(config))\n}\n/**\n * Get the session for the current request\n */\nexport function getSession<TSessionData extends SessionData = SessionData>(\n config: SessionConfig,\n): Promise<Session<TSessionData>> {\n const event = getH3Event()\n return h3_getSession(event, getDefaultSessionConfig(config))\n}\n\n/**\n * Update the session data for the current request.\n */\nexport function updateSession<TSessionData extends SessionData = SessionData>(\n config: SessionConfig,\n update?: SessionUpdate<TSessionData>,\n): Promise<Session<TSessionData>> {\n const event = getH3Event()\n return h3_updateSession(event, getDefaultSessionConfig(config), update)\n}\n\n/**\n * Encrypt and sign the session data for the current request.\n */\nexport function sealSession(config: SessionConfig): Promise<string> {\n const event = getH3Event()\n return h3_sealSession(event, getDefaultSessionConfig(config))\n}\n/**\n * Decrypt and verify the session data for the current request.\n */\nexport function unsealSession(\n config: SessionConfig,\n sealed: string,\n): Promise<Partial<Session>> {\n const event = getH3Event()\n return h3_unsealSession(event, getDefaultSessionConfig(config), sealed)\n}\n\n/**\n * Clear the session data for the current request.\n */\nexport function clearSession(config: Partial<SessionConfig>): Promise<void> {\n const event = getH3Event()\n return h3_clearSession(event, { name: 'start', ...config })\n}\n\n// not public API\nexport function getResponse() {\n const event = getH3Event()\n return event._res\n}\n\n// not public API (yet)\nexport function getValidatedQuery<TSchema extends StandardSchemaV1>(\n schema: StandardSchemaV1,\n): Promise<StandardSchemaV1.InferOutput<TSchema>> {\n return h3_getValidatedQuery(getH3Event(), schema)\n}\n"],"names":["h3_toResponse","h3_getRequestIP","h3_getRequestHost","h3_getRequestURL","h3_getRequestProtocol","h3_sanitizeStatusCode","h3_sanitizeStatusMessage","h3_parseCookies","h3_setCookie","h3_deleteCookie","h3_useSession","h3_getSession","h3_updateSession","h3_sealSession","h3_unsealSession","h3_clearSession","h3_getValidatedQuery"],"mappings":"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"}
{"version":3,"file":"request-response.js","sources":["../../src/request-response.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\n\nimport {\n H3Event,\n clearSession as h3_clearSession,\n deleteCookie as h3_deleteCookie,\n getRequestHost as h3_getRequestHost,\n getRequestIP as h3_getRequestIP,\n getRequestProtocol as h3_getRequestProtocol,\n getRequestURL as h3_getRequestURL,\n getSession as h3_getSession,\n getValidatedQuery as h3_getValidatedQuery,\n parseCookies as h3_parseCookies,\n sanitizeStatusCode as h3_sanitizeStatusCode,\n sanitizeStatusMessage as h3_sanitizeStatusMessage,\n sealSession as h3_sealSession,\n setCookie as h3_setCookie,\n toResponse as h3_toResponse,\n unsealSession as h3_unsealSession,\n updateSession as h3_updateSession,\n useSession as h3_useSession,\n} from 'h3-v2'\nimport type {\n RequestHeaderMap,\n RequestHeaderName,\n ResponseHeaderMap,\n ResponseHeaderName,\n TypedHeaders,\n} from 'fetchdts'\n\nimport type { CookieSerializeOptions } from 'cookie-es'\nimport type {\n Session,\n SessionConfig,\n SessionData,\n SessionManager,\n SessionUpdate,\n} from './session'\nimport type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type { RequestHandler } from './request-handler'\n\ninterface StartEvent {\n h3Event: H3Event\n}\n\n// Use a global symbol to ensure the same AsyncLocalStorage instance is shared\n// across different bundles that may each bundle this module.\nconst GLOBAL_EVENT_STORAGE_KEY = Symbol.for('tanstack-start:event-storage')\n\nconst globalObj = globalThis as typeof globalThis & {\n [GLOBAL_EVENT_STORAGE_KEY]?: AsyncLocalStorage<StartEvent>\n}\n\nif (!globalObj[GLOBAL_EVENT_STORAGE_KEY]) {\n globalObj[GLOBAL_EVENT_STORAGE_KEY] = new AsyncLocalStorage<StartEvent>()\n}\n\nconst eventStorage = globalObj[GLOBAL_EVENT_STORAGE_KEY]\n\nexport type { ResponseHeaderName, RequestHeaderName }\n\nexport function requestHandler<TRegister = unknown>(\n handler: RequestHandler<TRegister>,\n) {\n return (request: Request, requestOpts: any): Promise<Response> | Response => {\n const h3Event = new H3Event(request)\n\n const response = eventStorage.run({ h3Event }, () =>\n handler(request, requestOpts),\n )\n return h3_toResponse(response, h3Event)\n }\n}\n\nfunction getH3Event() {\n const event = eventStorage.getStore()\n if (!event) {\n throw new Error(\n `No StartEvent found in AsyncLocalStorage. Make sure you are using the function within the server runtime.`,\n )\n }\n return event.h3Event\n}\n\nexport function getRequest(): Request {\n const event = getH3Event()\n return event.req\n}\n\nexport function getRequestHeaders(): TypedHeaders<RequestHeaderMap> {\n // TODO `as any` not needed when fetchdts is updated\n return getH3Event().req.headers as any\n}\n\nexport function getRequestHeader(name: RequestHeaderName): string | undefined {\n return getRequestHeaders().get(name) || undefined\n}\n\nexport function getRequestIP(opts?: {\n /**\n * Use the X-Forwarded-For HTTP header set by proxies.\n *\n * Note: Make sure that this header can be trusted (your application running behind a CDN or reverse proxy) before enabling.\n */\n xForwardedFor?: boolean\n}) {\n return h3_getRequestIP(getH3Event(), opts)\n}\n\n/**\n * Get the request hostname.\n *\n * If `xForwardedHost` is `true`, it will use the `x-forwarded-host` header if it exists.\n *\n * If no host header is found, it will default to \"localhost\".\n */\nexport function getRequestHost(opts?: { xForwardedHost?: boolean }) {\n return h3_getRequestHost(getH3Event(), opts)\n}\n\n/**\n * Get the full incoming request URL.\n *\n * If `xForwardedHost` is `true`, it will use the `x-forwarded-host` header if it exists.\n *\n * If `xForwardedProto` is `false`, it will not use the `x-forwarded-proto` header.\n */\nexport function getRequestUrl(opts?: {\n xForwardedHost?: boolean\n xForwardedProto?: boolean\n}) {\n return h3_getRequestURL(getH3Event(), opts)\n}\n\n/**\n * Get the request protocol.\n *\n * If `x-forwarded-proto` header is set to \"https\", it will return \"https\". You can disable this behavior by setting `xForwardedProto` to `false`.\n *\n * If protocol cannot be determined, it will default to \"http\".\n */\nexport function getRequestProtocol(opts?: {\n xForwardedProto?: boolean\n}): 'http' | 'https' | (string & {}) {\n return h3_getRequestProtocol(getH3Event(), opts)\n}\n\nexport function setResponseHeaders(\n headers: TypedHeaders<ResponseHeaderMap>,\n): void {\n const event = getH3Event()\n for (const [name, value] of Object.entries(headers)) {\n event.res.headers.set(name, value)\n }\n}\n\nexport function getResponseHeaders(): TypedHeaders<ResponseHeaderMap> {\n const event = getH3Event()\n return event.res.headers\n}\n\nexport function getResponseHeader(\n name: ResponseHeaderName,\n): string | undefined {\n const event = getH3Event()\n return event.res.headers.get(name) || undefined\n}\n\nexport function setResponseHeader(\n name: ResponseHeaderName,\n value: string | Array<string>,\n): void {\n const event = getH3Event()\n if (Array.isArray(value)) {\n event.res.headers.delete(name)\n for (const valueItem of value) {\n event.res.headers.append(name, valueItem)\n }\n } else {\n event.res.headers.set(name, value)\n }\n}\nexport function removeResponseHeader(name: ResponseHeaderName): void {\n const event = getH3Event()\n event.res.headers.delete(name)\n}\n\nexport function clearResponseHeaders(\n headerNames?: Array<ResponseHeaderName>,\n): void {\n const event = getH3Event()\n // If headerNames is provided, clear only those headers\n if (headerNames && headerNames.length > 0) {\n for (const name of headerNames) {\n event.res.headers.delete(name)\n }\n // Otherwise, clear all headers\n } else {\n for (const name of event.res.headers.keys()) {\n event.res.headers.delete(name)\n }\n }\n}\n\nexport function getResponseStatus(): number {\n return getH3Event().res.status || 200\n}\n\nexport function setResponseStatus(code?: number, text?: string): void {\n const event = getH3Event()\n if (code) {\n event.res.status = h3_sanitizeStatusCode(code, event.res.status)\n }\n if (text) {\n event.res.statusText = h3_sanitizeStatusMessage(text)\n }\n}\n\n/**\n * Parse the request to get HTTP Cookie header string and return an object of all cookie name-value pairs.\n * @returns Object of cookie name-value pairs\n * ```ts\n * const cookies = getCookies()\n * ```\n */\nexport function getCookies(): Record<string, string> {\n const event = getH3Event()\n return h3_parseCookies(event)\n}\n\n/**\n * Get a cookie value by name.\n * @param name Name of the cookie to get\n * @returns {*} Value of the cookie (String or undefined)\n * ```ts\n * const authorization = getCookie('Authorization')\n * ```\n */\nexport function getCookie(name: string): string | undefined {\n return getCookies()[name] || undefined\n}\n\n/**\n * Set a cookie value by name.\n * @param name Name of the cookie to set\n * @param value Value of the cookie to set\n * @param options {CookieSerializeOptions} Options for serializing the cookie\n * ```ts\n * setCookie('Authorization', '1234567')\n * ```\n */\nexport function setCookie(\n name: string,\n value: string,\n options?: CookieSerializeOptions,\n): void {\n const event = getH3Event()\n h3_setCookie(event, name, value, options)\n}\n\n/**\n * Remove a cookie by name.\n * @param name Name of the cookie to delete\n * @param serializeOptions {CookieSerializeOptions} Cookie options\n * ```ts\n * deleteCookie('SessionId')\n * ```\n */\nexport function deleteCookie(\n name: string,\n options?: CookieSerializeOptions,\n): void {\n const event = getH3Event()\n h3_deleteCookie(event, name, options)\n}\n\nfunction getDefaultSessionConfig(config: SessionConfig): SessionConfig {\n return {\n name: 'start',\n ...config,\n }\n}\n\n/**\n * Create a session manager for the current request.\n */\nexport function useSession<TSessionData extends SessionData = SessionData>(\n config: SessionConfig,\n): Promise<SessionManager<TSessionData>> {\n const event = getH3Event()\n return h3_useSession(event, getDefaultSessionConfig(config))\n}\n/**\n * Get the session for the current request\n */\nexport function getSession<TSessionData extends SessionData = SessionData>(\n config: SessionConfig,\n): Promise<Session<TSessionData>> {\n const event = getH3Event()\n return h3_getSession(event, getDefaultSessionConfig(config))\n}\n\n/**\n * Update the session data for the current request.\n */\nexport function updateSession<TSessionData extends SessionData = SessionData>(\n config: SessionConfig,\n update?: SessionUpdate<TSessionData>,\n): Promise<Session<TSessionData>> {\n const event = getH3Event()\n return h3_updateSession(event, getDefaultSessionConfig(config), update)\n}\n\n/**\n * Encrypt and sign the session data for the current request.\n */\nexport function sealSession(config: SessionConfig): Promise<string> {\n const event = getH3Event()\n return h3_sealSession(event, getDefaultSessionConfig(config))\n}\n/**\n * Decrypt and verify the session data for the current request.\n */\nexport function unsealSession(\n config: SessionConfig,\n sealed: string,\n): Promise<Partial<Session>> {\n const event = getH3Event()\n return h3_unsealSession(event, getDefaultSessionConfig(config), sealed)\n}\n\n/**\n * Clear the session data for the current request.\n */\nexport function clearSession(config: Partial<SessionConfig>): Promise<void> {\n const event = getH3Event()\n return h3_clearSession(event, { name: 'start', ...config })\n}\n\n// not public API\nexport function getResponse() {\n const event = getH3Event()\n // @ts-expect-error accessing internal symbol\n return event[Symbol.for('h3.internal.event.res')]\n}\n\n// not public API (yet)\nexport function getValidatedQuery<TSchema extends StandardSchemaV1>(\n schema: StandardSchemaV1,\n): Promise<StandardSchemaV1.InferOutput<TSchema>> {\n return h3_getValidatedQuery(getH3Event(), schema)\n}\n"],"names":["h3_toResponse","h3_getRequestIP","h3_getRequestHost","h3_getRequestURL","h3_getRequestProtocol","h3_sanitizeStatusCode","h3_sanitizeStatusMessage","h3_parseCookies","h3_setCookie","h3_deleteCookie","h3_useSession","h3_getSession","h3_updateSession","h3_sealSession","h3_unsealSession","h3_clearSession","h3_getValidatedQuery"],"mappings":";;AA+CA,MAAM,2BAA2B,OAAO,IAAI,8BAA8B;AAE1E,MAAM,YAAY;AAIlB,IAAI,CAAC,UAAU,wBAAwB,GAAG;AACxC,YAAU,wBAAwB,IAAI,IAAI,kBAAA;AAC5C;AAEA,MAAM,eAAe,UAAU,wBAAwB;AAIhD,SAAS,eACd,SACA;AACA,SAAO,CAAC,SAAkB,gBAAmD;AAC3E,UAAM,UAAU,IAAI,QAAQ,OAAO;AAEnC,UAAM,WAAW,aAAa;AAAA,MAAI,EAAE,QAAA;AAAA,MAAW,MAC7C,QAAQ,SAAS,WAAW;AAAA,IAAA;AAE9B,WAAOA,WAAc,UAAU,OAAO;AAAA,EACxC;AACF;AAEA,SAAS,aAAa;AACpB,QAAM,QAAQ,aAAa,SAAA;AAC3B,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AACA,SAAO,MAAM;AACf;AAEO,SAAS,aAAsB;AACpC,QAAM,QAAQ,WAAA;AACd,SAAO,MAAM;AACf;AAEO,SAAS,oBAAoD;AAElE,SAAO,WAAA,EAAa,IAAI;AAC1B;AAEO,SAAS,iBAAiB,MAA6C;AAC5E,SAAO,kBAAA,EAAoB,IAAI,IAAI,KAAK;AAC1C;AAEO,SAAS,aAAa,MAO1B;AACD,SAAOC,eAAgB,WAAA,GAAc,IAAI;AAC3C;AASO,SAAS,eAAe,MAAqC;AAClE,SAAOC,iBAAkB,WAAA,GAAc,IAAI;AAC7C;AASO,SAAS,cAAc,MAG3B;AACD,SAAOC,cAAiB,WAAA,GAAc,IAAI;AAC5C;AASO,SAAS,mBAAmB,MAEE;AACnC,SAAOC,qBAAsB,WAAA,GAAc,IAAI;AACjD;AAEO,SAAS,mBACd,SACM;AACN,QAAM,QAAQ,WAAA;AACd,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AACnD,UAAM,IAAI,QAAQ,IAAI,MAAM,KAAK;AAAA,EACnC;AACF;AAEO,SAAS,qBAAsD;AACpE,QAAM,QAAQ,WAAA;AACd,SAAO,MAAM,IAAI;AACnB;AAEO,SAAS,kBACd,MACoB;AACpB,QAAM,QAAQ,WAAA;AACd,SAAO,MAAM,IAAI,QAAQ,IAAI,IAAI,KAAK;AACxC;AAEO,SAAS,kBACd,MACA,OACM;AACN,QAAM,QAAQ,WAAA;AACd,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,UAAM,IAAI,QAAQ,OAAO,IAAI;AAC7B,eAAW,aAAa,OAAO;AAC7B,YAAM,IAAI,QAAQ,OAAO,MAAM,SAAS;AAAA,IAC1C;AAAA,EACF,OAAO;AACL,UAAM,IAAI,QAAQ,IAAI,MAAM,KAAK;AAAA,EACnC;AACF;AACO,SAAS,qBAAqB,MAAgC;AACnE,QAAM,QAAQ,WAAA;AACd,QAAM,IAAI,QAAQ,OAAO,IAAI;AAC/B;AAEO,SAAS,qBACd,aACM;AACN,QAAM,QAAQ,WAAA;AAEd,MAAI,eAAe,YAAY,SAAS,GAAG;AACzC,eAAW,QAAQ,aAAa;AAC9B,YAAM,IAAI,QAAQ,OAAO,IAAI;AAAA,IAC/B;AAAA,EAEF,OAAO;AACL,eAAW,QAAQ,MAAM,IAAI,QAAQ,QAAQ;AAC3C,YAAM,IAAI,QAAQ,OAAO,IAAI;AAAA,IAC/B;AAAA,EACF;AACF;AAEO,SAAS,oBAA4B;AAC1C,SAAO,WAAA,EAAa,IAAI,UAAU;AACpC;AAEO,SAAS,kBAAkB,MAAe,MAAqB;AACpE,QAAM,QAAQ,WAAA;AACd,MAAI,MAAM;AACR,UAAM,IAAI,SAASC,mBAAsB,MAAM,MAAM,IAAI,MAAM;AAAA,EACjE;AACA,MAAI,MAAM;AACR,UAAM,IAAI,aAAaC,sBAAyB,IAAI;AAAA,EACtD;AACF;AASO,SAAS,aAAqC;AACnD,QAAM,QAAQ,WAAA;AACd,SAAOC,aAAgB,KAAK;AAC9B;AAUO,SAAS,UAAU,MAAkC;AAC1D,SAAO,WAAA,EAAa,IAAI,KAAK;AAC/B;AAWO,SAAS,UACd,MACA,OACA,SACM;AACN,QAAM,QAAQ,WAAA;AACdC,cAAa,OAAO,MAAM,OAAO,OAAO;AAC1C;AAUO,SAAS,aACd,MACA,SACM;AACN,QAAM,QAAQ,WAAA;AACdC,iBAAgB,OAAO,MAAM,OAAO;AACtC;AAEA,SAAS,wBAAwB,QAAsC;AACrE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,GAAG;AAAA,EAAA;AAEP;AAKO,SAAS,WACd,QACuC;AACvC,QAAM,QAAQ,WAAA;AACd,SAAOC,aAAc,OAAO,wBAAwB,MAAM,CAAC;AAC7D;AAIO,SAAS,WACd,QACgC;AAChC,QAAM,QAAQ,WAAA;AACd,SAAOC,aAAc,OAAO,wBAAwB,MAAM,CAAC;AAC7D;AAKO,SAAS,cACd,QACA,QACgC;AAChC,QAAM,QAAQ,WAAA;AACd,SAAOC,gBAAiB,OAAO,wBAAwB,MAAM,GAAG,MAAM;AACxE;AAKO,SAAS,YAAY,QAAwC;AAClE,QAAM,QAAQ,WAAA;AACd,SAAOC,cAAe,OAAO,wBAAwB,MAAM,CAAC;AAC9D;AAIO,SAAS,cACd,QACA,QAC2B;AAC3B,QAAM,QAAQ,WAAA;AACd,SAAOC,gBAAiB,OAAO,wBAAwB,MAAM,GAAG,MAAM;AACxE;AAKO,SAAS,aAAa,QAA+C;AAC1E,QAAM,QAAQ,WAAA;AACd,SAAOC,eAAgB,OAAO,EAAE,MAAM,SAAS,GAAG,QAAQ;AAC5D;AAGO,SAAS,cAAc;AAC5B,QAAM,QAAQ,WAAA;AAEd,SAAO,MAAM,OAAO,IAAI,uBAAuB,CAAC;AAClD;AAGO,SAAS,kBACd,QACgD;AAChD,SAAOC,oBAAqB,WAAA,GAAc,MAAM;AAClD;"}

@@ -15,3 +15,3 @@ import { createSerializationAdapter } from "@tanstack/router-core";

const fn = async (opts, signal) => {
const serverFn = await getServerFnById(functionId);
const serverFn = await getServerFnById(functionId, { fromClient: true });
const result = await serverFn(opts ?? {}, signal);

@@ -18,0 +18,0 @@ return result.result;

@@ -1,1 +0,1 @@

{"version":3,"file":"ServerFunctionSerializationAdapter.js","sources":["../../../src/serializer/ServerFunctionSerializationAdapter.ts"],"sourcesContent":["import { createSerializationAdapter } from '@tanstack/router-core'\nimport { TSS_SERVER_FUNCTION } from '@tanstack/start-client-core'\nimport { createServerRpc } from '../createServerRpc'\nimport { getServerFnById } from '../getServerFnById'\n\nexport const ServerFunctionSerializationAdapter = createSerializationAdapter({\n key: '$TSS/serverfn',\n test: (v): v is { functionId: string } => {\n if (typeof v !== 'function') return false\n\n if (!(TSS_SERVER_FUNCTION in v)) return false\n\n return !!v[TSS_SERVER_FUNCTION]\n },\n toSerializable: ({ functionId }) => ({ functionId }),\n fromSerializable: ({ functionId }) => {\n const fn = async (opts: any, signal: any): Promise<any> => {\n const serverFn = await getServerFnById(functionId)\n const result = await serverFn(opts ?? {}, signal)\n return result.result\n }\n return createServerRpc(functionId, fn)\n },\n})\n"],"names":[],"mappings":";;;;AAKO,MAAM,qCAAqC,2BAA2B;AAAA,EAC3E,KAAK;AAAA,EACL,MAAM,CAAC,MAAmC;AACxC,QAAI,OAAO,MAAM,WAAY,QAAO;AAEpC,QAAI,EAAE,uBAAuB,GAAI,QAAO;AAExC,WAAO,CAAC,CAAC,EAAE,mBAAmB;AAAA,EAChC;AAAA,EACA,gBAAgB,CAAC,EAAE,kBAAkB,EAAE,WAAA;AAAA,EACvC,kBAAkB,CAAC,EAAE,iBAAiB;AACpC,UAAM,KAAK,OAAO,MAAW,WAA8B;AACzD,YAAM,WAAW,MAAM,gBAAgB,UAAU;AACjD,YAAM,SAAS,MAAM,SAAS,QAAQ,CAAA,GAAI,MAAM;AAChD,aAAO,OAAO;AAAA,IAChB;AACA,WAAO,gBAAgB,YAAY,EAAE;AAAA,EACvC;AACF,CAAC;"}
{"version":3,"file":"ServerFunctionSerializationAdapter.js","sources":["../../../src/serializer/ServerFunctionSerializationAdapter.ts"],"sourcesContent":["import { createSerializationAdapter } from '@tanstack/router-core'\nimport { TSS_SERVER_FUNCTION } from '@tanstack/start-client-core'\nimport { createServerRpc } from '../createServerRpc'\nimport { getServerFnById } from '../getServerFnById'\n\nexport const ServerFunctionSerializationAdapter = createSerializationAdapter({\n key: '$TSS/serverfn',\n test: (v): v is { functionId: string } => {\n if (typeof v !== 'function') return false\n\n if (!(TSS_SERVER_FUNCTION in v)) return false\n\n return !!v[TSS_SERVER_FUNCTION]\n },\n toSerializable: ({ functionId }) => ({ functionId }),\n fromSerializable: ({ functionId }) => {\n const fn = async (opts: any, signal: any): Promise<any> => {\n // When a function ID is received through serialization (e.g., as a parameter\n // to another server function), it originates from the client and must be\n // validated the same way as direct HTTP calls to server functions.\n const serverFn = await getServerFnById(functionId, { fromClient: true })\n const result = await serverFn(opts ?? {}, signal)\n return result.result\n }\n return createServerRpc(functionId, fn)\n },\n})\n"],"names":[],"mappings":";;;;AAKO,MAAM,qCAAqC,2BAA2B;AAAA,EAC3E,KAAK;AAAA,EACL,MAAM,CAAC,MAAmC;AACxC,QAAI,OAAO,MAAM,WAAY,QAAO;AAEpC,QAAI,EAAE,uBAAuB,GAAI,QAAO;AAExC,WAAO,CAAC,CAAC,EAAE,mBAAmB;AAAA,EAChC;AAAA,EACA,gBAAgB,CAAC,EAAE,kBAAkB,EAAE,WAAA;AAAA,EACvC,kBAAkB,CAAC,EAAE,iBAAiB;AACpC,UAAM,KAAK,OAAO,MAAW,WAA8B;AAIzD,YAAM,WAAW,MAAM,gBAAgB,YAAY,EAAE,YAAY,MAAM;AACvE,YAAM,SAAS,MAAM,SAAS,QAAQ,CAAA,GAAI,MAAM;AAChD,aAAO,OAAO;AAAA,IAChB;AACA,WAAO,gBAAgB,YAAY,EAAE;AAAA,EACvC;AACF,CAAC;"}

@@ -28,3 +28,3 @@ import { isNotFound } from "@tanstack/router-core";

}
const action = await getServerFnById(serverFnId);
const action = await getServerFnById(serverFnId, { fromClient: true });
const formDataContentTypes = [

@@ -31,0 +31,0 @@ "multipart/form-data",

@@ -1,1 +0,1 @@

{"version":3,"file":"server-functions-handler.js","sources":["../../src/server-functions-handler.ts"],"sourcesContent":["import { isNotFound } from '@tanstack/router-core'\nimport invariant from 'tiny-invariant'\nimport {\n TSS_FORMDATA_CONTEXT,\n X_TSS_RAW_RESPONSE,\n X_TSS_SERIALIZED,\n getDefaultSerovalPlugins,\n} from '@tanstack/start-client-core'\nimport { fromJSON, toCrossJSONAsync, toCrossJSONStream } from 'seroval'\nimport { getResponse } from './request-response'\nimport { getServerFnById } from './getServerFnById'\n\nlet regex: RegExp | undefined = undefined\n\nexport const handleServerAction = async ({\n request,\n context,\n}: {\n request: Request\n context: any\n}) => {\n const controller = new AbortController()\n const signal = controller.signal\n const abort = () => controller.abort()\n request.signal.addEventListener('abort', abort)\n\n if (regex === undefined) {\n regex = new RegExp(`${process.env.TSS_SERVER_FN_BASE}([^/?#]+)`)\n }\n\n const method = request.method\n const url = new URL(request.url, 'http://localhost:3000')\n // extract the serverFnId from the url as host/_serverFn/:serverFnId\n // Define a regex to match the path and extract the :thing part\n\n // Execute the regex\n const match = url.pathname.match(regex)\n const serverFnId = match ? match[1] : null\n const search = Object.fromEntries(url.searchParams.entries()) as {\n payload?: any\n createServerFn?: boolean\n }\n\n const isCreateServerFn = 'createServerFn' in search\n\n if (typeof serverFnId !== 'string') {\n throw new Error('Invalid server action param for serverFnId: ' + serverFnId)\n }\n\n const action = await getServerFnById(serverFnId)\n\n // Known FormData 'Content-Type' header values\n const formDataContentTypes = [\n 'multipart/form-data',\n 'application/x-www-form-urlencoded',\n ]\n\n const contentType = request.headers.get('Content-Type')\n const serovalPlugins = getDefaultSerovalPlugins()\n\n function parsePayload(payload: any) {\n const parsedPayload = fromJSON(payload, { plugins: serovalPlugins })\n return parsedPayload as any\n }\n\n const response = await (async () => {\n try {\n let result = await (async () => {\n // FormData\n if (\n formDataContentTypes.some(\n (type) => contentType && contentType.includes(type),\n )\n ) {\n // We don't support GET requests with FormData payloads... that seems impossible\n invariant(\n method.toLowerCase() !== 'get',\n 'GET requests with FormData payloads are not supported',\n )\n const formData = await request.formData()\n const serializedContext = formData.get(TSS_FORMDATA_CONTEXT)\n formData.delete(TSS_FORMDATA_CONTEXT)\n\n const params = {\n context,\n data: formData,\n }\n if (typeof serializedContext === 'string') {\n try {\n const parsedContext = JSON.parse(serializedContext)\n const deserializedContext = fromJSON(parsedContext, {\n plugins: serovalPlugins,\n })\n if (\n typeof deserializedContext === 'object' &&\n deserializedContext\n ) {\n params.context = { ...context, ...deserializedContext }\n }\n } catch {}\n }\n\n return await action(params, signal)\n }\n\n // Get requests use the query string\n if (method.toLowerCase() === 'get') {\n invariant(\n isCreateServerFn,\n 'expected GET request to originate from createServerFn',\n )\n // By default the payload is the search params\n let payload: any = search.payload\n // If there's a payload, we should try to parse it\n payload = payload ? parsePayload(JSON.parse(payload)) : {}\n payload.context = { ...context, ...payload.context }\n // Send it through!\n return await action(payload, signal)\n }\n\n if (method.toLowerCase() !== 'post') {\n throw new Error('expected POST method')\n }\n\n let jsonPayload\n if (contentType?.includes('application/json')) {\n jsonPayload = await request.json()\n }\n\n // If this POST request was created by createServerFn,\n // its payload will be the only argument\n if (isCreateServerFn) {\n const payload = jsonPayload ? parsePayload(jsonPayload) : {}\n payload.context = { ...payload.context, ...context }\n return await action(payload, signal)\n }\n\n // Otherwise, we'll spread the payload. Need to\n // support `use server` functions that take multiple\n // arguments.\n return await action(...jsonPayload)\n })()\n\n // Any time we get a Response back, we should just\n // return it immediately.\n if (result.result instanceof Response) {\n result.result.headers.set(X_TSS_RAW_RESPONSE, 'true')\n return result.result\n }\n\n // If this is a non createServerFn request, we need to\n // pull out the result from the result object\n if (!isCreateServerFn) {\n result = result.result\n\n // The result might again be a response,\n // and if it is, return it.\n if (result instanceof Response) {\n return result\n }\n }\n\n // TODO: RSCs Where are we getting this package?\n // if (isValidElement(result)) {\n // const { renderToPipeableStream } = await import(\n // // @ts-expect-error\n // 'react-server-dom/server'\n // )\n\n // const pipeableStream = renderToPipeableStream(result)\n\n // setHeaders(event, {\n // 'Content-Type': 'text/x-component',\n // } as any)\n\n // sendStream(event, response)\n // event._handled = true\n\n // return new Response(null, { status: 200 })\n // }\n\n if (isNotFound(result)) {\n return isNotFoundResponse(result)\n }\n\n const response = getResponse()\n let nonStreamingBody: any = undefined\n\n if (result !== undefined) {\n // first run without the stream in case `result` does not need streaming\n let done = false as boolean\n const callbacks: {\n onParse: (value: any) => void\n onDone: () => void\n onError: (error: any) => void\n } = {\n onParse: (value) => {\n nonStreamingBody = value\n },\n onDone: () => {\n done = true\n },\n onError: (error) => {\n throw error\n },\n }\n toCrossJSONStream(result, {\n refs: new Map(),\n plugins: serovalPlugins,\n onParse(value) {\n callbacks.onParse(value)\n },\n onDone() {\n callbacks.onDone()\n },\n onError: (error) => {\n callbacks.onError(error)\n },\n })\n if (done) {\n return new Response(\n nonStreamingBody ? JSON.stringify(nonStreamingBody) : undefined,\n {\n status: response?.status,\n statusText: response?.statusText,\n headers: {\n 'Content-Type': 'application/json',\n [X_TSS_SERIALIZED]: 'true',\n },\n },\n )\n }\n\n // not done yet, we need to stream\n const encoder = new TextEncoder()\n const stream = new ReadableStream({\n start(controller) {\n callbacks.onParse = (value) =>\n controller.enqueue(encoder.encode(JSON.stringify(value) + '\\n'))\n callbacks.onDone = () => {\n try {\n controller.close()\n } catch (error) {\n controller.error(error)\n }\n }\n callbacks.onError = (error) => controller.error(error)\n // stream the initial body\n if (nonStreamingBody !== undefined) {\n callbacks.onParse(nonStreamingBody)\n }\n },\n })\n return new Response(stream, {\n status: response?.status,\n statusText: response?.statusText,\n headers: {\n 'Content-Type': 'application/x-ndjson',\n [X_TSS_SERIALIZED]: 'true',\n },\n })\n }\n\n return new Response(undefined, {\n status: response?.status,\n statusText: response?.statusText,\n })\n } catch (error: any) {\n if (error instanceof Response) {\n return error\n }\n // else if (\n // isPlainObject(error) &&\n // 'result' in error &&\n // error.result instanceof Response\n // ) {\n // return error.result\n // }\n\n // Currently this server-side context has no idea how to\n // build final URLs, so we need to defer that to the client.\n // The client will check for __redirect and __notFound keys,\n // and if they exist, it will handle them appropriately.\n\n if (isNotFound(error)) {\n return isNotFoundResponse(error)\n }\n\n console.info()\n console.info('Server Fn Error!')\n console.info()\n console.error(error)\n console.info()\n\n const serializedError = JSON.stringify(\n await Promise.resolve(\n toCrossJSONAsync(error, {\n refs: new Map(),\n plugins: serovalPlugins,\n }),\n ),\n )\n const response = getResponse()\n return new Response(serializedError, {\n status: response?.status ?? 500,\n statusText: response?.statusText,\n headers: {\n 'Content-Type': 'application/json',\n [X_TSS_SERIALIZED]: 'true',\n },\n })\n }\n })()\n\n request.signal.removeEventListener('abort', abort)\n\n return response\n}\n\nfunction isNotFoundResponse(error: any) {\n const { headers, ...rest } = error\n\n return new Response(JSON.stringify(rest), {\n status: 404,\n headers: {\n 'Content-Type': 'application/json',\n ...(headers || {}),\n },\n })\n}\n"],"names":["response","controller"],"mappings":"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"}
{"version":3,"file":"server-functions-handler.js","sources":["../../src/server-functions-handler.ts"],"sourcesContent":["import { isNotFound } from '@tanstack/router-core'\nimport invariant from 'tiny-invariant'\nimport {\n TSS_FORMDATA_CONTEXT,\n X_TSS_RAW_RESPONSE,\n X_TSS_SERIALIZED,\n getDefaultSerovalPlugins,\n} from '@tanstack/start-client-core'\nimport { fromJSON, toCrossJSONAsync, toCrossJSONStream } from 'seroval'\nimport { getResponse } from './request-response'\nimport { getServerFnById } from './getServerFnById'\n\nlet regex: RegExp | undefined = undefined\n\nexport const handleServerAction = async ({\n request,\n context,\n}: {\n request: Request\n context: any\n}) => {\n const controller = new AbortController()\n const signal = controller.signal\n const abort = () => controller.abort()\n request.signal.addEventListener('abort', abort)\n\n if (regex === undefined) {\n regex = new RegExp(`${process.env.TSS_SERVER_FN_BASE}([^/?#]+)`)\n }\n\n const method = request.method\n const url = new URL(request.url, 'http://localhost:3000')\n // extract the serverFnId from the url as host/_serverFn/:serverFnId\n // Define a regex to match the path and extract the :thing part\n\n // Execute the regex\n const match = url.pathname.match(regex)\n const serverFnId = match ? match[1] : null\n const search = Object.fromEntries(url.searchParams.entries()) as {\n payload?: any\n createServerFn?: boolean\n }\n\n const isCreateServerFn = 'createServerFn' in search\n\n if (typeof serverFnId !== 'string') {\n throw new Error('Invalid server action param for serverFnId: ' + serverFnId)\n }\n\n const action = await getServerFnById(serverFnId, { fromClient: true })\n\n // Known FormData 'Content-Type' header values\n const formDataContentTypes = [\n 'multipart/form-data',\n 'application/x-www-form-urlencoded',\n ]\n\n const contentType = request.headers.get('Content-Type')\n const serovalPlugins = getDefaultSerovalPlugins()\n\n function parsePayload(payload: any) {\n const parsedPayload = fromJSON(payload, { plugins: serovalPlugins })\n return parsedPayload as any\n }\n\n const response = await (async () => {\n try {\n let result = await (async () => {\n // FormData\n if (\n formDataContentTypes.some(\n (type) => contentType && contentType.includes(type),\n )\n ) {\n // We don't support GET requests with FormData payloads... that seems impossible\n invariant(\n method.toLowerCase() !== 'get',\n 'GET requests with FormData payloads are not supported',\n )\n const formData = await request.formData()\n const serializedContext = formData.get(TSS_FORMDATA_CONTEXT)\n formData.delete(TSS_FORMDATA_CONTEXT)\n\n const params = {\n context,\n data: formData,\n }\n if (typeof serializedContext === 'string') {\n try {\n const parsedContext = JSON.parse(serializedContext)\n const deserializedContext = fromJSON(parsedContext, {\n plugins: serovalPlugins,\n })\n if (\n typeof deserializedContext === 'object' &&\n deserializedContext\n ) {\n params.context = { ...context, ...deserializedContext }\n }\n } catch {}\n }\n\n return await action(params, signal)\n }\n\n // Get requests use the query string\n if (method.toLowerCase() === 'get') {\n invariant(\n isCreateServerFn,\n 'expected GET request to originate from createServerFn',\n )\n // By default the payload is the search params\n let payload: any = search.payload\n // If there's a payload, we should try to parse it\n payload = payload ? parsePayload(JSON.parse(payload)) : {}\n payload.context = { ...context, ...payload.context }\n // Send it through!\n return await action(payload, signal)\n }\n\n if (method.toLowerCase() !== 'post') {\n throw new Error('expected POST method')\n }\n\n let jsonPayload\n if (contentType?.includes('application/json')) {\n jsonPayload = await request.json()\n }\n\n // If this POST request was created by createServerFn,\n // its payload will be the only argument\n if (isCreateServerFn) {\n const payload = jsonPayload ? parsePayload(jsonPayload) : {}\n payload.context = { ...payload.context, ...context }\n return await action(payload, signal)\n }\n\n // Otherwise, we'll spread the payload. Need to\n // support `use server` functions that take multiple\n // arguments.\n return await action(...jsonPayload)\n })()\n\n // Any time we get a Response back, we should just\n // return it immediately.\n if (result.result instanceof Response) {\n result.result.headers.set(X_TSS_RAW_RESPONSE, 'true')\n return result.result\n }\n\n // If this is a non createServerFn request, we need to\n // pull out the result from the result object\n if (!isCreateServerFn) {\n result = result.result\n\n // The result might again be a response,\n // and if it is, return it.\n if (result instanceof Response) {\n return result\n }\n }\n\n // TODO: RSCs Where are we getting this package?\n // if (isValidElement(result)) {\n // const { renderToPipeableStream } = await import(\n // // @ts-expect-error\n // 'react-server-dom/server'\n // )\n\n // const pipeableStream = renderToPipeableStream(result)\n\n // setHeaders(event, {\n // 'Content-Type': 'text/x-component',\n // } as any)\n\n // sendStream(event, response)\n // event._handled = true\n\n // return new Response(null, { status: 200 })\n // }\n\n if (isNotFound(result)) {\n return isNotFoundResponse(result)\n }\n\n const response = getResponse()\n let nonStreamingBody: any = undefined\n\n if (result !== undefined) {\n // first run without the stream in case `result` does not need streaming\n let done = false as boolean\n const callbacks: {\n onParse: (value: any) => void\n onDone: () => void\n onError: (error: any) => void\n } = {\n onParse: (value) => {\n nonStreamingBody = value\n },\n onDone: () => {\n done = true\n },\n onError: (error) => {\n throw error\n },\n }\n toCrossJSONStream(result, {\n refs: new Map(),\n plugins: serovalPlugins,\n onParse(value) {\n callbacks.onParse(value)\n },\n onDone() {\n callbacks.onDone()\n },\n onError: (error) => {\n callbacks.onError(error)\n },\n })\n if (done) {\n return new Response(\n nonStreamingBody ? JSON.stringify(nonStreamingBody) : undefined,\n {\n status: response?.status,\n statusText: response?.statusText,\n headers: {\n 'Content-Type': 'application/json',\n [X_TSS_SERIALIZED]: 'true',\n },\n },\n )\n }\n\n // not done yet, we need to stream\n const encoder = new TextEncoder()\n const stream = new ReadableStream({\n start(controller) {\n callbacks.onParse = (value) =>\n controller.enqueue(encoder.encode(JSON.stringify(value) + '\\n'))\n callbacks.onDone = () => {\n try {\n controller.close()\n } catch (error) {\n controller.error(error)\n }\n }\n callbacks.onError = (error) => controller.error(error)\n // stream the initial body\n if (nonStreamingBody !== undefined) {\n callbacks.onParse(nonStreamingBody)\n }\n },\n })\n return new Response(stream, {\n status: response?.status,\n statusText: response?.statusText,\n headers: {\n 'Content-Type': 'application/x-ndjson',\n [X_TSS_SERIALIZED]: 'true',\n },\n })\n }\n\n return new Response(undefined, {\n status: response?.status,\n statusText: response?.statusText,\n })\n } catch (error: any) {\n if (error instanceof Response) {\n return error\n }\n // else if (\n // isPlainObject(error) &&\n // 'result' in error &&\n // error.result instanceof Response\n // ) {\n // return error.result\n // }\n\n // Currently this server-side context has no idea how to\n // build final URLs, so we need to defer that to the client.\n // The client will check for __redirect and __notFound keys,\n // and if they exist, it will handle them appropriately.\n\n if (isNotFound(error)) {\n return isNotFoundResponse(error)\n }\n\n console.info()\n console.info('Server Fn Error!')\n console.info()\n console.error(error)\n console.info()\n\n const serializedError = JSON.stringify(\n await Promise.resolve(\n toCrossJSONAsync(error, {\n refs: new Map(),\n plugins: serovalPlugins,\n }),\n ),\n )\n const response = getResponse()\n return new Response(serializedError, {\n status: response?.status ?? 500,\n statusText: response?.statusText,\n headers: {\n 'Content-Type': 'application/json',\n [X_TSS_SERIALIZED]: 'true',\n },\n })\n }\n })()\n\n request.signal.removeEventListener('abort', abort)\n\n return response\n}\n\nfunction isNotFoundResponse(error: any) {\n const { headers, ...rest } = error\n\n return new Response(JSON.stringify(rest), {\n status: 404,\n headers: {\n 'Content-Type': 'application/json',\n ...(headers || {}),\n },\n })\n}\n"],"names":["response","controller"],"mappings":"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"}
{
"name": "@tanstack/start-server-core",
"version": "1.141.8",
"version": "1.142.1",
"description": "Modern and scalable routing for React applications",

@@ -63,9 +63,9 @@ "author": "Tanner Linsley",

"dependencies": {
"h3-v2": "npm:h3@2.0.0-beta.5",
"h3-v2": "npm:h3@2.0.1-rc.2",
"seroval": "^1.4.1",
"tiny-invariant": "^1.3.3",
"@tanstack/history": "1.141.0",
"@tanstack/start-client-core": "1.141.8",
"@tanstack/start-storage-context": "1.141.8",
"@tanstack/router-core": "1.141.8"
"@tanstack/router-core": "1.141.8",
"@tanstack/start-client-core": "1.142.1",
"@tanstack/start-storage-context": "1.142.1",
"@tanstack/history": "1.141.0"
},

@@ -72,0 +72,0 @@ "devDependencies": {

import { TSS_SERVER_FUNCTION } from '@tanstack/start-client-core'
import { getServerFnById } from './getServerFnById'
import type { ServerFn } from '#tanstack-start-server-fn-manifest'
export const createSsrRpc = (functionId: string) => {
export type SsrRpcImporter = () => Promise<ServerFn>
export const createSsrRpc = (functionId: string, importer?: SsrRpcImporter) => {
const url = process.env.TSS_SERVER_FN_BASE + functionId
const fn = async (...args: Array<any>): Promise<any> => {
const serverFn = await getServerFnById(functionId)
// If an importer is provided, use it directly (server-to-server call within the SSR environment)
// Otherwise, fall back to manifest lookup (client-to-server call, server functions that are only referenced on the server or if the provider environment is not SSR)
const serverFn = importer
? await importer()
: await getServerFnById(functionId)
return serverFn(...args)

@@ -9,0 +16,0 @@ }

@@ -45,4 +45,17 @@ import { AsyncLocalStorage } from 'node:async_hooks'

}
const eventStorage = new AsyncLocalStorage<StartEvent>()
// Use a global symbol to ensure the same AsyncLocalStorage instance is shared
// across different bundles that may each bundle this module.
const GLOBAL_EVENT_STORAGE_KEY = Symbol.for('tanstack-start:event-storage')
const globalObj = globalThis as typeof globalThis & {
[GLOBAL_EVENT_STORAGE_KEY]?: AsyncLocalStorage<StartEvent>
}
if (!globalObj[GLOBAL_EVENT_STORAGE_KEY]) {
globalObj[GLOBAL_EVENT_STORAGE_KEY] = new AsyncLocalStorage<StartEvent>()
}
const eventStorage = globalObj[GLOBAL_EVENT_STORAGE_KEY]
export type { ResponseHeaderName, RequestHeaderName }

@@ -331,3 +344,4 @@

const event = getH3Event()
return event._res
// @ts-expect-error accessing internal symbol
return event[Symbol.for('h3.internal.event.res')]
}

@@ -334,0 +348,0 @@

@@ -18,3 +18,6 @@ import { createSerializationAdapter } from '@tanstack/router-core'

const fn = async (opts: any, signal: any): Promise<any> => {
const serverFn = await getServerFnById(functionId)
// When a function ID is received through serialization (e.g., as a parameter
// to another server function), it originates from the client and must be
// validated the same way as direct HTTP calls to server functions.
const serverFn = await getServerFnById(functionId, { fromClient: true })
const result = await serverFn(opts ?? {}, signal)

@@ -21,0 +24,0 @@ return result.result

@@ -50,3 +50,3 @@ import { isNotFound } from '@tanstack/router-core'

const action = await getServerFnById(serverFnId)
const action = await getServerFnById(serverFnId, { fromClient: true })

@@ -53,0 +53,0 @@ // Known FormData 'Content-Type' header values

@@ -15,3 +15,6 @@ declare module 'tanstack-start-manifest:v' {

type ServerFn = (...args: Array<any>) => Promise<any>
export function getServerFnById(id: string): Promise<ServerFn>
export function getServerFnById(
id: string,
opts?: { fromClient?: boolean },
): Promise<ServerFn>
}

@@ -18,0 +21,0 @@