next-action-forge 0.2.2 → 0.2.3
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/dist/core/index.js +12 -7
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +12 -7
- package/dist/core/index.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +12 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +12 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/core/index.js
CHANGED
|
@@ -179,11 +179,12 @@ _args = new WeakMap();
|
|
|
179
179
|
var ServerActionClient = _ServerActionClient;
|
|
180
180
|
function createServerAction(config) {
|
|
181
181
|
const actionFn = async (...args) => {
|
|
182
|
-
const input = args[0];
|
|
183
182
|
const context = {};
|
|
183
|
+
const hasInputSchema = config.inputSchema !== void 0 && config.inputSchema !== null;
|
|
184
|
+
const input = hasInputSchema ? args[0] : void 0;
|
|
184
185
|
try {
|
|
185
|
-
let parsedInput =
|
|
186
|
-
if (config.inputSchema) {
|
|
186
|
+
let parsedInput = void 0;
|
|
187
|
+
if (hasInputSchema && config.inputSchema) {
|
|
187
188
|
const parseResult = config.inputSchema.safeParse(input);
|
|
188
189
|
if (!parseResult.success) {
|
|
189
190
|
return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError(err, { parsedInput: input }) : void 0);
|
|
@@ -193,7 +194,8 @@ function createServerAction(config) {
|
|
|
193
194
|
}
|
|
194
195
|
let middlewareContext = {};
|
|
195
196
|
for (const middleware of config.middlewareFns) {
|
|
196
|
-
const
|
|
197
|
+
const middlewareInput = hasInputSchema ? parsedInput : void 0;
|
|
198
|
+
const result2 = await middleware({ context: middlewareContext, input: middlewareInput });
|
|
197
199
|
if ("error" in result2) {
|
|
198
200
|
return {
|
|
199
201
|
success: false,
|
|
@@ -202,7 +204,7 @@ function createServerAction(config) {
|
|
|
202
204
|
}
|
|
203
205
|
middlewareContext = { ...middlewareContext, ...result2.context };
|
|
204
206
|
}
|
|
205
|
-
const result = await config.serverCodeFn(parsedInput, middlewareContext);
|
|
207
|
+
const result = hasInputSchema ? await config.serverCodeFn(parsedInput, middlewareContext) : await config.serverCodeFn(middlewareContext);
|
|
206
208
|
let validatedOutput = result;
|
|
207
209
|
if (config.outputSchema) {
|
|
208
210
|
const parseResult = config.outputSchema.safeParse(result);
|
|
@@ -228,6 +230,7 @@ function createServerAction(config) {
|
|
|
228
230
|
return handleServerActionError(error, errorHandler);
|
|
229
231
|
}
|
|
230
232
|
};
|
|
233
|
+
actionFn.__hasInputSchema = config.inputSchema !== void 0 && config.inputSchema !== null;
|
|
231
234
|
return actionFn;
|
|
232
235
|
}
|
|
233
236
|
function parseFormData(formData) {
|
|
@@ -252,6 +255,7 @@ function parseFormData(formData) {
|
|
|
252
255
|
function createFormServerAction(config) {
|
|
253
256
|
return async (_prev, formData) => {
|
|
254
257
|
const context = {};
|
|
258
|
+
const hasInputSchema = config.inputSchema !== void 0 && config.inputSchema !== null;
|
|
255
259
|
try {
|
|
256
260
|
let parsedInput = parseFormData(formData);
|
|
257
261
|
if (config.inputSchema) {
|
|
@@ -264,7 +268,8 @@ function createFormServerAction(config) {
|
|
|
264
268
|
}
|
|
265
269
|
let middlewareContext = {};
|
|
266
270
|
for (const middleware of config.middlewareFns) {
|
|
267
|
-
const
|
|
271
|
+
const middlewareInput = hasInputSchema ? parsedInput : void 0;
|
|
272
|
+
const result2 = await middleware({ context: middlewareContext, input: middlewareInput });
|
|
268
273
|
if ("error" in result2) {
|
|
269
274
|
return {
|
|
270
275
|
success: false,
|
|
@@ -273,7 +278,7 @@ function createFormServerAction(config) {
|
|
|
273
278
|
}
|
|
274
279
|
middlewareContext = { ...middlewareContext, ...result2.context };
|
|
275
280
|
}
|
|
276
|
-
const result = await config.serverCodeFn(parsedInput, middlewareContext);
|
|
281
|
+
const result = hasInputSchema ? await config.serverCodeFn(parsedInput, middlewareContext) : await config.serverCodeFn(middlewareContext);
|
|
277
282
|
let validatedOutput = result;
|
|
278
283
|
if (config.outputSchema) {
|
|
279
284
|
const parseResult = config.outputSchema.safeParse(result);
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/index.ts","../../src/core/error-handler.ts","../../src/core/server-action-client.ts"],"sourcesContent":["export * from \"./error-handler\";\nexport * from \"./server-action-client\";","import { z, ZodError } from \"zod\";\nimport type { ServerActionError, ServerActionResponse } from \"../types\";\n\nfunction convertZodError(error: ZodError): ServerActionError {\n const { fieldErrors, formErrors } = z.flattenError(error);\n const [field] = Object.keys(fieldErrors) as (keyof typeof fieldErrors)[];\n const message = (field && fieldErrors[field]?.[0]) ?? formErrors[0] ?? \"Validation failed\";\n return {\n message,\n code: \"VALIDATION_ERROR\",\n field,\n fields: fieldErrors,\n };\n}\n\nfunction convertGenericError(error: unknown): ServerActionError {\n const message = error instanceof Error ? error.message : \"An unexpected error occurred\";\n\n return {\n message: process.env.NODE_ENV === \"production\" ? \"An unexpected error occurred\" : message,\n code: \"INTERNAL_ERROR\",\n statusCode: 500,\n };\n}\n\nexport function handleServerActionError(\n error: unknown,\n customHandler?: (error: unknown) => ServerActionError | undefined\n): { success: false; error: ServerActionError } {\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.error(\"[Server Action Error]\", error?.constructor?.name || 'Unknown', error instanceof Error ? error.message : error);\n }\n\n // Try custom handler first\n if (customHandler) {\n try {\n const customError = customHandler(error);\n if (customError) {\n return {\n success: false,\n error: customError,\n };\n }\n } catch (handlerError) {\n console.error(\"[Server Action Error] Custom handler threw an error:\", handlerError);\n }\n }\n\n if (error instanceof ZodError) {\n return {\n success: false,\n error: convertZodError(error),\n };\n }\n\n if (error instanceof Error && \"toServerActionError\" in error && typeof error.toServerActionError === \"function\") {\n const serverError = error.toServerActionError() as ServerActionError;\n \n // Check if this is an auth error based on the error type/code\n if (serverError.code === \"AUTHENTICATION_ERROR\" || (error as any).type === \"AUTHENTICATION_ERROR\") {\n serverError.shouldRedirect = true;\n serverError.redirectTo = \"/login\";\n }\n \n return {\n success: false,\n error: serverError,\n };\n }\n\n return {\n success: false,\n error: convertGenericError(error),\n };\n}\n\nexport function isErrorResponse<T>(response: ServerActionResponse<T>): response is { success: false; error: ServerActionError } {\n return !response.success;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\n\ntype InferZodOutput<T> = T extends z.ZodTypeAny ? z.output<T> : never;\ntype InferZodInput<T> = T extends z.ZodTypeAny ? z.input<T> : never;\n\ntype ServerActionMiddleware<Context> = (params: { context: Context; input: unknown }) => Promise<{ context: Context } | { error: ServerActionError }>;\n\ntype SafeActionClientArgs<Context extends object, InputSchema extends z.ZodTypeAny | undefined, OutputSchema extends z.ZodTypeAny | undefined> = {\n middlewareFns: ServerActionMiddleware<any>[];\n inputSchema?: InputSchema;\n outputSchema?: OutputSchema;\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n ctxType?: Context;\n};\n\nexport class ServerActionClient<Context extends object = {}, InputSchema extends z.ZodTypeAny | undefined = undefined, OutputSchema extends z.ZodTypeAny | undefined = undefined> {\n readonly #args: SafeActionClientArgs<Context, InputSchema, OutputSchema>;\n\n constructor(\n args: SafeActionClientArgs<Context, InputSchema, OutputSchema> = {\n middlewareFns: [],\n }\n ) {\n this.#args = args;\n }\n\n /**\n * Use a middleware function.\n * @param middlewareFn Middleware function\n */\n use<NextContext extends object>(middlewareFn: ServerActionMiddleware<Context & NextContext>) {\n return new ServerActionClient<Context & NextContext, InputSchema, OutputSchema>({\n ...this.#args,\n middlewareFns: [...this.#args.middlewareFns, middlewareFn] as any,\n ctxType: {} as Context & NextContext,\n });\n }\n\n /**\n * Define the input validation schema for the action.\n * @param schema Input validation schema\n */\n inputSchema<IS extends z.ZodTypeAny>(schema: IS) {\n return new ServerActionClient<Context, IS, OutputSchema>({\n ...this.#args,\n inputSchema: schema,\n });\n }\n\n /**\n * Define the output validation schema for the action.\n * @param schema Output validation schema\n */\n outputSchema<OS extends z.ZodTypeAny>(schema: OS) {\n return new ServerActionClient<Context, InputSchema, OS>({\n ...this.#args,\n outputSchema: schema,\n });\n }\n\n /**\n * Define a custom error handler for the action.\n * @param handler Error handler function\n */\n onError(handler: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n onError: handler,\n });\n }\n\n /**\n * Define the action.\n * @param serverCodeFn Code that will be executed on the server side\n */\n action<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (input: void, context: Context) => Promise<Data>\n ): ServerAction<InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void, OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data> {\n return createServerAction<\n InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void,\n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n >({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn: serverCodeFn as any,\n });\n }\n\n /**\n * Define a form action that accepts FormData.\n * @param serverCodeFn Code that will be executed on the server side\n */\n formAction<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (input: void, context: Context) => Promise<Data>\n ): (prev: ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>, formData: FormData) => Promise<ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>> {\n return createFormServerAction({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn,\n });\n }\n}\n\n// Internal function to create the actual server action\nfunction createServerAction<TInput, TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (parsedInput: any, context: any) => Promise<any>;\n}): ServerAction<TInput, TOutput> {\n const actionFn = async (...args: TInput extends void ? [] : [input: TInput]): Promise<ServerActionResponse<TOutput>> => {\n const input = args[0] as TInput;\n const context: { parsedInput?: unknown } = {};\n\n try {\n let parsedInput: any = input;\n\n // Input validation\n if (config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(input);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput: input }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const result = await middleware({ context: middlewareContext, input: parsedInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = await config.serverCodeFn(parsedInput, middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n \n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[executeAction] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n \n // Use the handleServerActionError function with custom handler\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n \n return handleServerActionError(error, errorHandler);\n }\n };\n\n // Return the function with correct typing based on whether input is void\n return actionFn as ServerAction<TInput, TOutput>;\n}\n\n// Form data parser\nfunction parseFormData(formData: FormData): Record<string, any> {\n const result: Record<string, any> = {};\n const keys = new Set<string>();\n\n for (const [key] of formData.entries()) {\n keys.add(key);\n }\n\n for (const key of keys) {\n const values = formData.getAll(key);\n\n if (key.endsWith(\"[]\")) {\n const cleanKey = key.slice(0, -2);\n result[cleanKey] = values;\n } else if (values.length === 1) {\n result[key] = values[0];\n } else {\n result[key] = values;\n }\n }\n\n return result;\n}\n\n// Internal function to create form server action\nfunction createFormServerAction<TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (parsedInput: any, context: any) => Promise<any>;\n}): (prev: ServerActionResponse<TOutput>, formData: FormData) => Promise<ServerActionResponse<TOutput>> {\n return async (_prev: ServerActionResponse<TOutput>, formData: FormData): Promise<ServerActionResponse<TOutput>> => {\n const context: { parsedInput?: unknown } = {};\n\n try {\n let parsedInput: any = parseFormData(formData);\n\n // Input validation\n if (config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(parsedInput);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const result = await middleware({ context: middlewareContext, input: parsedInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = await config.serverCodeFn(parsedInput, middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[ServerActionClient] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n return handleServerActionError(error, errorHandler);\n }\n };\n}\n\n// Export factory function for creating a new client\nexport function createActionClient() {\n return new ServerActionClient();\n}\n"],"mappings":"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","names":["result"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/index.ts","../../src/core/error-handler.ts","../../src/core/server-action-client.ts"],"sourcesContent":["export * from \"./error-handler\";\nexport * from \"./server-action-client\";","import { z, ZodError } from \"zod\";\nimport type { ServerActionError, ServerActionResponse } from \"../types\";\n\nfunction convertZodError(error: ZodError): ServerActionError {\n const { fieldErrors, formErrors } = z.flattenError(error);\n const [field] = Object.keys(fieldErrors) as (keyof typeof fieldErrors)[];\n const message = (field && fieldErrors[field]?.[0]) ?? formErrors[0] ?? \"Validation failed\";\n return {\n message,\n code: \"VALIDATION_ERROR\",\n field,\n fields: fieldErrors,\n };\n}\n\nfunction convertGenericError(error: unknown): ServerActionError {\n const message = error instanceof Error ? error.message : \"An unexpected error occurred\";\n\n return {\n message: process.env.NODE_ENV === \"production\" ? \"An unexpected error occurred\" : message,\n code: \"INTERNAL_ERROR\",\n statusCode: 500,\n };\n}\n\nexport function handleServerActionError(\n error: unknown,\n customHandler?: (error: unknown) => ServerActionError | undefined\n): { success: false; error: ServerActionError } {\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.error(\"[Server Action Error]\", error?.constructor?.name || 'Unknown', error instanceof Error ? error.message : error);\n }\n\n // Try custom handler first\n if (customHandler) {\n try {\n const customError = customHandler(error);\n if (customError) {\n return {\n success: false,\n error: customError,\n };\n }\n } catch (handlerError) {\n console.error(\"[Server Action Error] Custom handler threw an error:\", handlerError);\n }\n }\n\n if (error instanceof ZodError) {\n return {\n success: false,\n error: convertZodError(error),\n };\n }\n\n if (error instanceof Error && \"toServerActionError\" in error && typeof error.toServerActionError === \"function\") {\n const serverError = error.toServerActionError() as ServerActionError;\n \n // Check if this is an auth error based on the error type/code\n if (serverError.code === \"AUTHENTICATION_ERROR\" || (error as any).type === \"AUTHENTICATION_ERROR\") {\n serverError.shouldRedirect = true;\n serverError.redirectTo = \"/login\";\n }\n \n return {\n success: false,\n error: serverError,\n };\n }\n\n return {\n success: false,\n error: convertGenericError(error),\n };\n}\n\nexport function isErrorResponse<T>(response: ServerActionResponse<T>): response is { success: false; error: ServerActionError } {\n return !response.success;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\n\ntype InferZodOutput<T> = T extends z.ZodTypeAny ? z.output<T> : never;\ntype InferZodInput<T> = T extends z.ZodTypeAny ? z.input<T> : never;\n\ntype ServerActionMiddleware<Context> = (params: { context: Context; input: unknown }) => Promise<{ context: Context } | { error: ServerActionError }>;\n\ntype SafeActionClientArgs<Context extends object, InputSchema extends z.ZodTypeAny | undefined, OutputSchema extends z.ZodTypeAny | undefined> = {\n middlewareFns: ServerActionMiddleware<any>[];\n inputSchema?: InputSchema;\n outputSchema?: OutputSchema;\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n ctxType?: Context;\n};\n\nexport class ServerActionClient<Context extends object = {}, InputSchema extends z.ZodTypeAny | undefined = undefined, OutputSchema extends z.ZodTypeAny | undefined = undefined> {\n readonly #args: SafeActionClientArgs<Context, InputSchema, OutputSchema>;\n\n constructor(\n args: SafeActionClientArgs<Context, InputSchema, OutputSchema> = {\n middlewareFns: [],\n }\n ) {\n this.#args = args;\n }\n\n /**\n * Use a middleware function.\n * @param middlewareFn Middleware function\n */\n use<NextContext extends object>(middlewareFn: ServerActionMiddleware<Context & NextContext>) {\n return new ServerActionClient<Context & NextContext, InputSchema, OutputSchema>({\n ...this.#args,\n middlewareFns: [...this.#args.middlewareFns, middlewareFn] as any,\n ctxType: {} as Context & NextContext,\n });\n }\n\n /**\n * Define the input validation schema for the action.\n * @param schema Input validation schema\n */\n inputSchema<IS extends z.ZodTypeAny>(schema: IS) {\n return new ServerActionClient<Context, IS, OutputSchema>({\n ...this.#args,\n inputSchema: schema,\n });\n }\n\n /**\n * Define the output validation schema for the action.\n * @param schema Output validation schema\n */\n outputSchema<OS extends z.ZodTypeAny>(schema: OS) {\n return new ServerActionClient<Context, InputSchema, OS>({\n ...this.#args,\n outputSchema: schema,\n });\n }\n\n /**\n * Define a custom error handler for the action.\n * @param handler Error handler function\n */\n onError(handler: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n onError: handler,\n });\n }\n\n /**\n * Define the action.\n * @param serverCodeFn Code that will be executed on the server side\n */\n action<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): ServerAction<InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void, OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data> {\n return createServerAction<\n InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void,\n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n >({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn: serverCodeFn as any,\n });\n }\n\n /**\n * Define a form action that accepts FormData.\n * @param serverCodeFn Code that will be executed on the server side\n */\n formAction<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): (prev: ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>, formData: FormData) => Promise<ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>> {\n return createFormServerAction({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn,\n });\n }\n}\n\n// Internal function to create the actual server action\nfunction createServerAction<TInput, TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (...args: any[]) => Promise<any>;\n}): ServerAction<TInput, TOutput> {\n const actionFn = async (...args: TInput extends void ? [] : [input: TInput]): Promise<ServerActionResponse<TOutput>> => {\n const context: { parsedInput?: unknown } = {};\n \n // Type guard: check if we have an input schema\n const hasInputSchema = config.inputSchema !== undefined && config.inputSchema !== null;\n const input = hasInputSchema ? args[0] as TInput : undefined;\n\n try {\n let parsedInput: any = undefined;\n\n // Input validation\n if (hasInputSchema && config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(input);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput: input }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const middlewareInput = hasInputSchema ? parsedInput : undefined;\n const result = await middleware({ context: middlewareContext, input: middlewareInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = hasInputSchema \n ? await config.serverCodeFn(parsedInput, middlewareContext)\n : await config.serverCodeFn(middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n \n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[executeAction] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n \n // Use the handleServerActionError function with custom handler\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n \n return handleServerActionError(error, errorHandler);\n }\n };\n\n // Add metadata for runtime type checking\n (actionFn as any).__hasInputSchema = config.inputSchema !== undefined && config.inputSchema !== null;\n \n // Return the function with correct typing based on whether input is void\n return actionFn as ServerAction<TInput, TOutput>;\n}\n\n// Form data parser\nfunction parseFormData(formData: FormData): Record<string, any> {\n const result: Record<string, any> = {};\n const keys = new Set<string>();\n\n for (const [key] of formData.entries()) {\n keys.add(key);\n }\n\n for (const key of keys) {\n const values = formData.getAll(key);\n\n if (key.endsWith(\"[]\")) {\n const cleanKey = key.slice(0, -2);\n result[cleanKey] = values;\n } else if (values.length === 1) {\n result[key] = values[0];\n } else {\n result[key] = values;\n }\n }\n\n return result;\n}\n\n// Internal function to create form server action\nfunction createFormServerAction<TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (...args: any[]) => Promise<any>;\n}): (prev: ServerActionResponse<TOutput>, formData: FormData) => Promise<ServerActionResponse<TOutput>> {\n return async (_prev: ServerActionResponse<TOutput>, formData: FormData): Promise<ServerActionResponse<TOutput>> => {\n const context: { parsedInput?: unknown } = {};\n const hasInputSchema = config.inputSchema !== undefined && config.inputSchema !== null;\n\n try {\n let parsedInput: any = parseFormData(formData);\n\n // Input validation\n if (config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(parsedInput);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const middlewareInput = hasInputSchema ? parsedInput : undefined;\n const result = await middleware({ context: middlewareContext, input: middlewareInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = hasInputSchema \n ? await config.serverCodeFn(parsedInput, middlewareContext)\n : await config.serverCodeFn(middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[ServerActionClient] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n return handleServerActionError(error, errorHandler);\n }\n };\n}\n\n// Export factory function for creating a new client\nexport function createActionClient() {\n return new ServerActionClient();\n}\n"],"mappings":"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","names":["result"]}
|
package/dist/core/index.mjs
CHANGED
|
@@ -151,11 +151,12 @@ _args = new WeakMap();
|
|
|
151
151
|
var ServerActionClient = _ServerActionClient;
|
|
152
152
|
function createServerAction(config) {
|
|
153
153
|
const actionFn = async (...args) => {
|
|
154
|
-
const input = args[0];
|
|
155
154
|
const context = {};
|
|
155
|
+
const hasInputSchema = config.inputSchema !== void 0 && config.inputSchema !== null;
|
|
156
|
+
const input = hasInputSchema ? args[0] : void 0;
|
|
156
157
|
try {
|
|
157
|
-
let parsedInput =
|
|
158
|
-
if (config.inputSchema) {
|
|
158
|
+
let parsedInput = void 0;
|
|
159
|
+
if (hasInputSchema && config.inputSchema) {
|
|
159
160
|
const parseResult = config.inputSchema.safeParse(input);
|
|
160
161
|
if (!parseResult.success) {
|
|
161
162
|
return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError(err, { parsedInput: input }) : void 0);
|
|
@@ -165,7 +166,8 @@ function createServerAction(config) {
|
|
|
165
166
|
}
|
|
166
167
|
let middlewareContext = {};
|
|
167
168
|
for (const middleware of config.middlewareFns) {
|
|
168
|
-
const
|
|
169
|
+
const middlewareInput = hasInputSchema ? parsedInput : void 0;
|
|
170
|
+
const result2 = await middleware({ context: middlewareContext, input: middlewareInput });
|
|
169
171
|
if ("error" in result2) {
|
|
170
172
|
return {
|
|
171
173
|
success: false,
|
|
@@ -174,7 +176,7 @@ function createServerAction(config) {
|
|
|
174
176
|
}
|
|
175
177
|
middlewareContext = { ...middlewareContext, ...result2.context };
|
|
176
178
|
}
|
|
177
|
-
const result = await config.serverCodeFn(parsedInput, middlewareContext);
|
|
179
|
+
const result = hasInputSchema ? await config.serverCodeFn(parsedInput, middlewareContext) : await config.serverCodeFn(middlewareContext);
|
|
178
180
|
let validatedOutput = result;
|
|
179
181
|
if (config.outputSchema) {
|
|
180
182
|
const parseResult = config.outputSchema.safeParse(result);
|
|
@@ -200,6 +202,7 @@ function createServerAction(config) {
|
|
|
200
202
|
return handleServerActionError(error, errorHandler);
|
|
201
203
|
}
|
|
202
204
|
};
|
|
205
|
+
actionFn.__hasInputSchema = config.inputSchema !== void 0 && config.inputSchema !== null;
|
|
203
206
|
return actionFn;
|
|
204
207
|
}
|
|
205
208
|
function parseFormData(formData) {
|
|
@@ -224,6 +227,7 @@ function parseFormData(formData) {
|
|
|
224
227
|
function createFormServerAction(config) {
|
|
225
228
|
return async (_prev, formData) => {
|
|
226
229
|
const context = {};
|
|
230
|
+
const hasInputSchema = config.inputSchema !== void 0 && config.inputSchema !== null;
|
|
227
231
|
try {
|
|
228
232
|
let parsedInput = parseFormData(formData);
|
|
229
233
|
if (config.inputSchema) {
|
|
@@ -236,7 +240,8 @@ function createFormServerAction(config) {
|
|
|
236
240
|
}
|
|
237
241
|
let middlewareContext = {};
|
|
238
242
|
for (const middleware of config.middlewareFns) {
|
|
239
|
-
const
|
|
243
|
+
const middlewareInput = hasInputSchema ? parsedInput : void 0;
|
|
244
|
+
const result2 = await middleware({ context: middlewareContext, input: middlewareInput });
|
|
240
245
|
if ("error" in result2) {
|
|
241
246
|
return {
|
|
242
247
|
success: false,
|
|
@@ -245,7 +250,7 @@ function createFormServerAction(config) {
|
|
|
245
250
|
}
|
|
246
251
|
middlewareContext = { ...middlewareContext, ...result2.context };
|
|
247
252
|
}
|
|
248
|
-
const result = await config.serverCodeFn(parsedInput, middlewareContext);
|
|
253
|
+
const result = hasInputSchema ? await config.serverCodeFn(parsedInput, middlewareContext) : await config.serverCodeFn(middlewareContext);
|
|
249
254
|
let validatedOutput = result;
|
|
250
255
|
if (config.outputSchema) {
|
|
251
256
|
const parseResult = config.outputSchema.safeParse(result);
|
package/dist/core/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/error-handler.ts","../../src/core/server-action-client.ts"],"sourcesContent":["import { z, ZodError } from \"zod\";\nimport type { ServerActionError, ServerActionResponse } from \"../types\";\n\nfunction convertZodError(error: ZodError): ServerActionError {\n const { fieldErrors, formErrors } = z.flattenError(error);\n const [field] = Object.keys(fieldErrors) as (keyof typeof fieldErrors)[];\n const message = (field && fieldErrors[field]?.[0]) ?? formErrors[0] ?? \"Validation failed\";\n return {\n message,\n code: \"VALIDATION_ERROR\",\n field,\n fields: fieldErrors,\n };\n}\n\nfunction convertGenericError(error: unknown): ServerActionError {\n const message = error instanceof Error ? error.message : \"An unexpected error occurred\";\n\n return {\n message: process.env.NODE_ENV === \"production\" ? \"An unexpected error occurred\" : message,\n code: \"INTERNAL_ERROR\",\n statusCode: 500,\n };\n}\n\nexport function handleServerActionError(\n error: unknown,\n customHandler?: (error: unknown) => ServerActionError | undefined\n): { success: false; error: ServerActionError } {\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.error(\"[Server Action Error]\", error?.constructor?.name || 'Unknown', error instanceof Error ? error.message : error);\n }\n\n // Try custom handler first\n if (customHandler) {\n try {\n const customError = customHandler(error);\n if (customError) {\n return {\n success: false,\n error: customError,\n };\n }\n } catch (handlerError) {\n console.error(\"[Server Action Error] Custom handler threw an error:\", handlerError);\n }\n }\n\n if (error instanceof ZodError) {\n return {\n success: false,\n error: convertZodError(error),\n };\n }\n\n if (error instanceof Error && \"toServerActionError\" in error && typeof error.toServerActionError === \"function\") {\n const serverError = error.toServerActionError() as ServerActionError;\n \n // Check if this is an auth error based on the error type/code\n if (serverError.code === \"AUTHENTICATION_ERROR\" || (error as any).type === \"AUTHENTICATION_ERROR\") {\n serverError.shouldRedirect = true;\n serverError.redirectTo = \"/login\";\n }\n \n return {\n success: false,\n error: serverError,\n };\n }\n\n return {\n success: false,\n error: convertGenericError(error),\n };\n}\n\nexport function isErrorResponse<T>(response: ServerActionResponse<T>): response is { success: false; error: ServerActionError } {\n return !response.success;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\n\ntype InferZodOutput<T> = T extends z.ZodTypeAny ? z.output<T> : never;\ntype InferZodInput<T> = T extends z.ZodTypeAny ? z.input<T> : never;\n\ntype ServerActionMiddleware<Context> = (params: { context: Context; input: unknown }) => Promise<{ context: Context } | { error: ServerActionError }>;\n\ntype SafeActionClientArgs<Context extends object, InputSchema extends z.ZodTypeAny | undefined, OutputSchema extends z.ZodTypeAny | undefined> = {\n middlewareFns: ServerActionMiddleware<any>[];\n inputSchema?: InputSchema;\n outputSchema?: OutputSchema;\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n ctxType?: Context;\n};\n\nexport class ServerActionClient<Context extends object = {}, InputSchema extends z.ZodTypeAny | undefined = undefined, OutputSchema extends z.ZodTypeAny | undefined = undefined> {\n readonly #args: SafeActionClientArgs<Context, InputSchema, OutputSchema>;\n\n constructor(\n args: SafeActionClientArgs<Context, InputSchema, OutputSchema> = {\n middlewareFns: [],\n }\n ) {\n this.#args = args;\n }\n\n /**\n * Use a middleware function.\n * @param middlewareFn Middleware function\n */\n use<NextContext extends object>(middlewareFn: ServerActionMiddleware<Context & NextContext>) {\n return new ServerActionClient<Context & NextContext, InputSchema, OutputSchema>({\n ...this.#args,\n middlewareFns: [...this.#args.middlewareFns, middlewareFn] as any,\n ctxType: {} as Context & NextContext,\n });\n }\n\n /**\n * Define the input validation schema for the action.\n * @param schema Input validation schema\n */\n inputSchema<IS extends z.ZodTypeAny>(schema: IS) {\n return new ServerActionClient<Context, IS, OutputSchema>({\n ...this.#args,\n inputSchema: schema,\n });\n }\n\n /**\n * Define the output validation schema for the action.\n * @param schema Output validation schema\n */\n outputSchema<OS extends z.ZodTypeAny>(schema: OS) {\n return new ServerActionClient<Context, InputSchema, OS>({\n ...this.#args,\n outputSchema: schema,\n });\n }\n\n /**\n * Define a custom error handler for the action.\n * @param handler Error handler function\n */\n onError(handler: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n onError: handler,\n });\n }\n\n /**\n * Define the action.\n * @param serverCodeFn Code that will be executed on the server side\n */\n action<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (input: void, context: Context) => Promise<Data>\n ): ServerAction<InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void, OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data> {\n return createServerAction<\n InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void,\n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n >({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn: serverCodeFn as any,\n });\n }\n\n /**\n * Define a form action that accepts FormData.\n * @param serverCodeFn Code that will be executed on the server side\n */\n formAction<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (input: void, context: Context) => Promise<Data>\n ): (prev: ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>, formData: FormData) => Promise<ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>> {\n return createFormServerAction({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn,\n });\n }\n}\n\n// Internal function to create the actual server action\nfunction createServerAction<TInput, TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (parsedInput: any, context: any) => Promise<any>;\n}): ServerAction<TInput, TOutput> {\n const actionFn = async (...args: TInput extends void ? [] : [input: TInput]): Promise<ServerActionResponse<TOutput>> => {\n const input = args[0] as TInput;\n const context: { parsedInput?: unknown } = {};\n\n try {\n let parsedInput: any = input;\n\n // Input validation\n if (config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(input);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput: input }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const result = await middleware({ context: middlewareContext, input: parsedInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = await config.serverCodeFn(parsedInput, middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n \n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[executeAction] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n \n // Use the handleServerActionError function with custom handler\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n \n return handleServerActionError(error, errorHandler);\n }\n };\n\n // Return the function with correct typing based on whether input is void\n return actionFn as ServerAction<TInput, TOutput>;\n}\n\n// Form data parser\nfunction parseFormData(formData: FormData): Record<string, any> {\n const result: Record<string, any> = {};\n const keys = new Set<string>();\n\n for (const [key] of formData.entries()) {\n keys.add(key);\n }\n\n for (const key of keys) {\n const values = formData.getAll(key);\n\n if (key.endsWith(\"[]\")) {\n const cleanKey = key.slice(0, -2);\n result[cleanKey] = values;\n } else if (values.length === 1) {\n result[key] = values[0];\n } else {\n result[key] = values;\n }\n }\n\n return result;\n}\n\n// Internal function to create form server action\nfunction createFormServerAction<TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (parsedInput: any, context: any) => Promise<any>;\n}): (prev: ServerActionResponse<TOutput>, formData: FormData) => Promise<ServerActionResponse<TOutput>> {\n return async (_prev: ServerActionResponse<TOutput>, formData: FormData): Promise<ServerActionResponse<TOutput>> => {\n const context: { parsedInput?: unknown } = {};\n\n try {\n let parsedInput: any = parseFormData(formData);\n\n // Input validation\n if (config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(parsedInput);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const result = await middleware({ context: middlewareContext, input: parsedInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = await config.serverCodeFn(parsedInput, middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[ServerActionClient] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n return handleServerActionError(error, errorHandler);\n }\n };\n}\n\n// Export factory function for creating a new client\nexport function createActionClient() {\n return new ServerActionClient();\n}\n"],"mappings":";;;;;;;;;AAAA,SAAS,GAAG,gBAAgB;AAG5B,SAAS,gBAAgB,OAAoC;AAC3D,QAAM,EAAE,aAAa,WAAW,IAAI,EAAE,aAAa,KAAK;AACxD,QAAM,CAAC,KAAK,IAAI,OAAO,KAAK,WAAW;AACvC,QAAM,WAAW,SAAS,YAAY,KAAK,IAAI,CAAC,MAAM,WAAW,CAAC,KAAK;AACvE,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA,QAAQ;AAAA,EACV;AACF;AAEA,SAAS,oBAAoB,OAAmC;AAC9D,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AAEzD,SAAO;AAAA,IACL,SAAS,QAAQ,IAAI,aAAa,eAAe,iCAAiC;AAAA,IAClF,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AACF;AAEO,SAAS,wBACd,OACA,eAC8C;AAE9C,MAAI,QAAQ,IAAI,aAAa,eAAe;AAC1C,YAAQ,MAAM,yBAAyB,OAAO,aAAa,QAAQ,WAAW,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AAAA,EAC9H;AAGA,MAAI,eAAe;AACjB,QAAI;AACF,YAAM,cAAc,cAAc,KAAK;AACvC,UAAI,aAAa;AACf,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,SAAS,cAAc;AACrB,cAAQ,MAAM,wDAAwD,YAAY;AAAA,IACpF;AAAA,EACF;AAEA,MAAI,iBAAiB,UAAU;AAC7B,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,gBAAgB,KAAK;AAAA,IAC9B;AAAA,EACF;AAEA,MAAI,iBAAiB,SAAS,yBAAyB,SAAS,OAAO,MAAM,wBAAwB,YAAY;AAC/G,UAAM,cAAc,MAAM,oBAAoB;AAG9C,QAAI,YAAY,SAAS,0BAA2B,MAAc,SAAS,wBAAwB;AACjG,kBAAY,iBAAiB;AAC7B,kBAAY,aAAa;AAAA,IAC3B;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO,oBAAoB,KAAK;AAAA,EAClC;AACF;AAEO,SAAS,gBAAmB,UAA6F;AAC9H,SAAO,CAAC,SAAS;AACnB;;;AC/EA;AAiBO,IAAM,sBAAN,MAAM,oBAAqK;AAAA,EAGhL,YACE,OAAiE;AAAA,IAC/D,eAAe,CAAC;AAAA,EAClB,GACA;AANF,uBAAS;AAOP,uBAAK,OAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAgC,cAA6D;AAC3F,WAAO,IAAI,oBAAqE;AAAA,MAC9E,GAAG,mBAAK;AAAA,MACR,eAAe,CAAC,GAAG,mBAAK,OAAM,eAAe,YAAY;AAAA,MACzD,SAAS,CAAC;AAAA,IACZ,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAqC,QAAY;AAC/C,WAAO,IAAI,oBAA8C;AAAA,MACvD,GAAG,mBAAK;AAAA,MACR,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAsC,QAAY;AAChD,WAAO,IAAI,oBAA6C;AAAA,MACtD,GAAG,mBAAK;AAAA,MACR,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,SAAgG;AACtG,WAAO,IAAI,oBAAuD;AAAA,MAChE,GAAG,mBAAK;AAAA,MACR,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OACE,cAG6J;AAC7J,WAAO,mBAGL;AAAA,MACA,aAAa,mBAAK,OAAM;AAAA,MACxB,cAAc,mBAAK,OAAM;AAAA,MACzB,eAAe,mBAAK,OAAM;AAAA,MAC1B,SAAS,mBAAK,OAAM;AAAA,MACpB;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WACE,cAGqO;AACrO,WAAO,uBAAuB;AAAA,MAC5B,aAAa,mBAAK,OAAM;AAAA,MACxB,cAAc,mBAAK,OAAM;AAAA,MACzB,eAAe,mBAAK,OAAM;AAAA,MAC1B,SAAS,mBAAK,OAAM;AAAA,MACpB;AAAA,IACF,CAAC;AAAA,EACH;AACF;AA7FW;AADJ,IAAM,qBAAN;AAiGP,SAAS,mBAAoC,QAMX;AAChC,QAAM,WAAW,UAAU,SAA6F;AACtH,UAAM,QAAQ,KAAK,CAAC;AACpB,UAAM,UAAqC,CAAC;AAE5C,QAAI;AACF,UAAI,cAAmB;AAGvB,UAAI,OAAO,aAAa;AACtB,cAAM,cAAc,OAAO,YAAY,UAAU,KAAK;AACtD,YAAI,CAAC,YAAY,SAAS;AACxB,iBAAO,wBAAwB,YAAY,OAAO,OAAO,UAAU,CAAC,QAAQ,OAAO,QAAS,KAAK,EAAE,aAAa,MAAM,CAAC,IAAI,MAAS;AAAA,QACtI;AACA,sBAAc,YAAY;AAC1B,gBAAQ,cAAc;AAAA,MACxB;AAGA,UAAI,oBAAoB,CAAC;AACzB,iBAAW,cAAc,OAAO,eAAe;AAC7C,cAAMA,UAAS,MAAM,WAAW,EAAE,SAAS,mBAAmB,OAAO,YAAY,CAAC;AAClF,YAAI,WAAWA,SAAQ;AACrB,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,OAAOA,QAAO;AAAA,UAChB;AAAA,QACF;AACA,4BAAoB,EAAE,GAAG,mBAAmB,GAAGA,QAAO,QAAQ;AAAA,MAChE;AAGA,YAAM,SAAS,MAAM,OAAO,aAAa,aAAa,iBAAiB;AAGvE,UAAI,kBAAuB;AAC3B,UAAI,OAAO,cAAc;AACvB,cAAM,cAAc,OAAO,aAAa,UAAU,MAAM;AACxD,YAAI,CAAC,YAAY,SAAS;AACxB,iBAAO,wBAAwB,YAAY,KAAK;AAAA,QAClD;AACA,0BAAkB,YAAY;AAAA,MAChC;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM;AAAA,MACR;AAAA,IACF,SAAS,OAAO;AAEd,UAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,eAAe,GAAG;AACrE,cAAM;AAAA,MACR;AAGA,UAAI,QAAQ,IAAI,aAAa,eAAe;AAC1C,gBAAQ,IAAI,0BAA0B,OAAO,aAAa,MAAM,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AAAA,MAChH;AAGA,YAAM,eAAe,OAAO,UAAU,CAAC,QAAiB;AACtD,eAAO,OAAO,QAAS,KAAK,EAAE,aAAa,QAAQ,YAAY,CAAC;AAAA,MAClE,IAAI;AAEJ,aAAO,wBAAwB,OAAO,YAAY;AAAA,IACpD;AAAA,EACF;AAGA,SAAO;AACT;AAGA,SAAS,cAAc,UAAyC;AAC9D,QAAM,SAA8B,CAAC;AACrC,QAAM,OAAO,oBAAI,IAAY;AAE7B,aAAW,CAAC,GAAG,KAAK,SAAS,QAAQ,GAAG;AACtC,SAAK,IAAI,GAAG;AAAA,EACd;AAEA,aAAW,OAAO,MAAM;AACtB,UAAM,SAAS,SAAS,OAAO,GAAG;AAElC,QAAI,IAAI,SAAS,IAAI,GAAG;AACtB,YAAM,WAAW,IAAI,MAAM,GAAG,EAAE;AAChC,aAAO,QAAQ,IAAI;AAAA,IACrB,WAAW,OAAO,WAAW,GAAG;AAC9B,aAAO,GAAG,IAAI,OAAO,CAAC;AAAA,IACxB,OAAO;AACL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;AAGA,SAAS,uBAAgC,QAM+D;AACtG,SAAO,OAAO,OAAsC,aAA+D;AACjH,UAAM,UAAqC,CAAC;AAE5C,QAAI;AACF,UAAI,cAAmB,cAAc,QAAQ;AAG7C,UAAI,OAAO,aAAa;AACtB,cAAM,cAAc,OAAO,YAAY,UAAU,WAAW;AAC5D,YAAI,CAAC,YAAY,SAAS;AACxB,iBAAO,wBAAwB,YAAY,OAAO,OAAO,UAAU,CAAC,QAAQ,OAAO,QAAS,KAAK,EAAE,YAAY,CAAC,IAAI,MAAS;AAAA,QAC/H;AACA,sBAAc,YAAY;AAC1B,gBAAQ,cAAc;AAAA,MACxB;AAGA,UAAI,oBAAoB,CAAC;AACzB,iBAAW,cAAc,OAAO,eAAe;AAC7C,cAAMA,UAAS,MAAM,WAAW,EAAE,SAAS,mBAAmB,OAAO,YAAY,CAAC;AAClF,YAAI,WAAWA,SAAQ;AACrB,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,OAAOA,QAAO;AAAA,UAChB;AAAA,QACF;AACA,4BAAoB,EAAE,GAAG,mBAAmB,GAAGA,QAAO,QAAQ;AAAA,MAChE;AAGA,YAAM,SAAS,MAAM,OAAO,aAAa,aAAa,iBAAiB;AAGvE,UAAI,kBAAuB;AAC3B,UAAI,OAAO,cAAc;AACvB,cAAM,cAAc,OAAO,aAAa,UAAU,MAAM;AACxD,YAAI,CAAC,YAAY,SAAS;AACxB,iBAAO,wBAAwB,YAAY,KAAK;AAAA,QAClD;AACA,0BAAkB,YAAY;AAAA,MAChC;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM;AAAA,MACR;AAAA,IACF,SAAS,OAAO;AAEd,UAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,eAAe,GAAG;AACrE,cAAM;AAAA,MACR;AAEA,UAAI,QAAQ,IAAI,aAAa,eAAe;AAC1C,gBAAQ,IAAI,+BAA+B,OAAO,aAAa,MAAM,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AAAA,MACrH;AACA,YAAM,eAAe,OAAO,UAAU,CAAC,QAAiB;AACtD,eAAO,OAAO,QAAS,KAAK,EAAE,aAAa,QAAQ,YAAY,CAAC;AAAA,MAClE,IAAI;AACJ,aAAO,wBAAwB,OAAO,YAAY;AAAA,IACpD;AAAA,EACF;AACF;AAGO,SAAS,qBAAqB;AACnC,SAAO,IAAI,mBAAmB;AAChC;","names":["result"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/error-handler.ts","../../src/core/server-action-client.ts"],"sourcesContent":["import { z, ZodError } from \"zod\";\nimport type { ServerActionError, ServerActionResponse } from \"../types\";\n\nfunction convertZodError(error: ZodError): ServerActionError {\n const { fieldErrors, formErrors } = z.flattenError(error);\n const [field] = Object.keys(fieldErrors) as (keyof typeof fieldErrors)[];\n const message = (field && fieldErrors[field]?.[0]) ?? formErrors[0] ?? \"Validation failed\";\n return {\n message,\n code: \"VALIDATION_ERROR\",\n field,\n fields: fieldErrors,\n };\n}\n\nfunction convertGenericError(error: unknown): ServerActionError {\n const message = error instanceof Error ? error.message : \"An unexpected error occurred\";\n\n return {\n message: process.env.NODE_ENV === \"production\" ? \"An unexpected error occurred\" : message,\n code: \"INTERNAL_ERROR\",\n statusCode: 500,\n };\n}\n\nexport function handleServerActionError(\n error: unknown,\n customHandler?: (error: unknown) => ServerActionError | undefined\n): { success: false; error: ServerActionError } {\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.error(\"[Server Action Error]\", error?.constructor?.name || 'Unknown', error instanceof Error ? error.message : error);\n }\n\n // Try custom handler first\n if (customHandler) {\n try {\n const customError = customHandler(error);\n if (customError) {\n return {\n success: false,\n error: customError,\n };\n }\n } catch (handlerError) {\n console.error(\"[Server Action Error] Custom handler threw an error:\", handlerError);\n }\n }\n\n if (error instanceof ZodError) {\n return {\n success: false,\n error: convertZodError(error),\n };\n }\n\n if (error instanceof Error && \"toServerActionError\" in error && typeof error.toServerActionError === \"function\") {\n const serverError = error.toServerActionError() as ServerActionError;\n \n // Check if this is an auth error based on the error type/code\n if (serverError.code === \"AUTHENTICATION_ERROR\" || (error as any).type === \"AUTHENTICATION_ERROR\") {\n serverError.shouldRedirect = true;\n serverError.redirectTo = \"/login\";\n }\n \n return {\n success: false,\n error: serverError,\n };\n }\n\n return {\n success: false,\n error: convertGenericError(error),\n };\n}\n\nexport function isErrorResponse<T>(response: ServerActionResponse<T>): response is { success: false; error: ServerActionError } {\n return !response.success;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\n\ntype InferZodOutput<T> = T extends z.ZodTypeAny ? z.output<T> : never;\ntype InferZodInput<T> = T extends z.ZodTypeAny ? z.input<T> : never;\n\ntype ServerActionMiddleware<Context> = (params: { context: Context; input: unknown }) => Promise<{ context: Context } | { error: ServerActionError }>;\n\ntype SafeActionClientArgs<Context extends object, InputSchema extends z.ZodTypeAny | undefined, OutputSchema extends z.ZodTypeAny | undefined> = {\n middlewareFns: ServerActionMiddleware<any>[];\n inputSchema?: InputSchema;\n outputSchema?: OutputSchema;\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n ctxType?: Context;\n};\n\nexport class ServerActionClient<Context extends object = {}, InputSchema extends z.ZodTypeAny | undefined = undefined, OutputSchema extends z.ZodTypeAny | undefined = undefined> {\n readonly #args: SafeActionClientArgs<Context, InputSchema, OutputSchema>;\n\n constructor(\n args: SafeActionClientArgs<Context, InputSchema, OutputSchema> = {\n middlewareFns: [],\n }\n ) {\n this.#args = args;\n }\n\n /**\n * Use a middleware function.\n * @param middlewareFn Middleware function\n */\n use<NextContext extends object>(middlewareFn: ServerActionMiddleware<Context & NextContext>) {\n return new ServerActionClient<Context & NextContext, InputSchema, OutputSchema>({\n ...this.#args,\n middlewareFns: [...this.#args.middlewareFns, middlewareFn] as any,\n ctxType: {} as Context & NextContext,\n });\n }\n\n /**\n * Define the input validation schema for the action.\n * @param schema Input validation schema\n */\n inputSchema<IS extends z.ZodTypeAny>(schema: IS) {\n return new ServerActionClient<Context, IS, OutputSchema>({\n ...this.#args,\n inputSchema: schema,\n });\n }\n\n /**\n * Define the output validation schema for the action.\n * @param schema Output validation schema\n */\n outputSchema<OS extends z.ZodTypeAny>(schema: OS) {\n return new ServerActionClient<Context, InputSchema, OS>({\n ...this.#args,\n outputSchema: schema,\n });\n }\n\n /**\n * Define a custom error handler for the action.\n * @param handler Error handler function\n */\n onError(handler: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n onError: handler,\n });\n }\n\n /**\n * Define the action.\n * @param serverCodeFn Code that will be executed on the server side\n */\n action<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): ServerAction<InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void, OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data> {\n return createServerAction<\n InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void,\n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n >({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn: serverCodeFn as any,\n });\n }\n\n /**\n * Define a form action that accepts FormData.\n * @param serverCodeFn Code that will be executed on the server side\n */\n formAction<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): (prev: ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>, formData: FormData) => Promise<ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>> {\n return createFormServerAction({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn,\n });\n }\n}\n\n// Internal function to create the actual server action\nfunction createServerAction<TInput, TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (...args: any[]) => Promise<any>;\n}): ServerAction<TInput, TOutput> {\n const actionFn = async (...args: TInput extends void ? [] : [input: TInput]): Promise<ServerActionResponse<TOutput>> => {\n const context: { parsedInput?: unknown } = {};\n \n // Type guard: check if we have an input schema\n const hasInputSchema = config.inputSchema !== undefined && config.inputSchema !== null;\n const input = hasInputSchema ? args[0] as TInput : undefined;\n\n try {\n let parsedInput: any = undefined;\n\n // Input validation\n if (hasInputSchema && config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(input);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput: input }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const middlewareInput = hasInputSchema ? parsedInput : undefined;\n const result = await middleware({ context: middlewareContext, input: middlewareInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = hasInputSchema \n ? await config.serverCodeFn(parsedInput, middlewareContext)\n : await config.serverCodeFn(middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n \n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[executeAction] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n \n // Use the handleServerActionError function with custom handler\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n \n return handleServerActionError(error, errorHandler);\n }\n };\n\n // Add metadata for runtime type checking\n (actionFn as any).__hasInputSchema = config.inputSchema !== undefined && config.inputSchema !== null;\n \n // Return the function with correct typing based on whether input is void\n return actionFn as ServerAction<TInput, TOutput>;\n}\n\n// Form data parser\nfunction parseFormData(formData: FormData): Record<string, any> {\n const result: Record<string, any> = {};\n const keys = new Set<string>();\n\n for (const [key] of formData.entries()) {\n keys.add(key);\n }\n\n for (const key of keys) {\n const values = formData.getAll(key);\n\n if (key.endsWith(\"[]\")) {\n const cleanKey = key.slice(0, -2);\n result[cleanKey] = values;\n } else if (values.length === 1) {\n result[key] = values[0];\n } else {\n result[key] = values;\n }\n }\n\n return result;\n}\n\n// Internal function to create form server action\nfunction createFormServerAction<TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (...args: any[]) => Promise<any>;\n}): (prev: ServerActionResponse<TOutput>, formData: FormData) => Promise<ServerActionResponse<TOutput>> {\n return async (_prev: ServerActionResponse<TOutput>, formData: FormData): Promise<ServerActionResponse<TOutput>> => {\n const context: { parsedInput?: unknown } = {};\n const hasInputSchema = config.inputSchema !== undefined && config.inputSchema !== null;\n\n try {\n let parsedInput: any = parseFormData(formData);\n\n // Input validation\n if (config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(parsedInput);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const middlewareInput = hasInputSchema ? parsedInput : undefined;\n const result = await middleware({ context: middlewareContext, input: middlewareInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = hasInputSchema \n ? await config.serverCodeFn(parsedInput, middlewareContext)\n : await config.serverCodeFn(middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[ServerActionClient] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n return handleServerActionError(error, errorHandler);\n }\n };\n}\n\n// Export factory function for creating a new client\nexport function createActionClient() {\n return new ServerActionClient();\n}\n"],"mappings":"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","names":["result"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -59,12 +59,12 @@ declare class ServerActionClient<Context extends object = {}, InputSchema extend
|
|
|
59
59
|
* Define the action.
|
|
60
60
|
* @param serverCodeFn Code that will be executed on the server side
|
|
61
61
|
*/
|
|
62
|
-
action<Data>(serverCodeFn: InputSchema extends z.ZodTypeAny ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data> : (
|
|
62
|
+
action<Data>(serverCodeFn: InputSchema extends z.ZodTypeAny ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data> : (context: Context) => Promise<Data>): ServerAction<InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void, OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>;
|
|
63
63
|
/**
|
|
64
64
|
* Define a form action that accepts FormData.
|
|
65
65
|
* @param serverCodeFn Code that will be executed on the server side
|
|
66
66
|
*/
|
|
67
|
-
formAction<Data>(serverCodeFn: InputSchema extends z.ZodTypeAny ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data> : (
|
|
67
|
+
formAction<Data>(serverCodeFn: InputSchema extends z.ZodTypeAny ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data> : (context: Context) => Promise<Data>): (prev: ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>, formData: FormData) => Promise<ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>>;
|
|
68
68
|
}
|
|
69
69
|
declare function createActionClient(): ServerActionClient<{}, undefined, undefined>;
|
|
70
70
|
|
package/dist/index.d.ts
CHANGED
|
@@ -59,12 +59,12 @@ declare class ServerActionClient<Context extends object = {}, InputSchema extend
|
|
|
59
59
|
* Define the action.
|
|
60
60
|
* @param serverCodeFn Code that will be executed on the server side
|
|
61
61
|
*/
|
|
62
|
-
action<Data>(serverCodeFn: InputSchema extends z.ZodTypeAny ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data> : (
|
|
62
|
+
action<Data>(serverCodeFn: InputSchema extends z.ZodTypeAny ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data> : (context: Context) => Promise<Data>): ServerAction<InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void, OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>;
|
|
63
63
|
/**
|
|
64
64
|
* Define a form action that accepts FormData.
|
|
65
65
|
* @param serverCodeFn Code that will be executed on the server side
|
|
66
66
|
*/
|
|
67
|
-
formAction<Data>(serverCodeFn: InputSchema extends z.ZodTypeAny ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data> : (
|
|
67
|
+
formAction<Data>(serverCodeFn: InputSchema extends z.ZodTypeAny ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data> : (context: Context) => Promise<Data>): (prev: ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>, formData: FormData) => Promise<ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>>;
|
|
68
68
|
}
|
|
69
69
|
declare function createActionClient(): ServerActionClient<{}, undefined, undefined>;
|
|
70
70
|
|
package/dist/index.js
CHANGED
|
@@ -179,11 +179,12 @@ _args = new WeakMap();
|
|
|
179
179
|
var ServerActionClient = _ServerActionClient;
|
|
180
180
|
function createServerAction(config) {
|
|
181
181
|
const actionFn = async (...args) => {
|
|
182
|
-
const input = args[0];
|
|
183
182
|
const context = {};
|
|
183
|
+
const hasInputSchema = config.inputSchema !== void 0 && config.inputSchema !== null;
|
|
184
|
+
const input = hasInputSchema ? args[0] : void 0;
|
|
184
185
|
try {
|
|
185
|
-
let parsedInput =
|
|
186
|
-
if (config.inputSchema) {
|
|
186
|
+
let parsedInput = void 0;
|
|
187
|
+
if (hasInputSchema && config.inputSchema) {
|
|
187
188
|
const parseResult = config.inputSchema.safeParse(input);
|
|
188
189
|
if (!parseResult.success) {
|
|
189
190
|
return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError(err, { parsedInput: input }) : void 0);
|
|
@@ -193,7 +194,8 @@ function createServerAction(config) {
|
|
|
193
194
|
}
|
|
194
195
|
let middlewareContext = {};
|
|
195
196
|
for (const middleware of config.middlewareFns) {
|
|
196
|
-
const
|
|
197
|
+
const middlewareInput = hasInputSchema ? parsedInput : void 0;
|
|
198
|
+
const result2 = await middleware({ context: middlewareContext, input: middlewareInput });
|
|
197
199
|
if ("error" in result2) {
|
|
198
200
|
return {
|
|
199
201
|
success: false,
|
|
@@ -202,7 +204,7 @@ function createServerAction(config) {
|
|
|
202
204
|
}
|
|
203
205
|
middlewareContext = { ...middlewareContext, ...result2.context };
|
|
204
206
|
}
|
|
205
|
-
const result = await config.serverCodeFn(parsedInput, middlewareContext);
|
|
207
|
+
const result = hasInputSchema ? await config.serverCodeFn(parsedInput, middlewareContext) : await config.serverCodeFn(middlewareContext);
|
|
206
208
|
let validatedOutput = result;
|
|
207
209
|
if (config.outputSchema) {
|
|
208
210
|
const parseResult = config.outputSchema.safeParse(result);
|
|
@@ -228,6 +230,7 @@ function createServerAction(config) {
|
|
|
228
230
|
return handleServerActionError(error, errorHandler);
|
|
229
231
|
}
|
|
230
232
|
};
|
|
233
|
+
actionFn.__hasInputSchema = config.inputSchema !== void 0 && config.inputSchema !== null;
|
|
231
234
|
return actionFn;
|
|
232
235
|
}
|
|
233
236
|
function parseFormData(formData) {
|
|
@@ -252,6 +255,7 @@ function parseFormData(formData) {
|
|
|
252
255
|
function createFormServerAction(config) {
|
|
253
256
|
return async (_prev, formData) => {
|
|
254
257
|
const context = {};
|
|
258
|
+
const hasInputSchema = config.inputSchema !== void 0 && config.inputSchema !== null;
|
|
255
259
|
try {
|
|
256
260
|
let parsedInput = parseFormData(formData);
|
|
257
261
|
if (config.inputSchema) {
|
|
@@ -264,7 +268,8 @@ function createFormServerAction(config) {
|
|
|
264
268
|
}
|
|
265
269
|
let middlewareContext = {};
|
|
266
270
|
for (const middleware of config.middlewareFns) {
|
|
267
|
-
const
|
|
271
|
+
const middlewareInput = hasInputSchema ? parsedInput : void 0;
|
|
272
|
+
const result2 = await middleware({ context: middlewareContext, input: middlewareInput });
|
|
268
273
|
if ("error" in result2) {
|
|
269
274
|
return {
|
|
270
275
|
success: false,
|
|
@@ -273,7 +278,7 @@ function createFormServerAction(config) {
|
|
|
273
278
|
}
|
|
274
279
|
middlewareContext = { ...middlewareContext, ...result2.context };
|
|
275
280
|
}
|
|
276
|
-
const result = await config.serverCodeFn(parsedInput, middlewareContext);
|
|
281
|
+
const result = hasInputSchema ? await config.serverCodeFn(parsedInput, middlewareContext) : await config.serverCodeFn(middlewareContext);
|
|
277
282
|
let validatedOutput = result;
|
|
278
283
|
if (config.outputSchema) {
|
|
279
284
|
const parseResult = config.outputSchema.safeParse(result);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/core/error-handler.ts","../src/core/server-action-client.ts"],"sourcesContent":["// Type exports\nexport * from \"./types\";\n\n// Core exports (server-safe)\nexport * from \"./core/error-handler\";\n\n// Server Action Client (class-based API)\nexport { ServerActionClient, createActionClient } from \"./core/server-action-client\";\n","import { z, ZodError } from \"zod\";\nimport type { ServerActionError, ServerActionResponse } from \"../types\";\n\nfunction convertZodError(error: ZodError): ServerActionError {\n const { fieldErrors, formErrors } = z.flattenError(error);\n const [field] = Object.keys(fieldErrors) as (keyof typeof fieldErrors)[];\n const message = (field && fieldErrors[field]?.[0]) ?? formErrors[0] ?? \"Validation failed\";\n return {\n message,\n code: \"VALIDATION_ERROR\",\n field,\n fields: fieldErrors,\n };\n}\n\nfunction convertGenericError(error: unknown): ServerActionError {\n const message = error instanceof Error ? error.message : \"An unexpected error occurred\";\n\n return {\n message: process.env.NODE_ENV === \"production\" ? \"An unexpected error occurred\" : message,\n code: \"INTERNAL_ERROR\",\n statusCode: 500,\n };\n}\n\nexport function handleServerActionError(\n error: unknown,\n customHandler?: (error: unknown) => ServerActionError | undefined\n): { success: false; error: ServerActionError } {\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.error(\"[Server Action Error]\", error?.constructor?.name || 'Unknown', error instanceof Error ? error.message : error);\n }\n\n // Try custom handler first\n if (customHandler) {\n try {\n const customError = customHandler(error);\n if (customError) {\n return {\n success: false,\n error: customError,\n };\n }\n } catch (handlerError) {\n console.error(\"[Server Action Error] Custom handler threw an error:\", handlerError);\n }\n }\n\n if (error instanceof ZodError) {\n return {\n success: false,\n error: convertZodError(error),\n };\n }\n\n if (error instanceof Error && \"toServerActionError\" in error && typeof error.toServerActionError === \"function\") {\n const serverError = error.toServerActionError() as ServerActionError;\n \n // Check if this is an auth error based on the error type/code\n if (serverError.code === \"AUTHENTICATION_ERROR\" || (error as any).type === \"AUTHENTICATION_ERROR\") {\n serverError.shouldRedirect = true;\n serverError.redirectTo = \"/login\";\n }\n \n return {\n success: false,\n error: serverError,\n };\n }\n\n return {\n success: false,\n error: convertGenericError(error),\n };\n}\n\nexport function isErrorResponse<T>(response: ServerActionResponse<T>): response is { success: false; error: ServerActionError } {\n return !response.success;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\n\ntype InferZodOutput<T> = T extends z.ZodTypeAny ? z.output<T> : never;\ntype InferZodInput<T> = T extends z.ZodTypeAny ? z.input<T> : never;\n\ntype ServerActionMiddleware<Context> = (params: { context: Context; input: unknown }) => Promise<{ context: Context } | { error: ServerActionError }>;\n\ntype SafeActionClientArgs<Context extends object, InputSchema extends z.ZodTypeAny | undefined, OutputSchema extends z.ZodTypeAny | undefined> = {\n middlewareFns: ServerActionMiddleware<any>[];\n inputSchema?: InputSchema;\n outputSchema?: OutputSchema;\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n ctxType?: Context;\n};\n\nexport class ServerActionClient<Context extends object = {}, InputSchema extends z.ZodTypeAny | undefined = undefined, OutputSchema extends z.ZodTypeAny | undefined = undefined> {\n readonly #args: SafeActionClientArgs<Context, InputSchema, OutputSchema>;\n\n constructor(\n args: SafeActionClientArgs<Context, InputSchema, OutputSchema> = {\n middlewareFns: [],\n }\n ) {\n this.#args = args;\n }\n\n /**\n * Use a middleware function.\n * @param middlewareFn Middleware function\n */\n use<NextContext extends object>(middlewareFn: ServerActionMiddleware<Context & NextContext>) {\n return new ServerActionClient<Context & NextContext, InputSchema, OutputSchema>({\n ...this.#args,\n middlewareFns: [...this.#args.middlewareFns, middlewareFn] as any,\n ctxType: {} as Context & NextContext,\n });\n }\n\n /**\n * Define the input validation schema for the action.\n * @param schema Input validation schema\n */\n inputSchema<IS extends z.ZodTypeAny>(schema: IS) {\n return new ServerActionClient<Context, IS, OutputSchema>({\n ...this.#args,\n inputSchema: schema,\n });\n }\n\n /**\n * Define the output validation schema for the action.\n * @param schema Output validation schema\n */\n outputSchema<OS extends z.ZodTypeAny>(schema: OS) {\n return new ServerActionClient<Context, InputSchema, OS>({\n ...this.#args,\n outputSchema: schema,\n });\n }\n\n /**\n * Define a custom error handler for the action.\n * @param handler Error handler function\n */\n onError(handler: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n onError: handler,\n });\n }\n\n /**\n * Define the action.\n * @param serverCodeFn Code that will be executed on the server side\n */\n action<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (input: void, context: Context) => Promise<Data>\n ): ServerAction<InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void, OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data> {\n return createServerAction<\n InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void,\n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n >({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn: serverCodeFn as any,\n });\n }\n\n /**\n * Define a form action that accepts FormData.\n * @param serverCodeFn Code that will be executed on the server side\n */\n formAction<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (input: void, context: Context) => Promise<Data>\n ): (prev: ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>, formData: FormData) => Promise<ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>> {\n return createFormServerAction({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn,\n });\n }\n}\n\n// Internal function to create the actual server action\nfunction createServerAction<TInput, TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (parsedInput: any, context: any) => Promise<any>;\n}): ServerAction<TInput, TOutput> {\n const actionFn = async (...args: TInput extends void ? [] : [input: TInput]): Promise<ServerActionResponse<TOutput>> => {\n const input = args[0] as TInput;\n const context: { parsedInput?: unknown } = {};\n\n try {\n let parsedInput: any = input;\n\n // Input validation\n if (config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(input);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput: input }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const result = await middleware({ context: middlewareContext, input: parsedInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = await config.serverCodeFn(parsedInput, middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n \n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[executeAction] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n \n // Use the handleServerActionError function with custom handler\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n \n return handleServerActionError(error, errorHandler);\n }\n };\n\n // Return the function with correct typing based on whether input is void\n return actionFn as ServerAction<TInput, TOutput>;\n}\n\n// Form data parser\nfunction parseFormData(formData: FormData): Record<string, any> {\n const result: Record<string, any> = {};\n const keys = new Set<string>();\n\n for (const [key] of formData.entries()) {\n keys.add(key);\n }\n\n for (const key of keys) {\n const values = formData.getAll(key);\n\n if (key.endsWith(\"[]\")) {\n const cleanKey = key.slice(0, -2);\n result[cleanKey] = values;\n } else if (values.length === 1) {\n result[key] = values[0];\n } else {\n result[key] = values;\n }\n }\n\n return result;\n}\n\n// Internal function to create form server action\nfunction createFormServerAction<TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (parsedInput: any, context: any) => Promise<any>;\n}): (prev: ServerActionResponse<TOutput>, formData: FormData) => Promise<ServerActionResponse<TOutput>> {\n return async (_prev: ServerActionResponse<TOutput>, formData: FormData): Promise<ServerActionResponse<TOutput>> => {\n const context: { parsedInput?: unknown } = {};\n\n try {\n let parsedInput: any = parseFormData(formData);\n\n // Input validation\n if (config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(parsedInput);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const result = await middleware({ context: middlewareContext, input: parsedInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = await config.serverCodeFn(parsedInput, middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[ServerActionClient] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n return handleServerActionError(error, errorHandler);\n }\n };\n}\n\n// Export factory function for creating a new client\nexport function createActionClient() {\n return new ServerActionClient();\n}\n"],"mappings":"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","names":["result"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/error-handler.ts","../src/core/server-action-client.ts"],"sourcesContent":["// Type exports\nexport * from \"./types\";\n\n// Core exports (server-safe)\nexport * from \"./core/error-handler\";\n\n// Server Action Client (class-based API)\nexport { ServerActionClient, createActionClient } from \"./core/server-action-client\";\n","import { z, ZodError } from \"zod\";\nimport type { ServerActionError, ServerActionResponse } from \"../types\";\n\nfunction convertZodError(error: ZodError): ServerActionError {\n const { fieldErrors, formErrors } = z.flattenError(error);\n const [field] = Object.keys(fieldErrors) as (keyof typeof fieldErrors)[];\n const message = (field && fieldErrors[field]?.[0]) ?? formErrors[0] ?? \"Validation failed\";\n return {\n message,\n code: \"VALIDATION_ERROR\",\n field,\n fields: fieldErrors,\n };\n}\n\nfunction convertGenericError(error: unknown): ServerActionError {\n const message = error instanceof Error ? error.message : \"An unexpected error occurred\";\n\n return {\n message: process.env.NODE_ENV === \"production\" ? \"An unexpected error occurred\" : message,\n code: \"INTERNAL_ERROR\",\n statusCode: 500,\n };\n}\n\nexport function handleServerActionError(\n error: unknown,\n customHandler?: (error: unknown) => ServerActionError | undefined\n): { success: false; error: ServerActionError } {\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.error(\"[Server Action Error]\", error?.constructor?.name || 'Unknown', error instanceof Error ? error.message : error);\n }\n\n // Try custom handler first\n if (customHandler) {\n try {\n const customError = customHandler(error);\n if (customError) {\n return {\n success: false,\n error: customError,\n };\n }\n } catch (handlerError) {\n console.error(\"[Server Action Error] Custom handler threw an error:\", handlerError);\n }\n }\n\n if (error instanceof ZodError) {\n return {\n success: false,\n error: convertZodError(error),\n };\n }\n\n if (error instanceof Error && \"toServerActionError\" in error && typeof error.toServerActionError === \"function\") {\n const serverError = error.toServerActionError() as ServerActionError;\n \n // Check if this is an auth error based on the error type/code\n if (serverError.code === \"AUTHENTICATION_ERROR\" || (error as any).type === \"AUTHENTICATION_ERROR\") {\n serverError.shouldRedirect = true;\n serverError.redirectTo = \"/login\";\n }\n \n return {\n success: false,\n error: serverError,\n };\n }\n\n return {\n success: false,\n error: convertGenericError(error),\n };\n}\n\nexport function isErrorResponse<T>(response: ServerActionResponse<T>): response is { success: false; error: ServerActionError } {\n return !response.success;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\n\ntype InferZodOutput<T> = T extends z.ZodTypeAny ? z.output<T> : never;\ntype InferZodInput<T> = T extends z.ZodTypeAny ? z.input<T> : never;\n\ntype ServerActionMiddleware<Context> = (params: { context: Context; input: unknown }) => Promise<{ context: Context } | { error: ServerActionError }>;\n\ntype SafeActionClientArgs<Context extends object, InputSchema extends z.ZodTypeAny | undefined, OutputSchema extends z.ZodTypeAny | undefined> = {\n middlewareFns: ServerActionMiddleware<any>[];\n inputSchema?: InputSchema;\n outputSchema?: OutputSchema;\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n ctxType?: Context;\n};\n\nexport class ServerActionClient<Context extends object = {}, InputSchema extends z.ZodTypeAny | undefined = undefined, OutputSchema extends z.ZodTypeAny | undefined = undefined> {\n readonly #args: SafeActionClientArgs<Context, InputSchema, OutputSchema>;\n\n constructor(\n args: SafeActionClientArgs<Context, InputSchema, OutputSchema> = {\n middlewareFns: [],\n }\n ) {\n this.#args = args;\n }\n\n /**\n * Use a middleware function.\n * @param middlewareFn Middleware function\n */\n use<NextContext extends object>(middlewareFn: ServerActionMiddleware<Context & NextContext>) {\n return new ServerActionClient<Context & NextContext, InputSchema, OutputSchema>({\n ...this.#args,\n middlewareFns: [...this.#args.middlewareFns, middlewareFn] as any,\n ctxType: {} as Context & NextContext,\n });\n }\n\n /**\n * Define the input validation schema for the action.\n * @param schema Input validation schema\n */\n inputSchema<IS extends z.ZodTypeAny>(schema: IS) {\n return new ServerActionClient<Context, IS, OutputSchema>({\n ...this.#args,\n inputSchema: schema,\n });\n }\n\n /**\n * Define the output validation schema for the action.\n * @param schema Output validation schema\n */\n outputSchema<OS extends z.ZodTypeAny>(schema: OS) {\n return new ServerActionClient<Context, InputSchema, OS>({\n ...this.#args,\n outputSchema: schema,\n });\n }\n\n /**\n * Define a custom error handler for the action.\n * @param handler Error handler function\n */\n onError(handler: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n onError: handler,\n });\n }\n\n /**\n * Define the action.\n * @param serverCodeFn Code that will be executed on the server side\n */\n action<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): ServerAction<InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void, OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data> {\n return createServerAction<\n InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void,\n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n >({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn: serverCodeFn as any,\n });\n }\n\n /**\n * Define a form action that accepts FormData.\n * @param serverCodeFn Code that will be executed on the server side\n */\n formAction<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): (prev: ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>, formData: FormData) => Promise<ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>> {\n return createFormServerAction({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn,\n });\n }\n}\n\n// Internal function to create the actual server action\nfunction createServerAction<TInput, TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (...args: any[]) => Promise<any>;\n}): ServerAction<TInput, TOutput> {\n const actionFn = async (...args: TInput extends void ? [] : [input: TInput]): Promise<ServerActionResponse<TOutput>> => {\n const context: { parsedInput?: unknown } = {};\n \n // Type guard: check if we have an input schema\n const hasInputSchema = config.inputSchema !== undefined && config.inputSchema !== null;\n const input = hasInputSchema ? args[0] as TInput : undefined;\n\n try {\n let parsedInput: any = undefined;\n\n // Input validation\n if (hasInputSchema && config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(input);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput: input }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const middlewareInput = hasInputSchema ? parsedInput : undefined;\n const result = await middleware({ context: middlewareContext, input: middlewareInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = hasInputSchema \n ? await config.serverCodeFn(parsedInput, middlewareContext)\n : await config.serverCodeFn(middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n \n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[executeAction] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n \n // Use the handleServerActionError function with custom handler\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n \n return handleServerActionError(error, errorHandler);\n }\n };\n\n // Add metadata for runtime type checking\n (actionFn as any).__hasInputSchema = config.inputSchema !== undefined && config.inputSchema !== null;\n \n // Return the function with correct typing based on whether input is void\n return actionFn as ServerAction<TInput, TOutput>;\n}\n\n// Form data parser\nfunction parseFormData(formData: FormData): Record<string, any> {\n const result: Record<string, any> = {};\n const keys = new Set<string>();\n\n for (const [key] of formData.entries()) {\n keys.add(key);\n }\n\n for (const key of keys) {\n const values = formData.getAll(key);\n\n if (key.endsWith(\"[]\")) {\n const cleanKey = key.slice(0, -2);\n result[cleanKey] = values;\n } else if (values.length === 1) {\n result[key] = values[0];\n } else {\n result[key] = values;\n }\n }\n\n return result;\n}\n\n// Internal function to create form server action\nfunction createFormServerAction<TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (...args: any[]) => Promise<any>;\n}): (prev: ServerActionResponse<TOutput>, formData: FormData) => Promise<ServerActionResponse<TOutput>> {\n return async (_prev: ServerActionResponse<TOutput>, formData: FormData): Promise<ServerActionResponse<TOutput>> => {\n const context: { parsedInput?: unknown } = {};\n const hasInputSchema = config.inputSchema !== undefined && config.inputSchema !== null;\n\n try {\n let parsedInput: any = parseFormData(formData);\n\n // Input validation\n if (config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(parsedInput);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const middlewareInput = hasInputSchema ? parsedInput : undefined;\n const result = await middleware({ context: middlewareContext, input: middlewareInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = hasInputSchema \n ? await config.serverCodeFn(parsedInput, middlewareContext)\n : await config.serverCodeFn(middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[ServerActionClient] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n return handleServerActionError(error, errorHandler);\n }\n };\n}\n\n// Export factory function for creating a new client\nexport function createActionClient() {\n return new ServerActionClient();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,iBAA4B;AAG5B,SAAS,gBAAgB,OAAoC;AAC3D,QAAM,EAAE,aAAa,WAAW,IAAI,aAAE,aAAa,KAAK;AACxD,QAAM,CAAC,KAAK,IAAI,OAAO,KAAK,WAAW;AACvC,QAAM,WAAW,SAAS,YAAY,KAAK,IAAI,CAAC,MAAM,WAAW,CAAC,KAAK;AACvE,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA,QAAQ;AAAA,EACV;AACF;AAEA,SAAS,oBAAoB,OAAmC;AAC9D,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AAEzD,SAAO;AAAA,IACL,SAAS,QAAQ,IAAI,aAAa,eAAe,iCAAiC;AAAA,IAClF,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AACF;AAEO,SAAS,wBACd,OACA,eAC8C;AAE9C,MAAI,QAAQ,IAAI,aAAa,eAAe;AAC1C,YAAQ,MAAM,yBAAyB,OAAO,aAAa,QAAQ,WAAW,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AAAA,EAC9H;AAGA,MAAI,eAAe;AACjB,QAAI;AACF,YAAM,cAAc,cAAc,KAAK;AACvC,UAAI,aAAa;AACf,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,SAAS,cAAc;AACrB,cAAQ,MAAM,wDAAwD,YAAY;AAAA,IACpF;AAAA,EACF;AAEA,MAAI,iBAAiB,qBAAU;AAC7B,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,gBAAgB,KAAK;AAAA,IAC9B;AAAA,EACF;AAEA,MAAI,iBAAiB,SAAS,yBAAyB,SAAS,OAAO,MAAM,wBAAwB,YAAY;AAC/G,UAAM,cAAc,MAAM,oBAAoB;AAG9C,QAAI,YAAY,SAAS,0BAA2B,MAAc,SAAS,wBAAwB;AACjG,kBAAY,iBAAiB;AAC7B,kBAAY,aAAa;AAAA,IAC3B;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO,oBAAoB,KAAK;AAAA,EAClC;AACF;AAEO,SAAS,gBAAmB,UAA6F;AAC9H,SAAO,CAAC,SAAS;AACnB;;;AC/EA;AAiBO,IAAM,sBAAN,MAAM,oBAAqK;AAAA,EAGhL,YACE,OAAiE;AAAA,IAC/D,eAAe,CAAC;AAAA,EAClB,GACA;AANF,uBAAS;AAOP,uBAAK,OAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAgC,cAA6D;AAC3F,WAAO,IAAI,oBAAqE;AAAA,MAC9E,GAAG,mBAAK;AAAA,MACR,eAAe,CAAC,GAAG,mBAAK,OAAM,eAAe,YAAY;AAAA,MACzD,SAAS,CAAC;AAAA,IACZ,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAqC,QAAY;AAC/C,WAAO,IAAI,oBAA8C;AAAA,MACvD,GAAG,mBAAK;AAAA,MACR,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAsC,QAAY;AAChD,WAAO,IAAI,oBAA6C;AAAA,MACtD,GAAG,mBAAK;AAAA,MACR,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,SAAgG;AACtG,WAAO,IAAI,oBAAuD;AAAA,MAChE,GAAG,mBAAK;AAAA,MACR,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OACE,cAG6J;AAC7J,WAAO,mBAGL;AAAA,MACA,aAAa,mBAAK,OAAM;AAAA,MACxB,cAAc,mBAAK,OAAM;AAAA,MACzB,eAAe,mBAAK,OAAM;AAAA,MAC1B,SAAS,mBAAK,OAAM;AAAA,MACpB;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WACE,cAGqO;AACrO,WAAO,uBAAuB;AAAA,MAC5B,aAAa,mBAAK,OAAM;AAAA,MACxB,cAAc,mBAAK,OAAM;AAAA,MACzB,eAAe,mBAAK,OAAM;AAAA,MAC1B,SAAS,mBAAK,OAAM;AAAA,MACpB;AAAA,IACF,CAAC;AAAA,EACH;AACF;AA7FW;AADJ,IAAM,qBAAN;AAiGP,SAAS,mBAAoC,QAMX;AAChC,QAAM,WAAW,UAAU,SAA6F;AACtH,UAAM,UAAqC,CAAC;AAG5C,UAAM,iBAAiB,OAAO,gBAAgB,UAAa,OAAO,gBAAgB;AAClF,UAAM,QAAQ,iBAAiB,KAAK,CAAC,IAAc;AAEnD,QAAI;AACF,UAAI,cAAmB;AAGvB,UAAI,kBAAkB,OAAO,aAAa;AACxC,cAAM,cAAc,OAAO,YAAY,UAAU,KAAK;AACtD,YAAI,CAAC,YAAY,SAAS;AACxB,iBAAO,wBAAwB,YAAY,OAAO,OAAO,UAAU,CAAC,QAAQ,OAAO,QAAS,KAAK,EAAE,aAAa,MAAM,CAAC,IAAI,MAAS;AAAA,QACtI;AACA,sBAAc,YAAY;AAC1B,gBAAQ,cAAc;AAAA,MACxB;AAGA,UAAI,oBAAoB,CAAC;AACzB,iBAAW,cAAc,OAAO,eAAe;AAC7C,cAAM,kBAAkB,iBAAiB,cAAc;AACvD,cAAMA,UAAS,MAAM,WAAW,EAAE,SAAS,mBAAmB,OAAO,gBAAgB,CAAC;AACtF,YAAI,WAAWA,SAAQ;AACrB,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,OAAOA,QAAO;AAAA,UAChB;AAAA,QACF;AACA,4BAAoB,EAAE,GAAG,mBAAmB,GAAGA,QAAO,QAAQ;AAAA,MAChE;AAGA,YAAM,SAAS,iBACX,MAAM,OAAO,aAAa,aAAa,iBAAiB,IACxD,MAAM,OAAO,aAAa,iBAAiB;AAG/C,UAAI,kBAAuB;AAC3B,UAAI,OAAO,cAAc;AACvB,cAAM,cAAc,OAAO,aAAa,UAAU,MAAM;AACxD,YAAI,CAAC,YAAY,SAAS;AACxB,iBAAO,wBAAwB,YAAY,KAAK;AAAA,QAClD;AACA,0BAAkB,YAAY;AAAA,MAChC;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM;AAAA,MACR;AAAA,IACF,SAAS,OAAO;AAEd,UAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,eAAe,GAAG;AACrE,cAAM;AAAA,MACR;AAGA,UAAI,QAAQ,IAAI,aAAa,eAAe;AAC1C,gBAAQ,IAAI,0BAA0B,OAAO,aAAa,MAAM,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AAAA,MAChH;AAGA,YAAM,eAAe,OAAO,UAAU,CAAC,QAAiB;AACtD,eAAO,OAAO,QAAS,KAAK,EAAE,aAAa,QAAQ,YAAY,CAAC;AAAA,MAClE,IAAI;AAEJ,aAAO,wBAAwB,OAAO,YAAY;AAAA,IACpD;AAAA,EACF;AAGA,EAAC,SAAiB,mBAAmB,OAAO,gBAAgB,UAAa,OAAO,gBAAgB;AAGhG,SAAO;AACT;AAGA,SAAS,cAAc,UAAyC;AAC9D,QAAM,SAA8B,CAAC;AACrC,QAAM,OAAO,oBAAI,IAAY;AAE7B,aAAW,CAAC,GAAG,KAAK,SAAS,QAAQ,GAAG;AACtC,SAAK,IAAI,GAAG;AAAA,EACd;AAEA,aAAW,OAAO,MAAM;AACtB,UAAM,SAAS,SAAS,OAAO,GAAG;AAElC,QAAI,IAAI,SAAS,IAAI,GAAG;AACtB,YAAM,WAAW,IAAI,MAAM,GAAG,EAAE;AAChC,aAAO,QAAQ,IAAI;AAAA,IACrB,WAAW,OAAO,WAAW,GAAG;AAC9B,aAAO,GAAG,IAAI,OAAO,CAAC;AAAA,IACxB,OAAO;AACL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;AAGA,SAAS,uBAAgC,QAM+D;AACtG,SAAO,OAAO,OAAsC,aAA+D;AACjH,UAAM,UAAqC,CAAC;AAC5C,UAAM,iBAAiB,OAAO,gBAAgB,UAAa,OAAO,gBAAgB;AAElF,QAAI;AACF,UAAI,cAAmB,cAAc,QAAQ;AAG7C,UAAI,OAAO,aAAa;AACtB,cAAM,cAAc,OAAO,YAAY,UAAU,WAAW;AAC5D,YAAI,CAAC,YAAY,SAAS;AACxB,iBAAO,wBAAwB,YAAY,OAAO,OAAO,UAAU,CAAC,QAAQ,OAAO,QAAS,KAAK,EAAE,YAAY,CAAC,IAAI,MAAS;AAAA,QAC/H;AACA,sBAAc,YAAY;AAC1B,gBAAQ,cAAc;AAAA,MACxB;AAGA,UAAI,oBAAoB,CAAC;AACzB,iBAAW,cAAc,OAAO,eAAe;AAC7C,cAAM,kBAAkB,iBAAiB,cAAc;AACvD,cAAMA,UAAS,MAAM,WAAW,EAAE,SAAS,mBAAmB,OAAO,gBAAgB,CAAC;AACtF,YAAI,WAAWA,SAAQ;AACrB,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,OAAOA,QAAO;AAAA,UAChB;AAAA,QACF;AACA,4BAAoB,EAAE,GAAG,mBAAmB,GAAGA,QAAO,QAAQ;AAAA,MAChE;AAGA,YAAM,SAAS,iBACX,MAAM,OAAO,aAAa,aAAa,iBAAiB,IACxD,MAAM,OAAO,aAAa,iBAAiB;AAG/C,UAAI,kBAAuB;AAC3B,UAAI,OAAO,cAAc;AACvB,cAAM,cAAc,OAAO,aAAa,UAAU,MAAM;AACxD,YAAI,CAAC,YAAY,SAAS;AACxB,iBAAO,wBAAwB,YAAY,KAAK;AAAA,QAClD;AACA,0BAAkB,YAAY;AAAA,MAChC;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM;AAAA,MACR;AAAA,IACF,SAAS,OAAO;AAEd,UAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,eAAe,GAAG;AACrE,cAAM;AAAA,MACR;AAEA,UAAI,QAAQ,IAAI,aAAa,eAAe;AAC1C,gBAAQ,IAAI,+BAA+B,OAAO,aAAa,MAAM,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AAAA,MACrH;AACA,YAAM,eAAe,OAAO,UAAU,CAAC,QAAiB;AACtD,eAAO,OAAO,QAAS,KAAK,EAAE,aAAa,QAAQ,YAAY,CAAC;AAAA,MAClE,IAAI;AACJ,aAAO,wBAAwB,OAAO,YAAY;AAAA,IACpD;AAAA,EACF;AACF;AAGO,SAAS,qBAAqB;AACnC,SAAO,IAAI,mBAAmB;AAChC;","names":["result"]}
|
package/dist/index.mjs
CHANGED
|
@@ -151,11 +151,12 @@ _args = new WeakMap();
|
|
|
151
151
|
var ServerActionClient = _ServerActionClient;
|
|
152
152
|
function createServerAction(config) {
|
|
153
153
|
const actionFn = async (...args) => {
|
|
154
|
-
const input = args[0];
|
|
155
154
|
const context = {};
|
|
155
|
+
const hasInputSchema = config.inputSchema !== void 0 && config.inputSchema !== null;
|
|
156
|
+
const input = hasInputSchema ? args[0] : void 0;
|
|
156
157
|
try {
|
|
157
|
-
let parsedInput =
|
|
158
|
-
if (config.inputSchema) {
|
|
158
|
+
let parsedInput = void 0;
|
|
159
|
+
if (hasInputSchema && config.inputSchema) {
|
|
159
160
|
const parseResult = config.inputSchema.safeParse(input);
|
|
160
161
|
if (!parseResult.success) {
|
|
161
162
|
return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError(err, { parsedInput: input }) : void 0);
|
|
@@ -165,7 +166,8 @@ function createServerAction(config) {
|
|
|
165
166
|
}
|
|
166
167
|
let middlewareContext = {};
|
|
167
168
|
for (const middleware of config.middlewareFns) {
|
|
168
|
-
const
|
|
169
|
+
const middlewareInput = hasInputSchema ? parsedInput : void 0;
|
|
170
|
+
const result2 = await middleware({ context: middlewareContext, input: middlewareInput });
|
|
169
171
|
if ("error" in result2) {
|
|
170
172
|
return {
|
|
171
173
|
success: false,
|
|
@@ -174,7 +176,7 @@ function createServerAction(config) {
|
|
|
174
176
|
}
|
|
175
177
|
middlewareContext = { ...middlewareContext, ...result2.context };
|
|
176
178
|
}
|
|
177
|
-
const result = await config.serverCodeFn(parsedInput, middlewareContext);
|
|
179
|
+
const result = hasInputSchema ? await config.serverCodeFn(parsedInput, middlewareContext) : await config.serverCodeFn(middlewareContext);
|
|
178
180
|
let validatedOutput = result;
|
|
179
181
|
if (config.outputSchema) {
|
|
180
182
|
const parseResult = config.outputSchema.safeParse(result);
|
|
@@ -200,6 +202,7 @@ function createServerAction(config) {
|
|
|
200
202
|
return handleServerActionError(error, errorHandler);
|
|
201
203
|
}
|
|
202
204
|
};
|
|
205
|
+
actionFn.__hasInputSchema = config.inputSchema !== void 0 && config.inputSchema !== null;
|
|
203
206
|
return actionFn;
|
|
204
207
|
}
|
|
205
208
|
function parseFormData(formData) {
|
|
@@ -224,6 +227,7 @@ function parseFormData(formData) {
|
|
|
224
227
|
function createFormServerAction(config) {
|
|
225
228
|
return async (_prev, formData) => {
|
|
226
229
|
const context = {};
|
|
230
|
+
const hasInputSchema = config.inputSchema !== void 0 && config.inputSchema !== null;
|
|
227
231
|
try {
|
|
228
232
|
let parsedInput = parseFormData(formData);
|
|
229
233
|
if (config.inputSchema) {
|
|
@@ -236,7 +240,8 @@ function createFormServerAction(config) {
|
|
|
236
240
|
}
|
|
237
241
|
let middlewareContext = {};
|
|
238
242
|
for (const middleware of config.middlewareFns) {
|
|
239
|
-
const
|
|
243
|
+
const middlewareInput = hasInputSchema ? parsedInput : void 0;
|
|
244
|
+
const result2 = await middleware({ context: middlewareContext, input: middlewareInput });
|
|
240
245
|
if ("error" in result2) {
|
|
241
246
|
return {
|
|
242
247
|
success: false,
|
|
@@ -245,7 +250,7 @@ function createFormServerAction(config) {
|
|
|
245
250
|
}
|
|
246
251
|
middlewareContext = { ...middlewareContext, ...result2.context };
|
|
247
252
|
}
|
|
248
|
-
const result = await config.serverCodeFn(parsedInput, middlewareContext);
|
|
253
|
+
const result = hasInputSchema ? await config.serverCodeFn(parsedInput, middlewareContext) : await config.serverCodeFn(middlewareContext);
|
|
249
254
|
let validatedOutput = result;
|
|
250
255
|
if (config.outputSchema) {
|
|
251
256
|
const parseResult = config.outputSchema.safeParse(result);
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/error-handler.ts","../src/core/server-action-client.ts"],"sourcesContent":["import { z, ZodError } from \"zod\";\nimport type { ServerActionError, ServerActionResponse } from \"../types\";\n\nfunction convertZodError(error: ZodError): ServerActionError {\n const { fieldErrors, formErrors } = z.flattenError(error);\n const [field] = Object.keys(fieldErrors) as (keyof typeof fieldErrors)[];\n const message = (field && fieldErrors[field]?.[0]) ?? formErrors[0] ?? \"Validation failed\";\n return {\n message,\n code: \"VALIDATION_ERROR\",\n field,\n fields: fieldErrors,\n };\n}\n\nfunction convertGenericError(error: unknown): ServerActionError {\n const message = error instanceof Error ? error.message : \"An unexpected error occurred\";\n\n return {\n message: process.env.NODE_ENV === \"production\" ? \"An unexpected error occurred\" : message,\n code: \"INTERNAL_ERROR\",\n statusCode: 500,\n };\n}\n\nexport function handleServerActionError(\n error: unknown,\n customHandler?: (error: unknown) => ServerActionError | undefined\n): { success: false; error: ServerActionError } {\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.error(\"[Server Action Error]\", error?.constructor?.name || 'Unknown', error instanceof Error ? error.message : error);\n }\n\n // Try custom handler first\n if (customHandler) {\n try {\n const customError = customHandler(error);\n if (customError) {\n return {\n success: false,\n error: customError,\n };\n }\n } catch (handlerError) {\n console.error(\"[Server Action Error] Custom handler threw an error:\", handlerError);\n }\n }\n\n if (error instanceof ZodError) {\n return {\n success: false,\n error: convertZodError(error),\n };\n }\n\n if (error instanceof Error && \"toServerActionError\" in error && typeof error.toServerActionError === \"function\") {\n const serverError = error.toServerActionError() as ServerActionError;\n \n // Check if this is an auth error based on the error type/code\n if (serverError.code === \"AUTHENTICATION_ERROR\" || (error as any).type === \"AUTHENTICATION_ERROR\") {\n serverError.shouldRedirect = true;\n serverError.redirectTo = \"/login\";\n }\n \n return {\n success: false,\n error: serverError,\n };\n }\n\n return {\n success: false,\n error: convertGenericError(error),\n };\n}\n\nexport function isErrorResponse<T>(response: ServerActionResponse<T>): response is { success: false; error: ServerActionError } {\n return !response.success;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\n\ntype InferZodOutput<T> = T extends z.ZodTypeAny ? z.output<T> : never;\ntype InferZodInput<T> = T extends z.ZodTypeAny ? z.input<T> : never;\n\ntype ServerActionMiddleware<Context> = (params: { context: Context; input: unknown }) => Promise<{ context: Context } | { error: ServerActionError }>;\n\ntype SafeActionClientArgs<Context extends object, InputSchema extends z.ZodTypeAny | undefined, OutputSchema extends z.ZodTypeAny | undefined> = {\n middlewareFns: ServerActionMiddleware<any>[];\n inputSchema?: InputSchema;\n outputSchema?: OutputSchema;\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n ctxType?: Context;\n};\n\nexport class ServerActionClient<Context extends object = {}, InputSchema extends z.ZodTypeAny | undefined = undefined, OutputSchema extends z.ZodTypeAny | undefined = undefined> {\n readonly #args: SafeActionClientArgs<Context, InputSchema, OutputSchema>;\n\n constructor(\n args: SafeActionClientArgs<Context, InputSchema, OutputSchema> = {\n middlewareFns: [],\n }\n ) {\n this.#args = args;\n }\n\n /**\n * Use a middleware function.\n * @param middlewareFn Middleware function\n */\n use<NextContext extends object>(middlewareFn: ServerActionMiddleware<Context & NextContext>) {\n return new ServerActionClient<Context & NextContext, InputSchema, OutputSchema>({\n ...this.#args,\n middlewareFns: [...this.#args.middlewareFns, middlewareFn] as any,\n ctxType: {} as Context & NextContext,\n });\n }\n\n /**\n * Define the input validation schema for the action.\n * @param schema Input validation schema\n */\n inputSchema<IS extends z.ZodTypeAny>(schema: IS) {\n return new ServerActionClient<Context, IS, OutputSchema>({\n ...this.#args,\n inputSchema: schema,\n });\n }\n\n /**\n * Define the output validation schema for the action.\n * @param schema Output validation schema\n */\n outputSchema<OS extends z.ZodTypeAny>(schema: OS) {\n return new ServerActionClient<Context, InputSchema, OS>({\n ...this.#args,\n outputSchema: schema,\n });\n }\n\n /**\n * Define a custom error handler for the action.\n * @param handler Error handler function\n */\n onError(handler: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n onError: handler,\n });\n }\n\n /**\n * Define the action.\n * @param serverCodeFn Code that will be executed on the server side\n */\n action<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (input: void, context: Context) => Promise<Data>\n ): ServerAction<InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void, OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data> {\n return createServerAction<\n InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void,\n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n >({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn: serverCodeFn as any,\n });\n }\n\n /**\n * Define a form action that accepts FormData.\n * @param serverCodeFn Code that will be executed on the server side\n */\n formAction<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (input: void, context: Context) => Promise<Data>\n ): (prev: ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>, formData: FormData) => Promise<ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>> {\n return createFormServerAction({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn,\n });\n }\n}\n\n// Internal function to create the actual server action\nfunction createServerAction<TInput, TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (parsedInput: any, context: any) => Promise<any>;\n}): ServerAction<TInput, TOutput> {\n const actionFn = async (...args: TInput extends void ? [] : [input: TInput]): Promise<ServerActionResponse<TOutput>> => {\n const input = args[0] as TInput;\n const context: { parsedInput?: unknown } = {};\n\n try {\n let parsedInput: any = input;\n\n // Input validation\n if (config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(input);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput: input }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const result = await middleware({ context: middlewareContext, input: parsedInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = await config.serverCodeFn(parsedInput, middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n \n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[executeAction] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n \n // Use the handleServerActionError function with custom handler\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n \n return handleServerActionError(error, errorHandler);\n }\n };\n\n // Return the function with correct typing based on whether input is void\n return actionFn as ServerAction<TInput, TOutput>;\n}\n\n// Form data parser\nfunction parseFormData(formData: FormData): Record<string, any> {\n const result: Record<string, any> = {};\n const keys = new Set<string>();\n\n for (const [key] of formData.entries()) {\n keys.add(key);\n }\n\n for (const key of keys) {\n const values = formData.getAll(key);\n\n if (key.endsWith(\"[]\")) {\n const cleanKey = key.slice(0, -2);\n result[cleanKey] = values;\n } else if (values.length === 1) {\n result[key] = values[0];\n } else {\n result[key] = values;\n }\n }\n\n return result;\n}\n\n// Internal function to create form server action\nfunction createFormServerAction<TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (parsedInput: any, context: any) => Promise<any>;\n}): (prev: ServerActionResponse<TOutput>, formData: FormData) => Promise<ServerActionResponse<TOutput>> {\n return async (_prev: ServerActionResponse<TOutput>, formData: FormData): Promise<ServerActionResponse<TOutput>> => {\n const context: { parsedInput?: unknown } = {};\n\n try {\n let parsedInput: any = parseFormData(formData);\n\n // Input validation\n if (config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(parsedInput);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const result = await middleware({ context: middlewareContext, input: parsedInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = await config.serverCodeFn(parsedInput, middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[ServerActionClient] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n return handleServerActionError(error, errorHandler);\n }\n };\n}\n\n// Export factory function for creating a new client\nexport function createActionClient() {\n return new ServerActionClient();\n}\n"],"mappings":"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","names":["result"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/error-handler.ts","../src/core/server-action-client.ts"],"sourcesContent":["import { z, ZodError } from \"zod\";\nimport type { ServerActionError, ServerActionResponse } from \"../types\";\n\nfunction convertZodError(error: ZodError): ServerActionError {\n const { fieldErrors, formErrors } = z.flattenError(error);\n const [field] = Object.keys(fieldErrors) as (keyof typeof fieldErrors)[];\n const message = (field && fieldErrors[field]?.[0]) ?? formErrors[0] ?? \"Validation failed\";\n return {\n message,\n code: \"VALIDATION_ERROR\",\n field,\n fields: fieldErrors,\n };\n}\n\nfunction convertGenericError(error: unknown): ServerActionError {\n const message = error instanceof Error ? error.message : \"An unexpected error occurred\";\n\n return {\n message: process.env.NODE_ENV === \"production\" ? \"An unexpected error occurred\" : message,\n code: \"INTERNAL_ERROR\",\n statusCode: 500,\n };\n}\n\nexport function handleServerActionError(\n error: unknown,\n customHandler?: (error: unknown) => ServerActionError | undefined\n): { success: false; error: ServerActionError } {\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.error(\"[Server Action Error]\", error?.constructor?.name || 'Unknown', error instanceof Error ? error.message : error);\n }\n\n // Try custom handler first\n if (customHandler) {\n try {\n const customError = customHandler(error);\n if (customError) {\n return {\n success: false,\n error: customError,\n };\n }\n } catch (handlerError) {\n console.error(\"[Server Action Error] Custom handler threw an error:\", handlerError);\n }\n }\n\n if (error instanceof ZodError) {\n return {\n success: false,\n error: convertZodError(error),\n };\n }\n\n if (error instanceof Error && \"toServerActionError\" in error && typeof error.toServerActionError === \"function\") {\n const serverError = error.toServerActionError() as ServerActionError;\n \n // Check if this is an auth error based on the error type/code\n if (serverError.code === \"AUTHENTICATION_ERROR\" || (error as any).type === \"AUTHENTICATION_ERROR\") {\n serverError.shouldRedirect = true;\n serverError.redirectTo = \"/login\";\n }\n \n return {\n success: false,\n error: serverError,\n };\n }\n\n return {\n success: false,\n error: convertGenericError(error),\n };\n}\n\nexport function isErrorResponse<T>(response: ServerActionResponse<T>): response is { success: false; error: ServerActionError } {\n return !response.success;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\n\ntype InferZodOutput<T> = T extends z.ZodTypeAny ? z.output<T> : never;\ntype InferZodInput<T> = T extends z.ZodTypeAny ? z.input<T> : never;\n\ntype ServerActionMiddleware<Context> = (params: { context: Context; input: unknown }) => Promise<{ context: Context } | { error: ServerActionError }>;\n\ntype SafeActionClientArgs<Context extends object, InputSchema extends z.ZodTypeAny | undefined, OutputSchema extends z.ZodTypeAny | undefined> = {\n middlewareFns: ServerActionMiddleware<any>[];\n inputSchema?: InputSchema;\n outputSchema?: OutputSchema;\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n ctxType?: Context;\n};\n\nexport class ServerActionClient<Context extends object = {}, InputSchema extends z.ZodTypeAny | undefined = undefined, OutputSchema extends z.ZodTypeAny | undefined = undefined> {\n readonly #args: SafeActionClientArgs<Context, InputSchema, OutputSchema>;\n\n constructor(\n args: SafeActionClientArgs<Context, InputSchema, OutputSchema> = {\n middlewareFns: [],\n }\n ) {\n this.#args = args;\n }\n\n /**\n * Use a middleware function.\n * @param middlewareFn Middleware function\n */\n use<NextContext extends object>(middlewareFn: ServerActionMiddleware<Context & NextContext>) {\n return new ServerActionClient<Context & NextContext, InputSchema, OutputSchema>({\n ...this.#args,\n middlewareFns: [...this.#args.middlewareFns, middlewareFn] as any,\n ctxType: {} as Context & NextContext,\n });\n }\n\n /**\n * Define the input validation schema for the action.\n * @param schema Input validation schema\n */\n inputSchema<IS extends z.ZodTypeAny>(schema: IS) {\n return new ServerActionClient<Context, IS, OutputSchema>({\n ...this.#args,\n inputSchema: schema,\n });\n }\n\n /**\n * Define the output validation schema for the action.\n * @param schema Output validation schema\n */\n outputSchema<OS extends z.ZodTypeAny>(schema: OS) {\n return new ServerActionClient<Context, InputSchema, OS>({\n ...this.#args,\n outputSchema: schema,\n });\n }\n\n /**\n * Define a custom error handler for the action.\n * @param handler Error handler function\n */\n onError(handler: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n onError: handler,\n });\n }\n\n /**\n * Define the action.\n * @param serverCodeFn Code that will be executed on the server side\n */\n action<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): ServerAction<InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void, OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data> {\n return createServerAction<\n InputSchema extends z.ZodTypeAny ? InferZodInput<InputSchema> : void,\n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n >({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn: serverCodeFn as any,\n });\n }\n\n /**\n * Define a form action that accepts FormData.\n * @param serverCodeFn Code that will be executed on the server side\n */\n formAction<Data>(\n serverCodeFn: InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): (prev: ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>, formData: FormData) => Promise<ServerActionResponse<OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data>> {\n return createFormServerAction({\n inputSchema: this.#args.inputSchema,\n outputSchema: this.#args.outputSchema,\n middlewareFns: this.#args.middlewareFns,\n onError: this.#args.onError,\n serverCodeFn,\n });\n }\n}\n\n// Internal function to create the actual server action\nfunction createServerAction<TInput, TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (...args: any[]) => Promise<any>;\n}): ServerAction<TInput, TOutput> {\n const actionFn = async (...args: TInput extends void ? [] : [input: TInput]): Promise<ServerActionResponse<TOutput>> => {\n const context: { parsedInput?: unknown } = {};\n \n // Type guard: check if we have an input schema\n const hasInputSchema = config.inputSchema !== undefined && config.inputSchema !== null;\n const input = hasInputSchema ? args[0] as TInput : undefined;\n\n try {\n let parsedInput: any = undefined;\n\n // Input validation\n if (hasInputSchema && config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(input);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput: input }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const middlewareInput = hasInputSchema ? parsedInput : undefined;\n const result = await middleware({ context: middlewareContext, input: middlewareInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = hasInputSchema \n ? await config.serverCodeFn(parsedInput, middlewareContext)\n : await config.serverCodeFn(middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n \n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[executeAction] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n \n // Use the handleServerActionError function with custom handler\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n \n return handleServerActionError(error, errorHandler);\n }\n };\n\n // Add metadata for runtime type checking\n (actionFn as any).__hasInputSchema = config.inputSchema !== undefined && config.inputSchema !== null;\n \n // Return the function with correct typing based on whether input is void\n return actionFn as ServerAction<TInput, TOutput>;\n}\n\n// Form data parser\nfunction parseFormData(formData: FormData): Record<string, any> {\n const result: Record<string, any> = {};\n const keys = new Set<string>();\n\n for (const [key] of formData.entries()) {\n keys.add(key);\n }\n\n for (const key of keys) {\n const values = formData.getAll(key);\n\n if (key.endsWith(\"[]\")) {\n const cleanKey = key.slice(0, -2);\n result[cleanKey] = values;\n } else if (values.length === 1) {\n result[key] = values[0];\n } else {\n result[key] = values;\n }\n }\n\n return result;\n}\n\n// Internal function to create form server action\nfunction createFormServerAction<TOutput>(config: {\n inputSchema?: z.ZodTypeAny;\n outputSchema?: z.ZodTypeAny;\n middlewareFns: ServerActionMiddleware<any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (...args: any[]) => Promise<any>;\n}): (prev: ServerActionResponse<TOutput>, formData: FormData) => Promise<ServerActionResponse<TOutput>> {\n return async (_prev: ServerActionResponse<TOutput>, formData: FormData): Promise<ServerActionResponse<TOutput>> => {\n const context: { parsedInput?: unknown } = {};\n const hasInputSchema = config.inputSchema !== undefined && config.inputSchema !== null;\n\n try {\n let parsedInput: any = parseFormData(formData);\n\n // Input validation\n if (config.inputSchema) {\n const parseResult = config.inputSchema.safeParse(parsedInput);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error, config.onError ? (err) => config.onError!(err, { parsedInput }) : undefined);\n }\n parsedInput = parseResult.data;\n context.parsedInput = parsedInput;\n }\n\n // Execute middleware chain\n let middlewareContext = {};\n for (const middleware of config.middlewareFns) {\n const middlewareInput = hasInputSchema ? parsedInput : undefined;\n const result = await middleware({ context: middlewareContext, input: middlewareInput });\n if (\"error\" in result) {\n return {\n success: false,\n error: result.error,\n };\n }\n middlewareContext = { ...middlewareContext, ...result.context };\n }\n\n // Execute the server code\n const result = hasInputSchema \n ? await config.serverCodeFn(parsedInput, middlewareContext)\n : await config.serverCodeFn(middlewareContext);\n\n // Output validation\n let validatedOutput: any = result;\n if (config.outputSchema) {\n const parseResult = config.outputSchema.safeParse(result);\n if (!parseResult.success) {\n return handleServerActionError(parseResult.error);\n }\n validatedOutput = parseResult.data;\n }\n\n return {\n success: true,\n data: validatedOutput,\n };\n } catch (error) {\n // Preserve Next.js redirects\n if (error instanceof Error && error.message.includes(\"NEXT_REDIRECT\")) {\n throw error;\n }\n // Debug logging only in development\n if (process.env.NODE_ENV === 'development') {\n console.log(\"[ServerActionClient] Error:\", error?.constructor?.name, error instanceof Error ? error.message : error);\n }\n const errorHandler = config.onError ? (err: unknown) => {\n return config.onError!(err, { parsedInput: context.parsedInput });\n } : undefined;\n return handleServerActionError(error, errorHandler);\n }\n };\n}\n\n// Export factory function for creating a new client\nexport function createActionClient() {\n return new ServerActionClient();\n}\n"],"mappings":"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","names":["result"]}
|