⚡ createAction()

Automatically initializes the server client with cookies and returns a type-safe { data, error } object for all your Server Actions.

If you are using Server Actions ("use server";) heavily in Next.js, handling Try/Catch blocks rapidly becomes a massive chore. createAction abstracts this problem away entirely by catching thrown errors and cleanly serializing them.

Basic Usage

Wrap your asynchronous functions using createAction:

// app/actions.ts
"use server";
import { createAction } from "next-supa-utils/server";

export const getProfile = createAction(async (supabase, userId: string) => {
  const { data, error } = await supabase
    .from("profiles")
    .select()
    .eq("id", userId)
    .single();

  if (error) throw error; // Safe to throw. It will be serialized!
  return data;
});

Using it inside a Client Component remains fully type-safe and consistent:

// Usage
const result = await getProfile("123");

if (result.error) {
  // result.error is a parsed SupaError (exposes message, code, etc)
  console.error(result.error.message);
  return;
}

// result.data is correctly inferred as your query payload type!
console.log(result.data);

How It Works Under The Hood

Signature:

function createAction<TArgs extends unknown[], TResult>(
  fn: (supabase: SupabaseClient, ...args: TArgs) => Promise<TResult>
): (...args: TArgs) => Promise<ActionResponse<TResult>>
  1. Client Provisioning: createAction grabs cookies() from next/headers and creates an ephemeral, secure Supabase browser client, inserting it as the first argument of your callback.
  2. Execution Block: It runs your supplied function.
  3. Implicit Error Catching: Because it is enclosed in a try/catch, ANY thrown error inside the function is normalized into SupaError.
  4. Standardized Responses: It promises to return a discriminated union pattern heavily inspired by Supabase's JS SDK itself:
// Success Response:
{ data: TResult, error: null }

// Failure Response:
{ data: null, error: SupaError } // Next.js understands and safely serializes this over network boundaries.