next-action-forge 0.3.2 → 0.3.4

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.
@@ -12,9 +12,9 @@ declare function isErrorResponse<T>(response: ServerActionResponse<T>): response
12
12
 
13
13
  type InferZodOutput<T> = T extends z.ZodTypeAny ? z.output<T> : never;
14
14
  type InferZodInput<T> = T extends z.ZodTypeAny ? z.input<T> : never;
15
- type ServerActionMiddleware<Context> = (params: {
15
+ type ServerActionMiddleware<Context, Input = unknown> = (params: {
16
16
  context: Context;
17
- input: unknown;
17
+ input: Input;
18
18
  }) => Promise<{
19
19
  context: Context;
20
20
  } | {
@@ -22,7 +22,7 @@ type ServerActionMiddleware<Context> = (params: {
22
22
  }>;
23
23
 
24
24
  type SafeActionClientArgs<Context extends object, InputSchema extends z.ZodTypeAny | undefined, OutputSchema extends z.ZodTypeAny | undefined> = {
25
- middlewareFns: ServerActionMiddleware<any>[];
25
+ middlewareFns: ServerActionMiddleware<any, any>[];
26
26
  inputSchema?: InputSchema;
27
27
  outputSchema?: OutputSchema;
28
28
  onError?: (error: unknown, context: {
@@ -38,7 +38,7 @@ declare class ServerActionClient<Context extends object = {}, InputSchema extend
38
38
  * Use a middleware function.
39
39
  * @param middlewareFn Middleware function
40
40
  */
41
- use<NextContext extends object>(middlewareFn: ServerActionMiddleware<Context & NextContext>): ServerActionClient<Context & NextContext, InputSchema, OutputSchema>;
41
+ use<NextContext extends object>(middlewareFn: ServerActionMiddleware<Context & NextContext, InputSchema extends z.ZodTypeAny ? z.output<InputSchema> : undefined>): ServerActionClient<Context & NextContext, InputSchema, OutputSchema>;
42
42
  /**
43
43
  * Define the input validation schema for the action.
44
44
  * @param schema Input validation schema
@@ -12,9 +12,9 @@ declare function isErrorResponse<T>(response: ServerActionResponse<T>): response
12
12
 
13
13
  type InferZodOutput<T> = T extends z.ZodTypeAny ? z.output<T> : never;
14
14
  type InferZodInput<T> = T extends z.ZodTypeAny ? z.input<T> : never;
15
- type ServerActionMiddleware<Context> = (params: {
15
+ type ServerActionMiddleware<Context, Input = unknown> = (params: {
16
16
  context: Context;
17
- input: unknown;
17
+ input: Input;
18
18
  }) => Promise<{
19
19
  context: Context;
20
20
  } | {
@@ -22,7 +22,7 @@ type ServerActionMiddleware<Context> = (params: {
22
22
  }>;
23
23
 
24
24
  type SafeActionClientArgs<Context extends object, InputSchema extends z.ZodTypeAny | undefined, OutputSchema extends z.ZodTypeAny | undefined> = {
25
- middlewareFns: ServerActionMiddleware<any>[];
25
+ middlewareFns: ServerActionMiddleware<any, any>[];
26
26
  inputSchema?: InputSchema;
27
27
  outputSchema?: OutputSchema;
28
28
  onError?: (error: unknown, context: {
@@ -38,7 +38,7 @@ declare class ServerActionClient<Context extends object = {}, InputSchema extend
38
38
  * Use a middleware function.
39
39
  * @param middlewareFn Middleware function
40
40
  */
41
- use<NextContext extends object>(middlewareFn: ServerActionMiddleware<Context & NextContext>): ServerActionClient<Context & NextContext, InputSchema, OutputSchema>;
41
+ use<NextContext extends object>(middlewareFn: ServerActionMiddleware<Context & NextContext, InputSchema extends z.ZodTypeAny ? z.output<InputSchema> : undefined>): ServerActionClient<Context & NextContext, InputSchema, OutputSchema>;
42
42
  /**
43
43
  * Define the input validation schema for the action.
44
44
  * @param schema Input validation schema
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/index.ts","../../src/core/error-handler.ts","../../src/next/errors/redirect.ts","../../src/next/errors/http-access-fallback.ts","../../src/next/errors/index.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}","// Comes from: https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/redirect-error.ts\n\nenum RedirectStatusCode {\n\tSeeOther = 303,\n\tTemporaryRedirect = 307,\n\tPermanentRedirect = 308,\n}\n\nconst REDIRECT_ERROR_CODE = \"NEXT_REDIRECT\";\n\nenum RedirectType {\n\tpush = \"push\",\n\treplace = \"replace\",\n}\n\nexport type RedirectError = Error & {\n\tdigest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by the\n * `redirect(url)` helper.\n *\n * @param error the error that may reference a redirect error\n * @returns true if the error is a redirect error\n */\nexport function isRedirectError(error: unknown): error is RedirectError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\n\tconst digest = error.digest.split(\";\");\n\tconst [errorCode, type] = digest;\n\tconst destination = digest.slice(2, -2).join(\";\");\n\tconst status = digest.at(-2);\n\n\tconst statusCode = Number(status);\n\n\treturn (\n\t\terrorCode === REDIRECT_ERROR_CODE &&\n\t\t(type === \"replace\" || type === \"push\") &&\n\t\ttypeof destination === \"string\" &&\n\t\t!isNaN(statusCode) &&\n\t\tstatusCode in RedirectStatusCode\n\t);\n}","// Comes from https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/http-access-fallback/http-access-fallback.ts\n\nconst HTTPAccessErrorStatus = {\n\tNOT_FOUND: 404,\n\tFORBIDDEN: 403,\n\tUNAUTHORIZED: 401,\n};\n\nconst ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatus));\n\nconst HTTP_ERROR_FALLBACK_ERROR_CODE = \"NEXT_HTTP_ERROR_FALLBACK\";\n\nexport type HTTPAccessFallbackError = Error & {\n\tdigest: `${typeof HTTP_ERROR_FALLBACK_ERROR_CODE};${string}`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by\n * the HTTP navigation APIs `notFound()`, `forbidden()` or `unauthorized()`.\n *\n * @param error the error that may reference a HTTP access error\n * @returns true if the error is a HTTP access error\n */\nexport function isHTTPAccessFallbackError(error: unknown): error is HTTPAccessFallbackError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\tconst [prefix, httpStatus] = error.digest.split(\";\");\n\n\treturn prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));\n}\n\nexport function getAccessFallbackHTTPStatus(error: HTTPAccessFallbackError): number {\n\tconst httpStatus = error.digest.split(\";\")[1];\n\treturn Number(httpStatus);\n}","import { isRedirectError } from \"./redirect\";\nimport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\n\nexport { isRedirectError } from \"./redirect\";\nexport type { RedirectError } from \"./redirect\";\n\nexport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\nexport type { HTTPAccessFallbackError } from \"./http-access-fallback\";\n\n/**\n * Checks if the error is a navigation error that should be re-thrown\n * This includes redirect errors and HTTP access errors (notFound, forbidden, unauthorized)\n */\nexport function isNextNavigationError(error: unknown): boolean {\n\treturn isRedirectError(error) || isHTTPAccessFallbackError(error);\n}\n\n/**\n * Checks if the error is a notFound error\n * Note: Next.js implements notFound() using HTTP_ERROR_FALLBACK with status 404,\n * not as a separate error type like NEXT_REDIRECT\n */\nexport function isNotFoundError(error: unknown): boolean {\n\treturn isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error as any) === 404;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\nimport { isNextNavigationError } from \"../next/errors\";\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\nimport type { RedirectConfig } from \"../types\";\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 a redirect configuration for successful actions.\n * @param config Redirect URL, config object, or function that returns redirect config based on result\n */\n redirect<Data = any>(\n config: string | RedirectConfig | ((result: Data) => string | RedirectConfig | undefined)\n ) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n redirectConfig: config,\n });\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 undefined\n ? (context: Context) => Promise<Data>\n : InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): ServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : void, \n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n > {\n return createServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : 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 redirectConfig: this.#args.redirectConfig,\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 undefined\n ? (context: Context) => Promise<Data>\n : 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 redirectConfig: this.#args.redirectConfig,\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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":["RedirectStatusCode","result"]}
1
+ {"version":3,"sources":["../../src/core/index.ts","../../src/core/error-handler.ts","../../src/next/errors/redirect.ts","../../src/next/errors/http-access-fallback.ts","../../src/next/errors/index.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}","// Comes from: https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/redirect-error.ts\n\nenum RedirectStatusCode {\n\tSeeOther = 303,\n\tTemporaryRedirect = 307,\n\tPermanentRedirect = 308,\n}\n\nconst REDIRECT_ERROR_CODE = \"NEXT_REDIRECT\";\n\nenum RedirectType {\n\tpush = \"push\",\n\treplace = \"replace\",\n}\n\nexport type RedirectError = Error & {\n\tdigest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by the\n * `redirect(url)` helper.\n *\n * @param error the error that may reference a redirect error\n * @returns true if the error is a redirect error\n */\nexport function isRedirectError(error: unknown): error is RedirectError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\n\tconst digest = error.digest.split(\";\");\n\tconst [errorCode, type] = digest;\n\tconst destination = digest.slice(2, -2).join(\";\");\n\tconst status = digest.at(-2);\n\n\tconst statusCode = Number(status);\n\n\treturn (\n\t\terrorCode === REDIRECT_ERROR_CODE &&\n\t\t(type === \"replace\" || type === \"push\") &&\n\t\ttypeof destination === \"string\" &&\n\t\t!isNaN(statusCode) &&\n\t\tstatusCode in RedirectStatusCode\n\t);\n}","// Comes from https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/http-access-fallback/http-access-fallback.ts\n\nconst HTTPAccessErrorStatus = {\n\tNOT_FOUND: 404,\n\tFORBIDDEN: 403,\n\tUNAUTHORIZED: 401,\n};\n\nconst ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatus));\n\nconst HTTP_ERROR_FALLBACK_ERROR_CODE = \"NEXT_HTTP_ERROR_FALLBACK\";\n\nexport type HTTPAccessFallbackError = Error & {\n\tdigest: `${typeof HTTP_ERROR_FALLBACK_ERROR_CODE};${string}`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by\n * the HTTP navigation APIs `notFound()`, `forbidden()` or `unauthorized()`.\n *\n * @param error the error that may reference a HTTP access error\n * @returns true if the error is a HTTP access error\n */\nexport function isHTTPAccessFallbackError(error: unknown): error is HTTPAccessFallbackError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\tconst [prefix, httpStatus] = error.digest.split(\";\");\n\n\treturn prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));\n}\n\nexport function getAccessFallbackHTTPStatus(error: HTTPAccessFallbackError): number {\n\tconst httpStatus = error.digest.split(\";\")[1];\n\treturn Number(httpStatus);\n}","import { isRedirectError } from \"./redirect\";\nimport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\n\nexport { isRedirectError } from \"./redirect\";\nexport type { RedirectError } from \"./redirect\";\n\nexport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\nexport type { HTTPAccessFallbackError } from \"./http-access-fallback\";\n\n/**\n * Checks if the error is a navigation error that should be re-thrown\n * This includes redirect errors and HTTP access errors (notFound, forbidden, unauthorized)\n */\nexport function isNextNavigationError(error: unknown): boolean {\n\treturn isRedirectError(error) || isHTTPAccessFallbackError(error);\n}\n\n/**\n * Checks if the error is a notFound error\n * Note: Next.js implements notFound() using HTTP_ERROR_FALLBACK with status 404,\n * not as a separate error type like NEXT_REDIRECT\n */\nexport function isNotFoundError(error: unknown): boolean {\n\treturn isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error as any) === 404;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\nimport { isNextNavigationError } from \"../next/errors\";\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, Input = unknown> = (params: { context: Context; input: Input }) => Promise<{ context: Context } | { error: ServerActionError }>;\n\nimport type { RedirectConfig } from \"../types\";\n\ntype SafeActionClientArgs<Context extends object, InputSchema extends z.ZodTypeAny | undefined, OutputSchema extends z.ZodTypeAny | undefined> = {\n middlewareFns: ServerActionMiddleware<any, any>[];\n inputSchema?: InputSchema;\n outputSchema?: OutputSchema;\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n ctxType?: Context;\n redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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>(\n middlewareFn: ServerActionMiddleware<\n Context & NextContext, \n InputSchema extends z.ZodTypeAny ? z.output<InputSchema> : undefined\n >\n ) {\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 a redirect configuration for successful actions.\n * @param config Redirect URL, config object, or function that returns redirect config based on result\n */\n redirect<Data = any>(\n config: string | RedirectConfig | ((result: Data) => string | RedirectConfig | undefined)\n ) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n redirectConfig: config,\n });\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 undefined\n ? (context: Context) => Promise<Data>\n : InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): ServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : void, \n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n > {\n return createServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : 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 redirectConfig: this.#args.redirectConfig,\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 undefined\n ? (context: Context) => Promise<Data>\n : 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 redirectConfig: this.#args.redirectConfig,\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, any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (...args: any[]) => Promise<any>;\n redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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":["RedirectStatusCode","result"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/error-handler.ts","../../src/next/errors/redirect.ts","../../src/next/errors/http-access-fallback.ts","../../src/next/errors/index.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}","// Comes from: https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/redirect-error.ts\n\nenum RedirectStatusCode {\n\tSeeOther = 303,\n\tTemporaryRedirect = 307,\n\tPermanentRedirect = 308,\n}\n\nconst REDIRECT_ERROR_CODE = \"NEXT_REDIRECT\";\n\nenum RedirectType {\n\tpush = \"push\",\n\treplace = \"replace\",\n}\n\nexport type RedirectError = Error & {\n\tdigest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by the\n * `redirect(url)` helper.\n *\n * @param error the error that may reference a redirect error\n * @returns true if the error is a redirect error\n */\nexport function isRedirectError(error: unknown): error is RedirectError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\n\tconst digest = error.digest.split(\";\");\n\tconst [errorCode, type] = digest;\n\tconst destination = digest.slice(2, -2).join(\";\");\n\tconst status = digest.at(-2);\n\n\tconst statusCode = Number(status);\n\n\treturn (\n\t\terrorCode === REDIRECT_ERROR_CODE &&\n\t\t(type === \"replace\" || type === \"push\") &&\n\t\ttypeof destination === \"string\" &&\n\t\t!isNaN(statusCode) &&\n\t\tstatusCode in RedirectStatusCode\n\t);\n}","// Comes from https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/http-access-fallback/http-access-fallback.ts\n\nconst HTTPAccessErrorStatus = {\n\tNOT_FOUND: 404,\n\tFORBIDDEN: 403,\n\tUNAUTHORIZED: 401,\n};\n\nconst ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatus));\n\nconst HTTP_ERROR_FALLBACK_ERROR_CODE = \"NEXT_HTTP_ERROR_FALLBACK\";\n\nexport type HTTPAccessFallbackError = Error & {\n\tdigest: `${typeof HTTP_ERROR_FALLBACK_ERROR_CODE};${string}`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by\n * the HTTP navigation APIs `notFound()`, `forbidden()` or `unauthorized()`.\n *\n * @param error the error that may reference a HTTP access error\n * @returns true if the error is a HTTP access error\n */\nexport function isHTTPAccessFallbackError(error: unknown): error is HTTPAccessFallbackError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\tconst [prefix, httpStatus] = error.digest.split(\";\");\n\n\treturn prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));\n}\n\nexport function getAccessFallbackHTTPStatus(error: HTTPAccessFallbackError): number {\n\tconst httpStatus = error.digest.split(\";\")[1];\n\treturn Number(httpStatus);\n}","import { isRedirectError } from \"./redirect\";\nimport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\n\nexport { isRedirectError } from \"./redirect\";\nexport type { RedirectError } from \"./redirect\";\n\nexport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\nexport type { HTTPAccessFallbackError } from \"./http-access-fallback\";\n\n/**\n * Checks if the error is a navigation error that should be re-thrown\n * This includes redirect errors and HTTP access errors (notFound, forbidden, unauthorized)\n */\nexport function isNextNavigationError(error: unknown): boolean {\n\treturn isRedirectError(error) || isHTTPAccessFallbackError(error);\n}\n\n/**\n * Checks if the error is a notFound error\n * Note: Next.js implements notFound() using HTTP_ERROR_FALLBACK with status 404,\n * not as a separate error type like NEXT_REDIRECT\n */\nexport function isNotFoundError(error: unknown): boolean {\n\treturn isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error as any) === 404;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\nimport { isNextNavigationError } from \"../next/errors\";\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\nimport type { RedirectConfig } from \"../types\";\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 a redirect configuration for successful actions.\n * @param config Redirect URL, config object, or function that returns redirect config based on result\n */\n redirect<Data = any>(\n config: string | RedirectConfig | ((result: Data) => string | RedirectConfig | undefined)\n ) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n redirectConfig: config,\n });\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 undefined\n ? (context: Context) => Promise<Data>\n : InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): ServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : void, \n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n > {\n return createServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : 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 redirectConfig: this.#args.redirectConfig,\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 undefined\n ? (context: Context) => Promise<Data>\n : 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 redirectConfig: this.#args.redirectConfig,\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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":["RedirectStatusCode","result"]}
1
+ {"version":3,"sources":["../../src/core/error-handler.ts","../../src/next/errors/redirect.ts","../../src/next/errors/http-access-fallback.ts","../../src/next/errors/index.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}","// Comes from: https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/redirect-error.ts\n\nenum RedirectStatusCode {\n\tSeeOther = 303,\n\tTemporaryRedirect = 307,\n\tPermanentRedirect = 308,\n}\n\nconst REDIRECT_ERROR_CODE = \"NEXT_REDIRECT\";\n\nenum RedirectType {\n\tpush = \"push\",\n\treplace = \"replace\",\n}\n\nexport type RedirectError = Error & {\n\tdigest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by the\n * `redirect(url)` helper.\n *\n * @param error the error that may reference a redirect error\n * @returns true if the error is a redirect error\n */\nexport function isRedirectError(error: unknown): error is RedirectError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\n\tconst digest = error.digest.split(\";\");\n\tconst [errorCode, type] = digest;\n\tconst destination = digest.slice(2, -2).join(\";\");\n\tconst status = digest.at(-2);\n\n\tconst statusCode = Number(status);\n\n\treturn (\n\t\terrorCode === REDIRECT_ERROR_CODE &&\n\t\t(type === \"replace\" || type === \"push\") &&\n\t\ttypeof destination === \"string\" &&\n\t\t!isNaN(statusCode) &&\n\t\tstatusCode in RedirectStatusCode\n\t);\n}","// Comes from https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/http-access-fallback/http-access-fallback.ts\n\nconst HTTPAccessErrorStatus = {\n\tNOT_FOUND: 404,\n\tFORBIDDEN: 403,\n\tUNAUTHORIZED: 401,\n};\n\nconst ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatus));\n\nconst HTTP_ERROR_FALLBACK_ERROR_CODE = \"NEXT_HTTP_ERROR_FALLBACK\";\n\nexport type HTTPAccessFallbackError = Error & {\n\tdigest: `${typeof HTTP_ERROR_FALLBACK_ERROR_CODE};${string}`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by\n * the HTTP navigation APIs `notFound()`, `forbidden()` or `unauthorized()`.\n *\n * @param error the error that may reference a HTTP access error\n * @returns true if the error is a HTTP access error\n */\nexport function isHTTPAccessFallbackError(error: unknown): error is HTTPAccessFallbackError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\tconst [prefix, httpStatus] = error.digest.split(\";\");\n\n\treturn prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));\n}\n\nexport function getAccessFallbackHTTPStatus(error: HTTPAccessFallbackError): number {\n\tconst httpStatus = error.digest.split(\";\")[1];\n\treturn Number(httpStatus);\n}","import { isRedirectError } from \"./redirect\";\nimport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\n\nexport { isRedirectError } from \"./redirect\";\nexport type { RedirectError } from \"./redirect\";\n\nexport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\nexport type { HTTPAccessFallbackError } from \"./http-access-fallback\";\n\n/**\n * Checks if the error is a navigation error that should be re-thrown\n * This includes redirect errors and HTTP access errors (notFound, forbidden, unauthorized)\n */\nexport function isNextNavigationError(error: unknown): boolean {\n\treturn isRedirectError(error) || isHTTPAccessFallbackError(error);\n}\n\n/**\n * Checks if the error is a notFound error\n * Note: Next.js implements notFound() using HTTP_ERROR_FALLBACK with status 404,\n * not as a separate error type like NEXT_REDIRECT\n */\nexport function isNotFoundError(error: unknown): boolean {\n\treturn isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error as any) === 404;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\nimport { isNextNavigationError } from \"../next/errors\";\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, Input = unknown> = (params: { context: Context; input: Input }) => Promise<{ context: Context } | { error: ServerActionError }>;\n\nimport type { RedirectConfig } from \"../types\";\n\ntype SafeActionClientArgs<Context extends object, InputSchema extends z.ZodTypeAny | undefined, OutputSchema extends z.ZodTypeAny | undefined> = {\n middlewareFns: ServerActionMiddleware<any, any>[];\n inputSchema?: InputSchema;\n outputSchema?: OutputSchema;\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n ctxType?: Context;\n redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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>(\n middlewareFn: ServerActionMiddleware<\n Context & NextContext, \n InputSchema extends z.ZodTypeAny ? z.output<InputSchema> : undefined\n >\n ) {\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 a redirect configuration for successful actions.\n * @param config Redirect URL, config object, or function that returns redirect config based on result\n */\n redirect<Data = any>(\n config: string | RedirectConfig | ((result: Data) => string | RedirectConfig | undefined)\n ) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n redirectConfig: config,\n });\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 undefined\n ? (context: Context) => Promise<Data>\n : InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): ServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : void, \n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n > {\n return createServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : 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 redirectConfig: this.#args.redirectConfig,\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 undefined\n ? (context: Context) => Promise<Data>\n : 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 redirectConfig: this.#args.redirectConfig,\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, any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (...args: any[]) => Promise<any>;\n redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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":["RedirectStatusCode","result"]}
@@ -125,7 +125,6 @@ function useServerAction(action, options = {}) {
125
125
  } else {
126
126
  router.push(redirectConfig.url);
127
127
  }
128
- setIsRedirecting(false);
129
128
  }, delay);
130
129
  }
131
130
  } else if (!response.success && response.error) {
@@ -371,7 +370,6 @@ function useFormAction({
371
370
  } else {
372
371
  router.push(redirectConfig.url);
373
372
  }
374
- setIsRedirecting(false);
375
373
  }, delay || 100);
376
374
  }
377
375
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/index.ts","../../src/hooks/use-server-action.ts","../../src/next/errors/redirect.ts","../../src/next/errors/http-access-fallback.ts","../../src/next/errors/index.ts","../../src/hooks/use-optimistic-action.ts","../../src/hooks/use-form-action.ts","../../src/hooks/toast-restorer.tsx"],"sourcesContent":["export * from \"./use-server-action\";\nexport * from \"./use-optimistic-action\";\nexport * from \"./use-form-action\";\nexport { ToastRestorer } from \"./toast-restorer\";","import { useCallback, useState, useTransition } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport { toast } from \"sonner\";\nimport type { ServerAction, ActionResult, ServerActionResponse } from \"../types\";\nimport { isNextNavigationError } from \"../next/errors\";\n\nexport interface UseServerActionOptions<TOutput> {\n onSuccess?: (data: TOutput) => void | Promise<void>;\n onError?: (error: ActionResult<TOutput>) => void | Promise<void>;\n \n successMessage?: string | ((data: TOutput) => string);\n errorMessage?: string | ((error: ActionResult<TOutput>) => string);\n showSuccessToast?: boolean;\n showErrorToast?: boolean;\n \n redirectOnAuthError?: boolean;\n preventRedirect?: boolean;\n redirectDelay?: number;\n}\n\nexport interface UseServerActionReturn<TInput, TOutput> {\n execute: TInput extends void \n ? () => Promise<ActionResult<TOutput>>\n : (input: TInput) => Promise<ActionResult<TOutput>>;\n \n result: ActionResult<TOutput> | undefined;\n isExecuting: boolean;\n isRedirecting: boolean;\n hasSucceeded: boolean;\n hasErrored: boolean;\n \n reset: () => void;\n}\n\n// Overload for void actions\nexport function useServerAction<TOutput>(\n action: ServerAction<void, TOutput>,\n options?: UseServerActionOptions<TOutput>\n): UseServerActionReturn<void, TOutput>;\n\n// Overload for actions with input\nexport function useServerAction<TInput, TOutput>(\n action: ServerAction<TInput, TOutput>,\n options?: UseServerActionOptions<TOutput>\n): UseServerActionReturn<TInput, TOutput>;\n\n// Implementation\nexport function useServerAction<TInput, TOutput>(\n action: ServerAction<TInput, TOutput>,\n options: UseServerActionOptions<TOutput> = {}\n): UseServerActionReturn<TInput, TOutput> {\n const router = useRouter();\n const [result, setResult] = useState<ActionResult<TOutput>>();\n const [isExecuting, setIsExecuting] = useState(false);\n const [isRedirecting, setIsRedirecting] = useState(false);\n const [, startTransition] = useTransition();\n \n const {\n onSuccess,\n onError,\n successMessage,\n errorMessage,\n showSuccessToast = false,\n showErrorToast = true,\n redirectOnAuthError = true,\n preventRedirect = false,\n redirectDelay = 0,\n } = options;\n \n const hasSucceeded = !!result?.data;\n const hasErrored = !!result?.serverError || !!result?.validationErrors || !!result?.fetchError;\n \n const reset = useCallback(() => {\n setResult(undefined);\n setIsRedirecting(false);\n }, []);\n \n const execute = useCallback(\n async (input?: TInput): Promise<ActionResult<TOutput>> => {\n setIsExecuting(true);\n \n try {\n const response = await (input === undefined \n ? (action as () => Promise<ServerActionResponse<TOutput>>)()\n : (action as (input: TInput) => Promise<ServerActionResponse<TOutput>>)(input));\n \n let actionResult: ActionResult<TOutput>;\n \n if (response.success) {\n actionResult = { data: response.data };\n \n if (process.env.NODE_ENV === 'development') {\n console.log('[useServerAction] Success response:', response);\n console.log('[useServerAction] Has redirect?', !!response.redirect);\n }\n \n if (showSuccessToast && successMessage) {\n const message = typeof successMessage === \"function\" \n ? successMessage(response.data) \n : successMessage;\n toast.success(message);\n }\n \n await onSuccess?.(response.data);\n \n // Handle redirect if present in response\n if (response.redirect && !preventRedirect) {\n setIsRedirecting(true);\n const redirectConfig = typeof response.redirect === 'string'\n ? { url: response.redirect }\n : response.redirect;\n \n const delay = redirectConfig.delay ?? redirectDelay;\n \n setTimeout(() => {\n if (redirectConfig.replace) {\n router.replace(redirectConfig.url);\n } else {\n router.push(redirectConfig.url);\n }\n setIsRedirecting(false);\n }, delay);\n }\n \n } else if (!response.success && response.error) {\n actionResult = {\n serverError: response.error,\n validationErrors: response.error.fields,\n };\n \n // Debug logging\n if (process.env.NODE_ENV === 'development') {\n console.log('[useServerAction] Error response:', response.error);\n console.log('[useServerAction] Should redirect?', response.error.shouldRedirect);\n console.log('[useServerAction] Redirect to:', response.error.redirectTo);\n }\n \n if (redirectOnAuthError && response.error.shouldRedirect) {\n // Handle toast before redirect\n if (showErrorToast) {\n const message = errorMessage \n ? (typeof errorMessage === \"function\" \n ? errorMessage(actionResult) \n : errorMessage)\n : response.error.message || \"An error occurred\";\n \n // Always save to localStorage for redirect cases\n // This ensures compatibility with both current and future sonner versions\n if (typeof window !== 'undefined') {\n try {\n const storageKey = 'sonner-toasts';\n const existingToasts = JSON.parse(\n localStorage.getItem(storageKey) || '[]'\n );\n \n // Add our toast in the same format as the PR\n const persistentToast = {\n id: Date.now(),\n type: 'error',\n message,\n persistent: true,\n createdAt: Date.now()\n };\n \n existingToasts.push(persistentToast);\n localStorage.setItem(storageKey, JSON.stringify(existingToasts));\n } catch (err) {\n console.error('Failed to persist toast:', err);\n }\n }\n \n // Always show the toast (with persistent if supported)\n (toast.error as any)(message, { persistent: true });\n }\n \n setIsRedirecting(true);\n router.push(response.error.redirectTo || \"/login\");\n return actionResult;\n }\n \n if (showErrorToast) {\n const message = errorMessage \n ? (typeof errorMessage === \"function\" \n ? errorMessage(actionResult) \n : errorMessage)\n : response.error.message || \"An error occurred\";\n toast.error(message);\n }\n \n await onError?.(actionResult);\n } else {\n actionResult = { fetchError: \"Unexpected response format\" };\n }\n \n setResult(actionResult);\n return actionResult;\n \n } catch (error) {\n // Check if this is a Next.js navigation error that should be re-thrown\n if (isNextNavigationError(error)) {\n // Re-throw navigation errors to let Next.js handle them\n throw error;\n }\n \n const fetchError = error instanceof Error ? error.message : \"Network error\";\n const actionResult: ActionResult<TOutput> = { fetchError };\n \n setResult(actionResult);\n \n if (showErrorToast) {\n toast.error(fetchError);\n }\n \n await onError?.(actionResult);\n return actionResult;\n } finally {\n setIsExecuting(false);\n }\n },\n [action, router, showSuccessToast, successMessage, showErrorToast, errorMessage, redirectOnAuthError, onSuccess, onError]\n );\n \n const executeWithTransition = useCallback(\n (...args: TInput extends void ? [] : [input: TInput]): Promise<ActionResult<TOutput>> => {\n return new Promise((resolve) => {\n startTransition(async () => {\n const result = await execute(args[0] as TInput);\n resolve(result);\n });\n });\n },\n [execute]\n ) as TInput extends void \n ? () => Promise<ActionResult<TOutput>>\n : (input: TInput) => Promise<ActionResult<TOutput>>;\n \n return {\n execute: executeWithTransition,\n result,\n isExecuting,\n isRedirecting,\n hasSucceeded,\n hasErrored,\n reset,\n };\n}\n\n","// Comes from: https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/redirect-error.ts\n\nenum RedirectStatusCode {\n\tSeeOther = 303,\n\tTemporaryRedirect = 307,\n\tPermanentRedirect = 308,\n}\n\nconst REDIRECT_ERROR_CODE = \"NEXT_REDIRECT\";\n\nenum RedirectType {\n\tpush = \"push\",\n\treplace = \"replace\",\n}\n\nexport type RedirectError = Error & {\n\tdigest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by the\n * `redirect(url)` helper.\n *\n * @param error the error that may reference a redirect error\n * @returns true if the error is a redirect error\n */\nexport function isRedirectError(error: unknown): error is RedirectError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\n\tconst digest = error.digest.split(\";\");\n\tconst [errorCode, type] = digest;\n\tconst destination = digest.slice(2, -2).join(\";\");\n\tconst status = digest.at(-2);\n\n\tconst statusCode = Number(status);\n\n\treturn (\n\t\terrorCode === REDIRECT_ERROR_CODE &&\n\t\t(type === \"replace\" || type === \"push\") &&\n\t\ttypeof destination === \"string\" &&\n\t\t!isNaN(statusCode) &&\n\t\tstatusCode in RedirectStatusCode\n\t);\n}","// Comes from https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/http-access-fallback/http-access-fallback.ts\n\nconst HTTPAccessErrorStatus = {\n\tNOT_FOUND: 404,\n\tFORBIDDEN: 403,\n\tUNAUTHORIZED: 401,\n};\n\nconst ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatus));\n\nconst HTTP_ERROR_FALLBACK_ERROR_CODE = \"NEXT_HTTP_ERROR_FALLBACK\";\n\nexport type HTTPAccessFallbackError = Error & {\n\tdigest: `${typeof HTTP_ERROR_FALLBACK_ERROR_CODE};${string}`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by\n * the HTTP navigation APIs `notFound()`, `forbidden()` or `unauthorized()`.\n *\n * @param error the error that may reference a HTTP access error\n * @returns true if the error is a HTTP access error\n */\nexport function isHTTPAccessFallbackError(error: unknown): error is HTTPAccessFallbackError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\tconst [prefix, httpStatus] = error.digest.split(\";\");\n\n\treturn prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));\n}\n\nexport function getAccessFallbackHTTPStatus(error: HTTPAccessFallbackError): number {\n\tconst httpStatus = error.digest.split(\";\")[1];\n\treturn Number(httpStatus);\n}","import { isRedirectError } from \"./redirect\";\nimport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\n\nexport { isRedirectError } from \"./redirect\";\nexport type { RedirectError } from \"./redirect\";\n\nexport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\nexport type { HTTPAccessFallbackError } from \"./http-access-fallback\";\n\n/**\n * Checks if the error is a navigation error that should be re-thrown\n * This includes redirect errors and HTTP access errors (notFound, forbidden, unauthorized)\n */\nexport function isNextNavigationError(error: unknown): boolean {\n\treturn isRedirectError(error) || isHTTPAccessFallbackError(error);\n}\n\n/**\n * Checks if the error is a notFound error\n * Note: Next.js implements notFound() using HTTP_ERROR_FALLBACK with status 404,\n * not as a separate error type like NEXT_REDIRECT\n */\nexport function isNotFoundError(error: unknown): boolean {\n\treturn isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error as any) === 404;\n}","import { useOptimistic, useTransition } from \"react\";\nimport { useServerAction, type UseServerActionOptions } from \"./use-server-action\";\nimport type { ServerAction, ActionResult } from \"../types\";\n\nexport interface UseOptimisticActionOptions<TInput, TOutput, TOptimistic> extends UseServerActionOptions<TOutput> {\n /**\n * Function to update the optimistic state\n */\n updateFn: TInput extends void \n ? (current: TOptimistic) => TOptimistic\n : (current: TOptimistic, input: TInput) => TOptimistic;\n}\n\nexport interface UseOptimisticActionReturn<TInput, TOutput, TOptimistic> {\n /**\n * The optimistic state\n */\n optimisticState: TOptimistic;\n \n /**\n * Execute the action with optimistic update\n */\n execute: TInput extends void \n ? () => Promise<ActionResult<TOutput>>\n : (input: TInput) => Promise<ActionResult<TOutput>>;\n \n /**\n * Loading state\n */\n isExecuting: boolean;\n \n /**\n * Success state\n */\n hasSucceeded: boolean;\n \n /**\n * Error state\n */\n hasErrored: boolean;\n \n /**\n * Last result\n */\n result: ActionResult<TOutput> | undefined;\n \n /**\n * Reset state\n */\n reset: () => void;\n}\n\n/**\n * Hook for server actions with optimistic updates\n * \n * @example\n * ```typescript\n * const { optimisticState, execute } = useOptimisticAction(\n * currentTodos,\n * addTodoAction,\n * {\n * updateFn: (todos, newTodo) => [...todos, newTodo],\n * onSuccess: (savedTodo) => {\n * // Update with server response if needed\n * }\n * }\n * );\n * ```\n */\nexport function useOptimisticAction<TInput, TOutput, TOptimistic>(\n initialState: TOptimistic,\n action: ServerAction<TInput, TOutput>,\n options: UseOptimisticActionOptions<TInput, TOutput, TOptimistic>\n): UseOptimisticActionReturn<TInput, TOutput, TOptimistic> {\n const [optimisticState, addOptimisticUpdate] = useOptimistic(\n initialState,\n options.updateFn\n );\n \n const [, startTransition] = useTransition();\n \n // Extract updateFn from options to pass the rest to useServerAction\n const { updateFn: _, ...serverActionOptions } = options;\n \n const {\n execute: executeAction,\n isExecuting,\n hasSucceeded,\n hasErrored,\n result,\n reset\n } = useServerAction(action, serverActionOptions);\n \n const execute = (async (input?: TInput): Promise<ActionResult<TOutput>> => {\n // Apply optimistic update\n startTransition(() => {\n if (input !== undefined) {\n addOptimisticUpdate(input);\n } else {\n addOptimisticUpdate(undefined as any);\n }\n });\n \n // Execute the server action\n return executeAction(input as any);\n }) as any;\n \n return {\n optimisticState,\n execute,\n isExecuting,\n hasSucceeded,\n hasErrored,\n result,\n reset\n };\n}","import { useActionState, useEffect, useTransition, useRef, useState } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport type { UseFormProps, UseFormReturn, Path, FieldValues, DefaultValues } from \"react-hook-form\";\nimport { useForm } from \"react-hook-form\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { toast } from \"sonner\";\nimport type { z } from \"zod\";\nimport type { ServerActionResponse, ServerActionError, RedirectConfig } from \"../types\";\n\nexport interface UseFormActionOptions<TFieldValues extends FieldValues, TOutput> {\n // Required - the server action to execute (form action format)\n action: (prevState: ServerActionResponse<TOutput>, formData: FormData) => Promise<ServerActionResponse<TOutput>>;\n \n // Optional Zod schema for validation\n schema?: z.ZodTypeAny;\n \n // React Hook Form options\n defaultValues?: DefaultValues<TFieldValues>;\n mode?: UseFormProps<TFieldValues>[\"mode\"];\n \n // Transform function if you need custom FormData creation\n transformData?: (data: TFieldValues) => FormData;\n \n // Callbacks\n onSuccess?: (data: TOutput) => void | Promise<void>;\n onError?: (error: ServerActionError) => void;\n \n // Behavior options\n resetOnSuccess?: boolean;\n showSuccessToast?: boolean | string | ((data: TOutput) => string);\n showErrorToast?: boolean | string | ((error: ServerActionError) => string);\n \n // Redirect options (same as useServerAction)\n preventRedirect?: boolean;\n redirectDelay?: number;\n}\n\nexport interface UseFormActionReturn<TFieldValues extends FieldValues, TOutput> {\n // React Hook Form instance\n form: UseFormReturn<TFieldValues>;\n \n // Submit handler (pre-bound with handleSubmit)\n onSubmit: (e?: React.BaseSyntheticEvent) => void;\n \n // Loading state (combines isPending and isTransitioning)\n isSubmitting: boolean;\n \n // Redirecting state (true when redirect is in progress)\n isRedirecting: boolean;\n \n // The current action state\n actionState: ServerActionResponse<TOutput>;\n \n // Utilities\n reset: () => void;\n \n // Raw handlers if needed\n handleSubmit: (data: TFieldValues) => Promise<void>;\n}\n\nfunction isSuccessResponse<T>(response: ServerActionResponse<T>): response is { success: true; data: T; redirect?: string | RedirectConfig } {\n return response.success === true;\n}\n\nfunction objectToFormData(obj: any): FormData {\n const formData = new FormData();\n \n Object.entries(obj).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (value instanceof File || value instanceof Blob) {\n formData.append(key, value);\n } else if (Array.isArray(value)) {\n value.forEach((item) => formData.append(`${key}[]`, String(item)));\n } else if (typeof value === \"object\") {\n formData.append(key, JSON.stringify(value));\n } else {\n formData.append(key, String(value));\n }\n }\n });\n \n return formData;\n}\n\nexport function useFormAction<TFieldValues extends FieldValues = FieldValues, TOutput = void>({\n action,\n schema,\n defaultValues,\n mode = \"onChange\",\n transformData,\n onSuccess,\n onError,\n resetOnSuccess = false,\n showSuccessToast = false,\n showErrorToast = true,\n preventRedirect = false,\n redirectDelay = 0,\n}: UseFormActionOptions<TFieldValues, TOutput>): UseFormActionReturn<TFieldValues, TOutput> {\n const router = useRouter();\n const [isRedirecting, setIsRedirecting] = useState(false);\n \n // Store callbacks in refs to prevent effect re-runs\n const onSuccessRef = useRef(onSuccess);\n const onErrorRef = useRef(onError);\n const showSuccessToastRef = useRef(showSuccessToast);\n const showErrorToastRef = useRef(showErrorToast);\n \n // Update refs when callbacks change\n useEffect(() => {\n onSuccessRef.current = onSuccess;\n onErrorRef.current = onError;\n showSuccessToastRef.current = showSuccessToast;\n showErrorToastRef.current = showErrorToast;\n });\n \n // 1. Setup form with React Hook Form\n const form = useForm<TFieldValues>({\n resolver: schema ? (zodResolver as any)(schema) : undefined,\n defaultValues,\n mode,\n } as UseFormProps<TFieldValues>);\n \n // 2. Setup server action state with useActionState\n const initialState: ServerActionResponse<TOutput> = { success: true, data: undefined as TOutput };\n const [actionState, formAction, isPending] = useActionState(action, initialState);\n const [isTransitioning, startTransition] = useTransition();\n \n // 3. Handle server errors and success\n useEffect(() => {\n // Skip initial state\n if (actionState.success === true && actionState.data === undefined) {\n return;\n }\n \n // Reset redirecting state if we're processing a new action\n setIsRedirecting(false);\n \n // Keep track of timeout for cleanup\n let timeoutId: NodeJS.Timeout | undefined;\n \n if (!isSuccessResponse(actionState) && actionState.error) {\n const { error } = actionState;\n \n // Map field errors to form\n if (error.fields) {\n Object.entries(error.fields).forEach(([field, messages]) => {\n if (Array.isArray(messages) && messages.length > 0) {\n form.setError(field as Path<TFieldValues>, {\n type: \"server\",\n message: messages[0],\n });\n }\n });\n }\n \n // Single field error\n if (error.field && error.message && !error.fields) {\n form.setError(error.field as Path<TFieldValues>, {\n type: \"server\",\n message: error.message,\n });\n }\n \n // Global error (no specific field)\n if (error.message && !error.field && !error.fields) {\n const showToast = showErrorToastRef.current;\n if (showToast) {\n const message = typeof showToast === \"function\" \n ? showToast(error)\n : typeof showToast === \"string\"\n ? showToast\n : error.message;\n toast.error(message);\n }\n \n // Also set on root for inline display\n form.setError(\"root\", {\n type: \"server\",\n message: error.message,\n });\n }\n \n // Call error callback\n onErrorRef.current?.(error);\n }\n \n // Handle success\n if (isSuccessResponse(actionState) && actionState.data !== undefined) {\n const showToast = showSuccessToastRef.current;\n if (showToast) {\n const message = typeof showToast === \"function\"\n ? showToast(actionState.data)\n : typeof showToast === \"string\"\n ? showToast\n : \"Success!\";\n toast.success(message);\n }\n \n if (resetOnSuccess) {\n form.reset();\n }\n \n // Call success callback first\n onSuccessRef.current?.(actionState.data);\n \n // Handle redirect if present in response - delay to ensure state updates complete\n if (actionState.redirect && !preventRedirect) {\n setIsRedirecting(true);\n const redirectConfig = typeof actionState.redirect === 'string'\n ? { url: actionState.redirect }\n : actionState.redirect;\n \n const delay = redirectConfig.delay ?? redirectDelay;\n \n timeoutId = setTimeout(() => {\n if (redirectConfig.replace) {\n router.replace(redirectConfig.url);\n } else {\n router.push(redirectConfig.url);\n }\n setIsRedirecting(false);\n }, delay || 100); // Add small delay by default\n }\n }\n \n // Always return cleanup function\n return () => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n };\n }, [actionState]); // Minimal dependencies - only actionState\n \n // 4. Submit handler\n const handleSubmit = async (data: TFieldValues): Promise<void> => {\n // Clear any previous errors\n form.clearErrors();\n \n // Transform to FormData\n const formData = transformData \n ? transformData(data)\n : objectToFormData(data);\n \n // Execute with transition for better UX\n startTransition(() => {\n formAction(formData);\n });\n };\n \n // 5. Combined loading state\n const isSubmitting = isPending || isTransitioning;\n \n // 6. Pre-bound submit handler\n const onSubmit = (e?: React.BaseSyntheticEvent): void => {\n e?.preventDefault();\n void form.handleSubmit(handleSubmit)(e!);\n };\n \n return {\n form,\n onSubmit,\n isSubmitting,\n isRedirecting,\n actionState,\n reset: form.reset,\n handleSubmit,\n };\n}","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { toast } from \"sonner\";\n\nexport function ToastRestorer() {\n useEffect(() => {\n // Only run on client side\n if (typeof window === \"undefined\") return;\n \n const storageKey = \"sonner-toasts\";\n \n try {\n const storedToasts = localStorage.getItem(storageKey);\n \n if (storedToasts) {\n const persistentToasts = JSON.parse(storedToasts);\n \n if (Array.isArray(persistentToasts) && persistentToasts.length > 0) {\n // Clear the storage immediately to prevent duplicate toasts\n localStorage.removeItem(storageKey);\n \n // Filter out old toasts (older than 30 seconds)\n const recentToasts = persistentToasts.filter(\n (t: any) => Date.now() - (t.createdAt || 0) < 30000\n );\n \n // Restore toasts with staggered animation like in the PR\n recentToasts.forEach((persistedToast: any, index: number) => {\n // Skip loading toasts as per the PR implementation\n if (persistedToast.type === \"loading\") return;\n \n setTimeout(() => {\n const toastFunction = toast[persistedToast.type as keyof typeof toast];\n \n if (typeof toastFunction === \"function\") {\n // Check if current sonner supports persistent\n if (toastFunction.length >= 2) {\n // Use persistent if available\n (toastFunction as any)(persistedToast.message, { \n persistent: true,\n id: persistedToast.id \n });\n } else {\n // Fallback to normal toast\n toastFunction(persistedToast.message);\n }\n }\n }, index * 150); // Staggered delay like in the PR\n });\n }\n }\n } catch (error) {\n console.error(\"Failed to restore toasts:\", error);\n // Clean up on error\n localStorage.removeItem(storageKey);\n }\n }, []);\n \n return null;\n}"],"mappings":"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","names":["RedirectStatusCode","result","import_react","import_react","import_navigation","import_sonner","import_react","import_sonner"]}
1
+ {"version":3,"sources":["../../src/hooks/index.ts","../../src/hooks/use-server-action.ts","../../src/next/errors/redirect.ts","../../src/next/errors/http-access-fallback.ts","../../src/next/errors/index.ts","../../src/hooks/use-optimistic-action.ts","../../src/hooks/use-form-action.ts","../../src/hooks/toast-restorer.tsx"],"sourcesContent":["export * from \"./use-server-action\";\nexport * from \"./use-optimistic-action\";\nexport * from \"./use-form-action\";\nexport { ToastRestorer } from \"./toast-restorer\";","import { useCallback, useState, useTransition } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport { toast } from \"sonner\";\nimport type { ServerAction, ActionResult, ServerActionResponse } from \"../types\";\nimport { isNextNavigationError } from \"../next/errors\";\n\nexport interface UseServerActionOptions<TOutput> {\n onSuccess?: (data: TOutput) => void | Promise<void>;\n onError?: (error: ActionResult<TOutput>) => void | Promise<void>;\n \n successMessage?: string | ((data: TOutput) => string);\n errorMessage?: string | ((error: ActionResult<TOutput>) => string);\n showSuccessToast?: boolean;\n showErrorToast?: boolean;\n \n redirectOnAuthError?: boolean;\n preventRedirect?: boolean;\n redirectDelay?: number;\n}\n\nexport interface UseServerActionReturn<TInput, TOutput> {\n execute: TInput extends void \n ? () => Promise<ActionResult<TOutput>>\n : (input: TInput) => Promise<ActionResult<TOutput>>;\n \n result: ActionResult<TOutput> | undefined;\n isExecuting: boolean;\n isRedirecting: boolean;\n hasSucceeded: boolean;\n hasErrored: boolean;\n \n reset: () => void;\n}\n\n// Overload for void actions\nexport function useServerAction<TOutput>(\n action: ServerAction<void, TOutput>,\n options?: UseServerActionOptions<TOutput>\n): UseServerActionReturn<void, TOutput>;\n\n// Overload for actions with input\nexport function useServerAction<TInput, TOutput>(\n action: ServerAction<TInput, TOutput>,\n options?: UseServerActionOptions<TOutput>\n): UseServerActionReturn<TInput, TOutput>;\n\n// Implementation\nexport function useServerAction<TInput, TOutput>(\n action: ServerAction<TInput, TOutput>,\n options: UseServerActionOptions<TOutput> = {}\n): UseServerActionReturn<TInput, TOutput> {\n const router = useRouter();\n const [result, setResult] = useState<ActionResult<TOutput>>();\n const [isExecuting, setIsExecuting] = useState(false);\n const [isRedirecting, setIsRedirecting] = useState(false);\n const [, startTransition] = useTransition();\n \n const {\n onSuccess,\n onError,\n successMessage,\n errorMessage,\n showSuccessToast = false,\n showErrorToast = true,\n redirectOnAuthError = true,\n preventRedirect = false,\n redirectDelay = 0,\n } = options;\n \n const hasSucceeded = !!result?.data;\n const hasErrored = !!result?.serverError || !!result?.validationErrors || !!result?.fetchError;\n \n const reset = useCallback(() => {\n setResult(undefined);\n setIsRedirecting(false);\n }, []);\n \n const execute = useCallback(\n async (input?: TInput): Promise<ActionResult<TOutput>> => {\n setIsExecuting(true);\n \n try {\n const response = await (input === undefined \n ? (action as () => Promise<ServerActionResponse<TOutput>>)()\n : (action as (input: TInput) => Promise<ServerActionResponse<TOutput>>)(input));\n \n let actionResult: ActionResult<TOutput>;\n \n if (response.success) {\n actionResult = { data: response.data };\n \n if (process.env.NODE_ENV === 'development') {\n console.log('[useServerAction] Success response:', response);\n console.log('[useServerAction] Has redirect?', !!response.redirect);\n }\n \n if (showSuccessToast && successMessage) {\n const message = typeof successMessage === \"function\" \n ? successMessage(response.data) \n : successMessage;\n toast.success(message);\n }\n \n await onSuccess?.(response.data);\n \n // Handle redirect if present in response\n if (response.redirect && !preventRedirect) {\n setIsRedirecting(true);\n const redirectConfig = typeof response.redirect === 'string'\n ? { url: response.redirect }\n : response.redirect;\n \n const delay = redirectConfig.delay ?? redirectDelay;\n \n setTimeout(() => {\n if (redirectConfig.replace) {\n router.replace(redirectConfig.url);\n } else {\n router.push(redirectConfig.url);\n }\n // Don't reset isRedirecting - the component will unmount anyway\n }, delay);\n }\n \n } else if (!response.success && response.error) {\n actionResult = {\n serverError: response.error,\n validationErrors: response.error.fields,\n };\n \n // Debug logging\n if (process.env.NODE_ENV === 'development') {\n console.log('[useServerAction] Error response:', response.error);\n console.log('[useServerAction] Should redirect?', response.error.shouldRedirect);\n console.log('[useServerAction] Redirect to:', response.error.redirectTo);\n }\n \n if (redirectOnAuthError && response.error.shouldRedirect) {\n // Handle toast before redirect\n if (showErrorToast) {\n const message = errorMessage \n ? (typeof errorMessage === \"function\" \n ? errorMessage(actionResult) \n : errorMessage)\n : response.error.message || \"An error occurred\";\n \n // Always save to localStorage for redirect cases\n // This ensures compatibility with both current and future sonner versions\n if (typeof window !== 'undefined') {\n try {\n const storageKey = 'sonner-toasts';\n const existingToasts = JSON.parse(\n localStorage.getItem(storageKey) || '[]'\n );\n \n // Add our toast in the same format as the PR\n const persistentToast = {\n id: Date.now(),\n type: 'error',\n message,\n persistent: true,\n createdAt: Date.now()\n };\n \n existingToasts.push(persistentToast);\n localStorage.setItem(storageKey, JSON.stringify(existingToasts));\n } catch (err) {\n console.error('Failed to persist toast:', err);\n }\n }\n \n // Always show the toast (with persistent if supported)\n (toast.error as any)(message, { persistent: true });\n }\n \n setIsRedirecting(true);\n router.push(response.error.redirectTo || \"/login\");\n return actionResult;\n }\n \n if (showErrorToast) {\n const message = errorMessage \n ? (typeof errorMessage === \"function\" \n ? errorMessage(actionResult) \n : errorMessage)\n : response.error.message || \"An error occurred\";\n toast.error(message);\n }\n \n await onError?.(actionResult);\n } else {\n actionResult = { fetchError: \"Unexpected response format\" };\n }\n \n setResult(actionResult);\n return actionResult;\n \n } catch (error) {\n // Check if this is a Next.js navigation error that should be re-thrown\n if (isNextNavigationError(error)) {\n // Re-throw navigation errors to let Next.js handle them\n throw error;\n }\n \n const fetchError = error instanceof Error ? error.message : \"Network error\";\n const actionResult: ActionResult<TOutput> = { fetchError };\n \n setResult(actionResult);\n \n if (showErrorToast) {\n toast.error(fetchError);\n }\n \n await onError?.(actionResult);\n return actionResult;\n } finally {\n setIsExecuting(false);\n }\n },\n [action, router, showSuccessToast, successMessage, showErrorToast, errorMessage, redirectOnAuthError, onSuccess, onError]\n );\n \n const executeWithTransition = useCallback(\n (...args: TInput extends void ? [] : [input: TInput]): Promise<ActionResult<TOutput>> => {\n return new Promise((resolve) => {\n startTransition(async () => {\n const result = await execute(args[0] as TInput);\n resolve(result);\n });\n });\n },\n [execute]\n ) as TInput extends void \n ? () => Promise<ActionResult<TOutput>>\n : (input: TInput) => Promise<ActionResult<TOutput>>;\n \n return {\n execute: executeWithTransition,\n result,\n isExecuting,\n isRedirecting,\n hasSucceeded,\n hasErrored,\n reset,\n };\n}\n\n","// Comes from: https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/redirect-error.ts\n\nenum RedirectStatusCode {\n\tSeeOther = 303,\n\tTemporaryRedirect = 307,\n\tPermanentRedirect = 308,\n}\n\nconst REDIRECT_ERROR_CODE = \"NEXT_REDIRECT\";\n\nenum RedirectType {\n\tpush = \"push\",\n\treplace = \"replace\",\n}\n\nexport type RedirectError = Error & {\n\tdigest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by the\n * `redirect(url)` helper.\n *\n * @param error the error that may reference a redirect error\n * @returns true if the error is a redirect error\n */\nexport function isRedirectError(error: unknown): error is RedirectError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\n\tconst digest = error.digest.split(\";\");\n\tconst [errorCode, type] = digest;\n\tconst destination = digest.slice(2, -2).join(\";\");\n\tconst status = digest.at(-2);\n\n\tconst statusCode = Number(status);\n\n\treturn (\n\t\terrorCode === REDIRECT_ERROR_CODE &&\n\t\t(type === \"replace\" || type === \"push\") &&\n\t\ttypeof destination === \"string\" &&\n\t\t!isNaN(statusCode) &&\n\t\tstatusCode in RedirectStatusCode\n\t);\n}","// Comes from https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/http-access-fallback/http-access-fallback.ts\n\nconst HTTPAccessErrorStatus = {\n\tNOT_FOUND: 404,\n\tFORBIDDEN: 403,\n\tUNAUTHORIZED: 401,\n};\n\nconst ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatus));\n\nconst HTTP_ERROR_FALLBACK_ERROR_CODE = \"NEXT_HTTP_ERROR_FALLBACK\";\n\nexport type HTTPAccessFallbackError = Error & {\n\tdigest: `${typeof HTTP_ERROR_FALLBACK_ERROR_CODE};${string}`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by\n * the HTTP navigation APIs `notFound()`, `forbidden()` or `unauthorized()`.\n *\n * @param error the error that may reference a HTTP access error\n * @returns true if the error is a HTTP access error\n */\nexport function isHTTPAccessFallbackError(error: unknown): error is HTTPAccessFallbackError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\tconst [prefix, httpStatus] = error.digest.split(\";\");\n\n\treturn prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));\n}\n\nexport function getAccessFallbackHTTPStatus(error: HTTPAccessFallbackError): number {\n\tconst httpStatus = error.digest.split(\";\")[1];\n\treturn Number(httpStatus);\n}","import { isRedirectError } from \"./redirect\";\nimport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\n\nexport { isRedirectError } from \"./redirect\";\nexport type { RedirectError } from \"./redirect\";\n\nexport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\nexport type { HTTPAccessFallbackError } from \"./http-access-fallback\";\n\n/**\n * Checks if the error is a navigation error that should be re-thrown\n * This includes redirect errors and HTTP access errors (notFound, forbidden, unauthorized)\n */\nexport function isNextNavigationError(error: unknown): boolean {\n\treturn isRedirectError(error) || isHTTPAccessFallbackError(error);\n}\n\n/**\n * Checks if the error is a notFound error\n * Note: Next.js implements notFound() using HTTP_ERROR_FALLBACK with status 404,\n * not as a separate error type like NEXT_REDIRECT\n */\nexport function isNotFoundError(error: unknown): boolean {\n\treturn isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error as any) === 404;\n}","import { useOptimistic, useTransition } from \"react\";\nimport { useServerAction, type UseServerActionOptions } from \"./use-server-action\";\nimport type { ServerAction, ActionResult } from \"../types\";\n\nexport interface UseOptimisticActionOptions<TInput, TOutput, TOptimistic> extends UseServerActionOptions<TOutput> {\n /**\n * Function to update the optimistic state\n */\n updateFn: TInput extends void \n ? (current: TOptimistic) => TOptimistic\n : (current: TOptimistic, input: TInput) => TOptimistic;\n}\n\nexport interface UseOptimisticActionReturn<TInput, TOutput, TOptimistic> {\n /**\n * The optimistic state\n */\n optimisticState: TOptimistic;\n \n /**\n * Execute the action with optimistic update\n */\n execute: TInput extends void \n ? () => Promise<ActionResult<TOutput>>\n : (input: TInput) => Promise<ActionResult<TOutput>>;\n \n /**\n * Loading state\n */\n isExecuting: boolean;\n \n /**\n * Success state\n */\n hasSucceeded: boolean;\n \n /**\n * Error state\n */\n hasErrored: boolean;\n \n /**\n * Last result\n */\n result: ActionResult<TOutput> | undefined;\n \n /**\n * Reset state\n */\n reset: () => void;\n}\n\n/**\n * Hook for server actions with optimistic updates\n * \n * @example\n * ```typescript\n * const { optimisticState, execute } = useOptimisticAction(\n * currentTodos,\n * addTodoAction,\n * {\n * updateFn: (todos, newTodo) => [...todos, newTodo],\n * onSuccess: (savedTodo) => {\n * // Update with server response if needed\n * }\n * }\n * );\n * ```\n */\nexport function useOptimisticAction<TInput, TOutput, TOptimistic>(\n initialState: TOptimistic,\n action: ServerAction<TInput, TOutput>,\n options: UseOptimisticActionOptions<TInput, TOutput, TOptimistic>\n): UseOptimisticActionReturn<TInput, TOutput, TOptimistic> {\n const [optimisticState, addOptimisticUpdate] = useOptimistic(\n initialState,\n options.updateFn\n );\n \n const [, startTransition] = useTransition();\n \n // Extract updateFn from options to pass the rest to useServerAction\n const { updateFn: _, ...serverActionOptions } = options;\n \n const {\n execute: executeAction,\n isExecuting,\n hasSucceeded,\n hasErrored,\n result,\n reset\n } = useServerAction(action, serverActionOptions);\n \n const execute = (async (input?: TInput): Promise<ActionResult<TOutput>> => {\n // Apply optimistic update\n startTransition(() => {\n if (input !== undefined) {\n addOptimisticUpdate(input);\n } else {\n addOptimisticUpdate(undefined as any);\n }\n });\n \n // Execute the server action\n return executeAction(input as any);\n }) as any;\n \n return {\n optimisticState,\n execute,\n isExecuting,\n hasSucceeded,\n hasErrored,\n result,\n reset\n };\n}","import { useActionState, useEffect, useTransition, useRef, useState } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport type { UseFormProps, UseFormReturn, Path, FieldValues, DefaultValues } from \"react-hook-form\";\nimport { useForm } from \"react-hook-form\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { toast } from \"sonner\";\nimport type { z } from \"zod\";\nimport type { ServerActionResponse, ServerActionError, RedirectConfig } from \"../types\";\n\nexport interface UseFormActionOptions<TFieldValues extends FieldValues, TOutput> {\n // Required - the server action to execute (form action format)\n action: (prevState: ServerActionResponse<TOutput>, formData: FormData) => Promise<ServerActionResponse<TOutput>>;\n \n // Optional Zod schema for validation\n schema?: z.ZodTypeAny;\n \n // React Hook Form options\n defaultValues?: DefaultValues<TFieldValues>;\n mode?: UseFormProps<TFieldValues>[\"mode\"];\n \n // Transform function if you need custom FormData creation\n transformData?: (data: TFieldValues) => FormData;\n \n // Callbacks\n onSuccess?: (data: TOutput) => void | Promise<void>;\n onError?: (error: ServerActionError) => void;\n \n // Behavior options\n resetOnSuccess?: boolean;\n showSuccessToast?: boolean | string | ((data: TOutput) => string);\n showErrorToast?: boolean | string | ((error: ServerActionError) => string);\n \n // Redirect options (same as useServerAction)\n preventRedirect?: boolean;\n redirectDelay?: number;\n}\n\nexport interface UseFormActionReturn<TFieldValues extends FieldValues, TOutput> {\n // React Hook Form instance\n form: UseFormReturn<TFieldValues>;\n \n // Submit handler (pre-bound with handleSubmit)\n onSubmit: (e?: React.BaseSyntheticEvent) => void;\n \n // Loading state (combines isPending and isTransitioning)\n isSubmitting: boolean;\n \n // Redirecting state (true when redirect is in progress)\n isRedirecting: boolean;\n \n // The current action state\n actionState: ServerActionResponse<TOutput>;\n \n // Utilities\n reset: () => void;\n \n // Raw handlers if needed\n handleSubmit: (data: TFieldValues) => Promise<void>;\n}\n\nfunction isSuccessResponse<T>(response: ServerActionResponse<T>): response is { success: true; data: T; redirect?: string | RedirectConfig } {\n return response.success === true;\n}\n\nfunction objectToFormData(obj: any): FormData {\n const formData = new FormData();\n \n Object.entries(obj).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (value instanceof File || value instanceof Blob) {\n formData.append(key, value);\n } else if (Array.isArray(value)) {\n value.forEach((item) => formData.append(`${key}[]`, String(item)));\n } else if (typeof value === \"object\") {\n formData.append(key, JSON.stringify(value));\n } else {\n formData.append(key, String(value));\n }\n }\n });\n \n return formData;\n}\n\nexport function useFormAction<TFieldValues extends FieldValues = FieldValues, TOutput = void>({\n action,\n schema,\n defaultValues,\n mode = \"onChange\",\n transformData,\n onSuccess,\n onError,\n resetOnSuccess = false,\n showSuccessToast = false,\n showErrorToast = true,\n preventRedirect = false,\n redirectDelay = 0,\n}: UseFormActionOptions<TFieldValues, TOutput>): UseFormActionReturn<TFieldValues, TOutput> {\n const router = useRouter();\n const [isRedirecting, setIsRedirecting] = useState(false);\n \n // Store callbacks in refs to prevent effect re-runs\n const onSuccessRef = useRef(onSuccess);\n const onErrorRef = useRef(onError);\n const showSuccessToastRef = useRef(showSuccessToast);\n const showErrorToastRef = useRef(showErrorToast);\n \n // Update refs when callbacks change\n useEffect(() => {\n onSuccessRef.current = onSuccess;\n onErrorRef.current = onError;\n showSuccessToastRef.current = showSuccessToast;\n showErrorToastRef.current = showErrorToast;\n });\n \n // 1. Setup form with React Hook Form\n const form = useForm<TFieldValues>({\n resolver: schema ? (zodResolver as any)(schema) : undefined,\n defaultValues,\n mode,\n } as UseFormProps<TFieldValues>);\n \n // 2. Setup server action state with useActionState\n const initialState: ServerActionResponse<TOutput> = { success: true, data: undefined as TOutput };\n const [actionState, formAction, isPending] = useActionState(action, initialState);\n const [isTransitioning, startTransition] = useTransition();\n \n // 3. Handle server errors and success\n useEffect(() => {\n // Skip initial state\n if (actionState.success === true && actionState.data === undefined) {\n return;\n }\n \n // Reset redirecting state if we're processing a new action\n setIsRedirecting(false);\n \n // Keep track of timeout for cleanup\n let timeoutId: NodeJS.Timeout | undefined;\n \n if (!isSuccessResponse(actionState) && actionState.error) {\n const { error } = actionState;\n \n // Map field errors to form\n if (error.fields) {\n Object.entries(error.fields).forEach(([field, messages]) => {\n if (Array.isArray(messages) && messages.length > 0) {\n form.setError(field as Path<TFieldValues>, {\n type: \"server\",\n message: messages[0],\n });\n }\n });\n }\n \n // Single field error\n if (error.field && error.message && !error.fields) {\n form.setError(error.field as Path<TFieldValues>, {\n type: \"server\",\n message: error.message,\n });\n }\n \n // Global error (no specific field)\n if (error.message && !error.field && !error.fields) {\n const showToast = showErrorToastRef.current;\n if (showToast) {\n const message = typeof showToast === \"function\" \n ? showToast(error)\n : typeof showToast === \"string\"\n ? showToast\n : error.message;\n toast.error(message);\n }\n \n // Also set on root for inline display\n form.setError(\"root\", {\n type: \"server\",\n message: error.message,\n });\n }\n \n // Call error callback\n onErrorRef.current?.(error);\n }\n \n // Handle success\n if (isSuccessResponse(actionState) && actionState.data !== undefined) {\n const showToast = showSuccessToastRef.current;\n if (showToast) {\n const message = typeof showToast === \"function\"\n ? showToast(actionState.data)\n : typeof showToast === \"string\"\n ? showToast\n : \"Success!\";\n toast.success(message);\n }\n \n if (resetOnSuccess) {\n form.reset();\n }\n \n // Call success callback first\n onSuccessRef.current?.(actionState.data);\n \n // Handle redirect if present in response - delay to ensure state updates complete\n if (actionState.redirect && !preventRedirect) {\n setIsRedirecting(true);\n const redirectConfig = typeof actionState.redirect === 'string'\n ? { url: actionState.redirect }\n : actionState.redirect;\n \n const delay = redirectConfig.delay ?? redirectDelay;\n \n timeoutId = setTimeout(() => {\n if (redirectConfig.replace) {\n router.replace(redirectConfig.url);\n } else {\n router.push(redirectConfig.url);\n }\n // Don't reset isRedirecting - the component will unmount anyway\n }, delay || 100); // Add small delay by default\n }\n }\n \n // Always return cleanup function\n return () => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n };\n }, [actionState]); // Minimal dependencies - only actionState\n \n // 4. Submit handler\n const handleSubmit = async (data: TFieldValues): Promise<void> => {\n // Clear any previous errors\n form.clearErrors();\n \n // Transform to FormData\n const formData = transformData \n ? transformData(data)\n : objectToFormData(data);\n \n // Execute with transition for better UX\n startTransition(() => {\n formAction(formData);\n });\n };\n \n // 5. Combined loading state\n const isSubmitting = isPending || isTransitioning;\n \n // 6. Pre-bound submit handler\n const onSubmit = (e?: React.BaseSyntheticEvent): void => {\n e?.preventDefault();\n void form.handleSubmit(handleSubmit)(e!);\n };\n \n return {\n form,\n onSubmit,\n isSubmitting,\n isRedirecting,\n actionState,\n reset: form.reset,\n handleSubmit,\n };\n}","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { toast } from \"sonner\";\n\nexport function ToastRestorer() {\n useEffect(() => {\n // Only run on client side\n if (typeof window === \"undefined\") return;\n \n const storageKey = \"sonner-toasts\";\n \n try {\n const storedToasts = localStorage.getItem(storageKey);\n \n if (storedToasts) {\n const persistentToasts = JSON.parse(storedToasts);\n \n if (Array.isArray(persistentToasts) && persistentToasts.length > 0) {\n // Clear the storage immediately to prevent duplicate toasts\n localStorage.removeItem(storageKey);\n \n // Filter out old toasts (older than 30 seconds)\n const recentToasts = persistentToasts.filter(\n (t: any) => Date.now() - (t.createdAt || 0) < 30000\n );\n \n // Restore toasts with staggered animation like in the PR\n recentToasts.forEach((persistedToast: any, index: number) => {\n // Skip loading toasts as per the PR implementation\n if (persistedToast.type === \"loading\") return;\n \n setTimeout(() => {\n const toastFunction = toast[persistedToast.type as keyof typeof toast];\n \n if (typeof toastFunction === \"function\") {\n // Check if current sonner supports persistent\n if (toastFunction.length >= 2) {\n // Use persistent if available\n (toastFunction as any)(persistedToast.message, { \n persistent: true,\n id: persistedToast.id \n });\n } else {\n // Fallback to normal toast\n toastFunction(persistedToast.message);\n }\n }\n }, index * 150); // Staggered delay like in the PR\n });\n }\n }\n } catch (error) {\n console.error(\"Failed to restore toasts:\", error);\n // Clean up on error\n localStorage.removeItem(storageKey);\n }\n }, []);\n \n return null;\n}"],"mappings":"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","names":["RedirectStatusCode","result","import_react","import_react","import_navigation","import_sonner","import_react","import_sonner"]}
@@ -96,7 +96,6 @@ function useServerAction(action, options = {}) {
96
96
  } else {
97
97
  router.push(redirectConfig.url);
98
98
  }
99
- setIsRedirecting(false);
100
99
  }, delay);
101
100
  }
102
101
  } else if (!response.success && response.error) {
@@ -342,7 +341,6 @@ function useFormAction({
342
341
  } else {
343
342
  router.push(redirectConfig.url);
344
343
  }
345
- setIsRedirecting(false);
346
344
  }, delay || 100);
347
345
  }
348
346
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/use-server-action.ts","../../src/next/errors/redirect.ts","../../src/next/errors/http-access-fallback.ts","../../src/next/errors/index.ts","../../src/hooks/use-optimistic-action.ts","../../src/hooks/use-form-action.ts","../../src/hooks/toast-restorer.tsx"],"sourcesContent":["import { useCallback, useState, useTransition } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport { toast } from \"sonner\";\nimport type { ServerAction, ActionResult, ServerActionResponse } from \"../types\";\nimport { isNextNavigationError } from \"../next/errors\";\n\nexport interface UseServerActionOptions<TOutput> {\n onSuccess?: (data: TOutput) => void | Promise<void>;\n onError?: (error: ActionResult<TOutput>) => void | Promise<void>;\n \n successMessage?: string | ((data: TOutput) => string);\n errorMessage?: string | ((error: ActionResult<TOutput>) => string);\n showSuccessToast?: boolean;\n showErrorToast?: boolean;\n \n redirectOnAuthError?: boolean;\n preventRedirect?: boolean;\n redirectDelay?: number;\n}\n\nexport interface UseServerActionReturn<TInput, TOutput> {\n execute: TInput extends void \n ? () => Promise<ActionResult<TOutput>>\n : (input: TInput) => Promise<ActionResult<TOutput>>;\n \n result: ActionResult<TOutput> | undefined;\n isExecuting: boolean;\n isRedirecting: boolean;\n hasSucceeded: boolean;\n hasErrored: boolean;\n \n reset: () => void;\n}\n\n// Overload for void actions\nexport function useServerAction<TOutput>(\n action: ServerAction<void, TOutput>,\n options?: UseServerActionOptions<TOutput>\n): UseServerActionReturn<void, TOutput>;\n\n// Overload for actions with input\nexport function useServerAction<TInput, TOutput>(\n action: ServerAction<TInput, TOutput>,\n options?: UseServerActionOptions<TOutput>\n): UseServerActionReturn<TInput, TOutput>;\n\n// Implementation\nexport function useServerAction<TInput, TOutput>(\n action: ServerAction<TInput, TOutput>,\n options: UseServerActionOptions<TOutput> = {}\n): UseServerActionReturn<TInput, TOutput> {\n const router = useRouter();\n const [result, setResult] = useState<ActionResult<TOutput>>();\n const [isExecuting, setIsExecuting] = useState(false);\n const [isRedirecting, setIsRedirecting] = useState(false);\n const [, startTransition] = useTransition();\n \n const {\n onSuccess,\n onError,\n successMessage,\n errorMessage,\n showSuccessToast = false,\n showErrorToast = true,\n redirectOnAuthError = true,\n preventRedirect = false,\n redirectDelay = 0,\n } = options;\n \n const hasSucceeded = !!result?.data;\n const hasErrored = !!result?.serverError || !!result?.validationErrors || !!result?.fetchError;\n \n const reset = useCallback(() => {\n setResult(undefined);\n setIsRedirecting(false);\n }, []);\n \n const execute = useCallback(\n async (input?: TInput): Promise<ActionResult<TOutput>> => {\n setIsExecuting(true);\n \n try {\n const response = await (input === undefined \n ? (action as () => Promise<ServerActionResponse<TOutput>>)()\n : (action as (input: TInput) => Promise<ServerActionResponse<TOutput>>)(input));\n \n let actionResult: ActionResult<TOutput>;\n \n if (response.success) {\n actionResult = { data: response.data };\n \n if (process.env.NODE_ENV === 'development') {\n console.log('[useServerAction] Success response:', response);\n console.log('[useServerAction] Has redirect?', !!response.redirect);\n }\n \n if (showSuccessToast && successMessage) {\n const message = typeof successMessage === \"function\" \n ? successMessage(response.data) \n : successMessage;\n toast.success(message);\n }\n \n await onSuccess?.(response.data);\n \n // Handle redirect if present in response\n if (response.redirect && !preventRedirect) {\n setIsRedirecting(true);\n const redirectConfig = typeof response.redirect === 'string'\n ? { url: response.redirect }\n : response.redirect;\n \n const delay = redirectConfig.delay ?? redirectDelay;\n \n setTimeout(() => {\n if (redirectConfig.replace) {\n router.replace(redirectConfig.url);\n } else {\n router.push(redirectConfig.url);\n }\n setIsRedirecting(false);\n }, delay);\n }\n \n } else if (!response.success && response.error) {\n actionResult = {\n serverError: response.error,\n validationErrors: response.error.fields,\n };\n \n // Debug logging\n if (process.env.NODE_ENV === 'development') {\n console.log('[useServerAction] Error response:', response.error);\n console.log('[useServerAction] Should redirect?', response.error.shouldRedirect);\n console.log('[useServerAction] Redirect to:', response.error.redirectTo);\n }\n \n if (redirectOnAuthError && response.error.shouldRedirect) {\n // Handle toast before redirect\n if (showErrorToast) {\n const message = errorMessage \n ? (typeof errorMessage === \"function\" \n ? errorMessage(actionResult) \n : errorMessage)\n : response.error.message || \"An error occurred\";\n \n // Always save to localStorage for redirect cases\n // This ensures compatibility with both current and future sonner versions\n if (typeof window !== 'undefined') {\n try {\n const storageKey = 'sonner-toasts';\n const existingToasts = JSON.parse(\n localStorage.getItem(storageKey) || '[]'\n );\n \n // Add our toast in the same format as the PR\n const persistentToast = {\n id: Date.now(),\n type: 'error',\n message,\n persistent: true,\n createdAt: Date.now()\n };\n \n existingToasts.push(persistentToast);\n localStorage.setItem(storageKey, JSON.stringify(existingToasts));\n } catch (err) {\n console.error('Failed to persist toast:', err);\n }\n }\n \n // Always show the toast (with persistent if supported)\n (toast.error as any)(message, { persistent: true });\n }\n \n setIsRedirecting(true);\n router.push(response.error.redirectTo || \"/login\");\n return actionResult;\n }\n \n if (showErrorToast) {\n const message = errorMessage \n ? (typeof errorMessage === \"function\" \n ? errorMessage(actionResult) \n : errorMessage)\n : response.error.message || \"An error occurred\";\n toast.error(message);\n }\n \n await onError?.(actionResult);\n } else {\n actionResult = { fetchError: \"Unexpected response format\" };\n }\n \n setResult(actionResult);\n return actionResult;\n \n } catch (error) {\n // Check if this is a Next.js navigation error that should be re-thrown\n if (isNextNavigationError(error)) {\n // Re-throw navigation errors to let Next.js handle them\n throw error;\n }\n \n const fetchError = error instanceof Error ? error.message : \"Network error\";\n const actionResult: ActionResult<TOutput> = { fetchError };\n \n setResult(actionResult);\n \n if (showErrorToast) {\n toast.error(fetchError);\n }\n \n await onError?.(actionResult);\n return actionResult;\n } finally {\n setIsExecuting(false);\n }\n },\n [action, router, showSuccessToast, successMessage, showErrorToast, errorMessage, redirectOnAuthError, onSuccess, onError]\n );\n \n const executeWithTransition = useCallback(\n (...args: TInput extends void ? [] : [input: TInput]): Promise<ActionResult<TOutput>> => {\n return new Promise((resolve) => {\n startTransition(async () => {\n const result = await execute(args[0] as TInput);\n resolve(result);\n });\n });\n },\n [execute]\n ) as TInput extends void \n ? () => Promise<ActionResult<TOutput>>\n : (input: TInput) => Promise<ActionResult<TOutput>>;\n \n return {\n execute: executeWithTransition,\n result,\n isExecuting,\n isRedirecting,\n hasSucceeded,\n hasErrored,\n reset,\n };\n}\n\n","// Comes from: https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/redirect-error.ts\n\nenum RedirectStatusCode {\n\tSeeOther = 303,\n\tTemporaryRedirect = 307,\n\tPermanentRedirect = 308,\n}\n\nconst REDIRECT_ERROR_CODE = \"NEXT_REDIRECT\";\n\nenum RedirectType {\n\tpush = \"push\",\n\treplace = \"replace\",\n}\n\nexport type RedirectError = Error & {\n\tdigest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by the\n * `redirect(url)` helper.\n *\n * @param error the error that may reference a redirect error\n * @returns true if the error is a redirect error\n */\nexport function isRedirectError(error: unknown): error is RedirectError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\n\tconst digest = error.digest.split(\";\");\n\tconst [errorCode, type] = digest;\n\tconst destination = digest.slice(2, -2).join(\";\");\n\tconst status = digest.at(-2);\n\n\tconst statusCode = Number(status);\n\n\treturn (\n\t\terrorCode === REDIRECT_ERROR_CODE &&\n\t\t(type === \"replace\" || type === \"push\") &&\n\t\ttypeof destination === \"string\" &&\n\t\t!isNaN(statusCode) &&\n\t\tstatusCode in RedirectStatusCode\n\t);\n}","// Comes from https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/http-access-fallback/http-access-fallback.ts\n\nconst HTTPAccessErrorStatus = {\n\tNOT_FOUND: 404,\n\tFORBIDDEN: 403,\n\tUNAUTHORIZED: 401,\n};\n\nconst ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatus));\n\nconst HTTP_ERROR_FALLBACK_ERROR_CODE = \"NEXT_HTTP_ERROR_FALLBACK\";\n\nexport type HTTPAccessFallbackError = Error & {\n\tdigest: `${typeof HTTP_ERROR_FALLBACK_ERROR_CODE};${string}`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by\n * the HTTP navigation APIs `notFound()`, `forbidden()` or `unauthorized()`.\n *\n * @param error the error that may reference a HTTP access error\n * @returns true if the error is a HTTP access error\n */\nexport function isHTTPAccessFallbackError(error: unknown): error is HTTPAccessFallbackError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\tconst [prefix, httpStatus] = error.digest.split(\";\");\n\n\treturn prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));\n}\n\nexport function getAccessFallbackHTTPStatus(error: HTTPAccessFallbackError): number {\n\tconst httpStatus = error.digest.split(\";\")[1];\n\treturn Number(httpStatus);\n}","import { isRedirectError } from \"./redirect\";\nimport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\n\nexport { isRedirectError } from \"./redirect\";\nexport type { RedirectError } from \"./redirect\";\n\nexport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\nexport type { HTTPAccessFallbackError } from \"./http-access-fallback\";\n\n/**\n * Checks if the error is a navigation error that should be re-thrown\n * This includes redirect errors and HTTP access errors (notFound, forbidden, unauthorized)\n */\nexport function isNextNavigationError(error: unknown): boolean {\n\treturn isRedirectError(error) || isHTTPAccessFallbackError(error);\n}\n\n/**\n * Checks if the error is a notFound error\n * Note: Next.js implements notFound() using HTTP_ERROR_FALLBACK with status 404,\n * not as a separate error type like NEXT_REDIRECT\n */\nexport function isNotFoundError(error: unknown): boolean {\n\treturn isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error as any) === 404;\n}","import { useOptimistic, useTransition } from \"react\";\nimport { useServerAction, type UseServerActionOptions } from \"./use-server-action\";\nimport type { ServerAction, ActionResult } from \"../types\";\n\nexport interface UseOptimisticActionOptions<TInput, TOutput, TOptimistic> extends UseServerActionOptions<TOutput> {\n /**\n * Function to update the optimistic state\n */\n updateFn: TInput extends void \n ? (current: TOptimistic) => TOptimistic\n : (current: TOptimistic, input: TInput) => TOptimistic;\n}\n\nexport interface UseOptimisticActionReturn<TInput, TOutput, TOptimistic> {\n /**\n * The optimistic state\n */\n optimisticState: TOptimistic;\n \n /**\n * Execute the action with optimistic update\n */\n execute: TInput extends void \n ? () => Promise<ActionResult<TOutput>>\n : (input: TInput) => Promise<ActionResult<TOutput>>;\n \n /**\n * Loading state\n */\n isExecuting: boolean;\n \n /**\n * Success state\n */\n hasSucceeded: boolean;\n \n /**\n * Error state\n */\n hasErrored: boolean;\n \n /**\n * Last result\n */\n result: ActionResult<TOutput> | undefined;\n \n /**\n * Reset state\n */\n reset: () => void;\n}\n\n/**\n * Hook for server actions with optimistic updates\n * \n * @example\n * ```typescript\n * const { optimisticState, execute } = useOptimisticAction(\n * currentTodos,\n * addTodoAction,\n * {\n * updateFn: (todos, newTodo) => [...todos, newTodo],\n * onSuccess: (savedTodo) => {\n * // Update with server response if needed\n * }\n * }\n * );\n * ```\n */\nexport function useOptimisticAction<TInput, TOutput, TOptimistic>(\n initialState: TOptimistic,\n action: ServerAction<TInput, TOutput>,\n options: UseOptimisticActionOptions<TInput, TOutput, TOptimistic>\n): UseOptimisticActionReturn<TInput, TOutput, TOptimistic> {\n const [optimisticState, addOptimisticUpdate] = useOptimistic(\n initialState,\n options.updateFn\n );\n \n const [, startTransition] = useTransition();\n \n // Extract updateFn from options to pass the rest to useServerAction\n const { updateFn: _, ...serverActionOptions } = options;\n \n const {\n execute: executeAction,\n isExecuting,\n hasSucceeded,\n hasErrored,\n result,\n reset\n } = useServerAction(action, serverActionOptions);\n \n const execute = (async (input?: TInput): Promise<ActionResult<TOutput>> => {\n // Apply optimistic update\n startTransition(() => {\n if (input !== undefined) {\n addOptimisticUpdate(input);\n } else {\n addOptimisticUpdate(undefined as any);\n }\n });\n \n // Execute the server action\n return executeAction(input as any);\n }) as any;\n \n return {\n optimisticState,\n execute,\n isExecuting,\n hasSucceeded,\n hasErrored,\n result,\n reset\n };\n}","import { useActionState, useEffect, useTransition, useRef, useState } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport type { UseFormProps, UseFormReturn, Path, FieldValues, DefaultValues } from \"react-hook-form\";\nimport { useForm } from \"react-hook-form\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { toast } from \"sonner\";\nimport type { z } from \"zod\";\nimport type { ServerActionResponse, ServerActionError, RedirectConfig } from \"../types\";\n\nexport interface UseFormActionOptions<TFieldValues extends FieldValues, TOutput> {\n // Required - the server action to execute (form action format)\n action: (prevState: ServerActionResponse<TOutput>, formData: FormData) => Promise<ServerActionResponse<TOutput>>;\n \n // Optional Zod schema for validation\n schema?: z.ZodTypeAny;\n \n // React Hook Form options\n defaultValues?: DefaultValues<TFieldValues>;\n mode?: UseFormProps<TFieldValues>[\"mode\"];\n \n // Transform function if you need custom FormData creation\n transformData?: (data: TFieldValues) => FormData;\n \n // Callbacks\n onSuccess?: (data: TOutput) => void | Promise<void>;\n onError?: (error: ServerActionError) => void;\n \n // Behavior options\n resetOnSuccess?: boolean;\n showSuccessToast?: boolean | string | ((data: TOutput) => string);\n showErrorToast?: boolean | string | ((error: ServerActionError) => string);\n \n // Redirect options (same as useServerAction)\n preventRedirect?: boolean;\n redirectDelay?: number;\n}\n\nexport interface UseFormActionReturn<TFieldValues extends FieldValues, TOutput> {\n // React Hook Form instance\n form: UseFormReturn<TFieldValues>;\n \n // Submit handler (pre-bound with handleSubmit)\n onSubmit: (e?: React.BaseSyntheticEvent) => void;\n \n // Loading state (combines isPending and isTransitioning)\n isSubmitting: boolean;\n \n // Redirecting state (true when redirect is in progress)\n isRedirecting: boolean;\n \n // The current action state\n actionState: ServerActionResponse<TOutput>;\n \n // Utilities\n reset: () => void;\n \n // Raw handlers if needed\n handleSubmit: (data: TFieldValues) => Promise<void>;\n}\n\nfunction isSuccessResponse<T>(response: ServerActionResponse<T>): response is { success: true; data: T; redirect?: string | RedirectConfig } {\n return response.success === true;\n}\n\nfunction objectToFormData(obj: any): FormData {\n const formData = new FormData();\n \n Object.entries(obj).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (value instanceof File || value instanceof Blob) {\n formData.append(key, value);\n } else if (Array.isArray(value)) {\n value.forEach((item) => formData.append(`${key}[]`, String(item)));\n } else if (typeof value === \"object\") {\n formData.append(key, JSON.stringify(value));\n } else {\n formData.append(key, String(value));\n }\n }\n });\n \n return formData;\n}\n\nexport function useFormAction<TFieldValues extends FieldValues = FieldValues, TOutput = void>({\n action,\n schema,\n defaultValues,\n mode = \"onChange\",\n transformData,\n onSuccess,\n onError,\n resetOnSuccess = false,\n showSuccessToast = false,\n showErrorToast = true,\n preventRedirect = false,\n redirectDelay = 0,\n}: UseFormActionOptions<TFieldValues, TOutput>): UseFormActionReturn<TFieldValues, TOutput> {\n const router = useRouter();\n const [isRedirecting, setIsRedirecting] = useState(false);\n \n // Store callbacks in refs to prevent effect re-runs\n const onSuccessRef = useRef(onSuccess);\n const onErrorRef = useRef(onError);\n const showSuccessToastRef = useRef(showSuccessToast);\n const showErrorToastRef = useRef(showErrorToast);\n \n // Update refs when callbacks change\n useEffect(() => {\n onSuccessRef.current = onSuccess;\n onErrorRef.current = onError;\n showSuccessToastRef.current = showSuccessToast;\n showErrorToastRef.current = showErrorToast;\n });\n \n // 1. Setup form with React Hook Form\n const form = useForm<TFieldValues>({\n resolver: schema ? (zodResolver as any)(schema) : undefined,\n defaultValues,\n mode,\n } as UseFormProps<TFieldValues>);\n \n // 2. Setup server action state with useActionState\n const initialState: ServerActionResponse<TOutput> = { success: true, data: undefined as TOutput };\n const [actionState, formAction, isPending] = useActionState(action, initialState);\n const [isTransitioning, startTransition] = useTransition();\n \n // 3. Handle server errors and success\n useEffect(() => {\n // Skip initial state\n if (actionState.success === true && actionState.data === undefined) {\n return;\n }\n \n // Reset redirecting state if we're processing a new action\n setIsRedirecting(false);\n \n // Keep track of timeout for cleanup\n let timeoutId: NodeJS.Timeout | undefined;\n \n if (!isSuccessResponse(actionState) && actionState.error) {\n const { error } = actionState;\n \n // Map field errors to form\n if (error.fields) {\n Object.entries(error.fields).forEach(([field, messages]) => {\n if (Array.isArray(messages) && messages.length > 0) {\n form.setError(field as Path<TFieldValues>, {\n type: \"server\",\n message: messages[0],\n });\n }\n });\n }\n \n // Single field error\n if (error.field && error.message && !error.fields) {\n form.setError(error.field as Path<TFieldValues>, {\n type: \"server\",\n message: error.message,\n });\n }\n \n // Global error (no specific field)\n if (error.message && !error.field && !error.fields) {\n const showToast = showErrorToastRef.current;\n if (showToast) {\n const message = typeof showToast === \"function\" \n ? showToast(error)\n : typeof showToast === \"string\"\n ? showToast\n : error.message;\n toast.error(message);\n }\n \n // Also set on root for inline display\n form.setError(\"root\", {\n type: \"server\",\n message: error.message,\n });\n }\n \n // Call error callback\n onErrorRef.current?.(error);\n }\n \n // Handle success\n if (isSuccessResponse(actionState) && actionState.data !== undefined) {\n const showToast = showSuccessToastRef.current;\n if (showToast) {\n const message = typeof showToast === \"function\"\n ? showToast(actionState.data)\n : typeof showToast === \"string\"\n ? showToast\n : \"Success!\";\n toast.success(message);\n }\n \n if (resetOnSuccess) {\n form.reset();\n }\n \n // Call success callback first\n onSuccessRef.current?.(actionState.data);\n \n // Handle redirect if present in response - delay to ensure state updates complete\n if (actionState.redirect && !preventRedirect) {\n setIsRedirecting(true);\n const redirectConfig = typeof actionState.redirect === 'string'\n ? { url: actionState.redirect }\n : actionState.redirect;\n \n const delay = redirectConfig.delay ?? redirectDelay;\n \n timeoutId = setTimeout(() => {\n if (redirectConfig.replace) {\n router.replace(redirectConfig.url);\n } else {\n router.push(redirectConfig.url);\n }\n setIsRedirecting(false);\n }, delay || 100); // Add small delay by default\n }\n }\n \n // Always return cleanup function\n return () => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n };\n }, [actionState]); // Minimal dependencies - only actionState\n \n // 4. Submit handler\n const handleSubmit = async (data: TFieldValues): Promise<void> => {\n // Clear any previous errors\n form.clearErrors();\n \n // Transform to FormData\n const formData = transformData \n ? transformData(data)\n : objectToFormData(data);\n \n // Execute with transition for better UX\n startTransition(() => {\n formAction(formData);\n });\n };\n \n // 5. Combined loading state\n const isSubmitting = isPending || isTransitioning;\n \n // 6. Pre-bound submit handler\n const onSubmit = (e?: React.BaseSyntheticEvent): void => {\n e?.preventDefault();\n void form.handleSubmit(handleSubmit)(e!);\n };\n \n return {\n form,\n onSubmit,\n isSubmitting,\n isRedirecting,\n actionState,\n reset: form.reset,\n handleSubmit,\n };\n}","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { toast } from \"sonner\";\n\nexport function ToastRestorer() {\n useEffect(() => {\n // Only run on client side\n if (typeof window === \"undefined\") return;\n \n const storageKey = \"sonner-toasts\";\n \n try {\n const storedToasts = localStorage.getItem(storageKey);\n \n if (storedToasts) {\n const persistentToasts = JSON.parse(storedToasts);\n \n if (Array.isArray(persistentToasts) && persistentToasts.length > 0) {\n // Clear the storage immediately to prevent duplicate toasts\n localStorage.removeItem(storageKey);\n \n // Filter out old toasts (older than 30 seconds)\n const recentToasts = persistentToasts.filter(\n (t: any) => Date.now() - (t.createdAt || 0) < 30000\n );\n \n // Restore toasts with staggered animation like in the PR\n recentToasts.forEach((persistedToast: any, index: number) => {\n // Skip loading toasts as per the PR implementation\n if (persistedToast.type === \"loading\") return;\n \n setTimeout(() => {\n const toastFunction = toast[persistedToast.type as keyof typeof toast];\n \n if (typeof toastFunction === \"function\") {\n // Check if current sonner supports persistent\n if (toastFunction.length >= 2) {\n // Use persistent if available\n (toastFunction as any)(persistedToast.message, { \n persistent: true,\n id: persistedToast.id \n });\n } else {\n // Fallback to normal toast\n toastFunction(persistedToast.message);\n }\n }\n }, index * 150); // Staggered delay like in the PR\n });\n }\n }\n } catch (error) {\n console.error(\"Failed to restore toasts:\", error);\n // Clean up on error\n localStorage.removeItem(storageKey);\n }\n }, []);\n \n return null;\n}"],"mappings":"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","names":["RedirectStatusCode","result","useTransition","useTransition","useTransition","useState","useRouter","toast","useEffect","toast"]}
1
+ {"version":3,"sources":["../../src/hooks/use-server-action.ts","../../src/next/errors/redirect.ts","../../src/next/errors/http-access-fallback.ts","../../src/next/errors/index.ts","../../src/hooks/use-optimistic-action.ts","../../src/hooks/use-form-action.ts","../../src/hooks/toast-restorer.tsx"],"sourcesContent":["import { useCallback, useState, useTransition } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport { toast } from \"sonner\";\nimport type { ServerAction, ActionResult, ServerActionResponse } from \"../types\";\nimport { isNextNavigationError } from \"../next/errors\";\n\nexport interface UseServerActionOptions<TOutput> {\n onSuccess?: (data: TOutput) => void | Promise<void>;\n onError?: (error: ActionResult<TOutput>) => void | Promise<void>;\n \n successMessage?: string | ((data: TOutput) => string);\n errorMessage?: string | ((error: ActionResult<TOutput>) => string);\n showSuccessToast?: boolean;\n showErrorToast?: boolean;\n \n redirectOnAuthError?: boolean;\n preventRedirect?: boolean;\n redirectDelay?: number;\n}\n\nexport interface UseServerActionReturn<TInput, TOutput> {\n execute: TInput extends void \n ? () => Promise<ActionResult<TOutput>>\n : (input: TInput) => Promise<ActionResult<TOutput>>;\n \n result: ActionResult<TOutput> | undefined;\n isExecuting: boolean;\n isRedirecting: boolean;\n hasSucceeded: boolean;\n hasErrored: boolean;\n \n reset: () => void;\n}\n\n// Overload for void actions\nexport function useServerAction<TOutput>(\n action: ServerAction<void, TOutput>,\n options?: UseServerActionOptions<TOutput>\n): UseServerActionReturn<void, TOutput>;\n\n// Overload for actions with input\nexport function useServerAction<TInput, TOutput>(\n action: ServerAction<TInput, TOutput>,\n options?: UseServerActionOptions<TOutput>\n): UseServerActionReturn<TInput, TOutput>;\n\n// Implementation\nexport function useServerAction<TInput, TOutput>(\n action: ServerAction<TInput, TOutput>,\n options: UseServerActionOptions<TOutput> = {}\n): UseServerActionReturn<TInput, TOutput> {\n const router = useRouter();\n const [result, setResult] = useState<ActionResult<TOutput>>();\n const [isExecuting, setIsExecuting] = useState(false);\n const [isRedirecting, setIsRedirecting] = useState(false);\n const [, startTransition] = useTransition();\n \n const {\n onSuccess,\n onError,\n successMessage,\n errorMessage,\n showSuccessToast = false,\n showErrorToast = true,\n redirectOnAuthError = true,\n preventRedirect = false,\n redirectDelay = 0,\n } = options;\n \n const hasSucceeded = !!result?.data;\n const hasErrored = !!result?.serverError || !!result?.validationErrors || !!result?.fetchError;\n \n const reset = useCallback(() => {\n setResult(undefined);\n setIsRedirecting(false);\n }, []);\n \n const execute = useCallback(\n async (input?: TInput): Promise<ActionResult<TOutput>> => {\n setIsExecuting(true);\n \n try {\n const response = await (input === undefined \n ? (action as () => Promise<ServerActionResponse<TOutput>>)()\n : (action as (input: TInput) => Promise<ServerActionResponse<TOutput>>)(input));\n \n let actionResult: ActionResult<TOutput>;\n \n if (response.success) {\n actionResult = { data: response.data };\n \n if (process.env.NODE_ENV === 'development') {\n console.log('[useServerAction] Success response:', response);\n console.log('[useServerAction] Has redirect?', !!response.redirect);\n }\n \n if (showSuccessToast && successMessage) {\n const message = typeof successMessage === \"function\" \n ? successMessage(response.data) \n : successMessage;\n toast.success(message);\n }\n \n await onSuccess?.(response.data);\n \n // Handle redirect if present in response\n if (response.redirect && !preventRedirect) {\n setIsRedirecting(true);\n const redirectConfig = typeof response.redirect === 'string'\n ? { url: response.redirect }\n : response.redirect;\n \n const delay = redirectConfig.delay ?? redirectDelay;\n \n setTimeout(() => {\n if (redirectConfig.replace) {\n router.replace(redirectConfig.url);\n } else {\n router.push(redirectConfig.url);\n }\n // Don't reset isRedirecting - the component will unmount anyway\n }, delay);\n }\n \n } else if (!response.success && response.error) {\n actionResult = {\n serverError: response.error,\n validationErrors: response.error.fields,\n };\n \n // Debug logging\n if (process.env.NODE_ENV === 'development') {\n console.log('[useServerAction] Error response:', response.error);\n console.log('[useServerAction] Should redirect?', response.error.shouldRedirect);\n console.log('[useServerAction] Redirect to:', response.error.redirectTo);\n }\n \n if (redirectOnAuthError && response.error.shouldRedirect) {\n // Handle toast before redirect\n if (showErrorToast) {\n const message = errorMessage \n ? (typeof errorMessage === \"function\" \n ? errorMessage(actionResult) \n : errorMessage)\n : response.error.message || \"An error occurred\";\n \n // Always save to localStorage for redirect cases\n // This ensures compatibility with both current and future sonner versions\n if (typeof window !== 'undefined') {\n try {\n const storageKey = 'sonner-toasts';\n const existingToasts = JSON.parse(\n localStorage.getItem(storageKey) || '[]'\n );\n \n // Add our toast in the same format as the PR\n const persistentToast = {\n id: Date.now(),\n type: 'error',\n message,\n persistent: true,\n createdAt: Date.now()\n };\n \n existingToasts.push(persistentToast);\n localStorage.setItem(storageKey, JSON.stringify(existingToasts));\n } catch (err) {\n console.error('Failed to persist toast:', err);\n }\n }\n \n // Always show the toast (with persistent if supported)\n (toast.error as any)(message, { persistent: true });\n }\n \n setIsRedirecting(true);\n router.push(response.error.redirectTo || \"/login\");\n return actionResult;\n }\n \n if (showErrorToast) {\n const message = errorMessage \n ? (typeof errorMessage === \"function\" \n ? errorMessage(actionResult) \n : errorMessage)\n : response.error.message || \"An error occurred\";\n toast.error(message);\n }\n \n await onError?.(actionResult);\n } else {\n actionResult = { fetchError: \"Unexpected response format\" };\n }\n \n setResult(actionResult);\n return actionResult;\n \n } catch (error) {\n // Check if this is a Next.js navigation error that should be re-thrown\n if (isNextNavigationError(error)) {\n // Re-throw navigation errors to let Next.js handle them\n throw error;\n }\n \n const fetchError = error instanceof Error ? error.message : \"Network error\";\n const actionResult: ActionResult<TOutput> = { fetchError };\n \n setResult(actionResult);\n \n if (showErrorToast) {\n toast.error(fetchError);\n }\n \n await onError?.(actionResult);\n return actionResult;\n } finally {\n setIsExecuting(false);\n }\n },\n [action, router, showSuccessToast, successMessage, showErrorToast, errorMessage, redirectOnAuthError, onSuccess, onError]\n );\n \n const executeWithTransition = useCallback(\n (...args: TInput extends void ? [] : [input: TInput]): Promise<ActionResult<TOutput>> => {\n return new Promise((resolve) => {\n startTransition(async () => {\n const result = await execute(args[0] as TInput);\n resolve(result);\n });\n });\n },\n [execute]\n ) as TInput extends void \n ? () => Promise<ActionResult<TOutput>>\n : (input: TInput) => Promise<ActionResult<TOutput>>;\n \n return {\n execute: executeWithTransition,\n result,\n isExecuting,\n isRedirecting,\n hasSucceeded,\n hasErrored,\n reset,\n };\n}\n\n","// Comes from: https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/redirect-error.ts\n\nenum RedirectStatusCode {\n\tSeeOther = 303,\n\tTemporaryRedirect = 307,\n\tPermanentRedirect = 308,\n}\n\nconst REDIRECT_ERROR_CODE = \"NEXT_REDIRECT\";\n\nenum RedirectType {\n\tpush = \"push\",\n\treplace = \"replace\",\n}\n\nexport type RedirectError = Error & {\n\tdigest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by the\n * `redirect(url)` helper.\n *\n * @param error the error that may reference a redirect error\n * @returns true if the error is a redirect error\n */\nexport function isRedirectError(error: unknown): error is RedirectError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\n\tconst digest = error.digest.split(\";\");\n\tconst [errorCode, type] = digest;\n\tconst destination = digest.slice(2, -2).join(\";\");\n\tconst status = digest.at(-2);\n\n\tconst statusCode = Number(status);\n\n\treturn (\n\t\terrorCode === REDIRECT_ERROR_CODE &&\n\t\t(type === \"replace\" || type === \"push\") &&\n\t\ttypeof destination === \"string\" &&\n\t\t!isNaN(statusCode) &&\n\t\tstatusCode in RedirectStatusCode\n\t);\n}","// Comes from https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/http-access-fallback/http-access-fallback.ts\n\nconst HTTPAccessErrorStatus = {\n\tNOT_FOUND: 404,\n\tFORBIDDEN: 403,\n\tUNAUTHORIZED: 401,\n};\n\nconst ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatus));\n\nconst HTTP_ERROR_FALLBACK_ERROR_CODE = \"NEXT_HTTP_ERROR_FALLBACK\";\n\nexport type HTTPAccessFallbackError = Error & {\n\tdigest: `${typeof HTTP_ERROR_FALLBACK_ERROR_CODE};${string}`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by\n * the HTTP navigation APIs `notFound()`, `forbidden()` or `unauthorized()`.\n *\n * @param error the error that may reference a HTTP access error\n * @returns true if the error is a HTTP access error\n */\nexport function isHTTPAccessFallbackError(error: unknown): error is HTTPAccessFallbackError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\tconst [prefix, httpStatus] = error.digest.split(\";\");\n\n\treturn prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));\n}\n\nexport function getAccessFallbackHTTPStatus(error: HTTPAccessFallbackError): number {\n\tconst httpStatus = error.digest.split(\";\")[1];\n\treturn Number(httpStatus);\n}","import { isRedirectError } from \"./redirect\";\nimport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\n\nexport { isRedirectError } from \"./redirect\";\nexport type { RedirectError } from \"./redirect\";\n\nexport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\nexport type { HTTPAccessFallbackError } from \"./http-access-fallback\";\n\n/**\n * Checks if the error is a navigation error that should be re-thrown\n * This includes redirect errors and HTTP access errors (notFound, forbidden, unauthorized)\n */\nexport function isNextNavigationError(error: unknown): boolean {\n\treturn isRedirectError(error) || isHTTPAccessFallbackError(error);\n}\n\n/**\n * Checks if the error is a notFound error\n * Note: Next.js implements notFound() using HTTP_ERROR_FALLBACK with status 404,\n * not as a separate error type like NEXT_REDIRECT\n */\nexport function isNotFoundError(error: unknown): boolean {\n\treturn isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error as any) === 404;\n}","import { useOptimistic, useTransition } from \"react\";\nimport { useServerAction, type UseServerActionOptions } from \"./use-server-action\";\nimport type { ServerAction, ActionResult } from \"../types\";\n\nexport interface UseOptimisticActionOptions<TInput, TOutput, TOptimistic> extends UseServerActionOptions<TOutput> {\n /**\n * Function to update the optimistic state\n */\n updateFn: TInput extends void \n ? (current: TOptimistic) => TOptimistic\n : (current: TOptimistic, input: TInput) => TOptimistic;\n}\n\nexport interface UseOptimisticActionReturn<TInput, TOutput, TOptimistic> {\n /**\n * The optimistic state\n */\n optimisticState: TOptimistic;\n \n /**\n * Execute the action with optimistic update\n */\n execute: TInput extends void \n ? () => Promise<ActionResult<TOutput>>\n : (input: TInput) => Promise<ActionResult<TOutput>>;\n \n /**\n * Loading state\n */\n isExecuting: boolean;\n \n /**\n * Success state\n */\n hasSucceeded: boolean;\n \n /**\n * Error state\n */\n hasErrored: boolean;\n \n /**\n * Last result\n */\n result: ActionResult<TOutput> | undefined;\n \n /**\n * Reset state\n */\n reset: () => void;\n}\n\n/**\n * Hook for server actions with optimistic updates\n * \n * @example\n * ```typescript\n * const { optimisticState, execute } = useOptimisticAction(\n * currentTodos,\n * addTodoAction,\n * {\n * updateFn: (todos, newTodo) => [...todos, newTodo],\n * onSuccess: (savedTodo) => {\n * // Update with server response if needed\n * }\n * }\n * );\n * ```\n */\nexport function useOptimisticAction<TInput, TOutput, TOptimistic>(\n initialState: TOptimistic,\n action: ServerAction<TInput, TOutput>,\n options: UseOptimisticActionOptions<TInput, TOutput, TOptimistic>\n): UseOptimisticActionReturn<TInput, TOutput, TOptimistic> {\n const [optimisticState, addOptimisticUpdate] = useOptimistic(\n initialState,\n options.updateFn\n );\n \n const [, startTransition] = useTransition();\n \n // Extract updateFn from options to pass the rest to useServerAction\n const { updateFn: _, ...serverActionOptions } = options;\n \n const {\n execute: executeAction,\n isExecuting,\n hasSucceeded,\n hasErrored,\n result,\n reset\n } = useServerAction(action, serverActionOptions);\n \n const execute = (async (input?: TInput): Promise<ActionResult<TOutput>> => {\n // Apply optimistic update\n startTransition(() => {\n if (input !== undefined) {\n addOptimisticUpdate(input);\n } else {\n addOptimisticUpdate(undefined as any);\n }\n });\n \n // Execute the server action\n return executeAction(input as any);\n }) as any;\n \n return {\n optimisticState,\n execute,\n isExecuting,\n hasSucceeded,\n hasErrored,\n result,\n reset\n };\n}","import { useActionState, useEffect, useTransition, useRef, useState } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport type { UseFormProps, UseFormReturn, Path, FieldValues, DefaultValues } from \"react-hook-form\";\nimport { useForm } from \"react-hook-form\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { toast } from \"sonner\";\nimport type { z } from \"zod\";\nimport type { ServerActionResponse, ServerActionError, RedirectConfig } from \"../types\";\n\nexport interface UseFormActionOptions<TFieldValues extends FieldValues, TOutput> {\n // Required - the server action to execute (form action format)\n action: (prevState: ServerActionResponse<TOutput>, formData: FormData) => Promise<ServerActionResponse<TOutput>>;\n \n // Optional Zod schema for validation\n schema?: z.ZodTypeAny;\n \n // React Hook Form options\n defaultValues?: DefaultValues<TFieldValues>;\n mode?: UseFormProps<TFieldValues>[\"mode\"];\n \n // Transform function if you need custom FormData creation\n transformData?: (data: TFieldValues) => FormData;\n \n // Callbacks\n onSuccess?: (data: TOutput) => void | Promise<void>;\n onError?: (error: ServerActionError) => void;\n \n // Behavior options\n resetOnSuccess?: boolean;\n showSuccessToast?: boolean | string | ((data: TOutput) => string);\n showErrorToast?: boolean | string | ((error: ServerActionError) => string);\n \n // Redirect options (same as useServerAction)\n preventRedirect?: boolean;\n redirectDelay?: number;\n}\n\nexport interface UseFormActionReturn<TFieldValues extends FieldValues, TOutput> {\n // React Hook Form instance\n form: UseFormReturn<TFieldValues>;\n \n // Submit handler (pre-bound with handleSubmit)\n onSubmit: (e?: React.BaseSyntheticEvent) => void;\n \n // Loading state (combines isPending and isTransitioning)\n isSubmitting: boolean;\n \n // Redirecting state (true when redirect is in progress)\n isRedirecting: boolean;\n \n // The current action state\n actionState: ServerActionResponse<TOutput>;\n \n // Utilities\n reset: () => void;\n \n // Raw handlers if needed\n handleSubmit: (data: TFieldValues) => Promise<void>;\n}\n\nfunction isSuccessResponse<T>(response: ServerActionResponse<T>): response is { success: true; data: T; redirect?: string | RedirectConfig } {\n return response.success === true;\n}\n\nfunction objectToFormData(obj: any): FormData {\n const formData = new FormData();\n \n Object.entries(obj).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (value instanceof File || value instanceof Blob) {\n formData.append(key, value);\n } else if (Array.isArray(value)) {\n value.forEach((item) => formData.append(`${key}[]`, String(item)));\n } else if (typeof value === \"object\") {\n formData.append(key, JSON.stringify(value));\n } else {\n formData.append(key, String(value));\n }\n }\n });\n \n return formData;\n}\n\nexport function useFormAction<TFieldValues extends FieldValues = FieldValues, TOutput = void>({\n action,\n schema,\n defaultValues,\n mode = \"onChange\",\n transformData,\n onSuccess,\n onError,\n resetOnSuccess = false,\n showSuccessToast = false,\n showErrorToast = true,\n preventRedirect = false,\n redirectDelay = 0,\n}: UseFormActionOptions<TFieldValues, TOutput>): UseFormActionReturn<TFieldValues, TOutput> {\n const router = useRouter();\n const [isRedirecting, setIsRedirecting] = useState(false);\n \n // Store callbacks in refs to prevent effect re-runs\n const onSuccessRef = useRef(onSuccess);\n const onErrorRef = useRef(onError);\n const showSuccessToastRef = useRef(showSuccessToast);\n const showErrorToastRef = useRef(showErrorToast);\n \n // Update refs when callbacks change\n useEffect(() => {\n onSuccessRef.current = onSuccess;\n onErrorRef.current = onError;\n showSuccessToastRef.current = showSuccessToast;\n showErrorToastRef.current = showErrorToast;\n });\n \n // 1. Setup form with React Hook Form\n const form = useForm<TFieldValues>({\n resolver: schema ? (zodResolver as any)(schema) : undefined,\n defaultValues,\n mode,\n } as UseFormProps<TFieldValues>);\n \n // 2. Setup server action state with useActionState\n const initialState: ServerActionResponse<TOutput> = { success: true, data: undefined as TOutput };\n const [actionState, formAction, isPending] = useActionState(action, initialState);\n const [isTransitioning, startTransition] = useTransition();\n \n // 3. Handle server errors and success\n useEffect(() => {\n // Skip initial state\n if (actionState.success === true && actionState.data === undefined) {\n return;\n }\n \n // Reset redirecting state if we're processing a new action\n setIsRedirecting(false);\n \n // Keep track of timeout for cleanup\n let timeoutId: NodeJS.Timeout | undefined;\n \n if (!isSuccessResponse(actionState) && actionState.error) {\n const { error } = actionState;\n \n // Map field errors to form\n if (error.fields) {\n Object.entries(error.fields).forEach(([field, messages]) => {\n if (Array.isArray(messages) && messages.length > 0) {\n form.setError(field as Path<TFieldValues>, {\n type: \"server\",\n message: messages[0],\n });\n }\n });\n }\n \n // Single field error\n if (error.field && error.message && !error.fields) {\n form.setError(error.field as Path<TFieldValues>, {\n type: \"server\",\n message: error.message,\n });\n }\n \n // Global error (no specific field)\n if (error.message && !error.field && !error.fields) {\n const showToast = showErrorToastRef.current;\n if (showToast) {\n const message = typeof showToast === \"function\" \n ? showToast(error)\n : typeof showToast === \"string\"\n ? showToast\n : error.message;\n toast.error(message);\n }\n \n // Also set on root for inline display\n form.setError(\"root\", {\n type: \"server\",\n message: error.message,\n });\n }\n \n // Call error callback\n onErrorRef.current?.(error);\n }\n \n // Handle success\n if (isSuccessResponse(actionState) && actionState.data !== undefined) {\n const showToast = showSuccessToastRef.current;\n if (showToast) {\n const message = typeof showToast === \"function\"\n ? showToast(actionState.data)\n : typeof showToast === \"string\"\n ? showToast\n : \"Success!\";\n toast.success(message);\n }\n \n if (resetOnSuccess) {\n form.reset();\n }\n \n // Call success callback first\n onSuccessRef.current?.(actionState.data);\n \n // Handle redirect if present in response - delay to ensure state updates complete\n if (actionState.redirect && !preventRedirect) {\n setIsRedirecting(true);\n const redirectConfig = typeof actionState.redirect === 'string'\n ? { url: actionState.redirect }\n : actionState.redirect;\n \n const delay = redirectConfig.delay ?? redirectDelay;\n \n timeoutId = setTimeout(() => {\n if (redirectConfig.replace) {\n router.replace(redirectConfig.url);\n } else {\n router.push(redirectConfig.url);\n }\n // Don't reset isRedirecting - the component will unmount anyway\n }, delay || 100); // Add small delay by default\n }\n }\n \n // Always return cleanup function\n return () => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n };\n }, [actionState]); // Minimal dependencies - only actionState\n \n // 4. Submit handler\n const handleSubmit = async (data: TFieldValues): Promise<void> => {\n // Clear any previous errors\n form.clearErrors();\n \n // Transform to FormData\n const formData = transformData \n ? transformData(data)\n : objectToFormData(data);\n \n // Execute with transition for better UX\n startTransition(() => {\n formAction(formData);\n });\n };\n \n // 5. Combined loading state\n const isSubmitting = isPending || isTransitioning;\n \n // 6. Pre-bound submit handler\n const onSubmit = (e?: React.BaseSyntheticEvent): void => {\n e?.preventDefault();\n void form.handleSubmit(handleSubmit)(e!);\n };\n \n return {\n form,\n onSubmit,\n isSubmitting,\n isRedirecting,\n actionState,\n reset: form.reset,\n handleSubmit,\n };\n}","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { toast } from \"sonner\";\n\nexport function ToastRestorer() {\n useEffect(() => {\n // Only run on client side\n if (typeof window === \"undefined\") return;\n \n const storageKey = \"sonner-toasts\";\n \n try {\n const storedToasts = localStorage.getItem(storageKey);\n \n if (storedToasts) {\n const persistentToasts = JSON.parse(storedToasts);\n \n if (Array.isArray(persistentToasts) && persistentToasts.length > 0) {\n // Clear the storage immediately to prevent duplicate toasts\n localStorage.removeItem(storageKey);\n \n // Filter out old toasts (older than 30 seconds)\n const recentToasts = persistentToasts.filter(\n (t: any) => Date.now() - (t.createdAt || 0) < 30000\n );\n \n // Restore toasts with staggered animation like in the PR\n recentToasts.forEach((persistedToast: any, index: number) => {\n // Skip loading toasts as per the PR implementation\n if (persistedToast.type === \"loading\") return;\n \n setTimeout(() => {\n const toastFunction = toast[persistedToast.type as keyof typeof toast];\n \n if (typeof toastFunction === \"function\") {\n // Check if current sonner supports persistent\n if (toastFunction.length >= 2) {\n // Use persistent if available\n (toastFunction as any)(persistedToast.message, { \n persistent: true,\n id: persistedToast.id \n });\n } else {\n // Fallback to normal toast\n toastFunction(persistedToast.message);\n }\n }\n }, index * 150); // Staggered delay like in the PR\n });\n }\n }\n } catch (error) {\n console.error(\"Failed to restore toasts:\", error);\n // Clean up on error\n localStorage.removeItem(storageKey);\n }\n }, []);\n \n return null;\n}"],"mappings":"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","names":["RedirectStatusCode","result","useTransition","useTransition","useTransition","useState","useRouter","toast","useEffect","toast"]}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/core/error-handler.ts","../src/next/errors/redirect.ts","../src/next/errors/http-access-fallback.ts","../src/next/errors/index.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\n// Navigation error utilities\nexport { \n isRedirectError, \n isNotFoundError, \n isHTTPAccessFallbackError,\n isNextNavigationError \n} from \"./next/errors\";\nexport type { RedirectError, HTTPAccessFallbackError } from \"./next/errors\";\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}","// Comes from: https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/redirect-error.ts\n\nenum RedirectStatusCode {\n\tSeeOther = 303,\n\tTemporaryRedirect = 307,\n\tPermanentRedirect = 308,\n}\n\nconst REDIRECT_ERROR_CODE = \"NEXT_REDIRECT\";\n\nenum RedirectType {\n\tpush = \"push\",\n\treplace = \"replace\",\n}\n\nexport type RedirectError = Error & {\n\tdigest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by the\n * `redirect(url)` helper.\n *\n * @param error the error that may reference a redirect error\n * @returns true if the error is a redirect error\n */\nexport function isRedirectError(error: unknown): error is RedirectError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\n\tconst digest = error.digest.split(\";\");\n\tconst [errorCode, type] = digest;\n\tconst destination = digest.slice(2, -2).join(\";\");\n\tconst status = digest.at(-2);\n\n\tconst statusCode = Number(status);\n\n\treturn (\n\t\terrorCode === REDIRECT_ERROR_CODE &&\n\t\t(type === \"replace\" || type === \"push\") &&\n\t\ttypeof destination === \"string\" &&\n\t\t!isNaN(statusCode) &&\n\t\tstatusCode in RedirectStatusCode\n\t);\n}","// Comes from https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/http-access-fallback/http-access-fallback.ts\n\nconst HTTPAccessErrorStatus = {\n\tNOT_FOUND: 404,\n\tFORBIDDEN: 403,\n\tUNAUTHORIZED: 401,\n};\n\nconst ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatus));\n\nconst HTTP_ERROR_FALLBACK_ERROR_CODE = \"NEXT_HTTP_ERROR_FALLBACK\";\n\nexport type HTTPAccessFallbackError = Error & {\n\tdigest: `${typeof HTTP_ERROR_FALLBACK_ERROR_CODE};${string}`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by\n * the HTTP navigation APIs `notFound()`, `forbidden()` or `unauthorized()`.\n *\n * @param error the error that may reference a HTTP access error\n * @returns true if the error is a HTTP access error\n */\nexport function isHTTPAccessFallbackError(error: unknown): error is HTTPAccessFallbackError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\tconst [prefix, httpStatus] = error.digest.split(\";\");\n\n\treturn prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));\n}\n\nexport function getAccessFallbackHTTPStatus(error: HTTPAccessFallbackError): number {\n\tconst httpStatus = error.digest.split(\";\")[1];\n\treturn Number(httpStatus);\n}","import { isRedirectError } from \"./redirect\";\nimport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\n\nexport { isRedirectError } from \"./redirect\";\nexport type { RedirectError } from \"./redirect\";\n\nexport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\nexport type { HTTPAccessFallbackError } from \"./http-access-fallback\";\n\n/**\n * Checks if the error is a navigation error that should be re-thrown\n * This includes redirect errors and HTTP access errors (notFound, forbidden, unauthorized)\n */\nexport function isNextNavigationError(error: unknown): boolean {\n\treturn isRedirectError(error) || isHTTPAccessFallbackError(error);\n}\n\n/**\n * Checks if the error is a notFound error\n * Note: Next.js implements notFound() using HTTP_ERROR_FALLBACK with status 404,\n * not as a separate error type like NEXT_REDIRECT\n */\nexport function isNotFoundError(error: unknown): boolean {\n\treturn isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error as any) === 404;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\nimport { isNextNavigationError } from \"../next/errors\";\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\nimport type { RedirectConfig } from \"../types\";\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 a redirect configuration for successful actions.\n * @param config Redirect URL, config object, or function that returns redirect config based on result\n */\n redirect<Data = any>(\n config: string | RedirectConfig | ((result: Data) => string | RedirectConfig | undefined)\n ) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n redirectConfig: config,\n });\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 undefined\n ? (context: Context) => Promise<Data>\n : InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): ServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : void, \n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n > {\n return createServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : 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 redirectConfig: this.#args.redirectConfig,\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 undefined\n ? (context: Context) => Promise<Data>\n : 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 redirectConfig: this.#args.redirectConfig,\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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":["RedirectStatusCode","result"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/core/error-handler.ts","../src/next/errors/redirect.ts","../src/next/errors/http-access-fallback.ts","../src/next/errors/index.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\n// Navigation error utilities\nexport { \n isRedirectError, \n isNotFoundError, \n isHTTPAccessFallbackError,\n isNextNavigationError \n} from \"./next/errors\";\nexport type { RedirectError, HTTPAccessFallbackError } from \"./next/errors\";\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}","// Comes from: https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/redirect-error.ts\n\nenum RedirectStatusCode {\n\tSeeOther = 303,\n\tTemporaryRedirect = 307,\n\tPermanentRedirect = 308,\n}\n\nconst REDIRECT_ERROR_CODE = \"NEXT_REDIRECT\";\n\nenum RedirectType {\n\tpush = \"push\",\n\treplace = \"replace\",\n}\n\nexport type RedirectError = Error & {\n\tdigest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by the\n * `redirect(url)` helper.\n *\n * @param error the error that may reference a redirect error\n * @returns true if the error is a redirect error\n */\nexport function isRedirectError(error: unknown): error is RedirectError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\n\tconst digest = error.digest.split(\";\");\n\tconst [errorCode, type] = digest;\n\tconst destination = digest.slice(2, -2).join(\";\");\n\tconst status = digest.at(-2);\n\n\tconst statusCode = Number(status);\n\n\treturn (\n\t\terrorCode === REDIRECT_ERROR_CODE &&\n\t\t(type === \"replace\" || type === \"push\") &&\n\t\ttypeof destination === \"string\" &&\n\t\t!isNaN(statusCode) &&\n\t\tstatusCode in RedirectStatusCode\n\t);\n}","// Comes from https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/http-access-fallback/http-access-fallback.ts\n\nconst HTTPAccessErrorStatus = {\n\tNOT_FOUND: 404,\n\tFORBIDDEN: 403,\n\tUNAUTHORIZED: 401,\n};\n\nconst ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatus));\n\nconst HTTP_ERROR_FALLBACK_ERROR_CODE = \"NEXT_HTTP_ERROR_FALLBACK\";\n\nexport type HTTPAccessFallbackError = Error & {\n\tdigest: `${typeof HTTP_ERROR_FALLBACK_ERROR_CODE};${string}`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by\n * the HTTP navigation APIs `notFound()`, `forbidden()` or `unauthorized()`.\n *\n * @param error the error that may reference a HTTP access error\n * @returns true if the error is a HTTP access error\n */\nexport function isHTTPAccessFallbackError(error: unknown): error is HTTPAccessFallbackError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\tconst [prefix, httpStatus] = error.digest.split(\";\");\n\n\treturn prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));\n}\n\nexport function getAccessFallbackHTTPStatus(error: HTTPAccessFallbackError): number {\n\tconst httpStatus = error.digest.split(\";\")[1];\n\treturn Number(httpStatus);\n}","import { isRedirectError } from \"./redirect\";\nimport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\n\nexport { isRedirectError } from \"./redirect\";\nexport type { RedirectError } from \"./redirect\";\n\nexport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\nexport type { HTTPAccessFallbackError } from \"./http-access-fallback\";\n\n/**\n * Checks if the error is a navigation error that should be re-thrown\n * This includes redirect errors and HTTP access errors (notFound, forbidden, unauthorized)\n */\nexport function isNextNavigationError(error: unknown): boolean {\n\treturn isRedirectError(error) || isHTTPAccessFallbackError(error);\n}\n\n/**\n * Checks if the error is a notFound error\n * Note: Next.js implements notFound() using HTTP_ERROR_FALLBACK with status 404,\n * not as a separate error type like NEXT_REDIRECT\n */\nexport function isNotFoundError(error: unknown): boolean {\n\treturn isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error as any) === 404;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\nimport { isNextNavigationError } from \"../next/errors\";\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, Input = unknown> = (params: { context: Context; input: Input }) => Promise<{ context: Context } | { error: ServerActionError }>;\n\nimport type { RedirectConfig } from \"../types\";\n\ntype SafeActionClientArgs<Context extends object, InputSchema extends z.ZodTypeAny | undefined, OutputSchema extends z.ZodTypeAny | undefined> = {\n middlewareFns: ServerActionMiddleware<any, any>[];\n inputSchema?: InputSchema;\n outputSchema?: OutputSchema;\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n ctxType?: Context;\n redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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>(\n middlewareFn: ServerActionMiddleware<\n Context & NextContext, \n InputSchema extends z.ZodTypeAny ? z.output<InputSchema> : undefined\n >\n ) {\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 a redirect configuration for successful actions.\n * @param config Redirect URL, config object, or function that returns redirect config based on result\n */\n redirect<Data = any>(\n config: string | RedirectConfig | ((result: Data) => string | RedirectConfig | undefined)\n ) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n redirectConfig: config,\n });\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 undefined\n ? (context: Context) => Promise<Data>\n : InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): ServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : void, \n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n > {\n return createServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : 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 redirectConfig: this.#args.redirectConfig,\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 undefined\n ? (context: Context) => Promise<Data>\n : 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 redirectConfig: this.#args.redirectConfig,\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, any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (...args: any[]) => Promise<any>;\n redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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;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;;;AC7EA,IAAK,qBAAL,kBAAKA,wBAAL;AACC,EAAAA,wCAAA,cAAW,OAAX;AACA,EAAAA,wCAAA,uBAAoB,OAApB;AACA,EAAAA,wCAAA,uBAAoB,OAApB;AAHI,SAAAA;AAAA,GAAA;AAML,IAAM,sBAAsB;AAkBrB,SAAS,gBAAgB,OAAwC;AACvE,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,EAAE,YAAY,UAAU,OAAO,MAAM,WAAW,UAAU;AAC5G,WAAO;AAAA,EACR;AAEA,QAAM,SAAS,MAAM,OAAO,MAAM,GAAG;AACrC,QAAM,CAAC,WAAW,IAAI,IAAI;AAC1B,QAAM,cAAc,OAAO,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG;AAChD,QAAM,SAAS,OAAO,GAAG,EAAE;AAE3B,QAAM,aAAa,OAAO,MAAM;AAEhC,SACC,cAAc,wBACb,SAAS,aAAa,SAAS,WAChC,OAAO,gBAAgB,YACvB,CAAC,MAAM,UAAU,KACjB,cAAc;AAEhB;;;AC3CA,IAAM,wBAAwB;AAAA,EAC7B,WAAW;AAAA,EACX,WAAW;AAAA,EACX,cAAc;AACf;AAEA,IAAM,gBAAgB,IAAI,IAAI,OAAO,OAAO,qBAAqB,CAAC;AAElE,IAAM,iCAAiC;AAahC,SAAS,0BAA0B,OAAkD;AAC3F,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,EAAE,YAAY,UAAU,OAAO,MAAM,WAAW,UAAU;AAC5G,WAAO;AAAA,EACR;AACA,QAAM,CAAC,QAAQ,UAAU,IAAI,MAAM,OAAO,MAAM,GAAG;AAEnD,SAAO,WAAW,kCAAkC,cAAc,IAAI,OAAO,UAAU,CAAC;AACzF;AAEO,SAAS,4BAA4B,OAAwC;AACnF,QAAM,aAAa,MAAM,OAAO,MAAM,GAAG,EAAE,CAAC;AAC5C,SAAO,OAAO,UAAU;AACzB;;;ACtBO,SAAS,sBAAsB,OAAyB;AAC9D,SAAO,gBAAgB,KAAK,KAAK,0BAA0B,KAAK;AACjE;AAOO,SAAS,gBAAgB,OAAyB;AACxD,SAAO,0BAA0B,KAAK,KAAK,4BAA4B,KAAY,MAAM;AAC1F;;;ACxBA;AAqBO,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,IACE,cAIA;AACA,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,SACE,QACA;AACA,WAAO,IAAI,oBAAuD;AAAA,MAChE,GAAG,mBAAK;AAAA,MACR,gBAAgB;AAAA,IAClB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OACE,cAYA;AACA,WAAO,mBAOL;AAAA,MACA,aAAa,mBAAK,OAAM;AAAA,MACxB,cAAc,mBAAK,OAAM;AAAA,MACzB,eAAe,mBAAK,OAAM;AAAA,MAC1B,SAAS,mBAAK,OAAM;AAAA,MACpB;AAAA,MACA,gBAAgB,mBAAK,OAAM;AAAA,IAC7B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WACE,cAKqO;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,MACA,gBAAgB,mBAAK,OAAM;AAAA,IAC7B,CAAC;AAAA,EACH;AACF;AAjIW;AADJ,IAAM,qBAAN;AAqIP,SAAS,mBAAoC,QAOX;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,cAAMC,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;AAGA,UAAI;AACJ,UAAI,OAAO,gBAAgB;AACzB,YAAI,OAAO,OAAO,mBAAmB,YAAY;AAC/C,0BAAgB,OAAO,eAAe,eAAe;AAAA,QACvD,OAAO;AACL,0BAAgB,OAAO;AAAA,QACzB;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM;AAAA,QACN,GAAI,iBAAiB,EAAE,UAAU,cAAc;AAAA,MACjD;AAAA,IACF,SAAS,OAAO;AAEd,UAAI,sBAAsB,KAAK,GAAG;AAChC,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,QAO+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;AAGA,UAAI;AACJ,UAAI,OAAO,gBAAgB;AACzB,YAAI,OAAO,OAAO,mBAAmB,YAAY;AAC/C,0BAAgB,OAAO,eAAe,eAAe;AAAA,QACvD,OAAO;AACL,0BAAgB,OAAO;AAAA,QACzB;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM;AAAA,QACN,GAAI,iBAAiB,EAAE,UAAU,cAAc;AAAA,MACjD;AAAA,IACF,SAAS,OAAO;AAEd,UAAI,sBAAsB,KAAK,GAAG;AAChC,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":["RedirectStatusCode","result"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/error-handler.ts","../src/next/errors/redirect.ts","../src/next/errors/http-access-fallback.ts","../src/next/errors/index.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}","// Comes from: https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/redirect-error.ts\n\nenum RedirectStatusCode {\n\tSeeOther = 303,\n\tTemporaryRedirect = 307,\n\tPermanentRedirect = 308,\n}\n\nconst REDIRECT_ERROR_CODE = \"NEXT_REDIRECT\";\n\nenum RedirectType {\n\tpush = \"push\",\n\treplace = \"replace\",\n}\n\nexport type RedirectError = Error & {\n\tdigest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by the\n * `redirect(url)` helper.\n *\n * @param error the error that may reference a redirect error\n * @returns true if the error is a redirect error\n */\nexport function isRedirectError(error: unknown): error is RedirectError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\n\tconst digest = error.digest.split(\";\");\n\tconst [errorCode, type] = digest;\n\tconst destination = digest.slice(2, -2).join(\";\");\n\tconst status = digest.at(-2);\n\n\tconst statusCode = Number(status);\n\n\treturn (\n\t\terrorCode === REDIRECT_ERROR_CODE &&\n\t\t(type === \"replace\" || type === \"push\") &&\n\t\ttypeof destination === \"string\" &&\n\t\t!isNaN(statusCode) &&\n\t\tstatusCode in RedirectStatusCode\n\t);\n}","// Comes from https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/http-access-fallback/http-access-fallback.ts\n\nconst HTTPAccessErrorStatus = {\n\tNOT_FOUND: 404,\n\tFORBIDDEN: 403,\n\tUNAUTHORIZED: 401,\n};\n\nconst ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatus));\n\nconst HTTP_ERROR_FALLBACK_ERROR_CODE = \"NEXT_HTTP_ERROR_FALLBACK\";\n\nexport type HTTPAccessFallbackError = Error & {\n\tdigest: `${typeof HTTP_ERROR_FALLBACK_ERROR_CODE};${string}`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by\n * the HTTP navigation APIs `notFound()`, `forbidden()` or `unauthorized()`.\n *\n * @param error the error that may reference a HTTP access error\n * @returns true if the error is a HTTP access error\n */\nexport function isHTTPAccessFallbackError(error: unknown): error is HTTPAccessFallbackError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\tconst [prefix, httpStatus] = error.digest.split(\";\");\n\n\treturn prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));\n}\n\nexport function getAccessFallbackHTTPStatus(error: HTTPAccessFallbackError): number {\n\tconst httpStatus = error.digest.split(\";\")[1];\n\treturn Number(httpStatus);\n}","import { isRedirectError } from \"./redirect\";\nimport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\n\nexport { isRedirectError } from \"./redirect\";\nexport type { RedirectError } from \"./redirect\";\n\nexport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\nexport type { HTTPAccessFallbackError } from \"./http-access-fallback\";\n\n/**\n * Checks if the error is a navigation error that should be re-thrown\n * This includes redirect errors and HTTP access errors (notFound, forbidden, unauthorized)\n */\nexport function isNextNavigationError(error: unknown): boolean {\n\treturn isRedirectError(error) || isHTTPAccessFallbackError(error);\n}\n\n/**\n * Checks if the error is a notFound error\n * Note: Next.js implements notFound() using HTTP_ERROR_FALLBACK with status 404,\n * not as a separate error type like NEXT_REDIRECT\n */\nexport function isNotFoundError(error: unknown): boolean {\n\treturn isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error as any) === 404;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\nimport { isNextNavigationError } from \"../next/errors\";\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\nimport type { RedirectConfig } from \"../types\";\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 a redirect configuration for successful actions.\n * @param config Redirect URL, config object, or function that returns redirect config based on result\n */\n redirect<Data = any>(\n config: string | RedirectConfig | ((result: Data) => string | RedirectConfig | undefined)\n ) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n redirectConfig: config,\n });\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 undefined\n ? (context: Context) => Promise<Data>\n : InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): ServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : void, \n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n > {\n return createServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : 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 redirectConfig: this.#args.redirectConfig,\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 undefined\n ? (context: Context) => Promise<Data>\n : 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 redirectConfig: this.#args.redirectConfig,\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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":["RedirectStatusCode","result"]}
1
+ {"version":3,"sources":["../src/core/error-handler.ts","../src/next/errors/redirect.ts","../src/next/errors/http-access-fallback.ts","../src/next/errors/index.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}","// Comes from: https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/redirect-error.ts\n\nenum RedirectStatusCode {\n\tSeeOther = 303,\n\tTemporaryRedirect = 307,\n\tPermanentRedirect = 308,\n}\n\nconst REDIRECT_ERROR_CODE = \"NEXT_REDIRECT\";\n\nenum RedirectType {\n\tpush = \"push\",\n\treplace = \"replace\",\n}\n\nexport type RedirectError = Error & {\n\tdigest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by the\n * `redirect(url)` helper.\n *\n * @param error the error that may reference a redirect error\n * @returns true if the error is a redirect error\n */\nexport function isRedirectError(error: unknown): error is RedirectError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\n\tconst digest = error.digest.split(\";\");\n\tconst [errorCode, type] = digest;\n\tconst destination = digest.slice(2, -2).join(\";\");\n\tconst status = digest.at(-2);\n\n\tconst statusCode = Number(status);\n\n\treturn (\n\t\terrorCode === REDIRECT_ERROR_CODE &&\n\t\t(type === \"replace\" || type === \"push\") &&\n\t\ttypeof destination === \"string\" &&\n\t\t!isNaN(statusCode) &&\n\t\tstatusCode in RedirectStatusCode\n\t);\n}","// Comes from https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/http-access-fallback/http-access-fallback.ts\n\nconst HTTPAccessErrorStatus = {\n\tNOT_FOUND: 404,\n\tFORBIDDEN: 403,\n\tUNAUTHORIZED: 401,\n};\n\nconst ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatus));\n\nconst HTTP_ERROR_FALLBACK_ERROR_CODE = \"NEXT_HTTP_ERROR_FALLBACK\";\n\nexport type HTTPAccessFallbackError = Error & {\n\tdigest: `${typeof HTTP_ERROR_FALLBACK_ERROR_CODE};${string}`;\n};\n\n/**\n * Checks an error to determine if it's an error generated by\n * the HTTP navigation APIs `notFound()`, `forbidden()` or `unauthorized()`.\n *\n * @param error the error that may reference a HTTP access error\n * @returns true if the error is a HTTP access error\n */\nexport function isHTTPAccessFallbackError(error: unknown): error is HTTPAccessFallbackError {\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\n\t\treturn false;\n\t}\n\tconst [prefix, httpStatus] = error.digest.split(\";\");\n\n\treturn prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));\n}\n\nexport function getAccessFallbackHTTPStatus(error: HTTPAccessFallbackError): number {\n\tconst httpStatus = error.digest.split(\";\")[1];\n\treturn Number(httpStatus);\n}","import { isRedirectError } from \"./redirect\";\nimport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\n\nexport { isRedirectError } from \"./redirect\";\nexport type { RedirectError } from \"./redirect\";\n\nexport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\nexport type { HTTPAccessFallbackError } from \"./http-access-fallback\";\n\n/**\n * Checks if the error is a navigation error that should be re-thrown\n * This includes redirect errors and HTTP access errors (notFound, forbidden, unauthorized)\n */\nexport function isNextNavigationError(error: unknown): boolean {\n\treturn isRedirectError(error) || isHTTPAccessFallbackError(error);\n}\n\n/**\n * Checks if the error is a notFound error\n * Note: Next.js implements notFound() using HTTP_ERROR_FALLBACK with status 404,\n * not as a separate error type like NEXT_REDIRECT\n */\nexport function isNotFoundError(error: unknown): boolean {\n\treturn isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error as any) === 404;\n}","import { z } from \"zod\";\nimport type { ServerActionError, ServerActionResponse, ServerAction } from \"../types\";\nimport { handleServerActionError } from \"./error-handler\";\nimport { isNextNavigationError } from \"../next/errors\";\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, Input = unknown> = (params: { context: Context; input: Input }) => Promise<{ context: Context } | { error: ServerActionError }>;\n\nimport type { RedirectConfig } from \"../types\";\n\ntype SafeActionClientArgs<Context extends object, InputSchema extends z.ZodTypeAny | undefined, OutputSchema extends z.ZodTypeAny | undefined> = {\n middlewareFns: ServerActionMiddleware<any, any>[];\n inputSchema?: InputSchema;\n outputSchema?: OutputSchema;\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n ctxType?: Context;\n redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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>(\n middlewareFn: ServerActionMiddleware<\n Context & NextContext, \n InputSchema extends z.ZodTypeAny ? z.output<InputSchema> : undefined\n >\n ) {\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 a redirect configuration for successful actions.\n * @param config Redirect URL, config object, or function that returns redirect config based on result\n */\n redirect<Data = any>(\n config: string | RedirectConfig | ((result: Data) => string | RedirectConfig | undefined)\n ) {\n return new ServerActionClient<Context, InputSchema, OutputSchema>({\n ...this.#args,\n redirectConfig: config,\n });\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 undefined\n ? (context: Context) => Promise<Data>\n : InputSchema extends z.ZodTypeAny \n ? (input: InferZodOutput<InputSchema>, context: Context) => Promise<Data>\n : (context: Context) => Promise<Data>\n ): ServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : void, \n OutputSchema extends z.ZodTypeAny ? InferZodOutput<OutputSchema> : Data\n > {\n return createServerAction<\n InputSchema extends undefined \n ? void \n : InputSchema extends z.ZodTypeAny \n ? InferZodInput<InputSchema> \n : 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 redirectConfig: this.#args.redirectConfig,\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 undefined\n ? (context: Context) => Promise<Data>\n : 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 redirectConfig: this.#args.redirectConfig,\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, any>[];\n onError?: (error: unknown, context: { parsedInput?: unknown }) => ServerActionError | undefined;\n serverCodeFn: (...args: any[]) => Promise<any>;\n redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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 redirectConfig?: string | RedirectConfig | ((result: any) => string | RedirectConfig | undefined);\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 // Handle redirect config if present\n let redirectValue: string | RedirectConfig | undefined;\n if (config.redirectConfig) {\n if (typeof config.redirectConfig === 'function') {\n redirectValue = config.redirectConfig(validatedOutput);\n } else {\n redirectValue = config.redirectConfig;\n }\n }\n\n return {\n success: true,\n data: validatedOutput,\n ...(redirectValue && { redirect: redirectValue }),\n };\n } catch (error) {\n // Preserve Next.js navigation errors (redirect, notFound, etc.)\n if (isNextNavigationError(error)) {\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":["RedirectStatusCode","result"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-action-forge",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "A simple, type-safe toolkit for Next.js server actions with Zod validation",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",