• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / functions-js / 3675544747

pending completion
3675544747

push

github

GitHub
update deno-relay to v1.5.0 in tests (#47)

26 of 33 branches covered (78.79%)

Branch coverage included in aggregate %.

181 of 192 relevant lines covered (94.27%)

6.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.28
/src/FunctionsClient.ts
1
import { resolveFetch } from './helper'
1✔
2
import {
1✔
3
  Fetch,
1✔
4
  FunctionsFetchError,
1✔
5
  FunctionsHttpError,
1✔
6
  FunctionsRelayError,
1✔
7
  FunctionsResponse,
1✔
8
  FunctionInvokeOptions,
1✔
9
} from './types'
1✔
10

1✔
11
export class FunctionsClient {
1✔
12
  protected url: string
1✔
13
  protected headers: Record<string, string>
1✔
14
  protected fetch: Fetch
1✔
15

1✔
16
  constructor(
1✔
17
    url: string,
20✔
18
    {
20✔
19
      headers = {},
20✔
20
      customFetch,
20✔
21
    }: {
20✔
22
      headers?: Record<string, string>
20✔
23
      customFetch?: Fetch
20✔
24
    } = {}
20✔
25
  ) {
20✔
26
    this.url = url
20✔
27
    this.headers = headers
20✔
28
    this.fetch = resolveFetch(customFetch)
20✔
29
  }
20✔
30

1✔
31
  /**
1✔
32
   * Updates the authorization header
1✔
33
   * @param token - the new jwt token sent in the authorisation header
1✔
34
   */
1✔
35
  setAuth(token: string) {
1✔
36
    this.headers.Authorization = `Bearer ${token}`
10✔
37
  }
10✔
38

1✔
39
  /**
1✔
40
   * Invokes a function
1✔
41
   * @param functionName - The name of the Function to invoke.
1✔
42
   * @param options - Options for invoking the Function.
1✔
43
   */
1✔
44
  async invoke<T = any>(
1✔
45
    functionName: string,
20✔
46
    options: FunctionInvokeOptions = {}
20✔
47
  ): Promise<FunctionsResponse<T>> {
20✔
48
    try {
20✔
49
      const { headers, body: functionArgs } = options
20✔
50

20✔
51
      let _headers: Record<string, string> = {}
20✔
52
      let body: any
20✔
53
      if (
20✔
54
        functionArgs &&
20✔
55
        ((headers && !Object.prototype.hasOwnProperty.call(headers, 'Content-Type')) || !headers)
4!
56
      ) {
20✔
57
        if (
4✔
58
          (typeof Blob !== 'undefined' && functionArgs instanceof Blob) ||
4✔
59
          functionArgs instanceof ArrayBuffer
4✔
60
        ) {
4✔
61
          // will work for File as File inherits Blob
2✔
62
          // also works for ArrayBuffer as it is the same underlying structure as a Blob
2✔
63
          _headers['Content-Type'] = 'application/octet-stream'
2✔
64
          body = functionArgs
2✔
65
        } else if (typeof functionArgs === 'string') {
2✔
66
          // plain string
1✔
67
          _headers['Content-Type'] = 'text/plain'
1✔
68
          body = functionArgs
1✔
69
        } else if (typeof FormData !== 'undefined' && functionArgs instanceof FormData) {
1✔
70
          // don't set content-type headers
1✔
71
          // Request will automatically add the right boundary value
1✔
72
          body = functionArgs
1✔
73
        } else {
1!
74
          // default, assume this is JSON
×
75
          _headers['Content-Type'] = 'application/json'
×
76
          body = JSON.stringify(functionArgs)
×
77
        }
×
78
      }
4✔
79

20✔
80
      const response = await this.fetch(`${this.url}/${functionName}`, {
20✔
81
        method: 'POST',
20✔
82
        // headers priority is (high to low):
20✔
83
        // 1. invoke-level headers
20✔
84
        // 2. client-level headers
20✔
85
        // 3. default Content-Type header
20✔
86
        headers: { ..._headers, ...this.headers, ...headers },
20✔
87
        body,
20✔
88
      }).catch((fetchError) => {
20✔
89
        throw new FunctionsFetchError(fetchError)
1✔
90
      })
20✔
91

19✔
92
      const isRelayError = response.headers.get('x-relay-error')
19✔
93
      if (isRelayError && isRelayError === 'true') {
20✔
94
        throw new FunctionsRelayError(response)
3✔
95
      }
3✔
96

16✔
97
      if (!response.ok) {
19!
98
        throw new FunctionsHttpError(response)
×
99
      }
×
100

16✔
101
      let responseType = (response.headers.get('Content-Type') ?? 'text/plain').split(';')[0].trim()
20!
102
      let data: any
20✔
103
      if (responseType === 'application/json') {
20✔
104
        data = await response.json()
8✔
105
      } else if (responseType === 'application/octet-stream') {
8!
106
        data = await response.blob()
×
107
      } else if (responseType === 'multipart/form-data') {
8!
108
        data = await response.formData()
×
109
      } else {
8✔
110
        // default to text
8✔
111
        data = await response.text()
8✔
112
      }
8✔
113

16✔
114
      return { data, error: null }
16✔
115
    } catch (error) {
20✔
116
      return { data: null, error }
4✔
117
    }
4✔
118
  }
20✔
119
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc