1
+ import { fail , type ActionFailure , type RequestEvent } from '@sveltejs/kit' ;
1
2
/* eslint-disable @typescript-eslint/no-explicit-any */
2
- import type { DeepPartial } from '@sjsf/form/lib/types' ;
3
+ import type { DeepPartial , MaybePromise } from '@sjsf/form/lib/types' ;
3
4
import type { Validator } from '@sjsf/form/core' ;
4
5
import {
5
6
DEFAULT_ID_PREFIX ,
6
7
isFormValueValidator ,
7
8
type Schema ,
8
- type SchemaValue ,
9
9
type UiSchemaRoot ,
10
10
type ValidationError ,
11
11
isAsyncFormValueValidator ,
@@ -69,7 +69,7 @@ export interface FormHandlerOptions<SendData extends boolean> extends IdOptions
69
69
schema : Schema ;
70
70
uiSchema ?: UiSchemaRoot ;
71
71
uiOptionsRegistry ?: UiOptionsRegistry ;
72
- idIndexSeparator ?: string
72
+ idIndexSeparator ?: string ;
73
73
validator : Creatable < Validator , ValidatorFactoryOptions > ;
74
74
merger : Creatable < FormMerger , MergerFactoryOptions > ;
75
75
createEntriesConverter ?: Creatable <
@@ -135,7 +135,13 @@ export function createFormHandler<SendData extends boolean>({
135
135
return async (
136
136
signal : AbortSignal ,
137
137
formData : FormData
138
- ) : Promise < [ ValidatedFormData < SendData > , FormValue ] > => {
138
+ ) : Promise <
139
+ [
140
+ ValidatedFormData < SendData > ,
141
+ FormValue ,
142
+ ( errors : ValidationError [ ] ) => ValidatedFormData < SendData >
143
+ ]
144
+ > => {
139
145
const data = formData . has ( JSON_CHUNKS_KEY )
140
146
? JSON . parse ( formData . getAll ( JSON_CHUNKS_KEY ) . join ( '' ) , createReviver ( formData ) )
141
147
: await parseSchemaValue ( signal , {
@@ -155,20 +161,58 @@ export function createFormHandler<SendData extends boolean>({
155
161
: isFormValueValidator ( validator )
156
162
? validator . validateFormValue ( schema , data )
157
163
: [ ] ;
158
- return [
159
- {
164
+ function validated ( errors : ValidationError [ ] ) {
165
+ return {
160
166
isValid : errors . length === 0 ,
161
- sendData,
162
- data : ( sendData ? data : undefined ) as SendData extends true
163
- ? SchemaValue | undefined
164
- : undefined ,
167
+ sendData : sendData ? data : undefined ,
168
+ data : data as FormValue ,
165
169
errors
166
- } ,
167
- data
168
- ] ;
170
+ } as ValidatedFormData < SendData > ;
171
+ }
172
+ return [ validated ( errors ) , data , validated ] ;
169
173
} ;
170
174
}
171
175
172
176
export function isValid < T > ( vfd : ValidatedFormData < boolean > , data : unknown ) : data is T {
173
177
return vfd . isValid ;
174
178
}
179
+
180
+ type FormRecord < F extends string , SendData extends boolean > = {
181
+ [ K in F ] : ValidatedFormData < SendData > ;
182
+ } ;
183
+
184
+ export function createAction <
185
+ const F extends string ,
186
+ const SendData extends boolean ,
187
+ E extends RequestEvent ,
188
+ R extends Record < string , any > | void
189
+ > (
190
+ options : FormHandlerOptions < SendData > & {
191
+ name : F ;
192
+ } ,
193
+ userAction : ( data : any , event : E ) => MaybePromise < ValidationError [ ] | R | void >
194
+ ) {
195
+ const handle = createFormHandler ( options ) ;
196
+ return async (
197
+ event : E
198
+ ) : Promise < ( FormRecord < F , SendData > & R ) | ActionFailure < FormRecord < F , SendData > > > => {
199
+ const [ form , data , validated ] = await handle (
200
+ event . request . signal ,
201
+ await event . request . formData ( )
202
+ ) ;
203
+ if ( ! form . isValid ) {
204
+ return fail ( 400 , { [ options . name ] : form } as FormRecord < F , SendData > ) ;
205
+ }
206
+ let result = await userAction ( data , event ) ;
207
+ if ( Array . isArray ( result ) ) {
208
+ if ( result . length > 0 ) {
209
+ return fail ( 400 , {
210
+ [ options . name ] : validated ( result )
211
+ } as FormRecord < F , SendData > ) ;
212
+ } else {
213
+ result = undefined ;
214
+ }
215
+ }
216
+ return { ...result , [ options . name ] : form } as FormRecord < F , SendData > & R ;
217
+ } ;
218
+ }
0 commit comments