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

supabase / functions-js / 12398927075

18 Dec 2024 06:18PM UTC coverage: 74.775% (-0.9%) from 75.684%
12398927075

push

github

web-flow
Merge pull request #92 from nyannyacha/fix-add-wait-until-typing

fix: add a type for `EdgeRuntime.waitUntil`

30 of 39 branches covered (76.92%)

Branch coverage included in aggregate %.

0 of 4 new or added lines in 1 file covered. (0.0%)

219 of 294 relevant lines covered (74.49%)

6.18 hits per line

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

90.06
/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
  FunctionRegion,
1✔
10
} from './types'
1✔
11

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

1✔
18
  constructor(
1✔
19
    url: string,
24✔
20
    {
24✔
21
      headers = {},
24✔
22
      customFetch,
24✔
23
      region = FunctionRegion.Any,
24✔
24
    }: {
24✔
25
      headers?: Record<string, string>
24✔
26
      customFetch?: Fetch
24✔
27
      region?: FunctionRegion
24✔
28
    } = {}
24✔
29
  ) {
24✔
30
    this.url = url
24✔
31
    this.headers = headers
24✔
32
    this.region = region
24✔
33
    this.fetch = resolveFetch(customFetch)
24✔
34
  }
24✔
35

1✔
36
  /**
1✔
37
   * Updates the authorization header
1✔
38
   * @param token - the new jwt token sent in the authorisation header
1✔
39
   */
1✔
40
  setAuth(token: string) {
1✔
41
    this.headers.Authorization = `Bearer ${token}`
10✔
42
  }
10✔
43

1✔
44
  /**
1✔
45
   * Invokes a function
1✔
46
   * @param functionName - The name of the Function to invoke.
1✔
47
   * @param options - Options for invoking the Function.
1✔
48
   */
1✔
49
  async invoke<T = any>(
1✔
50
    functionName: string,
24✔
51
    options: FunctionInvokeOptions = {}
24✔
52
  ): Promise<FunctionsResponse<T>> {
24✔
53
    try {
24✔
54
      const { headers, method, body: functionArgs } = options
24✔
55
      let _headers: Record<string, string> = {}
24✔
56
      let { region } = options
24✔
57
      if (!region) {
24✔
58
        region = this.region
21✔
59
      }
21✔
60
      if (region && region !== 'any') {
24✔
61
        _headers['x-region'] = region
3✔
62
      }
3✔
63
      let body: any
24✔
64
      if (
24✔
65
        functionArgs &&
24✔
66
        ((headers && !Object.prototype.hasOwnProperty.call(headers, 'Content-Type')) || !headers)
4!
67
      ) {
24✔
68
        if (
4✔
69
          (typeof Blob !== 'undefined' && functionArgs instanceof Blob) ||
4✔
70
          functionArgs instanceof ArrayBuffer
4✔
71
        ) {
4✔
72
          // will work for File as File inherits Blob
2✔
73
          // also works for ArrayBuffer as it is the same underlying structure as a Blob
2✔
74
          _headers['Content-Type'] = 'application/octet-stream'
2✔
75
          body = functionArgs
2✔
76
        } else if (typeof functionArgs === 'string') {
2✔
77
          // plain string
1✔
78
          _headers['Content-Type'] = 'text/plain'
1✔
79
          body = functionArgs
1✔
80
        } else if (typeof FormData !== 'undefined' && functionArgs instanceof FormData) {
1✔
81
          // don't set content-type headers
1✔
82
          // Request will automatically add the right boundary value
1✔
83
          body = functionArgs
1✔
84
        } else {
1!
85
          // default, assume this is JSON
×
86
          _headers['Content-Type'] = 'application/json'
×
87
          body = JSON.stringify(functionArgs)
×
88
        }
×
89
      }
4✔
90

24✔
91
      const response = await this.fetch(`${this.url}/${functionName}`, {
24✔
92
        method: method || 'POST',
24✔
93
        // headers priority is (high to low):
24✔
94
        // 1. invoke-level headers
24✔
95
        // 2. client-level headers
24✔
96
        // 3. default Content-Type header
24✔
97
        headers: { ..._headers, ...this.headers, ...headers },
24✔
98
        body,
24✔
99
      }).catch((fetchError) => {
24✔
100
        throw new FunctionsFetchError(fetchError)
1✔
101
      })
24✔
102

23✔
103
      const isRelayError = response.headers.get('x-relay-error')
23✔
104
      if (isRelayError && isRelayError === 'true') {
24✔
105
        throw new FunctionsRelayError(response)
3✔
106
      }
3✔
107

20✔
108
      if (!response.ok) {
23!
109
        throw new FunctionsHttpError(response)
×
110
      }
×
111

20✔
112
      let responseType = (response.headers.get('Content-Type') ?? 'text/plain').split(';')[0].trim()
24!
113
      let data: any
24✔
114
      if (responseType === 'application/json') {
24✔
115
        data = await response.json()
12✔
116
      } else if (responseType === 'application/octet-stream') {
23!
117
        data = await response.blob()
×
118
      } else if (responseType === 'text/event-stream') {
8!
119
        data = response
×
120
      } else if (responseType === 'multipart/form-data') {
8!
121
        data = await response.formData()
×
122
      } else {
8✔
123
        // default to text
8✔
124
        data = await response.text()
8✔
125
      }
8✔
126

20✔
127
      return { data, error: null }
20✔
128
    } catch (error) {
24✔
129
      return { data: null, error }
4✔
130
    }
4✔
131
  }
24✔
132
}
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

© 2025 Coveralls, Inc