refine icon indicating copy to clipboard operation
refine copied to clipboard

Proposal: Support `neverthrow`

Open typed-sigterm opened this issue 6 months ago • 0 comments

Personally I think it can improve DX (fewer duplicated code, fewer indents, fewer chars etc).

Without neverthrow:

async function login({ email, password, providerName }) {
  try {
    if (providerName) {
      const { data, error } = await supa.auth.signInWithOAuth({
        provider: providerName,
      });
      if (error) return { success: false, error };
      if (data?.url) return { success: true, redirectTo: '/' };
    }

    const { data, error } = await supa.auth.signInWithPassword({ email, password });
    if (error) return { success: false, error };
    if (data?.user) return { success: true, redirectTo: '/' };
  } catch (error: any) {
    return { success: false, error };
  }

  return {
    success: false,
    error: {
      message: 'Login failed',
      name: 'Invalid email or password',
    },
  };
}

With neverthrow:

const login = fromAsyncThrowable(async ({ email, password, providerName }) => {
  if (providerName) {
    const { data, error } = await supa.auth.signInWithOAuth({
      provider: providerName,
    });
    if (error) return err(error);
    if (data?.url) return ok({ redirectTo: '/' });
  }

  const { data, error } = await supa.auth.signInWithPassword({ email, password });
  if (error) return err(error);
  if (data?.user) return ok({ redirectTo: '/' });
  return err({
    message: 'Login failed',
    name: 'Invalid email or password',
  });
});

For those who prefer { success: boolean }, they can still use that. Internally:

let response = await call();
if ('success' in response) {
  response = response.success
    ? ok(response)
    : err(response.error)
}

typed-sigterm avatar May 16 '25 16:05 typed-sigterm