safe-action-advanced

824installs0stars

Install to Claude Code

npx -y skills add https://github.com/next-safe-action/skills --skill safe-action-advanced

Description

safe action advanced

SKILL.md

---
name: safe-action-advanced
description: Use when working with bind arguments, metadata schemas, framework errors (redirect/notFound/forbidden/unauthorized), type inference utilities (InferSafeActionFnInput/Result), or server-level action callbacks
---

# next-safe-action Advanced Features

## Overview

| Feature | Use Case |
|---|---|
| [Bind arguments](./bind-arguments.md) | Pass extra args to actions via `.bind()` (e.g., resource IDs) |
| [Metadata](./metadata.md) | Attach typed metadata to actions for use in middleware |
| [Framework errors](./framework-errors.md) | Handle redirect, notFound, forbidden, unauthorized in actions |
| [Type utilities](./type-utilities.md) | Infer types from action functions and middleware |

## Server-Level Action Callbacks

The second argument to `.action()` accepts callbacks that run **on the server** (not client-side hooks):

```ts
export const createPost = authActionClient
  .inputSchema(schema)
  .action(
    async ({ parsedInput, ctx }) => {
      const post = await db.post.create(parsedInput);
      return post;
    },
    {
      onSuccess: async ({ data, parsedInput, ctx, metadata, clientInput }) => {
        // Runs on the server after successful execution
        await invalidateCache("posts");
      },
      onError: async ({ error, metadata, ctx, clientInput, bindArgsClientInputs }) => {
        // error: { serverError?, validationErrors? }
        await logError(error);
      },
      onSettled: async ({ result }) => {
        // Always runs
        await recordMetrics(result);
      },
      onNavigation: async ({ navigationKind }) => {
        // Runs when a framework error (redirect, notFound, etc.) occurs
        console.log("Navigation:", navigationKind);
      },
    }
  );
```

These are distinct from hook callbacks (`useAction({ onSuccess })`) — server callbacks run in the Node.js runtime, hook callbacks run in the browser.

## throwServerError

Re-throw server errors instead of returning them as `result.serverError`:

```ts
export const myAction = actionClient
  .inputSchema(schema)
  .action(serverCodeFn, {
    throwServerError: true,
    // The handled server error (return of handleServerError) is thrown
  });
```