Adding types to the custom fetch function for Fauna when using Cloudflare Workers

I’m going through the tutorial on using Cloudflare Workers with Fauana…

I’m using the Typescript starter for Workers.

Are there any types available for the customFetch function and the getFaunaError function?

In particular I can’t seem to type the params parameter. What is included in the params?

The return type of the custom fetch is a tuple including the function abortPromise but that looks like it returns null or undefined … but what if it doesn’t resolve?

The other element is the fetch function with the url and params. So does this mean params is all the possible properties in a normal fetch call? Can we pair that down?

When you build the faunadb client instance, it says the fetch property expects a Promise.

But that does not seem to match up with what the custom fetch function is returning.

Thanks for any help. I would really prefer to use Typescript to build my Cloudflare Workers script.

Hi @danboyle8637 - welcome to the forums.

A couple of short answers:

Are there any types available for the customFetch function and the getFaunaError function?

Not yet, but I’d love to get that fixed.

When you build the faunadb client instance, it says the fetch property expects a Promise. But that does not seem to match up with what the custom fetch function is returning.

Can you say a little more? As I read it, customFetch() returns the return value of Promise.race(), which returns a Promise.

The other element is the fetch function with the url and params. So does this mean params is all the possible properties in a normal fetch call? Can we pair that down?

What do you mean here? Since params appears analogous to [, init] in the standard definition, I’m not sure how we would remove it.

The other stuff

As for the rest, I’m interested in the answer, but unfortunately not deep enough into TypeScript (yet) to work it out myself.

What I did find:

Cloudflare’s fetch() signature accepts:

  • request: Request | string
  • init: RequestInit

It returns Promise<Response>

Links to those types:

Hey Rob!

Blockquote Can you say a little more? As I read it, customFetch() returns the return value of Promise.race() , which returns a Promise.

I just was too focused on what was inside and disregarded that. My bad… it is a Promise.race()

But here’s where I am a little confused. In the custom fetch immediately after getting the signal property:

const signal = params.signal

It is deleted. I am new to the delete keyword but from the MDN docs it doesn’t seem to be async so it should be deleted from this point forward.

Why?

Here’s what I got so far. I am actually having trouble with the getFaunaError function right now.

interface ParamsType {
  method: string // typical method
  headers: {
    ['X-FaunaDB-API-Version']: string
  }
  Authorization: string // fauna key in Bearer
  body: string // actual query
  signal: AbortSignal
}

export function customFetch(
  url: RequestInfo,
  params: ParamsType,
): Promise<unknown | Response> {
  const signal = params.signal
  // delete params.signal
 // not sure why we are deleting the signal ??

  const abortPromise = new Promise((resolve) => {
    if (signal) {
      signal.onabort = () => resolve(null)
    }
  })

  return Promise.race([abortPromise, fetch(url, params)])
}

When it comes to the error I found this on GitHub:

https://github.com/fauna/faunadb-js/blob/main/src/types/RequestResult.d.ts

But of course the type we need is a generic.

const { code, description } = error.requestResult.responseContent.errors[0]

Not sure how the errors property/array is on responseContent.

I’ll keep looking but I think I’ll shut it down for tonight. Sorry for the confusion from above.

Hey Rob!

Blockquote Can you say a little more? As I read it, customFetch() returns the return value of Promise.race() , which returns a Promise.

I just was too focused on what was inside and disregarded that. My bad… it is a Promise.race()

But here’s where I am a little confused. In the custom fetch immediately after getting the signal property:

const signal = params.signal

It is deleted. I am new to the delete keyword but from the MDN docs it doesn’t seem to be async so it should be deleted from this point forward.

Why?

Here’s what I got so far. I am actually having trouble with the getFaunaError function right now.

interface ParamsType {
  method: string // typical method
  headers: {
    ['X-FaunaDB-API-Version']: string
  }
  Authorization: string // fauna key in Bearer
  body: string // actual query
  signal: AbortSignal
  // a lot more - https://developer.mozilla.org/en-US/docs/Web/API/fetch
}

export function customFetch(
  url: RequestInfo,
  params: RequestInit,
): Promise<unknown | Response> {
  const signal = params.signal
  // delete params.signal
  // not sure why we are deleting the signal ??

  const abortPromise = new Promise((resolve) => {
    if (signal) {
      signal.onabort = () => resolve(null)
    }
  })

  return Promise.race([abortPromise, fetch(url, params)])
}

When it comes to the error I found this on GitHub:

https://github.com/fauna/faunadb-js/blob/main/src/types/RequestResult.d.ts

But of course the type we need is a generic.

const { code, description } = error.requestResult.responseContent.errors[0]

Not sure how the errors property/array is on responseContent.

I’ll keep looking but I think I’ll shut it down for tonight. Sorry for the confusion from above.

UPDATE:

I found this: https://github.com/fauna/faunadb-js/blob/main/src/types/errors.d.ts

That seems to solve the issue so far. I changed the error function to this:

export function getFaunaError(
  error: FaunaHttpErrorResponseContent,
): GetFaunaError {
  const { code, description } = error.errors[0]
  let status

  switch (code) {
    case 'instance not found':
      status = 404
      break
    case 'instance not unique':
      status = 409
      break
    case 'permission denied':
      status = 403
      break
    case 'unauthorized':
    case 'authentication failed':
      status = 401
      break
    default:
      status = 500
  }

  return { code, description, status }
}

Now because of the AbortController the custom fetch function returns a Promise<unknown | Request> … I’m assuming the request would abort if the worker hit it’s time to run.

But the fauna client constructor does not like taking this.

Still working on it

Nice find!

Should this return a type FaunaError instead?

See https://github.com/fauna/faunadb-js/blob/f1fae16d4e5ed820d997593b21c0565edb2bdda2/src/types/errors.d.ts#L10

Feel like we’re almost there…