@sugardarius/anzen 2.2.1 → 2.3.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/README.md +53 -2
- package/dist/{chunk-WEUMYDOP.js → chunk-A7I43FHB.js} +2 -2
- package/dist/chunk-A7I43FHB.js.map +1 -0
- package/dist/{chunk-LYFK3PWU.cjs → chunk-MJPPHUFP.cjs} +2 -2
- package/dist/chunk-MJPPHUFP.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +454 -4
- package/dist/index.d.ts +454 -4
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/server-components/index.cjs +1 -1
- package/dist/server-components/index.d.cts +6 -6
- package/dist/server-components/index.d.ts +6 -6
- package/dist/server-components/index.js +1 -1
- package/dist/server-components/index.js.map +1 -1
- package/dist/standard-schema-BHEkWkzf.d.cts +73 -0
- package/dist/standard-schema-BHEkWkzf.d.ts +73 -0
- package/package.json +11 -11
- package/dist/chunk-LYFK3PWU.cjs.map +0 -1
- package/dist/chunk-WEUMYDOP.js.map +0 -1
- package/dist/types-D-blrRCr.d.cts +0 -266
- package/dist/types-D-blrRCr.d.ts +0 -266
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,196 @@
|
|
|
1
|
-
import { A as AuthContext,
|
|
2
|
-
|
|
1
|
+
import { A as AuthContext, S as StandardSchemaDictionary, a as StandardSchemaV1, b as Awaitable, U as UnwrapReadonlyObject, E as EmptyObjectType } from './standard-schema-BHEkWkzf.cjs';
|
|
2
|
+
|
|
3
|
+
type TSegmentsDict = StandardSchemaDictionary;
|
|
4
|
+
type TSearchParamsDict = StandardSchemaDictionary;
|
|
5
|
+
type TBodySchema = StandardSchemaV1;
|
|
6
|
+
type TFormDataDict = StandardSchemaDictionary;
|
|
7
|
+
type RouteHandlerAuthFunctionParams<TSegments extends TSegmentsDict | undefined, TSearchParams extends TSearchParamsDict | undefined, TBody extends TBodySchema | undefined, TFormData extends TFormDataDict | undefined> = {
|
|
8
|
+
/**
|
|
9
|
+
* ID for the route handler.
|
|
10
|
+
*/
|
|
11
|
+
readonly id: string;
|
|
12
|
+
/**
|
|
13
|
+
* Parsed request url
|
|
14
|
+
*/
|
|
15
|
+
readonly url: URL;
|
|
16
|
+
/**
|
|
17
|
+
* Original request
|
|
18
|
+
*
|
|
19
|
+
* Cloned from the incoming request to avoid side effects
|
|
20
|
+
* and to make it consumable in the `authorize` function.
|
|
21
|
+
* Due to `NextRequest` limitations as the req is cloned it's always a `Request`
|
|
22
|
+
*/
|
|
23
|
+
req: Request;
|
|
24
|
+
} & (TSegments extends TSegmentsDict ? {
|
|
25
|
+
/**
|
|
26
|
+
* Validated route dynamic segments
|
|
27
|
+
*/
|
|
28
|
+
readonly segments: UnwrapReadonlyObject<StandardSchemaDictionary.InferOutput<TSegments>>;
|
|
29
|
+
} : EmptyObjectType) & (TSearchParams extends TSearchParamsDict ? {
|
|
30
|
+
/**
|
|
31
|
+
* Validated search params
|
|
32
|
+
*/
|
|
33
|
+
readonly searchParams: UnwrapReadonlyObject<StandardSchemaDictionary.InferOutput<TSearchParams>>;
|
|
34
|
+
} : EmptyObjectType) & (TBody extends TBodySchema ? {
|
|
35
|
+
/**
|
|
36
|
+
* Validated request body
|
|
37
|
+
*/
|
|
38
|
+
readonly body: StandardSchemaV1.InferOutput<TBody>;
|
|
39
|
+
} : EmptyObjectType) & (TFormData extends TFormDataDict ? {
|
|
40
|
+
/**
|
|
41
|
+
* Validated form data
|
|
42
|
+
*/
|
|
43
|
+
readonly formData: UnwrapReadonlyObject<StandardSchemaDictionary.InferOutput<TFormData>>;
|
|
44
|
+
} : EmptyObjectType);
|
|
45
|
+
type RouteHandlerAuthFunction<AC extends AuthContext | undefined, TSegments extends TSegmentsDict | undefined, TSearchParams extends TSearchParamsDict | undefined, TBody extends TBodySchema | undefined, TFormData extends TFormDataDict | undefined> = (params: RouteHandlerAuthFunctionParams<TSegments, TSearchParams, TBody, TFormData>) => Awaitable<AC | Response | never>;
|
|
46
|
+
type OnValidationErrorResponse = (issues: readonly StandardSchemaV1.Issue[]) => Awaitable<Response>;
|
|
47
|
+
type CreateSafeRouteHandlerOptions<AC extends AuthContext | undefined, TSegments extends TSegmentsDict | undefined, TSearchParams extends TSearchParamsDict | undefined, TBody extends TBodySchema | undefined, TFormData extends TFormDataDict | undefined> = {
|
|
48
|
+
/**
|
|
49
|
+
* ID for the route handler.
|
|
50
|
+
* Used when logging in development or when `debug` is enabled.
|
|
51
|
+
*
|
|
52
|
+
* You can also use it to add extra logging or monitoring.
|
|
53
|
+
*/
|
|
54
|
+
id?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Callback triggered when the request fails.
|
|
57
|
+
* By default it returns a simple `500` response and the error is logged into the console.
|
|
58
|
+
*
|
|
59
|
+
* Use it if your handler use custom errors and
|
|
60
|
+
* you want to manage them properly by returning a proper response.
|
|
61
|
+
*/
|
|
62
|
+
onErrorResponse?: (err: unknown) => Awaitable<Response>;
|
|
63
|
+
/**
|
|
64
|
+
* Use this options to enable debug mode.
|
|
65
|
+
* It will add logs in the handler to help you debug the request.
|
|
66
|
+
*
|
|
67
|
+
* By default it's set to `false` for production builds.
|
|
68
|
+
* In development builds, it will be `true` if `NODE_ENV` is not set to `production`.
|
|
69
|
+
*/
|
|
70
|
+
debug?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Dynamic route segments used for the route handler path.
|
|
73
|
+
* By design it will handler if the segments are a `Promise` or not.
|
|
74
|
+
*
|
|
75
|
+
* Please note the expected input is a `StandardSchemaDictionary`.
|
|
76
|
+
*/
|
|
77
|
+
segments?: TSegments;
|
|
78
|
+
/**
|
|
79
|
+
* Callback triggered when dynamic segments validations returned issues.
|
|
80
|
+
* By default it returns a simple `400` response and issues are logged into the console.
|
|
81
|
+
*/
|
|
82
|
+
onSegmentsValidationErrorResponse?: OnValidationErrorResponse;
|
|
83
|
+
/**
|
|
84
|
+
* Search params used in the route.
|
|
85
|
+
*
|
|
86
|
+
* Please note the expected input is a `StandardSchemaDictionary`.
|
|
87
|
+
*/
|
|
88
|
+
searchParams?: TSearchParams;
|
|
89
|
+
/**
|
|
90
|
+
* Callback triggered when search params validations returned issues.
|
|
91
|
+
* By default it returns a simple `400` response and issues are logged into the console.
|
|
92
|
+
*/
|
|
93
|
+
onSearchParamsValidationErrorResponse?: OnValidationErrorResponse;
|
|
94
|
+
/**
|
|
95
|
+
* Request body.
|
|
96
|
+
*
|
|
97
|
+
* Returns a `405` response if the request method is not `POST`, 'PUT' or 'PATCH'.
|
|
98
|
+
* Returns a `415`response if the request does not explicitly set the `Content-Type` to `application/json`.
|
|
99
|
+
*
|
|
100
|
+
* IMPORTANT: The body is parsed as JSON, so it must be a valid JSON object!
|
|
101
|
+
* IMPORTANT: Body shouldn't be used with `formData` at the same time. They are exclusive.
|
|
102
|
+
* Why making the distinction? `formData` is used as a `StandardSchemaDictionary` whereas `body` is used as a `StandardSchemaV1`.
|
|
103
|
+
*/
|
|
104
|
+
body?: TBody;
|
|
105
|
+
/**
|
|
106
|
+
* Callback triggered when body validation returned issues.
|
|
107
|
+
* By default it returns a simple `400` response and issues are logged into the console.
|
|
108
|
+
*/
|
|
109
|
+
onBodyValidationErrorResponse?: OnValidationErrorResponse;
|
|
110
|
+
/**
|
|
111
|
+
* Request form data.
|
|
112
|
+
*
|
|
113
|
+
* Returns a `405` response if the request method is not `POST`, 'PUT' or 'PATCH'.
|
|
114
|
+
* Returns a `415`response if the request does not explicitly set the `Content-Type` to `multipart/form-data`
|
|
115
|
+
* or to `application/x-www-form-urlencoded`.
|
|
116
|
+
*
|
|
117
|
+
* IMPORTANT: formData shouldn't be used with `body` at the same time. They are exclusive.
|
|
118
|
+
* Why making the distinction? `formData` is used as a `StandardSchemaDictionary` whereas `body` is used as a `StandardSchemaV1`.
|
|
119
|
+
*/
|
|
120
|
+
formData?: TFormData;
|
|
121
|
+
/**
|
|
122
|
+
* Callback triggered when form data validation returned issues.
|
|
123
|
+
* By default it returns a simple `400` response and issues are logged into the console.
|
|
124
|
+
*/
|
|
125
|
+
onFormDataValidationErrorResponse?: OnValidationErrorResponse;
|
|
126
|
+
/**
|
|
127
|
+
* Function to use to authorize the request.
|
|
128
|
+
* By default it always authorize the request.
|
|
129
|
+
*
|
|
130
|
+
* When returning a response, it will be used as the response for the request.
|
|
131
|
+
* Return a response when the request is not authorized.
|
|
132
|
+
*/
|
|
133
|
+
authorize?: RouteHandlerAuthFunction<AC, TSegments, TSearchParams, TBody, TFormData>;
|
|
134
|
+
};
|
|
135
|
+
type ProvidedRouteContext = {
|
|
136
|
+
/**
|
|
137
|
+
* Route dynamic segments as params
|
|
138
|
+
*/
|
|
139
|
+
params: Awaitable<any> | undefined;
|
|
140
|
+
};
|
|
141
|
+
type CreateSafeRouteHandlerReturnType<TReq extends Request = Request> = (
|
|
142
|
+
/**
|
|
143
|
+
* Original request
|
|
144
|
+
*/
|
|
145
|
+
req: TReq,
|
|
146
|
+
/**
|
|
147
|
+
* Provided context added by Next.js itself
|
|
148
|
+
*/
|
|
149
|
+
providedContext: ProvidedRouteContext) => Promise<Response | never>;
|
|
150
|
+
type SafeRouteHandlerContext<AC extends AuthContext | undefined, TSegments extends TSegmentsDict | undefined, TSearchParams extends TSearchParamsDict | undefined, TBody extends TBodySchema | undefined, TFormData extends TFormDataDict | undefined> = {
|
|
151
|
+
/**
|
|
152
|
+
* Route handler ID
|
|
153
|
+
*/
|
|
154
|
+
readonly id: string;
|
|
155
|
+
/**
|
|
156
|
+
* Parsed request url
|
|
157
|
+
*/
|
|
158
|
+
readonly url: URL;
|
|
159
|
+
} & (AC extends AuthContext ? {
|
|
160
|
+
/**
|
|
161
|
+
* Auth context
|
|
162
|
+
*/
|
|
163
|
+
readonly auth: AC;
|
|
164
|
+
} : EmptyObjectType) & (TSegments extends TSegmentsDict ? {
|
|
165
|
+
/**
|
|
166
|
+
* Validated route dynamic segments
|
|
167
|
+
*/
|
|
168
|
+
readonly segments: UnwrapReadonlyObject<StandardSchemaDictionary.InferOutput<TSegments>>;
|
|
169
|
+
} : EmptyObjectType) & (TSearchParams extends TSearchParamsDict ? {
|
|
170
|
+
/**
|
|
171
|
+
* Validated search params
|
|
172
|
+
*/
|
|
173
|
+
readonly searchParams: UnwrapReadonlyObject<StandardSchemaDictionary.InferOutput<TSearchParams>>;
|
|
174
|
+
} : EmptyObjectType) & (TBody extends TBodySchema ? {
|
|
175
|
+
/**
|
|
176
|
+
* Validated request body
|
|
177
|
+
*/
|
|
178
|
+
readonly body: StandardSchemaV1.InferOutput<TBody>;
|
|
179
|
+
} : EmptyObjectType) & (TFormData extends TFormDataDict ? {
|
|
180
|
+
/**
|
|
181
|
+
* Validated form data
|
|
182
|
+
*/
|
|
183
|
+
readonly formData: UnwrapReadonlyObject<StandardSchemaDictionary.InferOutput<TFormData>>;
|
|
184
|
+
} : EmptyObjectType);
|
|
185
|
+
type SafeRouteHandler<AC extends AuthContext | undefined, TSegments extends TSegmentsDict | undefined, TSearchParams extends TSearchParamsDict | undefined, TBody extends TBodySchema | undefined, TFormData extends TFormDataDict | undefined, TReq extends Request = Request> = (
|
|
186
|
+
/**
|
|
187
|
+
* Safe route handler context
|
|
188
|
+
*/
|
|
189
|
+
ctx: SafeRouteHandlerContext<AC, TSegments, TSearchParams, TBody, TFormData>,
|
|
190
|
+
/**
|
|
191
|
+
* Original request
|
|
192
|
+
*/
|
|
193
|
+
req: TReq) => Promise<Response | never>;
|
|
3
194
|
|
|
4
195
|
/**
|
|
5
196
|
* Creates a safe route handler with data validation and error handling
|
|
@@ -13,7 +204,7 @@ export { e as AuthFunction, f as AuthFunctionParams, g as Awaitable, B as BaseOp
|
|
|
13
204
|
* @example
|
|
14
205
|
* ```ts
|
|
15
206
|
* import { string } from 'decoders'
|
|
16
|
-
*import { createSafeRouteHandler } from '@sugardarius/anzen'
|
|
207
|
+
* import { createSafeRouteHandler } from '@sugardarius/anzen'
|
|
17
208
|
* import { auth } from '~/lib/auth'
|
|
18
209
|
*
|
|
19
210
|
* export const GET = createSafeRouteHandler(
|
|
@@ -39,4 +230,263 @@ export { e as AuthFunction, f as AuthFunctionParams, g as Awaitable, B as BaseOp
|
|
|
39
230
|
*/
|
|
40
231
|
declare function createSafeRouteHandler<AC extends AuthContext | undefined = undefined, TRouteDynamicSegments extends TSegmentsDict | undefined = undefined, TSearchParams extends TSearchParamsDict | undefined = undefined, TBody extends TBodySchema | undefined = undefined, TFormData extends TFormDataDict | undefined = undefined, TReq extends Request = Request>(options: CreateSafeRouteHandlerOptions<AC, TRouteDynamicSegments, TSearchParams, TBody, TFormData>, handlerFn: SafeRouteHandler<AC, TRouteDynamicSegments, TSearchParams, TBody, TFormData, TReq>): CreateSafeRouteHandlerReturnType<TReq>;
|
|
41
232
|
|
|
42
|
-
|
|
233
|
+
type TInputSchema = StandardSchemaV1;
|
|
234
|
+
type ServerActionErrorContext = Record<string, unknown>;
|
|
235
|
+
/**
|
|
236
|
+
* Generic server error.
|
|
237
|
+
* Triggered when server action handler throws an unexpected error.
|
|
238
|
+
*
|
|
239
|
+
* Context `ctx` is used to store the error context.
|
|
240
|
+
* It can be customized by using the `onError` option when creating the server action.
|
|
241
|
+
*/
|
|
242
|
+
type ServerError = {
|
|
243
|
+
readonly code: 'SERVER_ERROR';
|
|
244
|
+
readonly ctx: ServerActionErrorContext;
|
|
245
|
+
};
|
|
246
|
+
/**
|
|
247
|
+
* Unauthorized error.
|
|
248
|
+
* Triggered when server action is not authorized by the `authorize` function
|
|
249
|
+
* 👉🏻 When `authorize` function throws an error.
|
|
250
|
+
*
|
|
251
|
+
*
|
|
252
|
+
* Context `ctx` is used to store the error context.
|
|
253
|
+
* It can be customized by using the `onError` option when creating the server action.
|
|
254
|
+
*/
|
|
255
|
+
type UnauthorizedError = {
|
|
256
|
+
readonly code: 'UNAUTHORIZED_ERROR';
|
|
257
|
+
readonly ctx: ServerActionErrorContext;
|
|
258
|
+
};
|
|
259
|
+
/**
|
|
260
|
+
* Validation error.
|
|
261
|
+
* Triggered when server action input validation returns issues.
|
|
262
|
+
*
|
|
263
|
+
* Context `ctx` is used to store the error context.
|
|
264
|
+
* It can be customized by using the `onInputValidationError` option when creating the server action.
|
|
265
|
+
*
|
|
266
|
+
* By default this error will return the issues `StandardSchemaV1.Issue[]` in the context when
|
|
267
|
+
* no context customization is provided.
|
|
268
|
+
*/
|
|
269
|
+
type ValidationError = {
|
|
270
|
+
readonly code: 'VALIDATION_ERROR';
|
|
271
|
+
readonly ctx: ServerActionErrorContext;
|
|
272
|
+
};
|
|
273
|
+
/**
|
|
274
|
+
* Tagged error.
|
|
275
|
+
* It represents an error expected to be used in the server action
|
|
276
|
+
* defined by developers themselves.
|
|
277
|
+
*/
|
|
278
|
+
type TaggedError = {
|
|
279
|
+
readonly code: string;
|
|
280
|
+
readonly ctx: ServerActionErrorContext;
|
|
281
|
+
};
|
|
282
|
+
type SafeServerActionError = ValidationError | UnauthorizedError | ServerError | TaggedError;
|
|
283
|
+
type SafeServerActionResultSuccess<TOutput> = {
|
|
284
|
+
readonly success: true;
|
|
285
|
+
readonly output: TOutput;
|
|
286
|
+
readonly error?: never;
|
|
287
|
+
};
|
|
288
|
+
type SafeServerActionResultError<TError> = {
|
|
289
|
+
readonly success: false;
|
|
290
|
+
readonly output?: never;
|
|
291
|
+
readonly error: TError;
|
|
292
|
+
};
|
|
293
|
+
type ServerActionAuthFunctionParams<TInput extends TInputSchema | undefined> = {
|
|
294
|
+
/**
|
|
295
|
+
* Server action ID
|
|
296
|
+
*/
|
|
297
|
+
readonly id: string;
|
|
298
|
+
} & (TInput extends TInputSchema ? {
|
|
299
|
+
/**
|
|
300
|
+
* Validated input
|
|
301
|
+
*/
|
|
302
|
+
readonly input: UnwrapReadonlyObject<StandardSchemaV1.InferOutput<TInput>>;
|
|
303
|
+
} : EmptyObjectType);
|
|
304
|
+
type ServerActionAuthFunction<AC extends AuthContext | undefined, TInput extends TInputSchema | undefined> = (
|
|
305
|
+
/**
|
|
306
|
+
* Auth function parameters
|
|
307
|
+
* Contains the server action ID and the validated input.
|
|
308
|
+
*
|
|
309
|
+
* If the input is not provided, the property do not exists.
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```ts
|
|
313
|
+
* authorize: async ({ id, input }) => {
|
|
314
|
+
* const auth = await getAuth()
|
|
315
|
+
* if (!auth) {
|
|
316
|
+
* throw new UnauthenticatedError()
|
|
317
|
+
* }
|
|
318
|
+
*
|
|
319
|
+
* const hasAccess = await checkAccess({
|
|
320
|
+
* userId: auth.user.id,
|
|
321
|
+
* resourceId: input.resourceId,
|
|
322
|
+
* })
|
|
323
|
+
*
|
|
324
|
+
* if (!hasAccess) {
|
|
325
|
+
* throw new ForbiddenError()
|
|
326
|
+
* }
|
|
327
|
+
*
|
|
328
|
+
* return { user: auth.user }
|
|
329
|
+
* }
|
|
330
|
+
* ```
|
|
331
|
+
*/
|
|
332
|
+
params: ServerActionAuthFunctionParams<TInput>) => Awaitable<AC | never>;
|
|
333
|
+
type OnError = (err: unknown) => Awaitable<ServerActionErrorContext>;
|
|
334
|
+
type OnInputValidationError = (issues: readonly StandardSchemaV1.Issue[]) => Awaitable<ServerActionErrorContext>;
|
|
335
|
+
type CreateSafeServerActionOptions<TInput extends TInputSchema | undefined, AC extends AuthContext | undefined> = {
|
|
336
|
+
/**
|
|
337
|
+
* ID for the server action.
|
|
338
|
+
* Used when logging in development or when `debug` is enabled.
|
|
339
|
+
*
|
|
340
|
+
* You can also use it to add extra logging or monitoring.
|
|
341
|
+
*/
|
|
342
|
+
id?: string;
|
|
343
|
+
/**
|
|
344
|
+
* Use this options to enable debug mode.
|
|
345
|
+
* It will add logs in the handler to help you debug server action.
|
|
346
|
+
*
|
|
347
|
+
* By default it's set to `false` for production builds.
|
|
348
|
+
* In development builds, it will be `true` if `NODE_ENV` is not set to `production`.
|
|
349
|
+
*/
|
|
350
|
+
debug?: boolean;
|
|
351
|
+
/**
|
|
352
|
+
* Callback triggered when the server action throws an unhandled error.
|
|
353
|
+
* By default it will return an error context object and the error is logged into the console.
|
|
354
|
+
*
|
|
355
|
+
* Use it if you want to manage unexpected errors properly
|
|
356
|
+
* to log or trace and define custom error contexts objects.
|
|
357
|
+
*
|
|
358
|
+
* ⚠️ By design, this callback isn't mean to be used to manage navigation behaviors like using `notFound` or `redirect`,
|
|
359
|
+
* or with `throw` statements as it's best to handle them in the UI. ⚠️
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```ts
|
|
363
|
+
* // ✅ Valid use case
|
|
364
|
+
* onError: async (err: unknown) => {
|
|
365
|
+
* log.error(`🛑 Unexpected error in server action '${id}'`, err)
|
|
366
|
+
* if (err instanceof NotFoundError) {
|
|
367
|
+
* return {
|
|
368
|
+
* message: 'Resource not found',
|
|
369
|
+
* }
|
|
370
|
+
* }
|
|
371
|
+
*
|
|
372
|
+
* return {
|
|
373
|
+
* message: 'An unexpected error occurred',
|
|
374
|
+
* err: JSON.stringify(err),
|
|
375
|
+
* }
|
|
376
|
+
* }
|
|
377
|
+
*
|
|
378
|
+
* // ❌ Invalid use case
|
|
379
|
+
* onError: async (err: unknown) => {
|
|
380
|
+
* throw err
|
|
381
|
+
* // or redirect('/')
|
|
382
|
+
* }
|
|
383
|
+
*/
|
|
384
|
+
onError?: OnError;
|
|
385
|
+
/**
|
|
386
|
+
* Server action input schema used to validate the input
|
|
387
|
+
* when calling the server action.
|
|
388
|
+
*
|
|
389
|
+
* Please note the expected input is a `StandardSchemaV1`.
|
|
390
|
+
*/
|
|
391
|
+
input?: TInput;
|
|
392
|
+
/**
|
|
393
|
+
* Callback triggered when input validation returned issues
|
|
394
|
+
* By default it will return an error context object and the error is logged into the console.
|
|
395
|
+
*
|
|
396
|
+
* Use it if you want to manage input validation errors properly
|
|
397
|
+
* to log or trace and define custom error contexts objects.
|
|
398
|
+
*
|
|
399
|
+
* ⚠️ By design, this callback isn't mean to be used to manage navigation behaviors like using `notFound` or `redirect`,
|
|
400
|
+
* or with `throw` statements as it's best to handle them in the UI. ⚠️
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* ```ts
|
|
404
|
+
* // ✅ Valid use case
|
|
405
|
+
* onInputValidationError: async (issues: readonly StandardSchemaV1.Issue[]) => {
|
|
406
|
+
* log.error(`🛑 Invalid input for server action '${id}'`, issues)
|
|
407
|
+
* return {
|
|
408
|
+
* message: 'Invalid input',
|
|
409
|
+
* issues,
|
|
410
|
+
* }
|
|
411
|
+
* }
|
|
412
|
+
*
|
|
413
|
+
* // ❌ Invalid use case
|
|
414
|
+
* onInputValidationError: async (issues: readonly StandardSchemaV1.Issue[]) => {
|
|
415
|
+
* throw new Error('Invalid input')
|
|
416
|
+
* }
|
|
417
|
+
* ```
|
|
418
|
+
*/
|
|
419
|
+
onInputValidationError?: OnInputValidationError;
|
|
420
|
+
/**
|
|
421
|
+
* Function to use to authorize the server action.
|
|
422
|
+
* By default it always authorize the server action.
|
|
423
|
+
*
|
|
424
|
+
* Returns an unauthorized error when the server action is not authorized
|
|
425
|
+
* or never when `redirect`, `notFound`, `forbidden` or `unauthorized` are thrown.
|
|
426
|
+
*/
|
|
427
|
+
authorize?: ServerActionAuthFunction<AC, TInput>;
|
|
428
|
+
};
|
|
429
|
+
type SafeServerActionResult<TOutput, TError> = SafeServerActionResultSuccess<TOutput> | SafeServerActionResultError<TError> | never;
|
|
430
|
+
type InferServerActionProvidedInput<TInput extends TInputSchema | undefined> = TInput extends TInputSchema ? FormData | StandardSchemaV1.InferOutput<TInput> : undefined;
|
|
431
|
+
type CreateSafeServerActionReturnType<TInput extends TInputSchema | undefined, TOutput, TError> = [TInput] extends [TInputSchema] ? (providedInput: InferServerActionProvidedInput<TInput>) => Promise<SafeServerActionResult<TOutput, TError>> : (providedInput?: InferServerActionProvidedInput<TInput>) => Promise<SafeServerActionResult<TOutput, TError>>;
|
|
432
|
+
type SafeServerActionContext<TInput extends TInputSchema | undefined, AC extends AuthContext | undefined> = {
|
|
433
|
+
/**
|
|
434
|
+
* Server action ID
|
|
435
|
+
*/
|
|
436
|
+
readonly id: string;
|
|
437
|
+
/**
|
|
438
|
+
* Tag error function
|
|
439
|
+
* Throws a developer defined tagged error.
|
|
440
|
+
* @example
|
|
441
|
+
* ```ts
|
|
442
|
+
* // Server
|
|
443
|
+
* export const myAction = createSafeServerAction({
|
|
444
|
+
* id: 'my action,
|
|
445
|
+
* }, async ({ tagErr }) => {
|
|
446
|
+
* tagErr('CONFLICT', {
|
|
447
|
+
* message: 'resource already exists',
|
|
448
|
+
* })
|
|
449
|
+
* })
|
|
450
|
+
*
|
|
451
|
+
* // Client
|
|
452
|
+
* const result = await myAction()
|
|
453
|
+
* if (result.success === false) {
|
|
454
|
+
* if (result.error.code === 'CONFLICT') {
|
|
455
|
+
* return <span>{result.error.ctx.message}</span>
|
|
456
|
+
* }
|
|
457
|
+
* }
|
|
458
|
+
* ```
|
|
459
|
+
*/
|
|
460
|
+
readonly tagErr: (code: string, ctx: ServerActionErrorContext) => never;
|
|
461
|
+
} & (AC extends AuthContext ? {
|
|
462
|
+
/**
|
|
463
|
+
* Auth context
|
|
464
|
+
*/
|
|
465
|
+
readonly auth: AC;
|
|
466
|
+
} : EmptyObjectType) & (TInput extends TInputSchema ? {
|
|
467
|
+
/**
|
|
468
|
+
* Validated input
|
|
469
|
+
*/
|
|
470
|
+
readonly input: UnwrapReadonlyObject<StandardSchemaV1.InferOutput<TInput>>;
|
|
471
|
+
} : EmptyObjectType);
|
|
472
|
+
type SafeServerActionHandler<TOutput, TInput extends TInputSchema | undefined, AC extends AuthContext | undefined> = (
|
|
473
|
+
/**
|
|
474
|
+
* Safe server action context
|
|
475
|
+
*/
|
|
476
|
+
ctx: SafeServerActionContext<TInput, AC>) => Promise<TOutput | never>;
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Overload for server actions with no input.
|
|
480
|
+
* Used when calling server actions with no input schema provided,
|
|
481
|
+
* making the DX for developers easier and nicer. It avoids to call
|
|
482
|
+
* a server action with `undefined` as input.
|
|
483
|
+
*/
|
|
484
|
+
declare function createSafeServerAction<TOutput, AC extends AuthContext | undefined = undefined>(options: CreateSafeServerActionOptions<undefined, AC>, handler: SafeServerActionHandler<TOutput, undefined, AC>): CreateSafeServerActionReturnType<undefined, TOutput, SafeServerActionError>;
|
|
485
|
+
/**
|
|
486
|
+
* Overload for server actions with input.
|
|
487
|
+
*/
|
|
488
|
+
declare function createSafeServerAction<TOutput, TInput extends TInputSchema, AC extends AuthContext | undefined = undefined>(options: CreateSafeServerActionOptions<TInput, AC> & {
|
|
489
|
+
input: TInput;
|
|
490
|
+
}, handler: SafeServerActionHandler<TOutput, TInput, AC>): CreateSafeServerActionReturnType<TInput, TOutput, SafeServerActionError>;
|
|
491
|
+
|
|
492
|
+
export { AuthContext, Awaitable, type CreateSafeRouteHandlerOptions, type CreateSafeRouteHandlerReturnType, type CreateSafeServerActionOptions, type CreateSafeServerActionReturnType, type InferServerActionProvidedInput, type OnValidationErrorResponse, type ProvidedRouteContext, type RouteHandlerAuthFunction, type RouteHandlerAuthFunctionParams, type SafeRouteHandler, type SafeRouteHandlerContext, type SafeServerActionContext, type SafeServerActionError, type SafeServerActionHandler, type SafeServerActionResult, type SafeServerActionResultError, type SafeServerActionResultSuccess, type ServerActionAuthFunction, type ServerActionAuthFunctionParams, type ServerActionErrorContext, type ServerError, type TBodySchema, type TFormDataDict, type TSearchParamsDict, type TSegmentsDict, type UnauthorizedError, type ValidationError, createSafeRouteHandler, createSafeServerAction };
|