next-action-forge
Version:
A simple, type-safe toolkit for Next.js server actions with Zod validation
1 lines • 30.2 kB
Source Map (JSON)
{"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/**\n * Safely parses JSON strings back to objects/arrays and handles FormData boolean conventions.\n * \n * DESIGN PRINCIPLES:\n * - Parse objects and arrays (start with { or [)\n * - Parse \"true\"/\"false\" to booleans (FormData convention for checkboxes)\n * - DO NOT parse number strings (\"123\") to avoid ambiguity\n * - Fail gracefully on malformed JSON\n * - Maintain perfect symmetry with client-side objectToFormData\n * \n * WHY WE PARSE BOOLEANS:\n * - HTML forms cannot send real JavaScript booleans, only strings\n * - Checkboxes commonly send \"true\"/\"false\" strings\n * - React Hook Form uses this convention\n * - This is the expected behavior in FormData context\n */\nfunction tryParseJSON(value: unknown): unknown {\n // Non-strings pass through unchanged\n if (typeof value !== 'string') return value;\n \n const trimmed = value.trim();\n \n // Empty strings remain empty\n if (!trimmed) return value;\n \n // Parse boolean strings (common for checkboxes and React Hook Form)\n // This is safe in FormData context since HTML can't send real booleans\n if (trimmed === 'true') return true;\n if (trimmed === 'false') return false;\n \n // Parse null (less common but sometimes used)\n if (trimmed === 'null') return null;\n \n // Only attempt parsing for obvious JSON structures\n if ((trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'))) {\n try {\n const parsed = JSON.parse(trimmed);\n // Extra safety: verify we got an object/array\n if (typeof parsed === 'object' && parsed !== null) {\n return parsed;\n }\n } catch {\n // Malformed JSON - return original string\n }\n }\n \n // All other strings (including number strings like \"123\") remain as strings\n // This avoids ambiguity with actual string values that happen to be numeric\n return value;\n}\n\n// Form data parser with automatic JSON deserialization\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 // Parse each array item (handles nested objects in arrays)\n result[cleanKey] = values.map(tryParseJSON);\n } else if (values.length === 1) {\n // Parse single value (handles JSON stringified objects)\n result[key] = tryParseJSON(values[0]);\n } else {\n // Parse multiple values\n result[key] = values.map(tryParseJSON);\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"]}