@benjavicente/start-client-core 1.167.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +12 -0
- package/bin/intent.js +25 -0
- package/dist/esm/client/ServerFunctionSerializationAdapter.d.ts +7 -0
- package/dist/esm/client/ServerFunctionSerializationAdapter.js +18 -0
- package/dist/esm/client/ServerFunctionSerializationAdapter.js.map +1 -0
- package/dist/esm/client/hydrateStart.d.ts +2 -0
- package/dist/esm/client/hydrateStart.js +31 -0
- package/dist/esm/client/hydrateStart.js.map +1 -0
- package/dist/esm/client/index.d.ts +2 -0
- package/dist/esm/client/index.js +2 -0
- package/dist/esm/client-rpc/createClientRpc.d.ts +6 -0
- package/dist/esm/client-rpc/createClientRpc.js +21 -0
- package/dist/esm/client-rpc/createClientRpc.js.map +1 -0
- package/dist/esm/client-rpc/frame-decoder.d.ts +23 -0
- package/dist/esm/client-rpc/frame-decoder.js +231 -0
- package/dist/esm/client-rpc/frame-decoder.js.map +1 -0
- package/dist/esm/client-rpc/index.d.ts +1 -0
- package/dist/esm/client-rpc/index.js +2 -0
- package/dist/esm/client-rpc/serverFnFetcher.d.ts +1 -0
- package/dist/esm/client-rpc/serverFnFetcher.js +231 -0
- package/dist/esm/client-rpc/serverFnFetcher.js.map +1 -0
- package/dist/esm/constants.d.ts +53 -0
- package/dist/esm/constants.js +46 -0
- package/dist/esm/constants.js.map +1 -0
- package/dist/esm/createMiddleware.d.ts +195 -0
- package/dist/esm/createMiddleware.js +26 -0
- package/dist/esm/createMiddleware.js.map +1 -0
- package/dist/esm/createServerFn.d.ts +131 -0
- package/dist/esm/createServerFn.js +200 -0
- package/dist/esm/createServerFn.js.map +1 -0
- package/dist/esm/createStart.d.ts +50 -0
- package/dist/esm/createStart.js +29 -0
- package/dist/esm/createStart.js.map +1 -0
- package/dist/esm/fake-start-entry.d.ts +2 -0
- package/dist/esm/fake-start-entry.js +7 -0
- package/dist/esm/fake-start-entry.js.map +1 -0
- package/dist/esm/getDefaultSerovalPlugins.d.ts +1 -0
- package/dist/esm/getDefaultSerovalPlugins.js +10 -0
- package/dist/esm/getDefaultSerovalPlugins.js.map +1 -0
- package/dist/esm/getGlobalStartContext.d.ts +3 -0
- package/dist/esm/getGlobalStartContext.js +12 -0
- package/dist/esm/getGlobalStartContext.js.map +1 -0
- package/dist/esm/getRouterInstance.d.ts +2 -0
- package/dist/esm/getRouterInstance.js +8 -0
- package/dist/esm/getRouterInstance.js.map +1 -0
- package/dist/esm/getStartContextServerOnly.d.ts +2 -0
- package/dist/esm/getStartContextServerOnly.js +8 -0
- package/dist/esm/getStartContextServerOnly.js.map +1 -0
- package/dist/esm/getStartOptions.d.ts +2 -0
- package/dist/esm/getStartOptions.js +8 -0
- package/dist/esm/getStartOptions.js.map +1 -0
- package/dist/esm/global.d.ts +7 -0
- package/dist/esm/index.d.ts +20 -0
- package/dist/esm/index.js +12 -0
- package/dist/esm/safeObjectMerge.d.ts +10 -0
- package/dist/esm/safeObjectMerge.js +30 -0
- package/dist/esm/safeObjectMerge.js.map +1 -0
- package/dist/esm/serverRoute.d.ts +65 -0
- package/dist/esm/startEntry.d.ts +8 -0
- package/dist/esm/tests/createServerFn.test-d.d.ts +1 -0
- package/dist/esm/tests/createServerMiddleware.test-d.d.ts +1 -0
- package/package.json +98 -0
- package/skills/start-core/SKILL.md +210 -0
- package/skills/start-core/deployment/SKILL.md +306 -0
- package/skills/start-core/execution-model/SKILL.md +302 -0
- package/skills/start-core/middleware/SKILL.md +365 -0
- package/skills/start-core/server-functions/SKILL.md +335 -0
- package/skills/start-core/server-routes/SKILL.md +280 -0
- package/src/client/ServerFunctionSerializationAdapter.ts +16 -0
- package/src/client/hydrateStart.ts +43 -0
- package/src/client/index.ts +2 -0
- package/src/client-rpc/createClientRpc.ts +20 -0
- package/src/client-rpc/frame-decoder.ts +389 -0
- package/src/client-rpc/index.ts +1 -0
- package/src/client-rpc/serverFnFetcher.ts +416 -0
- package/src/constants.ts +90 -0
- package/src/createMiddleware.ts +824 -0
- package/src/createServerFn.ts +813 -0
- package/src/createStart.ts +166 -0
- package/src/fake-start-entry.ts +2 -0
- package/src/getDefaultSerovalPlugins.ts +17 -0
- package/src/getGlobalStartContext.ts +18 -0
- package/src/getRouterInstance.ts +8 -0
- package/src/getStartContextServerOnly.ts +4 -0
- package/src/getStartOptions.ts +8 -0
- package/src/global.ts +9 -0
- package/src/index.tsx +119 -0
- package/src/safeObjectMerge.ts +38 -0
- package/src/serverRoute.ts +509 -0
- package/src/start-entry.d.ts +11 -0
- package/src/startEntry.ts +10 -0
- package/src/tests/createServerFn.test-d.ts +866 -0
- package/src/tests/createServerMiddleware.test-d.ts +810 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createServerOnlyFn } from "@benjavicente/start-fn-stubs";
|
|
2
|
+
import { getStartContext } from "@benjavicente/start-storage-context";
|
|
3
|
+
//#region src/getStartContextServerOnly.ts
|
|
4
|
+
var getStartContextServerOnly = createServerOnlyFn(getStartContext);
|
|
5
|
+
//#endregion
|
|
6
|
+
export { getStartContextServerOnly };
|
|
7
|
+
|
|
8
|
+
//# sourceMappingURL=getStartContextServerOnly.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getStartContextServerOnly.js","names":[],"sources":["../../src/getStartContextServerOnly.ts"],"sourcesContent":["import { getStartContext } from '@benjavicente/start-storage-context'\nimport { createServerOnlyFn } from '@benjavicente/start-fn-stubs'\n\nexport const getStartContextServerOnly = createServerOnlyFn(getStartContext)\n"],"mappings":";;;AAGA,IAAa,4BAA4B,mBAAmB,gBAAgB"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createIsomorphicFn } from "@benjavicente/start-fn-stubs";
|
|
2
|
+
import { getStartContext } from "@benjavicente/start-storage-context";
|
|
3
|
+
//#region src/getStartOptions.ts
|
|
4
|
+
var getStartOptions = createIsomorphicFn().client(() => window.__TSS_START_OPTIONS__).server(() => getStartContext().startOptions);
|
|
5
|
+
//#endregion
|
|
6
|
+
export { getStartOptions };
|
|
7
|
+
|
|
8
|
+
//# sourceMappingURL=getStartOptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getStartOptions.js","names":[],"sources":["../../src/getStartOptions.ts"],"sourcesContent":["import { getStartContext } from '@benjavicente/start-storage-context'\nimport { createIsomorphicFn } from '@benjavicente/start-fn-stubs'\nimport type { AnyStartInstanceOptions } from './createStart'\n\nexport const getStartOptions: () => AnyStartInstanceOptions | undefined =\n createIsomorphicFn()\n .client(() => window.__TSS_START_OPTIONS__)\n .server(() => getStartContext().startOptions)\n"],"mappings":";;;AAIA,IAAa,kBACX,oBAAoB,CACjB,aAAa,OAAO,sBAAsB,CAC1C,aAAa,iBAAiB,CAAC,aAAa"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type { JsonResponse } from '@benjavicente/router-core/ssr/client';
|
|
2
|
+
export { hydrate, json, mergeHeaders } from '@benjavicente/router-core/ssr/client';
|
|
3
|
+
export { RawStream } from '@benjavicente/router-core';
|
|
4
|
+
export type { OnRawStreamCallback } from '@benjavicente/router-core';
|
|
5
|
+
export { createIsomorphicFn, createServerOnlyFn, createClientOnlyFn, type IsomorphicFn, type ServerOnlyFn, type ClientOnlyFn, type IsomorphicFnBase, } from '@benjavicente/start-fn-stubs';
|
|
6
|
+
export { createServerFn } from './createServerFn.js';
|
|
7
|
+
export { createMiddleware, type IntersectAllValidatorInputs, type IntersectAllValidatorOutputs, type FunctionMiddlewareServerFn, type AnyFunctionMiddleware, type FunctionMiddlewareOptions, type FunctionMiddlewareWithTypes, type FunctionMiddlewareValidator, type FunctionMiddlewareServer, type FunctionMiddlewareAfterClient, type FunctionMiddlewareAfterServer, type FunctionMiddleware, type FunctionMiddlewareAfterMiddleware, type FunctionMiddlewareClientFnOptions, type FunctionMiddlewareClientFnResult, type FunctionMiddlewareClientNextFn, type FunctionClientResultWithContext, type AssignAllClientContextBeforeNext, type AssignAllMiddleware, type FunctionMiddlewareAfterValidator, type FunctionMiddlewareClientFn, type FunctionMiddlewareServerFnResult, type FunctionMiddlewareClient, type FunctionMiddlewareServerFnOptions, type FunctionMiddlewareServerNextFn, type FunctionServerResultWithContext, type AnyRequestMiddleware, type RequestMiddlewareOptions, type RequestMiddlewareWithTypes, type RequestMiddlewareServer, type RequestMiddlewareAfterServer, type RequestMiddleware, type RequestMiddlewareAfterMiddleware, type RequestServerFn, type RequestMiddlewareServerFnResult, type RequestServerOptions, type RequestServerNextFn, type RequestServerNextFnOptions, type RequestServerResult, } from './createMiddleware.js';
|
|
8
|
+
export type { CompiledFetcherFnOptions, CompiledFetcherFn, CustomFetch, Fetcher, RscStream, FetcherBaseOptions, ServerFn, ServerFnCtx, MiddlewareFn, ServerFnMiddlewareOptions, ServerFnMiddlewareResult, ServerFnBuilder, ServerFnBaseOptions, NextFn, Method, OptionalFetcher, RequiredFetcher, } from './createServerFn.js';
|
|
9
|
+
export { execValidator, flattenMiddlewares, executeMiddleware, } from './createServerFn.js';
|
|
10
|
+
export { TSS_FORMDATA_CONTEXT, TSS_SERVER_FUNCTION, TSS_CONTENT_TYPE_FRAMED, TSS_CONTENT_TYPE_FRAMED_VERSIONED, TSS_FRAMED_PROTOCOL_VERSION, FrameType, FRAME_HEADER_SIZE, X_TSS_SERIALIZED, X_TSS_RAW_RESPONSE, X_TSS_CONTEXT, validateFramedProtocolVersion, } from './constants.js';
|
|
11
|
+
export type { FrameType as FrameTypeValue, ClientFnMeta, ServerFnMeta, } from './constants.js';
|
|
12
|
+
export type * from './serverRoute.js';
|
|
13
|
+
export type * from './startEntry.js';
|
|
14
|
+
export { createStart } from './createStart.js';
|
|
15
|
+
export type { AnyStartInstance, AnyStartInstanceOptions, StartInstance, StartInstanceOptions, } from './createStart.js';
|
|
16
|
+
export type { Register } from '@benjavicente/router-core';
|
|
17
|
+
export { getRouterInstance } from './getRouterInstance.js';
|
|
18
|
+
export { getDefaultSerovalPlugins } from './getDefaultSerovalPlugins.js';
|
|
19
|
+
export { getGlobalStartContext } from './getGlobalStartContext.js';
|
|
20
|
+
export { safeObjectMerge, createNullProtoObject } from './safeObjectMerge.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FRAME_HEADER_SIZE, FrameType, TSS_CONTENT_TYPE_FRAMED, TSS_CONTENT_TYPE_FRAMED_VERSIONED, TSS_FORMDATA_CONTEXT, TSS_FRAMED_PROTOCOL_VERSION, TSS_SERVER_FUNCTION, X_TSS_CONTEXT, X_TSS_RAW_RESPONSE, X_TSS_SERIALIZED, validateFramedProtocolVersion } from "./constants.js";
|
|
2
|
+
import { createNullProtoObject, safeObjectMerge } from "./safeObjectMerge.js";
|
|
3
|
+
import { createServerFn, execValidator, executeMiddleware, flattenMiddlewares } from "./createServerFn.js";
|
|
4
|
+
import { createMiddleware } from "./createMiddleware.js";
|
|
5
|
+
import { createStart } from "./createStart.js";
|
|
6
|
+
import { getRouterInstance } from "./getRouterInstance.js";
|
|
7
|
+
import { getDefaultSerovalPlugins } from "./getDefaultSerovalPlugins.js";
|
|
8
|
+
import { getGlobalStartContext } from "./getGlobalStartContext.js";
|
|
9
|
+
import { hydrate, json, mergeHeaders } from "@benjavicente/router-core/ssr/client";
|
|
10
|
+
import { RawStream } from "@benjavicente/router-core";
|
|
11
|
+
import { createClientOnlyFn, createIsomorphicFn, createServerOnlyFn } from "@benjavicente/start-fn-stubs";
|
|
12
|
+
export { FRAME_HEADER_SIZE, FrameType, RawStream, TSS_CONTENT_TYPE_FRAMED, TSS_CONTENT_TYPE_FRAMED_VERSIONED, TSS_FORMDATA_CONTEXT, TSS_FRAMED_PROTOCOL_VERSION, TSS_SERVER_FUNCTION, X_TSS_CONTEXT, X_TSS_RAW_RESPONSE, X_TSS_SERIALIZED, createClientOnlyFn, createIsomorphicFn, createMiddleware, createNullProtoObject, createServerFn, createServerOnlyFn, createStart, execValidator, executeMiddleware, flattenMiddlewares, getDefaultSerovalPlugins, getGlobalStartContext, getRouterInstance, hydrate, json, mergeHeaders, safeObjectMerge, validateFramedProtocolVersion };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge target and source into a new null-proto object, filtering dangerous keys.
|
|
3
|
+
*/
|
|
4
|
+
export declare function safeObjectMerge<T extends Record<string, unknown>>(target: T | undefined, source: Record<string, unknown> | null | undefined): T;
|
|
5
|
+
/**
|
|
6
|
+
* Create a null-prototype object, optionally copying from source.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createNullProtoObject<T extends object>(source?: T): {
|
|
9
|
+
[K in keyof T]: T[K];
|
|
10
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/safeObjectMerge.ts
|
|
2
|
+
function isSafeKey(key) {
|
|
3
|
+
return key !== "__proto__" && key !== "constructor" && key !== "prototype";
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Merge target and source into a new null-proto object, filtering dangerous keys.
|
|
7
|
+
*/
|
|
8
|
+
function safeObjectMerge(target, source) {
|
|
9
|
+
const result = Object.create(null);
|
|
10
|
+
if (target) {
|
|
11
|
+
for (const key of Object.keys(target)) if (isSafeKey(key)) result[key] = target[key];
|
|
12
|
+
}
|
|
13
|
+
if (source && typeof source === "object") {
|
|
14
|
+
for (const key of Object.keys(source)) if (isSafeKey(key)) result[key] = source[key];
|
|
15
|
+
}
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create a null-prototype object, optionally copying from source.
|
|
20
|
+
*/
|
|
21
|
+
function createNullProtoObject(source) {
|
|
22
|
+
if (!source) return Object.create(null);
|
|
23
|
+
const obj = Object.create(null);
|
|
24
|
+
for (const key of Object.keys(source)) if (isSafeKey(key)) obj[key] = source[key];
|
|
25
|
+
return obj;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { createNullProtoObject, safeObjectMerge };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=safeObjectMerge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safeObjectMerge.js","names":[],"sources":["../../src/safeObjectMerge.ts"],"sourcesContent":["function isSafeKey(key: string): boolean {\n return key !== '__proto__' && key !== 'constructor' && key !== 'prototype'\n}\n\n/**\n * Merge target and source into a new null-proto object, filtering dangerous keys.\n */\nexport function safeObjectMerge<T extends Record<string, unknown>>(\n target: T | undefined,\n source: Record<string, unknown> | null | undefined,\n): T {\n const result = Object.create(null) as T\n if (target) {\n for (const key of Object.keys(target)) {\n if (isSafeKey(key)) result[key as keyof T] = target[key] as T[keyof T]\n }\n }\n if (source && typeof source === 'object') {\n for (const key of Object.keys(source)) {\n if (isSafeKey(key)) result[key as keyof T] = source[key] as T[keyof T]\n }\n }\n return result\n}\n\n/**\n * Create a null-prototype object, optionally copying from source.\n */\nexport function createNullProtoObject<T extends object>(\n source?: T,\n): { [K in keyof T]: T[K] } {\n if (!source) return Object.create(null)\n const obj = Object.create(null)\n for (const key of Object.keys(source)) {\n if (isSafeKey(key)) obj[key] = (source as Record<string, unknown>)[key]\n }\n return obj\n}\n"],"mappings":";AAAA,SAAS,UAAU,KAAsB;AACvC,QAAO,QAAQ,eAAe,QAAQ,iBAAiB,QAAQ;;;;;AAMjE,SAAgB,gBACd,QACA,QACG;CACH,MAAM,SAAS,OAAO,OAAO,KAAK;AAClC,KAAI;OACG,MAAM,OAAO,OAAO,KAAK,OAAO,CACnC,KAAI,UAAU,IAAI,CAAE,QAAO,OAAkB,OAAO;;AAGxD,KAAI,UAAU,OAAO,WAAW;OACzB,MAAM,OAAO,OAAO,KAAK,OAAO,CACnC,KAAI,UAAU,IAAI,CAAE,QAAO,OAAkB,OAAO;;AAGxD,QAAO;;;;;AAMT,SAAgB,sBACd,QAC0B;AAC1B,KAAI,CAAC,OAAQ,QAAO,OAAO,OAAO,KAAK;CACvC,MAAM,MAAM,OAAO,OAAO,KAAK;AAC/B,MAAK,MAAM,OAAO,OAAO,KAAK,OAAO,CACnC,KAAI,UAAU,IAAI,CAAE,KAAI,OAAQ,OAAmC;AAErE,QAAO"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { AnyContext, AnyRoute, Assign, Constrain, Expand, ResolveAllParamsFromParent, UnionToIntersection } from '@benjavicente/router-core';
|
|
2
|
+
import { AnyRequestMiddleware, AssignAllServerRequestContext } from './createMiddleware.js';
|
|
3
|
+
declare module '@benjavicente/router-core' {
|
|
4
|
+
interface FilebaseRouteOptionsInterface<TRegister, TParentRoute extends AnyRoute = AnyRoute, TId extends string = string, TPath extends string = string, TSearchValidator = undefined, TParams = {}, TLoaderDeps extends Record<string, any> = {}, TLoaderFn = undefined, TRouterContext = {}, TRouteContextFn = AnyContext, TBeforeLoadFn = AnyContext, TRemountDepsFn = AnyContext, TSSR = unknown, TServerMiddlewares = unknown, THandlers = undefined> {
|
|
5
|
+
server?: RouteServerOptions<TRegister, TParentRoute, TPath, TParams, TLoaderDeps, TLoaderFn, TRouterContext, TRouteContextFn, TBeforeLoadFn, TServerMiddlewares, THandlers>;
|
|
6
|
+
}
|
|
7
|
+
interface RouteTypes<in out TRegister, in out TParentRoute extends AnyRoute, in out TPath extends string, in out TFullPath extends string, in out TCustomId extends string, in out TId extends string, in out TSearchValidator, in out TParams, in out TRouterContext, in out TRouteContextFn, in out TBeforeLoadFn, in out TLoaderDeps, in out TLoaderFn, in out TChildren, in out TFileRouteTypes, in out TSSR, in out TServerMiddlewares, in out THandlers> {
|
|
8
|
+
middleware: TServerMiddlewares;
|
|
9
|
+
allServerContext: ResolveAllServerContext<TRegister, TParentRoute, TServerMiddlewares>;
|
|
10
|
+
}
|
|
11
|
+
interface BeforeLoadContextOptionsExtensions<in out TRegister, in out TParentRoute extends AnyRoute, in out TSearchValidator, in out TParams, in out TRouterContext, in out TRouteContextFn, in out TRouteId, in out TServerMiddlewares, in out THandlers> {
|
|
12
|
+
serverContext?: Expand<Assign<ResolveAllServerContext<TRegister, TParentRoute, TServerMiddlewares>, ExtractHandlersContext<THandlers>>>;
|
|
13
|
+
}
|
|
14
|
+
interface LoaderFnContextExtensions<in out TRegister, in out TParentRoute extends AnyRoute = AnyRoute, in out TId extends string = string, in out TParams = {}, in out TLoaderDeps = {}, in out TRouterContext = {}, in out TRouteContextFn = AnyContext, in out TBeforeLoadFn = AnyContext, in out TServerMiddlewares = unknown, in out THandlers = undefined> {
|
|
15
|
+
serverContext?: Expand<Assign<ResolveAllServerContext<TRegister, TParentRoute, TServerMiddlewares>, ExtractHandlersContext<THandlers>>>;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
type ExtractHandlersContext<THandlers> = THandlers extends (...args: any) => CustomHandlerFunctionsRecord<any, any, any, any, any, any, infer TServerContext> ? UnionToIntersection<TServerContext> : THandlers extends Record<string, RouteMethodHandler<any, any, any, any, any, any, infer TServerContext>> ? UnionToIntersection<TServerContext> : undefined;
|
|
19
|
+
export interface RouteServerOptions<TRegister, TParentRoute extends AnyRoute, TFullPath extends string, TParams, TLoaderDeps, TLoaderFn, TRouterContext, TRouteContextFn, TBeforeLoadFn, TServerMiddlewares, THandlers> {
|
|
20
|
+
middleware?: Constrain<TServerMiddlewares, ReadonlyArray<AnyRequestMiddleware>>;
|
|
21
|
+
handlers?: Constrain<THandlers, Partial<Record<RouteMethod, RouteMethodHandlerFn<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, any, any>>> | ((opts: HandlersFnOpts<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares>) => CustomHandlerFunctionsRecord<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, any, any>)>;
|
|
22
|
+
}
|
|
23
|
+
declare const createHandlersSymbol: unique symbol;
|
|
24
|
+
type CustomHandlerFunctionsRecord<TRegister, TParentRoute extends AnyRoute, TFullPath extends string, TParams, TServerMiddlewares, TMethodMiddlewares, TServerContext> = {
|
|
25
|
+
[createHandlersSymbol]: true;
|
|
26
|
+
} & Partial<Record<RouteMethod, RouteMethodHandler<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, TMethodMiddlewares, TServerContext>>>;
|
|
27
|
+
export interface HandlersFnOpts<TRegister, TParentRoute extends AnyRoute, TFullPath extends string, TParams, TServerMiddlewares> {
|
|
28
|
+
createHandlers: CreateHandlersFn<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares>;
|
|
29
|
+
}
|
|
30
|
+
export type CreateHandlersFn<TRegister, TParentRoute extends AnyRoute, TFullPath extends string, TParams, TServerMiddlewares> = <const TMethodAllMiddlewares, const TMethodGetMiddlewares, const TMethodPostMiddlewares, const TMethodPutMiddlewares, const TMethodPatchMiddlewares, const TMethodDeleteMiddlewares, const TMethodOptionsMiddlewares, const TMethodHeadMiddlewares, TServerContext>(opts: CreateMethodFnOpts<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, TMethodAllMiddlewares, TMethodGetMiddlewares, TMethodPostMiddlewares, TMethodPutMiddlewares, TMethodPatchMiddlewares, TMethodDeleteMiddlewares, TMethodOptionsMiddlewares, TMethodHeadMiddlewares, TServerContext>) => CustomHandlerFunctionsRecord<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, any, TServerContext>;
|
|
31
|
+
export interface CreateMethodFnOpts<TRegister, TParentRoute extends AnyRoute, TFullPath extends string, TParams, TServerMiddlewares, TMethodAllMiddlewares, TMethodGetMiddlewares, TMethodPostMiddlewares, TMethodPutMiddlewares, TMethodPatchMiddlewares, TMethodDeleteMiddlewares, TMethodOptionsMiddlewares, TMethodHeadMiddlewares, TServerContext> {
|
|
32
|
+
ANY?: RouteMethodHandler<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, TMethodAllMiddlewares, TServerContext>;
|
|
33
|
+
GET?: RouteMethodHandler<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, TMethodGetMiddlewares, TServerContext>;
|
|
34
|
+
POST?: RouteMethodHandler<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, TMethodPostMiddlewares, TServerContext>;
|
|
35
|
+
PUT?: RouteMethodHandler<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, TMethodPutMiddlewares, TServerContext>;
|
|
36
|
+
PATCH?: RouteMethodHandler<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, TMethodPatchMiddlewares, TServerContext>;
|
|
37
|
+
DELETE?: RouteMethodHandler<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, TMethodDeleteMiddlewares, TServerContext>;
|
|
38
|
+
OPTIONS?: RouteMethodHandler<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, TMethodOptionsMiddlewares, TServerContext>;
|
|
39
|
+
HEAD?: RouteMethodHandler<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, TMethodHeadMiddlewares, TServerContext>;
|
|
40
|
+
}
|
|
41
|
+
export type RouteMethodHandler<TRegister, TParentRoute extends AnyRoute, TFullPath extends string, TParams, TServerMiddlewares, TMethodMiddlewares, TServerContext> = RouteMethodHandlerFn<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, TMethodMiddlewares, TServerContext> | RouteMethodBuilderOptions<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, TMethodMiddlewares, TServerContext>;
|
|
42
|
+
export interface RouteMethodBuilderOptions<TRegister, TParentRoute extends AnyRoute, TFullPath extends string, TParams, TServerMiddlewares, TMethodMiddlewares, TResponse> {
|
|
43
|
+
handler?: RouteMethodHandlerFn<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, TMethodMiddlewares, TResponse>;
|
|
44
|
+
middleware?: Constrain<TMethodMiddlewares, ReadonlyArray<AnyRequestMiddleware>>;
|
|
45
|
+
}
|
|
46
|
+
export type ResolveAllServerContext<TRegister, TParentRoute extends AnyRoute, TServerMiddlewares> = unknown extends TParentRoute ? AssignAllServerRequestContext<TRegister, TServerMiddlewares, {}> : Assign<TParentRoute['types']['allServerContext'], AssignAllServerRequestContext<TRegister, TServerMiddlewares, {}>>;
|
|
47
|
+
export type RouteMethod = 'ANY' | 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
|
|
48
|
+
export type RouteMethodHandlerFn<TRegister, TParentRoute extends AnyRoute, TFullPath extends string, TParams, TServerMiddlewares, TMethodMiddlewares, TServerContext> = (ctx: RouteMethodHandlerCtx<TRegister, TParentRoute, TFullPath, TParams, TServerMiddlewares, TMethodMiddlewares>) => RouteMethodResult<TServerContext> | Promise<RouteMethodResult<TServerContext>>;
|
|
49
|
+
export type RouteMethodResult<TContext> = Response | undefined | RouteMethodNextResult<TContext>;
|
|
50
|
+
export type RouteMethodNextResult<TContext> = {
|
|
51
|
+
isNext: true;
|
|
52
|
+
context: TContext;
|
|
53
|
+
};
|
|
54
|
+
export interface RouteMethodHandlerCtx<in out TRegister, in out TParentRoute extends AnyRoute, in out TFullPath extends string, in out TParams, in out TServerMiddlewares, in out TMethodMiddlewares> {
|
|
55
|
+
context: Expand<AssignAllMethodContext<TRegister, TParentRoute, TServerMiddlewares, TMethodMiddlewares>>;
|
|
56
|
+
request: Request;
|
|
57
|
+
params: Expand<ResolveAllParamsFromParent<TParentRoute, TParams>>;
|
|
58
|
+
pathname: TFullPath;
|
|
59
|
+
next: <TContext = undefined>(options?: {
|
|
60
|
+
context?: TContext;
|
|
61
|
+
}) => RouteMethodNextResult<TContext>;
|
|
62
|
+
}
|
|
63
|
+
export type MergeMethodMiddlewares<TServerMiddlewares, TMethodMiddlewares> = TServerMiddlewares extends ReadonlyArray<any> ? TMethodMiddlewares extends ReadonlyArray<any> ? readonly [...TServerMiddlewares, ...TMethodMiddlewares] : TServerMiddlewares : TMethodMiddlewares;
|
|
64
|
+
export type AssignAllMethodContext<TRegister, TParentRoute extends AnyRoute, TServerMiddlewares, TMethodMiddlewares> = ResolveAllServerContext<TRegister, TParentRoute, MergeMethodMiddlewares<TServerMiddlewares, TMethodMiddlewares>>;
|
|
65
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AnyRouter, Awaitable } from '@benjavicente/router-core';
|
|
2
|
+
import { AnyStartInstance } from './createStart.js';
|
|
3
|
+
export interface StartEntry {
|
|
4
|
+
startInstance: AnyStartInstance | undefined;
|
|
5
|
+
}
|
|
6
|
+
export interface RouterEntry {
|
|
7
|
+
getRouter: () => Awaitable<AnyRouter>;
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@benjavicente/start-client-core",
|
|
3
|
+
"version": "1.167.9",
|
|
4
|
+
"description": "Modern and scalable routing for React applications",
|
|
5
|
+
"author": "Tanner Linsley",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/TanStack/router.git",
|
|
10
|
+
"directory": "packages/start-client-core"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://tanstack.com/start",
|
|
13
|
+
"funding": {
|
|
14
|
+
"type": "github",
|
|
15
|
+
"url": "https://github.com/sponsors/tannerlinsley"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"react",
|
|
19
|
+
"location",
|
|
20
|
+
"router",
|
|
21
|
+
"routing",
|
|
22
|
+
"async",
|
|
23
|
+
"async router",
|
|
24
|
+
"typescript"
|
|
25
|
+
],
|
|
26
|
+
"type": "module",
|
|
27
|
+
"types": "dist/esm/index.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"import": {
|
|
31
|
+
"types": "./dist/esm/index.d.ts",
|
|
32
|
+
"default": "./dist/esm/index.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"./client": {
|
|
36
|
+
"import": {
|
|
37
|
+
"types": "./dist/esm/client/index.d.ts",
|
|
38
|
+
"default": "./dist/esm/client/index.js"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"./client-rpc": {
|
|
42
|
+
"import": {
|
|
43
|
+
"types": "./dist/esm/client-rpc/index.d.ts",
|
|
44
|
+
"default": "./dist/esm/client-rpc/index.js"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"./package.json": "./package.json"
|
|
48
|
+
},
|
|
49
|
+
"imports": {
|
|
50
|
+
"#tanstack-start-entry": {
|
|
51
|
+
"default": "./dist/esm/fake-start-entry.js"
|
|
52
|
+
},
|
|
53
|
+
"#tanstack-router-entry": {
|
|
54
|
+
"default": "./dist/esm/fake-start-entry.js"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"sideEffects": false,
|
|
58
|
+
"files": [
|
|
59
|
+
"dist",
|
|
60
|
+
"src",
|
|
61
|
+
"skills",
|
|
62
|
+
"bin",
|
|
63
|
+
"!skills/_artifacts"
|
|
64
|
+
],
|
|
65
|
+
"engines": {
|
|
66
|
+
"node": ">=22.12.0"
|
|
67
|
+
},
|
|
68
|
+
"dependencies": {
|
|
69
|
+
"seroval": "^1.4.2",
|
|
70
|
+
"@benjavicente/router-core": "1.168.9",
|
|
71
|
+
"@benjavicente/start-fn-stubs": "1.161.6",
|
|
72
|
+
"@benjavicente/start-storage-context": "1.166.23"
|
|
73
|
+
},
|
|
74
|
+
"devDependencies": {
|
|
75
|
+
"@tanstack/intent": "^0.0.14",
|
|
76
|
+
"vite": "*",
|
|
77
|
+
"@types/node": ">=20"
|
|
78
|
+
},
|
|
79
|
+
"bin": {
|
|
80
|
+
"intent": "./bin/intent.js"
|
|
81
|
+
},
|
|
82
|
+
"scripts": {
|
|
83
|
+
"clean": "rimraf ./dist && rimraf ./coverage",
|
|
84
|
+
"test": "pnpm test:eslint && pnpm test:types && pnpm test:build && pnpm test:unit",
|
|
85
|
+
"test:unit": "vitest",
|
|
86
|
+
"test:unit:dev": "vitest --watch",
|
|
87
|
+
"test:eslint": "eslint ./src",
|
|
88
|
+
"test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"",
|
|
89
|
+
"test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js",
|
|
90
|
+
"test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js",
|
|
91
|
+
"test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js",
|
|
92
|
+
"test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js",
|
|
93
|
+
"test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js",
|
|
94
|
+
"test:types:ts60": "tsc",
|
|
95
|
+
"test:build": "publint --strict && attw --ignore-rules no-resolution --pack .",
|
|
96
|
+
"build": "vite build"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: start-core
|
|
3
|
+
description: >-
|
|
4
|
+
Core overview for TanStack Start: tanstackStart() Vite plugin,
|
|
5
|
+
getRouter() factory, root route document shell (HeadContent,
|
|
6
|
+
Scripts, Outlet), client/server entry points, routeTree.gen.ts,
|
|
7
|
+
tsconfig configuration. Entry point for all Start skills.
|
|
8
|
+
type: core
|
|
9
|
+
library: tanstack-start
|
|
10
|
+
library_version: '1.166.2'
|
|
11
|
+
sources:
|
|
12
|
+
- TanStack/router:docs/start/framework/react/build-from-scratch.md
|
|
13
|
+
- TanStack/router:docs/start/framework/react/quick-start.md
|
|
14
|
+
- TanStack/router:docs/start/framework/react/guide/routing.md
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# TanStack Start Core
|
|
18
|
+
|
|
19
|
+
TanStack Start is a full-stack React framework built on TanStack Router and Vite. It adds SSR, streaming, server functions (type-safe RPCs), middleware, server routes, and universal deployment.
|
|
20
|
+
|
|
21
|
+
> **CRITICAL**: All code in TanStack Start is ISOMORPHIC by default — it runs in BOTH server and client environments. Loaders run on both server AND client. To run code exclusively on the server, use `createServerFn`. This is the #1 AI agent mistake.
|
|
22
|
+
> **CRITICAL**: TanStack Start is NOT Next.js. Do not generate `getServerSideProps`, `"use server"` directives, `app/layout.tsx`, or any Next.js/Remix patterns. Use `createServerFn` for server-only code.
|
|
23
|
+
> **CRITICAL**: Types are FULLY INFERRED. Never cast, never annotate inferred values.
|
|
24
|
+
|
|
25
|
+
## Sub-Skills
|
|
26
|
+
|
|
27
|
+
| Task | Sub-Skill |
|
|
28
|
+
| -------------------------------------------- | ------------------------------------------------------------------- |
|
|
29
|
+
| Type-safe RPCs, data fetching, mutations | [start-core/server-functions/SKILL.md](./server-functions/SKILL.md) |
|
|
30
|
+
| Request/function middleware, context, auth | [start-core/middleware/SKILL.md](./middleware/SKILL.md) |
|
|
31
|
+
| Isomorphic execution, environment boundaries | [start-core/execution-model/SKILL.md](./execution-model/SKILL.md) |
|
|
32
|
+
| REST API endpoints alongside app routes | [start-core/server-routes/SKILL.md](./server-routes/SKILL.md) |
|
|
33
|
+
| Hosting, SSR modes, prerendering, SEO | [start-core/deployment/SKILL.md](./deployment/SKILL.md) |
|
|
34
|
+
|
|
35
|
+
## Quick Decision Tree
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
Need to run code exclusively on the server (DB, secrets)?
|
|
39
|
+
→ start-core/server-functions
|
|
40
|
+
|
|
41
|
+
Need auth checks, logging, or shared logic across server functions?
|
|
42
|
+
→ start-core/middleware
|
|
43
|
+
|
|
44
|
+
Need to understand where code runs (server vs client)?
|
|
45
|
+
→ start-core/execution-model
|
|
46
|
+
|
|
47
|
+
Need a REST API endpoint (GET/POST/PUT/DELETE)?
|
|
48
|
+
→ start-core/server-routes
|
|
49
|
+
|
|
50
|
+
Need to deploy, configure SSR, or prerender?
|
|
51
|
+
→ start-core/deployment
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Project Setup
|
|
55
|
+
|
|
56
|
+
### 1. Install Dependencies
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm i @benjavicente/react-start @benjavicente/react-router react react-dom
|
|
60
|
+
npm i -D vite @vitejs/plugin-react typescript
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 2. Configure Vite
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
// vite.config.ts
|
|
67
|
+
import { defineConfig } from 'vite'
|
|
68
|
+
import { tanstackStart } from '@benjavicente/react-start/plugin/vite'
|
|
69
|
+
import viteReact from '@vitejs/plugin-react'
|
|
70
|
+
|
|
71
|
+
export default defineConfig({
|
|
72
|
+
plugins: [
|
|
73
|
+
// MUST come before react()
|
|
74
|
+
tanstackStart(),
|
|
75
|
+
viteReact(),
|
|
76
|
+
],
|
|
77
|
+
})
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 3. Create Router Factory
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
// src/router.tsx
|
|
84
|
+
import { createRouter } from '@benjavicente/react-router'
|
|
85
|
+
import { routeTree } from './routeTree.gen'
|
|
86
|
+
|
|
87
|
+
export function getRouter() {
|
|
88
|
+
const router = createRouter({
|
|
89
|
+
routeTree,
|
|
90
|
+
scrollRestoration: true,
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
return router
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 4. Create Root Route with Document Shell
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
// src/routes/__root.tsx
|
|
101
|
+
import type { ReactNode } from 'react'
|
|
102
|
+
import {
|
|
103
|
+
Outlet,
|
|
104
|
+
createRootRoute,
|
|
105
|
+
HeadContent,
|
|
106
|
+
Scripts,
|
|
107
|
+
} from '@benjavicente/react-router'
|
|
108
|
+
|
|
109
|
+
export const Route = createRootRoute({
|
|
110
|
+
head: () => ({
|
|
111
|
+
meta: [
|
|
112
|
+
{ charSet: 'utf-8' },
|
|
113
|
+
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
|
114
|
+
{ title: 'My App' },
|
|
115
|
+
],
|
|
116
|
+
}),
|
|
117
|
+
component: RootComponent,
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
function RootComponent() {
|
|
121
|
+
return (
|
|
122
|
+
<html>
|
|
123
|
+
<head>
|
|
124
|
+
<HeadContent />
|
|
125
|
+
</head>
|
|
126
|
+
<body>
|
|
127
|
+
<Outlet />
|
|
128
|
+
<Scripts />
|
|
129
|
+
</body>
|
|
130
|
+
</html>
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 5. Create Index Route with Server Function
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
// src/routes/index.tsx
|
|
139
|
+
import { createFileRoute } from '@benjavicente/react-router'
|
|
140
|
+
import { createServerFn } from '@benjavicente/react-start'
|
|
141
|
+
|
|
142
|
+
const getGreeting = createServerFn({ method: 'GET' }).handler(async () => {
|
|
143
|
+
return { message: 'Hello from the server!' }
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
export const Route = createFileRoute('/')({
|
|
147
|
+
loader: () => getGreeting(),
|
|
148
|
+
component: HomePage,
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
function HomePage() {
|
|
152
|
+
const data = Route.useLoaderData()
|
|
153
|
+
return <h1>{data.message}</h1>
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Common Mistakes
|
|
158
|
+
|
|
159
|
+
### 1. CRITICAL: React plugin before Start plugin in Vite config
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
// WRONG — route generation and server function compilation fail
|
|
163
|
+
plugins: [react(), tanstackStart()]
|
|
164
|
+
|
|
165
|
+
// CORRECT — Start plugin must come first
|
|
166
|
+
plugins: [tanstackStart(), react()]
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### 2. HIGH: Enabling verbatimModuleSyntax in tsconfig
|
|
170
|
+
|
|
171
|
+
`verbatimModuleSyntax` causes server bundles to leak into client bundles. Keep it disabled.
|
|
172
|
+
|
|
173
|
+
### 3. HIGH: Missing Scripts component in root route
|
|
174
|
+
|
|
175
|
+
The `<Scripts />` component must be rendered in the `<body>` of the root route. Without it, client-side JavaScript does not load and hydration fails.
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
// WRONG — no Scripts
|
|
179
|
+
function RootComponent() {
|
|
180
|
+
return (
|
|
181
|
+
<html>
|
|
182
|
+
<head>
|
|
183
|
+
<HeadContent />
|
|
184
|
+
</head>
|
|
185
|
+
<body>
|
|
186
|
+
<Outlet />
|
|
187
|
+
</body>
|
|
188
|
+
</html>
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// CORRECT — Scripts in body
|
|
193
|
+
function RootComponent() {
|
|
194
|
+
return (
|
|
195
|
+
<html>
|
|
196
|
+
<head>
|
|
197
|
+
<HeadContent />
|
|
198
|
+
</head>
|
|
199
|
+
<body>
|
|
200
|
+
<Outlet />
|
|
201
|
+
<Scripts />
|
|
202
|
+
</body>
|
|
203
|
+
</html>
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Version Note
|
|
209
|
+
|
|
210
|
+
This skill targets `@benjavicente/react-start` v1.166.2 and `@benjavicente/start-client-core` v1.166.2.
|