UNPKG

@supabase/functions-js

Version:
174 lines 7.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FunctionsClient = void 0; const tslib_1 = require("tslib"); const helper_1 = require("./helper"); const types_1 = require("./types"); /** * Client for invoking Supabase Edge Functions. */ class FunctionsClient { /** * Creates a new Functions client bound to an Edge Functions URL. * * @example * ```ts * import { FunctionsClient, FunctionRegion } from '@supabase/functions-js' * * const functions = new FunctionsClient('https://xyzcompany.supabase.co/functions/v1', { * headers: { apikey: 'public-anon-key' }, * region: FunctionRegion.UsEast1, * }) * ``` */ constructor(url, { headers = {}, customFetch, region = types_1.FunctionRegion.Any, } = {}) { this.url = url; this.headers = headers; this.region = region; this.fetch = (0, helper_1.resolveFetch)(customFetch); } /** * Updates the authorization header * @param token - the new jwt token sent in the authorisation header * @example * ```ts * functions.setAuth(session.access_token) * ``` */ setAuth(token) { this.headers.Authorization = `Bearer ${token}`; } /** * Invokes a function * @param functionName - The name of the Function to invoke. * @param options - Options for invoking the Function. * @example * ```ts * const { data, error } = await functions.invoke('hello-world', { * body: { name: 'Ada' }, * }) * ``` */ invoke(functionName_1) { return tslib_1.__awaiter(this, arguments, void 0, function* (functionName, options = {}) { var _a; let timeoutId; let timeoutController; try { const { headers, method, body: functionArgs, signal, timeout } = options; let _headers = {}; let { region } = options; if (!region) { region = this.region; } // Add region as query parameter using URL API const url = new URL(`${this.url}/${functionName}`); if (region && region !== 'any') { _headers['x-region'] = region; url.searchParams.set('forceFunctionRegion', region); } let body; if (functionArgs && ((headers && !Object.prototype.hasOwnProperty.call(headers, 'Content-Type')) || !headers)) { if ((typeof Blob !== 'undefined' && functionArgs instanceof Blob) || functionArgs instanceof ArrayBuffer) { // will work for File as File inherits Blob // also works for ArrayBuffer as it is the same underlying structure as a Blob _headers['Content-Type'] = 'application/octet-stream'; body = functionArgs; } else if (typeof functionArgs === 'string') { // plain string _headers['Content-Type'] = 'text/plain'; body = functionArgs; } else if (typeof FormData !== 'undefined' && functionArgs instanceof FormData) { // don't set content-type headers // Request will automatically add the right boundary value body = functionArgs; } else { // default, assume this is JSON _headers['Content-Type'] = 'application/json'; body = JSON.stringify(functionArgs); } } else { // if the Content-Type was supplied, simply set the body body = functionArgs; } // Handle timeout by creating an AbortController let effectiveSignal = signal; if (timeout) { timeoutController = new AbortController(); timeoutId = setTimeout(() => timeoutController.abort(), timeout); // If user provided their own signal, we need to respect both if (signal) { effectiveSignal = timeoutController.signal; // If the user's signal is aborted, abort our timeout controller too signal.addEventListener('abort', () => timeoutController.abort()); } else { effectiveSignal = timeoutController.signal; } } const response = yield this.fetch(url.toString(), { method: method || 'POST', // headers priority is (high to low): // 1. invoke-level headers // 2. client-level headers // 3. default Content-Type header headers: Object.assign(Object.assign(Object.assign({}, _headers), this.headers), headers), body, signal: effectiveSignal, }).catch((fetchError) => { throw new types_1.FunctionsFetchError(fetchError); }); const isRelayError = response.headers.get('x-relay-error'); if (isRelayError && isRelayError === 'true') { throw new types_1.FunctionsRelayError(response); } if (!response.ok) { throw new types_1.FunctionsHttpError(response); } let responseType = ((_a = response.headers.get('Content-Type')) !== null && _a !== void 0 ? _a : 'text/plain').split(';')[0].trim(); let data; if (responseType === 'application/json') { data = yield response.json(); } else if (responseType === 'application/octet-stream' || responseType === 'application/pdf') { data = yield response.blob(); } else if (responseType === 'text/event-stream') { data = response; } else if (responseType === 'multipart/form-data') { data = yield response.formData(); } else { // default to text data = yield response.text(); } return { data, error: null, response }; } catch (error) { return { data: null, error, response: error instanceof types_1.FunctionsHttpError || error instanceof types_1.FunctionsRelayError ? error.context : undefined, }; } finally { // Clear the timeout if it was set if (timeoutId) { clearTimeout(timeoutId); } } }); } } exports.FunctionsClient = FunctionsClient; //# sourceMappingURL=FunctionsClient.js.map