npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@feierstoff-gmbh/better-next-action

v0.2.0

Published

> This is a forked version of the next-safe-action package. > See original source here: https://github.com/TheEdoRan/next-safe-action > The original package is licensed under the MIT license.

Downloads

11

Readme

better-next-action

This is a forked version of the next-safe-action package. See original source here: https://github.com/TheEdoRan/next-safe-action The original package is licensed under the MIT license.

This is for internal use. But feel free to use it too.

What changed?

In the future I possibly will fork the docs as well and make the corresponding changes.

Aliases for status-checking

For convinience I added boolean values to the client hook that can be used instead of checking against the status variable.

// action as a client hook
const myAction = useBetterAction(action);

// aliases
myAction.isIdle; // equals myAction.status === "idle"
myAction.isExecuting; // equals myAction.status === "executing"
myAction.hasSucceeded; // equals myAction.status === "hasSucceeded"
myAction.hasErrored; // equals myAction.status === "hasErrored"

Curry the action handler

In the original package the created client takes two arguments: the schema and the implementation. To establish the new features i wanted to introduce, the client now is a function that takes the schema as first argument and an optional options object as the second one. It then returns another function that takes the implementation as argument. In the implementation callback, the input and context (and other new things) aren't seperate arguments anymore, but one object.

// before
const action = createAction(
  z.object({ id: z.string() }),
  async (input, ctx) => {
    // ... implementation
  }
);

// after
const action = createAction(z.object({ id: z.string() }), {
  // ... options
})(async ({ input, ctx }) => {
  // ... implementation
});

Add optional custom errors that can be checked with typesafety

I always wanted to be able to throw some simple error messages that I can check for in the onError callback with automatic typesafety. One can now add those custom error messages in the added option argument in the action-client as an array. The implementation callback then exposes a function error which you can use to throw a defined message. On the client you can then check for the error message via the first error argument in the onError callback.

// defining action
const addUserAction = createAction(z.object({ email: z.string().email() }), {
  // define the error messages
  errors: ["EMAIL_ALREADY_USED"],
})(async ({ ctx, input, error }) => {
  // check if user with given email exists
  if (user) {
    error("EMAIL_ALREADY_USED"); // throws an error
  }
});

// on the client
const addUser = useBetterAction(addUserAction, {
  onError: (e) => {
    if (e.actionError === "EMAIL_ALREADY_USED") {
      // ... handle error
    }
  },
});

Add custom options for middleware.

!!! CAUTION: The implementation uses two @ts-ignores, so i don't know if there could potentially be a way to break this feature typewise but i will just ignore that for my own sanity !!!

I was missing the option to add custom information to an action (kinda like the meta field in tRPC), which then could be used in the middleware. That's why i added the possibility to define them directly in the middleware function.

// example: add custom field to check if the user is authenticated every time the action gets called

const createAction = createBetterActionClient({
  // just explicitly type the first argument of the middleware function
  async middleware(opts?: { secured?: boolean }) {
    const session = await getSession();

    if (opts?.secured && !session?.user) {
      // when the secured flag is set and the user is not logged in: throw error
      throw new Error("Unauthorized");
    }

    // return the context in the known way
    return {
      //...
    };
  },
});

const addItemAction = createAction(z.object({ name: z.string() }), {
  // ... now all options defined in the middleware function are exposed in this object
  secured: true,
})(async ({ ctx, input }) => {
  // ...
});

Add executeAsync

In some cases i wanted to wait for the result of the executing hook but that was not possible in the original package. The function will only throw if an unknown error occurs. In every other case the function will return an object with a key "ok" which is either true, which reveals the returned data or false, which reveals the possible errors. I decided to do that because you can still check for the custom custom action errors in a typesafe way. If an error would be thrown, one couldn't directly infer the error from it, without any additional functions.

const myAction = useBetterAction(action);

async function execute() {
  const res = await myAction.executeAsync();
}

No useOptimisticAction

I currently don't use it and was to lazy to get busy with implementing it with the new features.

TO-DO

  • [ ] useOptimisticAction

License

better-next-action is released under the MIT license.