@flightdev/forms 0.0.2
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 +210 -0
- package/dist/adapters/valibot.d.ts +38 -0
- package/dist/adapters/valibot.js +66 -0
- package/dist/adapters/valibot.js.map +1 -0
- package/dist/adapters/yup.d.ts +44 -0
- package/dist/adapters/yup.js +56 -0
- package/dist/adapters/yup.js.map +1 -0
- package/dist/adapters/zod.d.ts +83 -0
- package/dist/adapters/zod.js +47 -0
- package/dist/adapters/zod.js.map +1 -0
- package/dist/chunk-5LLYBEXV.js +110 -0
- package/dist/chunk-5LLYBEXV.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +10 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/frameworks/react.d.ts +85 -0
- package/dist/frameworks/react.js +195 -0
- package/dist/frameworks/react.js.map +1 -0
- package/dist/frameworks/solid.d.ts +63 -0
- package/dist/frameworks/solid.js +138 -0
- package/dist/frameworks/solid.js.map +1 -0
- package/dist/frameworks/svelte.d.ts +61 -0
- package/dist/frameworks/svelte.js +143 -0
- package/dist/frameworks/svelte.js.map +1 -0
- package/dist/frameworks/vue.d.ts +60 -0
- package/dist/frameworks/vue.js +127 -0
- package/dist/frameworks/vue.js.map +1 -0
- package/dist/index.d.ts +181 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/package.json +102 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @flightdev/forms - Agnostic Full-Stack Form Handling
|
|
3
|
+
*
|
|
4
|
+
* Flight provides form primitives, you choose the validator.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { createForm } from '@flightdev/forms';
|
|
9
|
+
* import { zod } from '@flightdev/forms/zod';
|
|
10
|
+
* import { z } from 'zod';
|
|
11
|
+
*
|
|
12
|
+
* const contactForm = createForm({
|
|
13
|
+
* validator: zod(z.object({
|
|
14
|
+
* email: z.string().email(),
|
|
15
|
+
* message: z.string().min(10),
|
|
16
|
+
* })),
|
|
17
|
+
* action: async (data) => {
|
|
18
|
+
* await sendEmail(data.email, data.message);
|
|
19
|
+
* return { success: true };
|
|
20
|
+
* },
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
/** Validation error for a single field */
|
|
25
|
+
interface FieldError {
|
|
26
|
+
/** Field path (e.g., 'email', 'address.street') */
|
|
27
|
+
path: string;
|
|
28
|
+
/** Error message */
|
|
29
|
+
message: string;
|
|
30
|
+
/** Error code (e.g., 'invalid_type', 'too_small') */
|
|
31
|
+
code?: string;
|
|
32
|
+
}
|
|
33
|
+
/** Result of validation */
|
|
34
|
+
interface ValidationResult<T> {
|
|
35
|
+
/** Whether validation passed */
|
|
36
|
+
success: boolean;
|
|
37
|
+
/** Validated and transformed data (if success) */
|
|
38
|
+
data?: T;
|
|
39
|
+
/** Validation errors (if not success) */
|
|
40
|
+
errors?: FieldError[];
|
|
41
|
+
}
|
|
42
|
+
/** Form submission result */
|
|
43
|
+
interface FormResult<T = unknown> {
|
|
44
|
+
/** Whether the action succeeded */
|
|
45
|
+
success: boolean;
|
|
46
|
+
/** Returned data from the action */
|
|
47
|
+
data?: T;
|
|
48
|
+
/** Error message if failed */
|
|
49
|
+
error?: string;
|
|
50
|
+
/** Field-specific errors */
|
|
51
|
+
fieldErrors?: FieldError[];
|
|
52
|
+
}
|
|
53
|
+
/** Form state during submission */
|
|
54
|
+
interface FormState<T = unknown> {
|
|
55
|
+
/** Whether form is currently submitting */
|
|
56
|
+
pending: boolean;
|
|
57
|
+
/** Last submission result */
|
|
58
|
+
result?: FormResult<T>;
|
|
59
|
+
/** Current form data */
|
|
60
|
+
data?: Partial<T>;
|
|
61
|
+
/** Current validation errors */
|
|
62
|
+
errors: Record<string, string>;
|
|
63
|
+
/** Fields that have been touched */
|
|
64
|
+
touched: Set<string>;
|
|
65
|
+
/** Whether form has been modified */
|
|
66
|
+
dirty: boolean;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Validation Adapter Interface
|
|
70
|
+
*
|
|
71
|
+
* Implement this to create a custom validator adapter.
|
|
72
|
+
* Flight provides Zod, Yup, and Valibot adapters.
|
|
73
|
+
*/
|
|
74
|
+
interface ValidationAdapter<TInput = unknown, TOutput = TInput> {
|
|
75
|
+
/** Adapter name for debugging */
|
|
76
|
+
readonly name: string;
|
|
77
|
+
/**
|
|
78
|
+
* Validate input data
|
|
79
|
+
*
|
|
80
|
+
* @param data - Raw input data to validate
|
|
81
|
+
* @returns Validation result with either typed data or errors
|
|
82
|
+
*/
|
|
83
|
+
validate(data: unknown): ValidationResult<TOutput>;
|
|
84
|
+
/**
|
|
85
|
+
* Async validate (for schemas with async refinements)
|
|
86
|
+
*/
|
|
87
|
+
validateAsync(data: unknown): Promise<ValidationResult<TOutput>>;
|
|
88
|
+
/**
|
|
89
|
+
* Get the inferred output type (for TypeScript)
|
|
90
|
+
* This is used for type inference only.
|
|
91
|
+
*/
|
|
92
|
+
readonly _output: TOutput;
|
|
93
|
+
}
|
|
94
|
+
/** Validation adapter factory type */
|
|
95
|
+
type ValidationAdapterFactory<TSchema, TOutput> = (schema: TSchema) => ValidationAdapter<unknown, TOutput>;
|
|
96
|
+
/** Form action function type */
|
|
97
|
+
type FormAction<TInput, TResult = unknown> = (data: TInput, context?: FormActionContext) => Promise<FormResult<TResult>>;
|
|
98
|
+
/** Context passed to form actions */
|
|
99
|
+
interface FormActionContext {
|
|
100
|
+
/** Original request (server-side) */
|
|
101
|
+
request?: Request;
|
|
102
|
+
/** Form data (for file uploads) */
|
|
103
|
+
formData?: FormData;
|
|
104
|
+
}
|
|
105
|
+
/** Form definition options */
|
|
106
|
+
interface FormOptions<TValidator extends ValidationAdapter<unknown, unknown>, TResult = unknown> {
|
|
107
|
+
/** Validation adapter with schema */
|
|
108
|
+
validator: TValidator;
|
|
109
|
+
/** Server action to execute on submit */
|
|
110
|
+
action: FormAction<TValidator['_output'], TResult>;
|
|
111
|
+
/** Enable CSRF protection */
|
|
112
|
+
csrf?: boolean;
|
|
113
|
+
/** Form ID (for multiple forms on same page) */
|
|
114
|
+
id?: string;
|
|
115
|
+
/** Redirect URL on success */
|
|
116
|
+
redirectOnSuccess?: string;
|
|
117
|
+
/** Enable progressive enhancement */
|
|
118
|
+
progressive?: boolean;
|
|
119
|
+
}
|
|
120
|
+
/** Form instance */
|
|
121
|
+
interface FormDefinition<TInput, TResult = unknown> {
|
|
122
|
+
/** Form ID */
|
|
123
|
+
readonly id: string;
|
|
124
|
+
/** Validate data */
|
|
125
|
+
validate(data: unknown): ValidationResult<TInput>;
|
|
126
|
+
/** Validate data async */
|
|
127
|
+
validateAsync(data: unknown): Promise<ValidationResult<TInput>>;
|
|
128
|
+
/** Execute the form action (server-side) */
|
|
129
|
+
execute(data: unknown, context?: FormActionContext): Promise<FormResult<TResult>>;
|
|
130
|
+
/** Parse FormData to object */
|
|
131
|
+
parseFormData(formData: FormData): Record<string, unknown>;
|
|
132
|
+
/** Handle form submission (server-side) */
|
|
133
|
+
handleSubmit(request: Request): Promise<FormResult<TResult>>;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Create a form definition
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* import { createForm } from '@flightdev/forms';
|
|
141
|
+
* import { zod } from '@flightdev/forms/zod';
|
|
142
|
+
* import { z } from 'zod';
|
|
143
|
+
*
|
|
144
|
+
* const loginForm = createForm({
|
|
145
|
+
* validator: zod(z.object({
|
|
146
|
+
* email: z.string().email(),
|
|
147
|
+
* password: z.string().min(8),
|
|
148
|
+
* })),
|
|
149
|
+
* action: async (data) => {
|
|
150
|
+
* const user = await authenticate(data.email, data.password);
|
|
151
|
+
* if (user) {
|
|
152
|
+
* return { success: true, data: { userId: user.id } };
|
|
153
|
+
* }
|
|
154
|
+
* return {
|
|
155
|
+
* success: false,
|
|
156
|
+
* error: 'Invalid credentials',
|
|
157
|
+
* fieldErrors: [{ path: 'email', message: 'Invalid email or password' }],
|
|
158
|
+
* };
|
|
159
|
+
* },
|
|
160
|
+
* });
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
declare function createForm<TValidator extends ValidationAdapter<unknown, unknown>, TResult = unknown>(options: FormOptions<TValidator, TResult>): FormDefinition<TValidator['_output'], TResult>;
|
|
164
|
+
/**
|
|
165
|
+
* Create initial form state
|
|
166
|
+
*/
|
|
167
|
+
declare function createFormState<T>(): FormState<T>;
|
|
168
|
+
/**
|
|
169
|
+
* Convert field errors array to errors object
|
|
170
|
+
*/
|
|
171
|
+
declare function errorsToObject(errors: FieldError[]): Record<string, string>;
|
|
172
|
+
/**
|
|
173
|
+
* Get error for a specific field
|
|
174
|
+
*/
|
|
175
|
+
declare function getFieldError(errors: FieldError[], path: string): string | undefined;
|
|
176
|
+
/**
|
|
177
|
+
* Check if form has any errors
|
|
178
|
+
*/
|
|
179
|
+
declare function hasErrors(state: FormState<unknown>): boolean;
|
|
180
|
+
|
|
181
|
+
export { type FieldError, type FormAction, type FormActionContext, type FormDefinition, type FormOptions, type FormResult, type FormState, type ValidationAdapter, type ValidationAdapterFactory, type ValidationResult, createForm, createFormState, errorsToObject, getFieldError, hasErrors };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
package/package.json
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@flightdev/forms",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Agnostic full-stack form handling for Flight Framework. Choose your validator: Zod, Yup, Valibot, or custom.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"./zod": {
|
|
12
|
+
"types": "./dist/adapters/zod.d.ts",
|
|
13
|
+
"import": "./dist/adapters/zod.js"
|
|
14
|
+
},
|
|
15
|
+
"./yup": {
|
|
16
|
+
"types": "./dist/adapters/yup.d.ts",
|
|
17
|
+
"import": "./dist/adapters/yup.js"
|
|
18
|
+
},
|
|
19
|
+
"./valibot": {
|
|
20
|
+
"types": "./dist/adapters/valibot.d.ts",
|
|
21
|
+
"import": "./dist/adapters/valibot.js"
|
|
22
|
+
},
|
|
23
|
+
"./react": {
|
|
24
|
+
"types": "./dist/frameworks/react.d.ts",
|
|
25
|
+
"import": "./dist/frameworks/react.js"
|
|
26
|
+
},
|
|
27
|
+
"./vue": {
|
|
28
|
+
"types": "./dist/frameworks/vue.d.ts",
|
|
29
|
+
"import": "./dist/frameworks/vue.js"
|
|
30
|
+
},
|
|
31
|
+
"./svelte": {
|
|
32
|
+
"types": "./dist/frameworks/svelte.d.ts",
|
|
33
|
+
"import": "./dist/frameworks/svelte.js"
|
|
34
|
+
},
|
|
35
|
+
"./solid": {
|
|
36
|
+
"types": "./dist/frameworks/solid.d.ts",
|
|
37
|
+
"import": "./dist/frameworks/solid.js"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"main": "./dist/index.js",
|
|
41
|
+
"types": "./dist/index.d.ts",
|
|
42
|
+
"files": [
|
|
43
|
+
"dist"
|
|
44
|
+
],
|
|
45
|
+
"dependencies": {},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"zod": ">=3.0.0",
|
|
48
|
+
"yup": ">=1.0.0",
|
|
49
|
+
"valibot": ">=0.30.0",
|
|
50
|
+
"react": ">=18.0.0",
|
|
51
|
+
"vue": ">=3.0.0",
|
|
52
|
+
"svelte": ">=4.0.0",
|
|
53
|
+
"solid-js": ">=1.0.0"
|
|
54
|
+
},
|
|
55
|
+
"peerDependenciesMeta": {
|
|
56
|
+
"zod": {
|
|
57
|
+
"optional": true
|
|
58
|
+
},
|
|
59
|
+
"yup": {
|
|
60
|
+
"optional": true
|
|
61
|
+
},
|
|
62
|
+
"valibot": {
|
|
63
|
+
"optional": true
|
|
64
|
+
},
|
|
65
|
+
"react": {
|
|
66
|
+
"optional": true
|
|
67
|
+
},
|
|
68
|
+
"vue": {
|
|
69
|
+
"optional": true
|
|
70
|
+
},
|
|
71
|
+
"svelte": {
|
|
72
|
+
"optional": true
|
|
73
|
+
},
|
|
74
|
+
"solid-js": {
|
|
75
|
+
"optional": true
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"devDependencies": {
|
|
79
|
+
"@types/node": "^22.0.0",
|
|
80
|
+
"tsup": "^8.0.0",
|
|
81
|
+
"typescript": "^5.7.0",
|
|
82
|
+
"vitest": "^2.0.0"
|
|
83
|
+
},
|
|
84
|
+
"keywords": [
|
|
85
|
+
"flight",
|
|
86
|
+
"forms",
|
|
87
|
+
"validation",
|
|
88
|
+
"zod",
|
|
89
|
+
"yup",
|
|
90
|
+
"valibot",
|
|
91
|
+
"progressive-enhancement"
|
|
92
|
+
],
|
|
93
|
+
"author": "Flight Contributors",
|
|
94
|
+
"license": "MIT",
|
|
95
|
+
"scripts": {
|
|
96
|
+
"build": "tsup",
|
|
97
|
+
"dev": "tsup --watch",
|
|
98
|
+
"test": "vitest run",
|
|
99
|
+
"test:watch": "vitest",
|
|
100
|
+
"typecheck": "tsc --noEmit"
|
|
101
|
+
}
|
|
102
|
+
}
|