@formadapter/tanstack-start 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +93 -0
- package/dist/client.d.ts +46 -0
- package/dist/client.js +48 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/server.d.ts +24 -0
- package/dist/server.js +18 -0
- package/dist/server.js.map +1 -0
- package/package.json +75 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ludicrous
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# `@formadapter/tanstack-start`
|
|
2
|
+
|
|
3
|
+
TanStack Start server-function integration for FormAdapter. It connects a
|
|
4
|
+
FormAdapter `onSubmit` callback to a POST server function while keeping parsing,
|
|
5
|
+
schema validation, and structured submission errors in `@formadapter/server`.
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
bun add @formadapter/tanstack-start @formadapter/server @tanstack/react-start
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Server function
|
|
12
|
+
|
|
13
|
+
Build the reusable submission first, then place the thin TanStack Start boundary
|
|
14
|
+
around it:
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { createServerFn } from "@tanstack/react-start";
|
|
18
|
+
import { createSubmissionHandler } from "@formadapter/server";
|
|
19
|
+
import {
|
|
20
|
+
formDataValidator,
|
|
21
|
+
tanstackStartHandler,
|
|
22
|
+
} from "@formadapter/tanstack-start/server";
|
|
23
|
+
import { profileSchema } from "./profile-schema";
|
|
24
|
+
|
|
25
|
+
const submission = createSubmissionHandler(
|
|
26
|
+
profileSchema,
|
|
27
|
+
async (profile) => database.profile.save(profile),
|
|
28
|
+
{ config: profileConfig },
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
export const saveProfile = createServerFn({ method: "POST" })
|
|
32
|
+
.validator(formDataValidator)
|
|
33
|
+
.handler(tanstackStartHandler(submission));
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`formDataValidator` only verifies the transport shape. The reusable submission
|
|
37
|
+
performs authoritative schema and presentation-rule validation so failures come
|
|
38
|
+
back as FormAdapter's shared `SubmissionState` instead of escaping TanStack
|
|
39
|
+
Start's validator as generic errors. Pass the same form config when conditional
|
|
40
|
+
`hidden` or `requiredWhenVisible` rules must also be enforced on the server.
|
|
41
|
+
|
|
42
|
+
TanStack's handler context is forwarded into the submission context. Middleware
|
|
43
|
+
auth data is available as `context.context`; `method` and `serverFnMeta` are
|
|
44
|
+
preserved too. Treat that data as request context, and still perform
|
|
45
|
+
authorization in the business handler.
|
|
46
|
+
|
|
47
|
+
Use `createSubmissionHandlerFactory<TanStackStartSubmissionContext<AuthContext>>()`
|
|
48
|
+
when the business callback needs that middleware context inferred. The returned
|
|
49
|
+
context-bound submission requires its invocation context, and
|
|
50
|
+
`tanstackStartHandler` always supplies it.
|
|
51
|
+
|
|
52
|
+
## Client form
|
|
53
|
+
|
|
54
|
+
Use the hook in the client component that renders the form:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
"use client";
|
|
58
|
+
|
|
59
|
+
import { useTanStackStartSubmission } from "@formadapter/tanstack-start";
|
|
60
|
+
import { Profile } from "./profile-form";
|
|
61
|
+
import { saveProfile } from "./profile.functions";
|
|
62
|
+
|
|
63
|
+
export function ProfileEditor() {
|
|
64
|
+
const onSubmit = useTanStackStartSubmission(saveProfile);
|
|
65
|
+
return <Profile.Form onSubmit={onSubmit} />;
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The hook calls TanStack Start's redirect-aware `useServerFn`, sends the form's
|
|
70
|
+
schema-aware `context.formData`, forwards its `AbortSignal`, and returns the
|
|
71
|
+
server's shared submission state. Options can supply static/dynamic headers, a
|
|
72
|
+
custom fetch implementation, or an alternate `FormData` value. GET server
|
|
73
|
+
functions are rejected because submissions require POST.
|
|
74
|
+
|
|
75
|
+
`UseTanStackStartSubmissionOptions<Values, Input>` types the `headers` and
|
|
76
|
+
`getFormData` customization callbacks without changing server-result inference.
|
|
77
|
+
|
|
78
|
+
Client and server exports are intentionally separate. The package root and
|
|
79
|
+
`/client` contain the hook; `/server` contains only the validator and handler
|
|
80
|
+
adapter, so server integration code cannot leak into the client entry.
|
|
81
|
+
|
|
82
|
+
## Progressive enhancement
|
|
83
|
+
|
|
84
|
+
TanStack Start exposes a server function's `.url` for raw HTML form actions.
|
|
85
|
+
`useTanStackStartSubmission` copies that URL from the original server function
|
|
86
|
+
onto the returned handler and exposes `{ url, method, encType }` as `metadata`.
|
|
87
|
+
TanStack's `useServerFn` callback itself does not retain this property.
|
|
88
|
+
|
|
89
|
+
The hook remains a JavaScript-enhanced submission path. Posting a raw HTML form
|
|
90
|
+
to `.url` can provide no-JavaScript transport, but FormAdapter's client-side
|
|
91
|
+
state mapping and inline structured errors do not run in that mode. Applications
|
|
92
|
+
that require full progressive enhancement should design the raw response and
|
|
93
|
+
redirect/error experience explicitly instead of assuming hook behavior applies.
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { SubmissionState } from "@formadapter/core";
|
|
2
|
+
|
|
3
|
+
//#region src/client.d.ts
|
|
4
|
+
interface FormAdapterSubmissionContext<Input = unknown> {
|
|
5
|
+
readonly input: Input;
|
|
6
|
+
readonly formData: FormData;
|
|
7
|
+
readonly signal: AbortSignal;
|
|
8
|
+
}
|
|
9
|
+
interface TanStackStartCallOptions {
|
|
10
|
+
readonly data: FormData;
|
|
11
|
+
readonly signal?: AbortSignal;
|
|
12
|
+
readonly headers?: HeadersInit;
|
|
13
|
+
readonly fetch?: typeof fetch;
|
|
14
|
+
}
|
|
15
|
+
/** The stable public surface used from a TanStack Start server function. */
|
|
16
|
+
type TanStackStartServerFn<Result extends SubmissionState = SubmissionState> = ((options: TanStackStartCallOptions) => Promise<Result>) & {
|
|
17
|
+
readonly url: string;
|
|
18
|
+
readonly method?: "GET" | "POST";
|
|
19
|
+
};
|
|
20
|
+
interface TanStackStartSubmissionMetadata {
|
|
21
|
+
readonly url: string;
|
|
22
|
+
readonly method: "post";
|
|
23
|
+
readonly encType: "multipart/form-data";
|
|
24
|
+
}
|
|
25
|
+
type HeadersOption<Values = unknown, Input = unknown> = HeadersInit | ((values: Values, context: FormAdapterSubmissionContext<Input>) => HeadersInit | undefined);
|
|
26
|
+
interface UseTanStackStartSubmissionOptions<Values = unknown, Input = unknown> {
|
|
27
|
+
/** Override the FormData sent to the server function. */
|
|
28
|
+
readonly getFormData?: (values: Values, context: FormAdapterSubmissionContext<Input>) => FormData;
|
|
29
|
+
readonly headers?: HeadersOption<Values, Input>;
|
|
30
|
+
readonly fetch?: typeof fetch;
|
|
31
|
+
}
|
|
32
|
+
type TanStackStartSubmissionHandler<Result extends SubmissionState = SubmissionState, Values = unknown, Input = unknown> = ((values: Values, context: FormAdapterSubmissionContext<Input>) => Promise<Result>) & {
|
|
33
|
+
/** Copied from the original server function, not the useServerFn callback. */readonly url: string;
|
|
34
|
+
readonly metadata: TanStackStartSubmissionMetadata;
|
|
35
|
+
};
|
|
36
|
+
declare function getTanStackStartSubmissionMetadata(serverFn: {
|
|
37
|
+
readonly url: string;
|
|
38
|
+
}): TanStackStartSubmissionMetadata;
|
|
39
|
+
/**
|
|
40
|
+
* Creates a FormAdapter `onSubmit` handler backed by TanStack Start's
|
|
41
|
+
* redirect-aware `useServerFn` invocation.
|
|
42
|
+
*/
|
|
43
|
+
declare function useTanStackStartSubmission<Result extends SubmissionState, Values = unknown, Input = unknown>(serverFn: TanStackStartServerFn<Result>, options?: UseTanStackStartSubmissionOptions<Values, Input>): TanStackStartSubmissionHandler<Result, Values, Input>;
|
|
44
|
+
//#endregion
|
|
45
|
+
export { FormAdapterSubmissionContext, TanStackStartCallOptions, TanStackStartServerFn, TanStackStartSubmissionHandler, TanStackStartSubmissionMetadata, UseTanStackStartSubmissionOptions, getTanStackStartSubmissionMetadata, useTanStackStartSubmission };
|
|
46
|
+
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useCallback, useMemo } from "react";
|
|
3
|
+
import { useServerFn } from "@tanstack/react-start";
|
|
4
|
+
//#region src/client.ts
|
|
5
|
+
function getTanStackStartSubmissionMetadata(serverFn) {
|
|
6
|
+
return {
|
|
7
|
+
encType: "multipart/form-data",
|
|
8
|
+
method: "post",
|
|
9
|
+
url: serverFn.url
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Creates a FormAdapter `onSubmit` handler backed by TanStack Start's
|
|
14
|
+
* redirect-aware `useServerFn` invocation.
|
|
15
|
+
*/
|
|
16
|
+
function useTanStackStartSubmission(serverFn, options = {}) {
|
|
17
|
+
if (serverFn.method !== void 0 && serverFn.method !== "POST") throw new Error("FormAdapter submissions require a TanStack Start POST server function.");
|
|
18
|
+
const invoke = useServerFn(serverFn);
|
|
19
|
+
const url = serverFn.url;
|
|
20
|
+
const { fetch: customFetch, getFormData, headers } = options;
|
|
21
|
+
const submit = useCallback(async (values, context) => {
|
|
22
|
+
const resolvedHeaders = typeof headers === "function" ? headers(values, context) : headers;
|
|
23
|
+
return invoke({
|
|
24
|
+
data: getFormData?.(values, context) ?? context.formData,
|
|
25
|
+
signal: context.signal,
|
|
26
|
+
...resolvedHeaders !== void 0 ? { headers: resolvedHeaders } : {},
|
|
27
|
+
...customFetch !== void 0 ? { fetch: customFetch } : {}
|
|
28
|
+
});
|
|
29
|
+
}, [
|
|
30
|
+
customFetch,
|
|
31
|
+
getFormData,
|
|
32
|
+
headers,
|
|
33
|
+
invoke
|
|
34
|
+
]);
|
|
35
|
+
const metadata = useMemo(() => getTanStackStartSubmissionMetadata({ url }), [url]);
|
|
36
|
+
return useMemo(() => Object.assign(submit, {
|
|
37
|
+
metadata,
|
|
38
|
+
url
|
|
39
|
+
}), [
|
|
40
|
+
metadata,
|
|
41
|
+
submit,
|
|
42
|
+
url
|
|
43
|
+
]);
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { getTanStackStartSubmissionMetadata, useTanStackStartSubmission };
|
|
47
|
+
|
|
48
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","names":[],"sources":["../src/client.ts"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useMemo,\n} from \"react\";\nimport { useServerFn } from \"@tanstack/react-start\";\n\nimport type { SubmissionState } from \"@formadapter/core\";\n\nexport interface FormAdapterSubmissionContext<Input = unknown> {\n readonly input: Input;\n readonly formData: FormData;\n readonly signal: AbortSignal;\n}\n\nexport interface TanStackStartCallOptions {\n readonly data: FormData;\n readonly signal?: AbortSignal;\n readonly headers?: HeadersInit;\n readonly fetch?: typeof fetch;\n}\n\n/** The stable public surface used from a TanStack Start server function. */\nexport type TanStackStartServerFn<\n Result extends SubmissionState = SubmissionState,\n> = ((options: TanStackStartCallOptions) => Promise<Result>) & {\n readonly url: string;\n readonly method?: \"GET\" | \"POST\";\n};\n\nexport interface TanStackStartSubmissionMetadata {\n readonly url: string;\n readonly method: \"post\";\n readonly encType: \"multipart/form-data\";\n}\n\ntype HeadersOption<Values = unknown, Input = unknown> =\n | HeadersInit\n | ((\n values: Values,\n context: FormAdapterSubmissionContext<Input>,\n ) => HeadersInit | undefined);\n\nexport interface UseTanStackStartSubmissionOptions<\n Values = unknown,\n Input = unknown,\n> {\n /** Override the FormData sent to the server function. */\n readonly getFormData?: (\n values: Values,\n context: FormAdapterSubmissionContext<Input>,\n ) => FormData;\n readonly headers?: HeadersOption<Values, Input>;\n readonly fetch?: typeof fetch;\n}\n\nexport type TanStackStartSubmissionHandler<\n Result extends SubmissionState = SubmissionState,\n Values = unknown,\n Input = unknown,\n> = ((\n values: Values,\n context: FormAdapterSubmissionContext<Input>,\n) => Promise<Result>) & {\n /** Copied from the original server function, not the useServerFn callback. */\n readonly url: string;\n readonly metadata: TanStackStartSubmissionMetadata;\n};\n\nexport function getTanStackStartSubmissionMetadata(\n serverFn: { readonly url: string },\n): TanStackStartSubmissionMetadata {\n return {\n encType: \"multipart/form-data\",\n method: \"post\",\n url: serverFn.url,\n };\n}\n\n/**\n * Creates a FormAdapter `onSubmit` handler backed by TanStack Start's\n * redirect-aware `useServerFn` invocation.\n */\nexport function useTanStackStartSubmission<\n Result extends SubmissionState,\n Values = unknown,\n Input = unknown,\n>(\n serverFn: TanStackStartServerFn<Result>,\n options: UseTanStackStartSubmissionOptions<Values, Input> = {},\n): TanStackStartSubmissionHandler<Result, Values, Input> {\n if (serverFn.method !== undefined && serverFn.method !== \"POST\") {\n throw new Error(\n \"FormAdapter submissions require a TanStack Start POST server function.\",\n );\n }\n\n const invoke = useServerFn(serverFn);\n const url = serverFn.url;\n const { fetch: customFetch, getFormData, headers } = options;\n const submit = useCallback(\n async (\n values: Values,\n context: FormAdapterSubmissionContext<Input>,\n ): Promise<Result> => {\n const resolvedHeaders = typeof headers === \"function\"\n ? headers(values, context)\n : headers;\n const call: TanStackStartCallOptions = {\n data: getFormData?.(values, context) ?? context.formData,\n signal: context.signal,\n ...(resolvedHeaders !== undefined ? { headers: resolvedHeaders } : {}),\n ...(customFetch !== undefined ? { fetch: customFetch } : {}),\n };\n return invoke(call);\n },\n [customFetch, getFormData, headers, invoke],\n );\n const metadata = useMemo(\n () => getTanStackStartSubmissionMetadata({ url }),\n [url],\n );\n\n return useMemo(\n () => Object.assign(submit, { metadata, url }),\n [metadata, submit, url],\n );\n}\n"],"mappings":";;;;AAsEA,SAAgB,mCACd,UACiC;AACjC,QAAO;EACL,SAAS;EACT,QAAQ;EACR,KAAK,SAAS;EACf;;;;;;AAOH,SAAgB,2BAKd,UACA,UAA4D,EAAE,EACP;AACvD,KAAI,SAAS,WAAW,KAAA,KAAa,SAAS,WAAW,OACvD,OAAM,IAAI,MACR,yEACD;CAGH,MAAM,SAAS,YAAY,SAAS;CACpC,MAAM,MAAM,SAAS;CACrB,MAAM,EAAE,OAAO,aAAa,aAAa,YAAY;CACrD,MAAM,SAAS,YACb,OACE,QACA,YACoB;EACpB,MAAM,kBAAkB,OAAO,YAAY,aACvC,QAAQ,QAAQ,QAAQ,GACxB;AAOJ,SAAO,OAAO;GALZ,MAAM,cAAc,QAAQ,QAAQ,IAAI,QAAQ;GAChD,QAAQ,QAAQ;GAChB,GAAI,oBAAoB,KAAA,IAAY,EAAE,SAAS,iBAAiB,GAAG,EAAE;GACrE,GAAI,gBAAgB,KAAA,IAAY,EAAE,OAAO,aAAa,GAAG,EAAE;GAE3C,CAAC;IAErB;EAAC;EAAa;EAAa;EAAS;EAAO,CAC5C;CACD,MAAM,WAAW,cACT,mCAAmC,EAAE,KAAK,CAAC,EACjD,CAAC,IAAI,CACN;AAED,QAAO,cACC,OAAO,OAAO,QAAQ;EAAE;EAAU;EAAK,CAAC,EAC9C;EAAC;EAAU;EAAQ;EAAI,CACxB"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { FormAdapterSubmissionContext, TanStackStartCallOptions, TanStackStartServerFn, TanStackStartSubmissionHandler, TanStackStartSubmissionMetadata, UseTanStackStartSubmissionOptions, getTanStackStartSubmissionMetadata, useTanStackStartSubmission } from "./client.js";
|
|
2
|
+
export { type FormAdapterSubmissionContext, type TanStackStartCallOptions, type TanStackStartServerFn, type TanStackStartSubmissionHandler, type TanStackStartSubmissionMetadata, type UseTanStackStartSubmissionOptions, getTanStackStartSubmissionMetadata, useTanStackStartSubmission };
|
package/dist/index.js
ADDED
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SubmissionState } from "@formadapter/core";
|
|
2
|
+
|
|
3
|
+
//#region src/server.d.ts
|
|
4
|
+
interface TanStackStartHandlerContext<Context = unknown> {
|
|
5
|
+
readonly data: FormData;
|
|
6
|
+
readonly context: Context;
|
|
7
|
+
readonly method: "POST";
|
|
8
|
+
readonly serverFnMeta: unknown;
|
|
9
|
+
}
|
|
10
|
+
type TanStackStartSubmissionContext<Context = unknown> = Omit<TanStackStartHandlerContext<Context>, "data">;
|
|
11
|
+
/** Structural shape of a prebuilt `@formadapter/server` submission. */
|
|
12
|
+
type FormAdapterSubmission<Result extends SubmissionState = SubmissionState, Context = unknown> = (payload: unknown, context: TanStackStartSubmissionContext<Context>) => Promise<Result>;
|
|
13
|
+
type TanStackStartHandler<Result extends SubmissionState = SubmissionState, Context = unknown> = (context: TanStackStartHandlerContext<Context>) => Promise<Result>;
|
|
14
|
+
/** A canonical TanStack Start `.validator(...)` for POSTed FormData. */
|
|
15
|
+
declare function formDataValidator(data: FormData): FormData;
|
|
16
|
+
/**
|
|
17
|
+
* Adapts a prebuilt FormAdapter submission to a TanStack Start `.handler(...)`.
|
|
18
|
+
* The remaining TanStack handler context is forwarded structurally as the
|
|
19
|
+
* submission's optional second argument.
|
|
20
|
+
*/
|
|
21
|
+
declare function tanstackStartHandler<Result extends SubmissionState, Context = unknown>(submission: FormAdapterSubmission<Result, Context>): TanStackStartHandler<Result, Context>;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { FormAdapterSubmission, TanStackStartHandler, TanStackStartHandlerContext, TanStackStartSubmissionContext, formDataValidator, tanstackStartHandler };
|
|
24
|
+
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/server.ts
|
|
2
|
+
/** A canonical TanStack Start `.validator(...)` for POSTed FormData. */
|
|
3
|
+
function formDataValidator(data) {
|
|
4
|
+
if (typeof FormData === "undefined" || !(data instanceof FormData)) throw new TypeError("Expected FormData from a TanStack Start POST server function.");
|
|
5
|
+
return data;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Adapts a prebuilt FormAdapter submission to a TanStack Start `.handler(...)`.
|
|
9
|
+
* The remaining TanStack handler context is forwarded structurally as the
|
|
10
|
+
* submission's optional second argument.
|
|
11
|
+
*/
|
|
12
|
+
function tanstackStartHandler(submission) {
|
|
13
|
+
return async ({ data, ...context }) => submission(data, context);
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { formDataValidator, tanstackStartHandler };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","names":[],"sources":["../src/server.ts"],"sourcesContent":["import type { SubmissionState } from \"@formadapter/core\";\n\nexport interface TanStackStartHandlerContext<Context = unknown> {\n readonly data: FormData;\n readonly context: Context;\n readonly method: \"POST\";\n readonly serverFnMeta: unknown;\n}\n\nexport type TanStackStartSubmissionContext<Context = unknown> = Omit<\n TanStackStartHandlerContext<Context>,\n \"data\"\n>;\n\n/** Structural shape of a prebuilt `@formadapter/server` submission. */\nexport type FormAdapterSubmission<\n Result extends SubmissionState = SubmissionState,\n Context = unknown,\n> = (\n payload: unknown,\n context: TanStackStartSubmissionContext<Context>,\n) => Promise<Result>;\n\nexport type TanStackStartHandler<\n Result extends SubmissionState = SubmissionState,\n Context = unknown,\n> = (context: TanStackStartHandlerContext<Context>) => Promise<Result>;\n\n/** A canonical TanStack Start `.validator(...)` for POSTed FormData. */\nexport function formDataValidator(data: FormData): FormData {\n if (typeof FormData === \"undefined\" || !(data instanceof FormData)) {\n throw new TypeError(\"Expected FormData from a TanStack Start POST server function.\");\n }\n return data;\n}\n\n/**\n * Adapts a prebuilt FormAdapter submission to a TanStack Start `.handler(...)`.\n * The remaining TanStack handler context is forwarded structurally as the\n * submission's optional second argument.\n */\nexport function tanstackStartHandler<\n Result extends SubmissionState,\n Context = unknown,\n>(\n submission: FormAdapterSubmission<Result, Context>,\n): TanStackStartHandler<Result, Context> {\n return async ({ data, ...context }): Promise<Result> =>\n submission(data, context);\n}\n"],"mappings":";;AA6BA,SAAgB,kBAAkB,MAA0B;AAC1D,KAAI,OAAO,aAAa,eAAe,EAAE,gBAAgB,UACvD,OAAM,IAAI,UAAU,gEAAgE;AAEtF,QAAO;;;;;;;AAQT,SAAgB,qBAId,YACuC;AACvC,QAAO,OAAO,EAAE,MAAM,GAAG,cACvB,WAAW,MAAM,QAAQ"}
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@formadapter/tanstack-start",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "TanStack Start server-function integration for FormAdapter.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"forms",
|
|
7
|
+
"server-functions",
|
|
8
|
+
"tanstack-start",
|
|
9
|
+
"typescript"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://formadapter.com",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/ludicroushq/formadapter/issues"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/ludicroushq/formadapter.git",
|
|
18
|
+
"directory": "packages/tanstack-start"
|
|
19
|
+
},
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"author": "ludicrous",
|
|
22
|
+
"type": "module",
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"README.md",
|
|
30
|
+
"LICENSE"
|
|
31
|
+
],
|
|
32
|
+
"main": "./dist/index.js",
|
|
33
|
+
"module": "./dist/index.js",
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"exports": {
|
|
36
|
+
".": {
|
|
37
|
+
"types": "./dist/index.d.ts",
|
|
38
|
+
"import": "./dist/index.js",
|
|
39
|
+
"default": "./dist/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./client": {
|
|
42
|
+
"types": "./dist/client.d.ts",
|
|
43
|
+
"import": "./dist/client.js",
|
|
44
|
+
"default": "./dist/client.js"
|
|
45
|
+
},
|
|
46
|
+
"./server": {
|
|
47
|
+
"types": "./dist/server.d.ts",
|
|
48
|
+
"import": "./dist/server.js",
|
|
49
|
+
"default": "./dist/server.js"
|
|
50
|
+
},
|
|
51
|
+
"./package.json": "./package.json"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@formadapter/core": "^0.0.0"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@tanstack/react-start": ">=1.168.25 <2",
|
|
58
|
+
"react": "^18.2.0 || ^19.0.0"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@tanstack/react-start": "1.168.25",
|
|
62
|
+
"@types/react": "^19.2.17",
|
|
63
|
+
"@types/react-dom": "^19.2.3",
|
|
64
|
+
"react": "19.2.7",
|
|
65
|
+
"react-dom": "19.2.7"
|
|
66
|
+
},
|
|
67
|
+
"scripts": {
|
|
68
|
+
"build": "tsdown",
|
|
69
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo .turbo",
|
|
70
|
+
"dev": "tsdown --watch",
|
|
71
|
+
"test": "vitest run --config vitest.config.ts",
|
|
72
|
+
"test:coverage": "vitest run --config vitest.config.ts --coverage",
|
|
73
|
+
"typecheck": "tsc --project tsconfig.json --noEmit"
|
|
74
|
+
}
|
|
75
|
+
}
|