SafeFn
Creating a SafeFn

Callback functions

While these functions are guaranteed to finish execution before your function returns (to prevent issues in serverless environments) and will be called in their logical order (onStart -> onSuccess | onError -> onComplete), they are not guaranteed to finish execution in that order (e.g., onComplete can finish execution before onStart if onStart makes a long async request).

These functions must return Promise<void>. All thrown errors are automatically caught, except for framework related ones like Next's Redirect.

The examples bellow use the following SafeFn

const parent = createSafeFn()
  .input(z.object({ firstName: z.string(), lastName: z.string() }))
  .handler((args) => {
    return ok(`${args.input.firstName} ${args.input.lastName}`);
  });
 
const child = createSafeFn()
  .use(parent)
  .output(z.object({ message: z.string() }))
  .handler((args) => {
    return ok({
      message: `Hello ${args.ctx}`,
    });
  });

onStart()

...
  .onStart(async (args) => {
    /*
    (parameter) args: {
        unsafeRawInput: {
            firstName: string;
            lastName: string;
        };
    */
  })

Starts execution right when you run your SafeFn and takes in the following parameters:

  • unsafeRawInput: the raw input passed when running your SafeFn. Keep in mind this can contain additional properties when using one SafeFn as the parent of another!

onSuccess()

...
  .onSuccess(async (args) => {
    /*
    (parameter) args: {
    input: {
        firstName: string;
        lastName: string;
    };
    unsafeRawInput: {
        firstName: string;
        lastName: string;
    }
   ctx: string;
    value: {
        message: string;
    };
    ctxInput :[{
      firstName: string;
      lastName: string;
    }]
    */
  })

Starts execution after output parsing has completed if you defined a schema, otherwise after your handler() or safeHandler() finished execution. Takes in the following parameters:

  • unsafeRawInput: the raw input passed when running your SafeFn. Keep in mind this can contain additional properties when using one SafeFn as the parent of another!
  • input: the results of parsing unsafeRawInput through your input schema if you defined one, otherwise undefined
  • ctx: the Ok value of your parent safe-fn if you defined one, otherwise undefined.
  • ctxInput: an array of all the parsed input of parent SafeFns.
  • value: the Ok value of the safe-fn this callback is defined on.

onError()

  .onError(async (args) => {
    /*
    (parameter) args: {
    asAction: boolean
    input: {
        firstName: string;
        lastName: string;
    } | undefined
    unsafeRawInput: {
        firstName: string;
        lastName: string;
    }
   ctx: string | undefined;
   ctxInput :[{
      firstName: string;
      lastName: string;
    }]
   error: {code: "INPUT_PARSING" ...} | ...
    */
  })

Starts execution after the first encountered Err return while executing your SafeFn. Takes in the following parameters:

  • asAction: wether the safe-fn was run as an action (createAction()()) or not (run()). This can be helpful the narrow down the type of error.
  • unsafeRawInput: the raw input passed when running your SafeFn. Keep in mind this can contain additional properties when using one SafeFn as the parent of another!
  • input: the results of parsing unsafeRawInput through your input schema if you defined one and parsing was successful, otherwise undefined.
  • ctx: the Ok value of your parent safe-fn if you defined one and execution was successful, otherwise undefined
  • ctxInput: an array of all the parsed input of parent SafeFns. (Note this is not properly typed yet, the value of this depends on where your function errors)
  • error: the Err error that caused your safe-fn to fail.

onComplete()

...
  .onComplete(async (args) => {
    /*
    (parameter) args: {
    asAction: boolean
    input: {
        firstName: string;
        lastName: string;
    } | undefined
    unsafeRawInput: {
        firstName: string;
        lastName: string;
    }
   ctx: string | undefined;
    ctxInput :[{
      firstName: string;
      lastName: string;
    }]
   result: Result<string, {code: "INPUT_PARSING" ...} ...>
    */
  })

Starts execution after either onSuccess() or onError() is called (not finished). Takes in the following parameters:

  • asAction: wether the safe-fn was run as an action (createAction()()) or not (run()). This can be helpful the narrow down the type of error.

  • unsafeRawInput: the raw input passed when running your SafeFn. Keep in mind this can contain additional properties when using one SafeFn as the parent of another!

  • input: the results of parsing unsafeRawInput through your input schema if you defined one and parsing was successful, otherwise undefined.

  • ctx: the Ok value of your parent safe-fn if you defined one and execution was successful, otherwise undefined

  • ctxInput: an array of all the parsed input of parent SafeFns. (Note this is not properly typed yet for the error case, the value of this depends on where your function errors)

  • result: a Result<T,E> with either the Ok value of the safe-fn this callback was defined on if execution was successful, or the Err error.

On this page