@tanstack/start-client-core 1.114.4 → 1.114.5

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.
Files changed (62) hide show
  1. package/dist/cjs/createIsomorphicFn.cjs +7 -0
  2. package/dist/cjs/createIsomorphicFn.cjs.map +1 -0
  3. package/dist/cjs/createIsomorphicFn.d.cts +12 -0
  4. package/dist/cjs/createMiddleware.cjs +34 -0
  5. package/dist/cjs/createMiddleware.cjs.map +1 -0
  6. package/dist/cjs/createMiddleware.d.cts +131 -0
  7. package/dist/cjs/createServerFn.cjs +227 -0
  8. package/dist/cjs/createServerFn.cjs.map +1 -0
  9. package/dist/cjs/createServerFn.d.cts +152 -0
  10. package/dist/cjs/envOnly.cjs +7 -0
  11. package/dist/cjs/envOnly.cjs.map +1 -0
  12. package/dist/cjs/envOnly.d.cts +4 -0
  13. package/dist/cjs/index.cjs +22 -0
  14. package/dist/cjs/index.cjs.map +1 -1
  15. package/dist/cjs/index.d.cts +8 -0
  16. package/dist/cjs/json.cjs +14 -0
  17. package/dist/cjs/json.cjs.map +1 -0
  18. package/dist/cjs/json.d.cts +2 -0
  19. package/dist/cjs/registerGlobalMiddleware.cjs +9 -0
  20. package/dist/cjs/registerGlobalMiddleware.cjs.map +1 -0
  21. package/dist/cjs/registerGlobalMiddleware.d.cts +5 -0
  22. package/dist/cjs/tests/createIsomorphicFn.test-d.d.cts +1 -0
  23. package/dist/cjs/tests/createServerMiddleware.test-d.d.cts +1 -0
  24. package/dist/cjs/tests/envOnly.test-d.d.cts +1 -0
  25. package/dist/cjs/tests/json.test.d.cts +1 -0
  26. package/dist/esm/createIsomorphicFn.d.ts +12 -0
  27. package/dist/esm/createIsomorphicFn.js +7 -0
  28. package/dist/esm/createIsomorphicFn.js.map +1 -0
  29. package/dist/esm/createMiddleware.d.ts +131 -0
  30. package/dist/esm/createMiddleware.js +34 -0
  31. package/dist/esm/createMiddleware.js.map +1 -0
  32. package/dist/esm/createServerFn.d.ts +152 -0
  33. package/dist/esm/createServerFn.js +206 -0
  34. package/dist/esm/createServerFn.js.map +1 -0
  35. package/dist/esm/envOnly.d.ts +4 -0
  36. package/dist/esm/envOnly.js +7 -0
  37. package/dist/esm/envOnly.js.map +1 -0
  38. package/dist/esm/index.d.ts +8 -0
  39. package/dist/esm/index.js +19 -0
  40. package/dist/esm/index.js.map +1 -1
  41. package/dist/esm/json.d.ts +2 -0
  42. package/dist/esm/json.js +14 -0
  43. package/dist/esm/json.js.map +1 -0
  44. package/dist/esm/registerGlobalMiddleware.d.ts +5 -0
  45. package/dist/esm/registerGlobalMiddleware.js +9 -0
  46. package/dist/esm/registerGlobalMiddleware.js.map +1 -0
  47. package/dist/esm/tests/createIsomorphicFn.test-d.d.ts +1 -0
  48. package/dist/esm/tests/createServerMiddleware.test-d.d.ts +1 -0
  49. package/dist/esm/tests/envOnly.test-d.d.ts +1 -0
  50. package/dist/esm/tests/json.test.d.ts +1 -0
  51. package/package.json +2 -1
  52. package/src/createIsomorphicFn.ts +36 -0
  53. package/src/createMiddleware.ts +595 -0
  54. package/src/createServerFn.ts +700 -0
  55. package/src/envOnly.ts +9 -0
  56. package/src/index.tsx +73 -0
  57. package/src/json.ts +15 -0
  58. package/src/registerGlobalMiddleware.ts +9 -0
  59. package/src/tests/createIsomorphicFn.test-d.ts +72 -0
  60. package/src/tests/createServerMiddleware.test-d.ts +611 -0
  61. package/src/tests/envOnly.test-d.ts +34 -0
  62. package/src/tests/json.test.ts +37 -0
@@ -0,0 +1,152 @@
1
+ import { Readable } from 'node:stream';
2
+ import { AnyValidator, Constrain, Expand, ResolveValidatorInput, SerializerParse, SerializerStringify, SerializerStringifyBy, Validator } from '@tanstack/router-core';
3
+ import { AnyMiddleware, AssignAllClientSendContext, AssignAllServerContext, IntersectAllValidatorInputs, IntersectAllValidatorOutputs } from './createMiddleware.js';
4
+ export interface JsonResponse<TData> extends Response {
5
+ json: () => Promise<TData>;
6
+ }
7
+ export type CompiledFetcherFnOptions = {
8
+ method: Method;
9
+ data: unknown;
10
+ response?: ServerFnResponseType;
11
+ headers?: HeadersInit;
12
+ signal?: AbortSignal;
13
+ context?: any;
14
+ };
15
+ export type Fetcher<TMiddlewares, TValidator, TResponse, TServerFnResponseType extends ServerFnResponseType> = undefined extends IntersectAllValidatorInputs<TMiddlewares, TValidator> ? OptionalFetcher<TMiddlewares, TValidator, TResponse, TServerFnResponseType> : RequiredFetcher<TMiddlewares, TValidator, TResponse, TServerFnResponseType>;
16
+ export interface FetcherBase {
17
+ url: string;
18
+ __executeServer: (opts: {
19
+ method: Method;
20
+ response?: ServerFnResponseType;
21
+ data: unknown;
22
+ headers?: HeadersInit;
23
+ context?: any;
24
+ signal: AbortSignal;
25
+ }) => Promise<unknown>;
26
+ }
27
+ export type FetchResult<TMiddlewares, TResponse, TServerFnResponseType extends ServerFnResponseType> = TServerFnResponseType extends 'raw' ? Promise<Response> : TServerFnResponseType extends 'full' ? Promise<FullFetcherData<TMiddlewares, TResponse>> : Promise<FetcherData<TResponse>>;
28
+ export interface OptionalFetcher<TMiddlewares, TValidator, TResponse, TServerFnResponseType extends ServerFnResponseType> extends FetcherBase {
29
+ (options?: OptionalFetcherDataOptions<TMiddlewares, TValidator>): FetchResult<TMiddlewares, TResponse, TServerFnResponseType>;
30
+ }
31
+ export interface RequiredFetcher<TMiddlewares, TValidator, TResponse, TServerFnResponseType extends ServerFnResponseType> extends FetcherBase {
32
+ (opts: RequiredFetcherDataOptions<TMiddlewares, TValidator>): FetchResult<TMiddlewares, TResponse, TServerFnResponseType>;
33
+ }
34
+ export type FetcherBaseOptions = {
35
+ headers?: HeadersInit;
36
+ type?: ServerFnType;
37
+ signal?: AbortSignal;
38
+ };
39
+ export type ServerFnType = 'static' | 'dynamic';
40
+ export interface OptionalFetcherDataOptions<TMiddlewares, TValidator> extends FetcherBaseOptions {
41
+ data?: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>;
42
+ }
43
+ export interface RequiredFetcherDataOptions<TMiddlewares, TValidator> extends FetcherBaseOptions {
44
+ data: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>;
45
+ }
46
+ export interface FullFetcherData<TMiddlewares, TResponse> {
47
+ error: unknown;
48
+ result: FetcherData<TResponse>;
49
+ context: AssignAllClientSendContext<TMiddlewares>;
50
+ }
51
+ export type FetcherData<TResponse> = TResponse extends JsonResponse<any> ? SerializerParse<ReturnType<TResponse['json']>> : SerializerParse<TResponse>;
52
+ export type RscStream<T> = {
53
+ __cacheState: T;
54
+ };
55
+ export type Method = 'GET' | 'POST';
56
+ export type ServerFnResponseType = 'data' | 'full' | 'raw';
57
+ export type RawResponse = Response | ReadableStream | Readable | null | string;
58
+ export type ServerFnReturnType<TServerFnResponseType extends ServerFnResponseType, TResponse> = TServerFnResponseType extends 'raw' ? RawResponse | Promise<RawResponse> : Promise<SerializerStringify<TResponse>> | SerializerStringify<TResponse>;
59
+ export type ServerFn<TMethod, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator, TResponse> = (ctx: ServerFnCtx<TMethod, TServerFnResponseType, TMiddlewares, TValidator>) => ServerFnReturnType<TServerFnResponseType, TResponse>;
60
+ export interface ServerFnCtx<TMethod, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> {
61
+ method: TMethod;
62
+ response: TServerFnResponseType;
63
+ data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TValidator>>;
64
+ context: Expand<AssignAllServerContext<TMiddlewares>>;
65
+ signal: AbortSignal;
66
+ }
67
+ export type CompiledFetcherFn<TResponse, TServerFnResponseType extends ServerFnResponseType> = {
68
+ (opts: CompiledFetcherFnOptions & ServerFnBaseOptions<Method, TServerFnResponseType>): Promise<TResponse>;
69
+ url: string;
70
+ };
71
+ export type ServerFnBaseOptions<TMethod extends Method = 'GET', TServerFnResponseType extends ServerFnResponseType = 'data', TResponse = unknown, TMiddlewares = unknown, TInput = unknown> = {
72
+ method: TMethod;
73
+ response?: TServerFnResponseType;
74
+ validateClient?: boolean;
75
+ middleware?: Constrain<TMiddlewares, ReadonlyArray<AnyMiddleware>>;
76
+ validator?: ConstrainValidator<TInput>;
77
+ extractedFn?: CompiledFetcherFn<TResponse, TServerFnResponseType>;
78
+ serverFn?: ServerFn<TMethod, TServerFnResponseType, TMiddlewares, TInput, TResponse>;
79
+ functionId: string;
80
+ type: ServerFnTypeOrTypeFn<TMethod, TServerFnResponseType, TMiddlewares, AnyValidator>;
81
+ };
82
+ export type ValidatorSerializerStringify<TValidator> = Validator<SerializerStringifyBy<ResolveValidatorInput<TValidator>, Date | undefined | FormData>, any>;
83
+ export type ConstrainValidator<TValidator> = unknown extends TValidator ? TValidator : Constrain<TValidator, ValidatorSerializerStringify<TValidator>>;
84
+ export interface ServerFnMiddleware<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TValidator> {
85
+ middleware: <const TNewMiddlewares = undefined>(middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyMiddleware>>) => ServerFnAfterMiddleware<TMethod, TServerFnResponseType, TNewMiddlewares, TValidator>;
86
+ }
87
+ export interface ServerFnAfterMiddleware<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> extends ServerFnValidator<TMethod, TServerFnResponseType, TMiddlewares>, ServerFnTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>, ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {
88
+ }
89
+ export type ValidatorFn<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares> = <TValidator>(validator: ConstrainValidator<TValidator>) => ServerFnAfterValidator<TMethod, TServerFnResponseType, TMiddlewares, TValidator>;
90
+ export interface ServerFnValidator<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares> {
91
+ validator: ValidatorFn<TMethod, TServerFnResponseType, TMiddlewares>;
92
+ }
93
+ export interface ServerFnAfterValidator<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> extends ServerFnMiddleware<TMethod, TServerFnResponseType, TValidator>, ServerFnTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>, ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {
94
+ }
95
+ export interface ServerFnTyper<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> {
96
+ type: (typer: ServerFnTypeOrTypeFn<TMethod, TServerFnResponseType, TMiddlewares, TValidator>) => ServerFnAfterTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>;
97
+ }
98
+ export type ServerFnTypeOrTypeFn<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> = ServerFnType | ((ctx: ServerFnCtx<TMethod, TServerFnResponseType, TMiddlewares, TValidator>) => ServerFnType);
99
+ export interface ServerFnAfterTyper<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> extends ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {
100
+ }
101
+ export interface ServerFnHandler<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> {
102
+ handler: <TNewResponse>(fn?: ServerFn<TMethod, TServerFnResponseType, TMiddlewares, TValidator, TNewResponse>) => Fetcher<TMiddlewares, TValidator, TNewResponse, TServerFnResponseType>;
103
+ }
104
+ export interface ServerFnBuilder<TMethod extends Method = 'GET', TServerFnResponseType extends ServerFnResponseType = 'data'> extends ServerFnMiddleware<TMethod, TServerFnResponseType, undefined>, ServerFnValidator<TMethod, TServerFnResponseType, undefined>, ServerFnTyper<TMethod, TServerFnResponseType, undefined, undefined>, ServerFnHandler<TMethod, TServerFnResponseType, undefined, undefined> {
105
+ options: ServerFnBaseOptions<TMethod, TServerFnResponseType, unknown, undefined, undefined>;
106
+ }
107
+ export type StaticCachedResult = {
108
+ ctx?: {
109
+ result: any;
110
+ context: any;
111
+ };
112
+ error?: any;
113
+ };
114
+ export type ServerFnStaticCache = {
115
+ getItem: (ctx: ServerFnMiddlewareResult) => StaticCachedResult | Promise<StaticCachedResult | undefined>;
116
+ setItem: (ctx: ServerFnMiddlewareResult, response: StaticCachedResult) => Promise<void>;
117
+ fetchItem: (ctx: ServerFnMiddlewareResult) => StaticCachedResult | Promise<StaticCachedResult | undefined>;
118
+ };
119
+ export declare let serverFnStaticCache: ServerFnStaticCache | undefined;
120
+ export declare function setServerFnStaticCache(cache?: ServerFnStaticCache | (() => ServerFnStaticCache | undefined)): () => void;
121
+ export declare function createServerFnStaticCache(serverFnStaticCache: ServerFnStaticCache): ServerFnStaticCache;
122
+ export declare function extractFormDataContext(formData: FormData): {
123
+ context: unknown;
124
+ data: FormData;
125
+ } | {
126
+ data: FormData;
127
+ context?: undefined;
128
+ };
129
+ export declare function flattenMiddlewares(middlewares: Array<AnyMiddleware>): Array<AnyMiddleware>;
130
+ export type ServerFnMiddlewareOptions = {
131
+ method: Method;
132
+ response?: ServerFnResponseType;
133
+ data: any;
134
+ headers?: HeadersInit;
135
+ signal?: AbortSignal;
136
+ sendContext?: any;
137
+ context?: any;
138
+ type: ServerFnTypeOrTypeFn<any, any, any, any>;
139
+ functionId: string;
140
+ };
141
+ export type ServerFnMiddlewareResult = ServerFnMiddlewareOptions & {
142
+ result?: unknown;
143
+ error?: unknown;
144
+ type: ServerFnTypeOrTypeFn<any, any, any, any>;
145
+ };
146
+ export type NextFn = (ctx: ServerFnMiddlewareResult) => Promise<ServerFnMiddlewareResult>;
147
+ export type MiddlewareFn = (ctx: ServerFnMiddlewareOptions & {
148
+ next: NextFn;
149
+ }) => Promise<ServerFnMiddlewareResult>;
150
+ export declare const applyMiddleware: (middlewareFn: MiddlewareFn, ctx: ServerFnMiddlewareOptions, nextFn: NextFn) => Promise<ServerFnMiddlewareResult>;
151
+ export declare function execValidator(validator: AnyValidator, input: unknown): unknown;
152
+ export declare function serverFnBaseToMiddleware(options: ServerFnBaseOptions<any, any, any, any, any>): AnyMiddleware;
@@ -0,0 +1,206 @@
1
+ import invariant from "tiny-invariant";
2
+ import warning from "tiny-warning";
3
+ import { startSerializer } from "./serializer.js";
4
+ import { mergeHeaders } from "./headers.js";
5
+ let serverFnStaticCache;
6
+ function setServerFnStaticCache(cache) {
7
+ const previousCache = serverFnStaticCache;
8
+ serverFnStaticCache = typeof cache === "function" ? cache() : cache;
9
+ return () => {
10
+ serverFnStaticCache = previousCache;
11
+ };
12
+ }
13
+ function createServerFnStaticCache(serverFnStaticCache2) {
14
+ return serverFnStaticCache2;
15
+ }
16
+ setServerFnStaticCache(() => {
17
+ const getStaticCacheUrl = (options, hash) => {
18
+ return `/__tsr/staticServerFnCache/${options.functionId}__${hash}.json`;
19
+ };
20
+ const jsonToFilenameSafeString = (json) => {
21
+ const sortedKeysReplacer = (key, value) => value && typeof value === "object" && !Array.isArray(value) ? Object.keys(value).sort().reduce((acc, curr) => {
22
+ acc[curr] = value[curr];
23
+ return acc;
24
+ }, {}) : value;
25
+ const jsonString = JSON.stringify(json ?? "", sortedKeysReplacer);
26
+ return jsonString.replace(/[/\\?%*:|"<>]/g, "-").replace(/\s+/g, "_");
27
+ };
28
+ const staticClientCache = typeof document !== "undefined" ? /* @__PURE__ */ new Map() : null;
29
+ return createServerFnStaticCache({
30
+ getItem: async (ctx) => {
31
+ if (typeof document === "undefined") {
32
+ const hash = jsonToFilenameSafeString(ctx.data);
33
+ const url = getStaticCacheUrl(ctx, hash);
34
+ const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR;
35
+ const { promises: fs } = await import("node:fs");
36
+ const path = await import("node:path");
37
+ const filePath = path.join(publicUrl, url);
38
+ const [cachedResult, readError] = await fs.readFile(filePath, "utf-8").then((c) => [
39
+ startSerializer.parse(c),
40
+ null
41
+ ]).catch((e) => [null, e]);
42
+ if (readError && readError.code !== "ENOENT") {
43
+ throw readError;
44
+ }
45
+ return cachedResult;
46
+ }
47
+ return void 0;
48
+ },
49
+ setItem: async (ctx, response) => {
50
+ const { promises: fs } = await import("node:fs");
51
+ const path = await import("node:path");
52
+ const hash = jsonToFilenameSafeString(ctx.data);
53
+ const url = getStaticCacheUrl(ctx, hash);
54
+ const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR;
55
+ const filePath = path.join(publicUrl, url);
56
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
57
+ await fs.writeFile(filePath, startSerializer.stringify(response));
58
+ },
59
+ fetchItem: async (ctx) => {
60
+ const hash = jsonToFilenameSafeString(ctx.data);
61
+ const url = getStaticCacheUrl(ctx, hash);
62
+ let result = staticClientCache == null ? void 0 : staticClientCache.get(url);
63
+ if (!result) {
64
+ result = await fetch(url, {
65
+ method: "GET"
66
+ }).then((r) => r.text()).then((d) => startSerializer.parse(d));
67
+ staticClientCache == null ? void 0 : staticClientCache.set(url, result);
68
+ }
69
+ return result;
70
+ }
71
+ });
72
+ });
73
+ function extractFormDataContext(formData) {
74
+ const serializedContext = formData.get("__TSR_CONTEXT");
75
+ formData.delete("__TSR_CONTEXT");
76
+ if (typeof serializedContext !== "string") {
77
+ return {
78
+ context: {},
79
+ data: formData
80
+ };
81
+ }
82
+ try {
83
+ const context = startSerializer.parse(serializedContext);
84
+ return {
85
+ context,
86
+ data: formData
87
+ };
88
+ } catch {
89
+ return {
90
+ data: formData
91
+ };
92
+ }
93
+ }
94
+ function flattenMiddlewares(middlewares) {
95
+ const seen = /* @__PURE__ */ new Set();
96
+ const flattened = [];
97
+ const recurse = (middleware) => {
98
+ middleware.forEach((m) => {
99
+ if (m.options.middleware) {
100
+ recurse(m.options.middleware);
101
+ }
102
+ if (!seen.has(m)) {
103
+ seen.add(m);
104
+ flattened.push(m);
105
+ }
106
+ });
107
+ };
108
+ recurse(middlewares);
109
+ return flattened;
110
+ }
111
+ const applyMiddleware = async (middlewareFn, ctx, nextFn) => {
112
+ return middlewareFn({
113
+ ...ctx,
114
+ next: async (userCtx = {}) => {
115
+ return nextFn({
116
+ ...ctx,
117
+ ...userCtx,
118
+ context: {
119
+ ...ctx.context,
120
+ ...userCtx.context
121
+ },
122
+ sendContext: {
123
+ ...ctx.sendContext,
124
+ ...userCtx.sendContext ?? {}
125
+ },
126
+ headers: mergeHeaders(ctx.headers, userCtx.headers),
127
+ result: userCtx.result !== void 0 ? userCtx.result : ctx.response === "raw" ? userCtx : ctx.result,
128
+ error: userCtx.error ?? ctx.error
129
+ });
130
+ }
131
+ });
132
+ };
133
+ function execValidator(validator, input) {
134
+ if (validator == null) return {};
135
+ if ("~standard" in validator) {
136
+ const result = validator["~standard"].validate(input);
137
+ if (result instanceof Promise)
138
+ throw new Error("Async validation not supported");
139
+ if (result.issues)
140
+ throw new Error(JSON.stringify(result.issues, void 0, 2));
141
+ return result.value;
142
+ }
143
+ if ("parse" in validator) {
144
+ return validator.parse(input);
145
+ }
146
+ if (typeof validator === "function") {
147
+ return validator(input);
148
+ }
149
+ throw new Error("Invalid validator type!");
150
+ }
151
+ function serverFnBaseToMiddleware(options) {
152
+ return {
153
+ _types: void 0,
154
+ options: {
155
+ validator: options.validator,
156
+ validateClient: options.validateClient,
157
+ client: async ({ next, sendContext, ...ctx }) => {
158
+ var _a;
159
+ const payload = {
160
+ ...ctx,
161
+ // switch the sendContext over to context
162
+ context: sendContext,
163
+ type: typeof ctx.type === "function" ? ctx.type(ctx) : ctx.type
164
+ };
165
+ if (ctx.type === "static" && process.env.NODE_ENV === "production" && typeof document !== "undefined") {
166
+ invariant(
167
+ serverFnStaticCache,
168
+ "serverFnStaticCache.fetchItem is not available!"
169
+ );
170
+ const result = await serverFnStaticCache.fetchItem(payload);
171
+ if (result) {
172
+ if (result.error) {
173
+ throw result.error;
174
+ }
175
+ return next(result.ctx);
176
+ }
177
+ warning(
178
+ result,
179
+ `No static cache item found for ${payload.functionId}__${JSON.stringify(payload.data)}, falling back to server function...`
180
+ );
181
+ }
182
+ const res = await ((_a = options.extractedFn) == null ? void 0 : _a.call(options, payload));
183
+ return next(res);
184
+ },
185
+ server: async ({ next, ...ctx }) => {
186
+ var _a;
187
+ const result = await ((_a = options.serverFn) == null ? void 0 : _a.call(options, ctx));
188
+ return next({
189
+ ...ctx,
190
+ result
191
+ });
192
+ }
193
+ }
194
+ };
195
+ }
196
+ export {
197
+ applyMiddleware,
198
+ createServerFnStaticCache,
199
+ execValidator,
200
+ extractFormDataContext,
201
+ flattenMiddlewares,
202
+ serverFnBaseToMiddleware,
203
+ serverFnStaticCache,
204
+ setServerFnStaticCache
205
+ };
206
+ //# sourceMappingURL=createServerFn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createServerFn.js","sources":["../../src/createServerFn.ts"],"sourcesContent":["import { default as invariant } from 'tiny-invariant'\nimport { default as warning } from 'tiny-warning'\nimport { startSerializer } from './serializer'\nimport { mergeHeaders } from './headers'\nimport type { Readable } from 'node:stream'\nimport type {\n AnyValidator,\n Constrain,\n Expand,\n ResolveValidatorInput,\n SerializerParse,\n SerializerStringify,\n SerializerStringifyBy,\n Validator,\n} from '@tanstack/router-core'\nimport type {\n AnyMiddleware,\n AssignAllClientSendContext,\n AssignAllServerContext,\n IntersectAllValidatorInputs,\n IntersectAllValidatorOutputs,\n MiddlewareClientFnResult,\n MiddlewareServerFnResult,\n} from './createMiddleware'\n\nexport interface JsonResponse<TData> extends Response {\n json: () => Promise<TData>\n}\n\nexport type CompiledFetcherFnOptions = {\n method: Method\n data: unknown\n response?: ServerFnResponseType\n headers?: HeadersInit\n signal?: AbortSignal\n context?: any\n}\n\nexport type Fetcher<\n TMiddlewares,\n TValidator,\n TResponse,\n TServerFnResponseType extends ServerFnResponseType,\n> =\n undefined extends IntersectAllValidatorInputs<TMiddlewares, TValidator>\n ? OptionalFetcher<\n TMiddlewares,\n TValidator,\n TResponse,\n TServerFnResponseType\n >\n : RequiredFetcher<\n TMiddlewares,\n TValidator,\n TResponse,\n TServerFnResponseType\n >\n\nexport interface FetcherBase {\n url: string\n __executeServer: (opts: {\n method: Method\n response?: ServerFnResponseType\n data: unknown\n headers?: HeadersInit\n context?: any\n signal: AbortSignal\n }) => Promise<unknown>\n}\n\nexport type FetchResult<\n TMiddlewares,\n TResponse,\n TServerFnResponseType extends ServerFnResponseType,\n> = TServerFnResponseType extends 'raw'\n ? Promise<Response>\n : TServerFnResponseType extends 'full'\n ? Promise<FullFetcherData<TMiddlewares, TResponse>>\n : Promise<FetcherData<TResponse>>\n\nexport interface OptionalFetcher<\n TMiddlewares,\n TValidator,\n TResponse,\n TServerFnResponseType extends ServerFnResponseType,\n> extends FetcherBase {\n (\n options?: OptionalFetcherDataOptions<TMiddlewares, TValidator>,\n ): FetchResult<TMiddlewares, TResponse, TServerFnResponseType>\n}\n\nexport interface RequiredFetcher<\n TMiddlewares,\n TValidator,\n TResponse,\n TServerFnResponseType extends ServerFnResponseType,\n> extends FetcherBase {\n (\n opts: RequiredFetcherDataOptions<TMiddlewares, TValidator>,\n ): FetchResult<TMiddlewares, TResponse, TServerFnResponseType>\n}\n\nexport type FetcherBaseOptions = {\n headers?: HeadersInit\n type?: ServerFnType\n signal?: AbortSignal\n}\n\nexport type ServerFnType = 'static' | 'dynamic'\n\nexport interface OptionalFetcherDataOptions<TMiddlewares, TValidator>\n extends FetcherBaseOptions {\n data?: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>\n}\n\nexport interface RequiredFetcherDataOptions<TMiddlewares, TValidator>\n extends FetcherBaseOptions {\n data: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>\n}\n\nexport interface FullFetcherData<TMiddlewares, TResponse> {\n error: unknown\n result: FetcherData<TResponse>\n context: AssignAllClientSendContext<TMiddlewares>\n}\n\nexport type FetcherData<TResponse> =\n TResponse extends JsonResponse<any>\n ? SerializerParse<ReturnType<TResponse['json']>>\n : SerializerParse<TResponse>\n\nexport type RscStream<T> = {\n __cacheState: T\n}\n\nexport type Method = 'GET' | 'POST'\nexport type ServerFnResponseType = 'data' | 'full' | 'raw'\n\n// see https://h3.unjs.io/guide/event-handler#responses-types\nexport type RawResponse = Response | ReadableStream | Readable | null | string\n\nexport type ServerFnReturnType<\n TServerFnResponseType extends ServerFnResponseType,\n TResponse,\n> = TServerFnResponseType extends 'raw'\n ? RawResponse | Promise<RawResponse>\n : Promise<SerializerStringify<TResponse>> | SerializerStringify<TResponse>\nexport type ServerFn<\n TMethod,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n TResponse,\n> = (\n ctx: ServerFnCtx<TMethod, TServerFnResponseType, TMiddlewares, TValidator>,\n) => ServerFnReturnType<TServerFnResponseType, TResponse>\n\nexport interface ServerFnCtx<\n TMethod,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> {\n method: TMethod\n response: TServerFnResponseType\n data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TValidator>>\n context: Expand<AssignAllServerContext<TMiddlewares>>\n signal: AbortSignal\n}\n\nexport type CompiledFetcherFn<\n TResponse,\n TServerFnResponseType extends ServerFnResponseType,\n> = {\n (\n opts: CompiledFetcherFnOptions &\n ServerFnBaseOptions<Method, TServerFnResponseType>,\n ): Promise<TResponse>\n url: string\n}\n\nexport type ServerFnBaseOptions<\n TMethod extends Method = 'GET',\n TServerFnResponseType extends ServerFnResponseType = 'data',\n TResponse = unknown,\n TMiddlewares = unknown,\n TInput = unknown,\n> = {\n method: TMethod\n response?: TServerFnResponseType\n validateClient?: boolean\n middleware?: Constrain<TMiddlewares, ReadonlyArray<AnyMiddleware>>\n validator?: ConstrainValidator<TInput>\n extractedFn?: CompiledFetcherFn<TResponse, TServerFnResponseType>\n serverFn?: ServerFn<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TInput,\n TResponse\n >\n functionId: string\n type: ServerFnTypeOrTypeFn<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n AnyValidator\n >\n}\n\nexport type ValidatorSerializerStringify<TValidator> = Validator<\n SerializerStringifyBy<\n ResolveValidatorInput<TValidator>,\n Date | undefined | FormData\n >,\n any\n>\n\nexport type ConstrainValidator<TValidator> = unknown extends TValidator\n ? TValidator\n : Constrain<TValidator, ValidatorSerializerStringify<TValidator>>\n\nexport interface ServerFnMiddleware<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TValidator,\n> {\n middleware: <const TNewMiddlewares = undefined>(\n middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyMiddleware>>,\n ) => ServerFnAfterMiddleware<\n TMethod,\n TServerFnResponseType,\n TNewMiddlewares,\n TValidator\n >\n}\n\nexport interface ServerFnAfterMiddleware<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> extends ServerFnValidator<TMethod, TServerFnResponseType, TMiddlewares>,\n ServerFnTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>,\n ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {}\n\nexport type ValidatorFn<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n> = <TValidator>(\n validator: ConstrainValidator<TValidator>,\n) => ServerFnAfterValidator<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n>\n\nexport interface ServerFnValidator<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n> {\n validator: ValidatorFn<TMethod, TServerFnResponseType, TMiddlewares>\n}\n\nexport interface ServerFnAfterValidator<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> extends ServerFnMiddleware<TMethod, TServerFnResponseType, TValidator>,\n ServerFnTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>,\n ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {}\n\n// Typer\nexport interface ServerFnTyper<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> {\n type: (\n typer: ServerFnTypeOrTypeFn<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n >,\n ) => ServerFnAfterTyper<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n >\n}\n\nexport type ServerFnTypeOrTypeFn<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> =\n | ServerFnType\n | ((\n ctx: ServerFnCtx<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n >,\n ) => ServerFnType)\n\nexport interface ServerFnAfterTyper<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> extends ServerFnHandler<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n > {}\n\n// Handler\nexport interface ServerFnHandler<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> {\n handler: <TNewResponse>(\n fn?: ServerFn<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator,\n TNewResponse\n >,\n ) => Fetcher<TMiddlewares, TValidator, TNewResponse, TServerFnResponseType>\n}\n\nexport interface ServerFnBuilder<\n TMethod extends Method = 'GET',\n TServerFnResponseType extends ServerFnResponseType = 'data',\n> extends ServerFnMiddleware<TMethod, TServerFnResponseType, undefined>,\n ServerFnValidator<TMethod, TServerFnResponseType, undefined>,\n ServerFnTyper<TMethod, TServerFnResponseType, undefined, undefined>,\n ServerFnHandler<TMethod, TServerFnResponseType, undefined, undefined> {\n options: ServerFnBaseOptions<\n TMethod,\n TServerFnResponseType,\n unknown,\n undefined,\n undefined\n >\n}\n\nexport type StaticCachedResult = {\n ctx?: {\n result: any\n context: any\n }\n error?: any\n}\n\nexport type ServerFnStaticCache = {\n getItem: (\n ctx: ServerFnMiddlewareResult,\n ) => StaticCachedResult | Promise<StaticCachedResult | undefined>\n setItem: (\n ctx: ServerFnMiddlewareResult,\n response: StaticCachedResult,\n ) => Promise<void>\n fetchItem: (\n ctx: ServerFnMiddlewareResult,\n ) => StaticCachedResult | Promise<StaticCachedResult | undefined>\n}\n\nexport let serverFnStaticCache: ServerFnStaticCache | undefined\n\nexport function setServerFnStaticCache(\n cache?: ServerFnStaticCache | (() => ServerFnStaticCache | undefined),\n) {\n const previousCache = serverFnStaticCache\n serverFnStaticCache = typeof cache === 'function' ? cache() : cache\n\n return () => {\n serverFnStaticCache = previousCache\n }\n}\n\nexport function createServerFnStaticCache(\n serverFnStaticCache: ServerFnStaticCache,\n) {\n return serverFnStaticCache\n}\n\nsetServerFnStaticCache(() => {\n const getStaticCacheUrl = (\n options: ServerFnMiddlewareResult,\n hash: string,\n ) => {\n return `/__tsr/staticServerFnCache/${options.functionId}__${hash}.json`\n }\n\n const jsonToFilenameSafeString = (json: any) => {\n // Custom replacer to sort keys\n const sortedKeysReplacer = (key: string, value: any) =>\n value && typeof value === 'object' && !Array.isArray(value)\n ? Object.keys(value)\n .sort()\n .reduce((acc: any, curr: string) => {\n acc[curr] = value[curr]\n return acc\n }, {})\n : value\n\n // Convert JSON to string with sorted keys\n const jsonString = JSON.stringify(json ?? '', sortedKeysReplacer)\n\n // Replace characters invalid in filenames\n return jsonString\n .replace(/[/\\\\?%*:|\"<>]/g, '-') // Replace invalid characters with a dash\n .replace(/\\s+/g, '_') // Optionally replace whitespace with underscores\n }\n\n const staticClientCache =\n typeof document !== 'undefined' ? new Map<string, any>() : null\n\n return createServerFnStaticCache({\n getItem: async (ctx) => {\n if (typeof document === 'undefined') {\n const hash = jsonToFilenameSafeString(ctx.data)\n const url = getStaticCacheUrl(ctx, hash)\n const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR!\n\n // Use fs instead of fetch to read from filesystem\n const { promises: fs } = await import('node:fs')\n const path = await import('node:path')\n const filePath = path.join(publicUrl, url)\n\n const [cachedResult, readError] = await fs\n .readFile(filePath, 'utf-8')\n .then((c) => [\n startSerializer.parse(c) as {\n ctx: unknown\n error: any\n },\n null,\n ])\n .catch((e) => [null, e])\n\n if (readError && readError.code !== 'ENOENT') {\n throw readError\n }\n\n return cachedResult as StaticCachedResult\n }\n\n return undefined\n },\n setItem: async (ctx, response) => {\n const { promises: fs } = await import('node:fs')\n const path = await import('node:path')\n\n const hash = jsonToFilenameSafeString(ctx.data)\n const url = getStaticCacheUrl(ctx, hash)\n const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR!\n const filePath = path.join(publicUrl, url)\n\n // Ensure the directory exists\n await fs.mkdir(path.dirname(filePath), { recursive: true })\n\n // Store the result with fs\n await fs.writeFile(filePath, startSerializer.stringify(response))\n },\n fetchItem: async (ctx) => {\n const hash = jsonToFilenameSafeString(ctx.data)\n const url = getStaticCacheUrl(ctx, hash)\n\n let result: any = staticClientCache?.get(url)\n\n if (!result) {\n result = await fetch(url, {\n method: 'GET',\n })\n .then((r) => r.text())\n .then((d) => startSerializer.parse(d))\n\n staticClientCache?.set(url, result)\n }\n\n return result\n },\n })\n})\n\nexport function extractFormDataContext(formData: FormData) {\n const serializedContext = formData.get('__TSR_CONTEXT')\n formData.delete('__TSR_CONTEXT')\n\n if (typeof serializedContext !== 'string') {\n return {\n context: {},\n data: formData,\n }\n }\n\n try {\n const context = startSerializer.parse(serializedContext)\n return {\n context,\n data: formData,\n }\n } catch {\n return {\n data: formData,\n }\n }\n}\n\nexport function flattenMiddlewares(\n middlewares: Array<AnyMiddleware>,\n): Array<AnyMiddleware> {\n const seen = new Set<AnyMiddleware>()\n const flattened: Array<AnyMiddleware> = []\n\n const recurse = (middleware: Array<AnyMiddleware>) => {\n middleware.forEach((m) => {\n if (m.options.middleware) {\n recurse(m.options.middleware)\n }\n\n if (!seen.has(m)) {\n seen.add(m)\n flattened.push(m)\n }\n })\n }\n\n recurse(middlewares)\n\n return flattened\n}\n\nexport type ServerFnMiddlewareOptions = {\n method: Method\n response?: ServerFnResponseType\n data: any\n headers?: HeadersInit\n signal?: AbortSignal\n sendContext?: any\n context?: any\n type: ServerFnTypeOrTypeFn<any, any, any, any>\n functionId: string\n}\n\nexport type ServerFnMiddlewareResult = ServerFnMiddlewareOptions & {\n result?: unknown\n error?: unknown\n type: ServerFnTypeOrTypeFn<any, any, any, any>\n}\n\nexport type NextFn = (\n ctx: ServerFnMiddlewareResult,\n) => Promise<ServerFnMiddlewareResult>\n\nexport type MiddlewareFn = (\n ctx: ServerFnMiddlewareOptions & {\n next: NextFn\n },\n) => Promise<ServerFnMiddlewareResult>\n\nexport const applyMiddleware = async (\n middlewareFn: MiddlewareFn,\n ctx: ServerFnMiddlewareOptions,\n nextFn: NextFn,\n) => {\n return middlewareFn({\n ...ctx,\n next: (async (\n userCtx: ServerFnMiddlewareResult | undefined = {} as any,\n ) => {\n // Return the next middleware\n return nextFn({\n ...ctx,\n ...userCtx,\n context: {\n ...ctx.context,\n ...userCtx.context,\n },\n sendContext: {\n ...ctx.sendContext,\n ...(userCtx.sendContext ?? {}),\n },\n headers: mergeHeaders(ctx.headers, userCtx.headers),\n result:\n userCtx.result !== undefined\n ? userCtx.result\n : ctx.response === 'raw'\n ? userCtx\n : (ctx as any).result,\n error: userCtx.error ?? (ctx as any).error,\n })\n }) as any,\n } as any)\n}\n\nexport function execValidator(\n validator: AnyValidator,\n input: unknown,\n): unknown {\n if (validator == null) return {}\n\n if ('~standard' in validator) {\n const result = validator['~standard'].validate(input)\n\n if (result instanceof Promise)\n throw new Error('Async validation not supported')\n\n if (result.issues)\n throw new Error(JSON.stringify(result.issues, undefined, 2))\n\n return result.value\n }\n\n if ('parse' in validator) {\n return validator.parse(input)\n }\n\n if (typeof validator === 'function') {\n return validator(input)\n }\n\n throw new Error('Invalid validator type!')\n}\n\nexport function serverFnBaseToMiddleware(\n options: ServerFnBaseOptions<any, any, any, any, any>,\n): AnyMiddleware {\n return {\n _types: undefined!,\n options: {\n validator: options.validator,\n validateClient: options.validateClient,\n client: async ({ next, sendContext, ...ctx }) => {\n const payload = {\n ...ctx,\n // switch the sendContext over to context\n context: sendContext,\n type: typeof ctx.type === 'function' ? ctx.type(ctx) : ctx.type,\n } as any\n\n if (\n ctx.type === 'static' &&\n process.env.NODE_ENV === 'production' &&\n typeof document !== 'undefined'\n ) {\n invariant(\n serverFnStaticCache,\n 'serverFnStaticCache.fetchItem is not available!',\n )\n\n const result = await serverFnStaticCache.fetchItem(payload)\n\n if (result) {\n if (result.error) {\n throw result.error\n }\n\n return next(result.ctx)\n }\n\n warning(\n result,\n `No static cache item found for ${payload.functionId}__${JSON.stringify(payload.data)}, falling back to server function...`,\n )\n }\n\n // Execute the extracted function\n // but not before serializing the context\n const res = await options.extractedFn?.(payload)\n\n return next(res) as unknown as MiddlewareClientFnResult<any, any, any>\n },\n server: async ({ next, ...ctx }) => {\n // Execute the server function\n const result = await options.serverFn?.(ctx)\n\n return next({\n ...ctx,\n result,\n } as any) as unknown as MiddlewareServerFnResult<any, any, any, any>\n },\n },\n }\n}\n"],"names":["serverFnStaticCache"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ type EnvOnlyFn = <TFn extends (...args: Array<any>) => any>(fn: TFn) => TFn;
2
+ export declare const serverOnly: EnvOnlyFn;
3
+ export declare const clientOnly: EnvOnlyFn;
4
+ export {};
@@ -0,0 +1,7 @@
1
+ const serverOnly = (fn) => fn;
2
+ const clientOnly = (fn) => fn;
3
+ export {
4
+ clientOnly,
5
+ serverOnly
6
+ };
7
+ //# sourceMappingURL=envOnly.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envOnly.js","sources":["../../src/envOnly.ts"],"sourcesContent":["type EnvOnlyFn = <TFn extends (...args: Array<any>) => any>(fn: TFn) => TFn\n\n// A function that will only be available in the server build\n// If called on the client, it will throw an error\nexport const serverOnly: EnvOnlyFn = (fn) => fn\n\n// A function that will only be available in the client build\n// If called on the server, it will throw an error\nexport const clientOnly: EnvOnlyFn = (fn) => fn\n"],"names":[],"mappings":"AAIa,MAAA,aAAwB,CAAC,OAAO;AAIhC,MAAA,aAAwB,CAAC,OAAO;"}
@@ -1,3 +1,11 @@
1
1
  export { mergeHeaders } from './headers.js';
2
2
  export { startSerializer } from './serializer.js';
3
3
  export { type DehydratedRouter, type ClientExtractedBaseEntry, type StartSsrGlobal, type ClientExtractedEntry, type SsrMatch, type ClientExtractedPromise, type ClientExtractedStream, type ResolvePromiseState, hydrate, } from './ssr-client.js';
4
+ export { createIsomorphicFn, type IsomorphicFn, type ServerOnlyFn, type ClientOnlyFn, type IsomorphicFnBase, } from './createIsomorphicFn.js';
5
+ export { serverOnly, clientOnly } from './envOnly.js';
6
+ export { type JsonResponse } from './createServerFn.js';
7
+ export { json } from './json.js';
8
+ export { createMiddleware, type IntersectAllValidatorInputs, type IntersectAllValidatorOutputs, type MiddlewareServerFn, type AnyMiddleware, type MiddlewareOptions, type MiddlewareWithTypes, type MiddlewareValidator, type MiddlewareServer, type MiddlewareAfterClient, type MiddlewareAfterMiddleware, type MiddlewareAfterServer, type Middleware, type MiddlewareClientFnOptions, type MiddlewareClientFnResult, type MiddlewareClientNextFn, type ClientResultWithContext, type AssignAllClientContextBeforeNext, type AssignAllMiddleware, type AssignAllServerContext, type MiddlewareAfterValidator, type MiddlewareClientFn, type MiddlewareServerFnResult, type MiddlewareClient, type MiddlewareServerFnOptions, type MiddlewareServerNextFn, type ServerResultWithContext, } from './createMiddleware.js';
9
+ export { registerGlobalMiddleware, globalMiddleware, } from './registerGlobalMiddleware.js';
10
+ export type { ServerFn as FetchFn, ServerFnCtx as FetchFnCtx, CompiledFetcherFnOptions, CompiledFetcherFn, Fetcher, RscStream, FetcherData, FetcherBaseOptions, ServerFn, ServerFnCtx, ServerFnResponseType, MiddlewareFn, ServerFnMiddlewareOptions, ServerFnMiddlewareResult, ServerFnBuilder, ServerFnType, ServerFnBaseOptions, NextFn, Method, StaticCachedResult, } from './createServerFn.js';
11
+ export { applyMiddleware, execValidator, serverFnBaseToMiddleware, extractFormDataContext, flattenMiddlewares, serverFnStaticCache, } from './createServerFn.js';
package/dist/esm/index.js CHANGED
@@ -1,9 +1,28 @@
1
1
  import { mergeHeaders } from "./headers.js";
2
2
  import { startSerializer } from "./serializer.js";
3
3
  import { hydrate } from "./ssr-client.js";
4
+ import { createIsomorphicFn } from "./createIsomorphicFn.js";
5
+ import { clientOnly, serverOnly } from "./envOnly.js";
6
+ import { json } from "./json.js";
7
+ import { createMiddleware } from "./createMiddleware.js";
8
+ import { globalMiddleware, registerGlobalMiddleware } from "./registerGlobalMiddleware.js";
9
+ import { applyMiddleware, execValidator, extractFormDataContext, flattenMiddlewares, serverFnBaseToMiddleware, serverFnStaticCache } from "./createServerFn.js";
4
10
  export {
11
+ applyMiddleware,
12
+ clientOnly,
13
+ createIsomorphicFn,
14
+ createMiddleware,
15
+ execValidator,
16
+ extractFormDataContext,
17
+ flattenMiddlewares,
18
+ globalMiddleware,
5
19
  hydrate,
20
+ json,
6
21
  mergeHeaders,
22
+ registerGlobalMiddleware,
23
+ serverFnBaseToMiddleware,
24
+ serverFnStaticCache,
25
+ serverOnly,
7
26
  startSerializer
8
27
  };
9
28
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
@@ -0,0 +1,2 @@
1
+ import { JsonResponse } from './createServerFn.js';
2
+ export declare function json<TData>(payload: TData, init?: ResponseInit): JsonResponse<TData>;
@@ -0,0 +1,14 @@
1
+ import { mergeHeaders } from "./headers.js";
2
+ function json(payload, init) {
3
+ return new Response(JSON.stringify(payload), {
4
+ ...init,
5
+ headers: mergeHeaders(
6
+ { "content-type": "application/json" },
7
+ init == null ? void 0 : init.headers
8
+ )
9
+ });
10
+ }
11
+ export {
12
+ json
13
+ };
14
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sources":["../../src/json.ts"],"sourcesContent":["import { mergeHeaders } from './headers'\nimport type { JsonResponse } from './createServerFn'\n\nexport function json<TData>(\n payload: TData,\n init?: ResponseInit,\n): JsonResponse<TData> {\n return new Response(JSON.stringify(payload), {\n ...init,\n headers: mergeHeaders(\n { 'content-type': 'application/json' },\n init?.headers,\n ),\n })\n}\n"],"names":[],"mappings":";AAGgB,SAAA,KACd,SACA,MACqB;AACrB,SAAO,IAAI,SAAS,KAAK,UAAU,OAAO,GAAG;AAAA,IAC3C,GAAG;AAAA,IACH,SAAS;AAAA,MACP,EAAE,gBAAgB,mBAAmB;AAAA,MACrC,6BAAM;AAAA,IAAA;AAAA,EACR,CACD;AACH;"}
@@ -0,0 +1,5 @@
1
+ import { AnyMiddleware } from './createMiddleware.js';
2
+ export declare const globalMiddleware: Array<AnyMiddleware>;
3
+ export declare function registerGlobalMiddleware(options: {
4
+ middleware: Array<AnyMiddleware>;
5
+ }): void;
@@ -0,0 +1,9 @@
1
+ const globalMiddleware = [];
2
+ function registerGlobalMiddleware(options) {
3
+ globalMiddleware.push(...options.middleware);
4
+ }
5
+ export {
6
+ globalMiddleware,
7
+ registerGlobalMiddleware
8
+ };
9
+ //# sourceMappingURL=registerGlobalMiddleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registerGlobalMiddleware.js","sources":["../../src/registerGlobalMiddleware.ts"],"sourcesContent":["import type { AnyMiddleware } from './createMiddleware'\n\nexport const globalMiddleware: Array<AnyMiddleware> = []\n\nexport function registerGlobalMiddleware(options: {\n middleware: Array<AnyMiddleware>\n}) {\n globalMiddleware.push(...options.middleware)\n}\n"],"names":[],"mappings":"AAEO,MAAM,mBAAyC,CAAA;AAE/C,SAAS,yBAAyB,SAEtC;AACgB,mBAAA,KAAK,GAAG,QAAQ,UAAU;AAC7C;"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/start-client-core",
3
- "version": "1.114.4",
3
+ "version": "1.114.5",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -49,6 +49,7 @@
49
49
  "dependencies": {
50
50
  "cookie-es": "^1.2.2",
51
51
  "tiny-invariant": "^1.3.3",
52
+ "tiny-warning": "^1.0.3",
52
53
  "@tanstack/router-core": "^1.114.3"
53
54
  },
54
55
  "scripts": {}
@@ -0,0 +1,36 @@
1
+ // a function that can have different implementations on the client and server.
2
+ // implementations not provided will default to a no-op function.
3
+
4
+ export type IsomorphicFn<
5
+ TArgs extends Array<any> = [],
6
+ TServer = undefined,
7
+ TClient = undefined,
8
+ > = (...args: TArgs) => TServer | TClient
9
+
10
+ export interface ServerOnlyFn<TArgs extends Array<any>, TServer>
11
+ extends IsomorphicFn<TArgs, TServer> {
12
+ client: <TClient>(
13
+ clientImpl: (...args: TArgs) => TClient,
14
+ ) => IsomorphicFn<TArgs, TServer, TClient>
15
+ }
16
+
17
+ export interface ClientOnlyFn<TArgs extends Array<any>, TClient>
18
+ extends IsomorphicFn<TArgs, undefined, TClient> {
19
+ server: <TServer>(
20
+ serverImpl: (...args: TArgs) => TServer,
21
+ ) => IsomorphicFn<TArgs, TServer, TClient>
22
+ }
23
+
24
+ export interface IsomorphicFnBase extends IsomorphicFn {
25
+ server: <TArgs extends Array<any>, TServer>(
26
+ serverImpl: (...args: TArgs) => TServer,
27
+ ) => ServerOnlyFn<TArgs, TServer>
28
+ client: <TArgs extends Array<any>, TClient>(
29
+ clientImpl: (...args: TArgs) => TClient,
30
+ ) => ClientOnlyFn<TArgs, TClient>
31
+ }
32
+
33
+ // this is a dummy function, it will be replaced by the transformer
34
+ export function createIsomorphicFn(): IsomorphicFnBase {
35
+ return null!
36
+ }