UNPKG

@supabase/supabase-js

Version:

Isomorphic Javascript client for Supabase

233 lines 10.7 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const functions_js_1 = require("@supabase/functions-js"); const postgrest_js_1 = require("@supabase/postgrest-js"); const realtime_js_1 = require("@supabase/realtime-js"); const storage_js_1 = require("@supabase/storage-js"); const constants_1 = require("./lib/constants"); const fetch_1 = require("./lib/fetch"); const helpers_1 = require("./lib/helpers"); const SupabaseAuthClient_1 = require("./lib/SupabaseAuthClient"); /** * Supabase Client. * * An isomorphic Javascript client for interacting with Postgres. */ class SupabaseClient { /** * Create a new client for use in the browser. * @param supabaseUrl The unique Supabase URL which is supplied when you create a new project in your project dashboard. * @param supabaseKey The unique Supabase Key which is supplied when you create a new project in your project dashboard. * @param options.db.schema You can switch in between schemas. The schema needs to be on the list of exposed schemas inside Supabase. * @param options.auth.autoRefreshToken Set to "true" if you want to automatically refresh the token before expiring. * @param options.auth.persistSession Set to "true" if you want to automatically save the user session into local storage. * @param options.auth.detectSessionInUrl Set to "true" if you want to automatically detects OAuth grants in the URL and signs in the user. * @param options.realtime Options passed along to realtime-js constructor. * @param options.global.fetch A custom fetch implementation. * @param options.global.headers Any additional headers to send with each network request. */ constructor(supabaseUrl, supabaseKey, options) { var _a, _b, _c; this.supabaseUrl = supabaseUrl; this.supabaseKey = supabaseKey; if (!supabaseUrl) throw new Error('supabaseUrl is required.'); if (!supabaseKey) throw new Error('supabaseKey is required.'); const _supabaseUrl = (0, helpers_1.ensureTrailingSlash)(supabaseUrl); const baseUrl = new URL(_supabaseUrl); this.realtimeUrl = new URL('realtime/v1', baseUrl); this.realtimeUrl.protocol = this.realtimeUrl.protocol.replace('http', 'ws'); this.authUrl = new URL('auth/v1', baseUrl); this.storageUrl = new URL('storage/v1', baseUrl); this.functionsUrl = new URL('functions/v1', baseUrl); // default storage key uses the supabase project ref as a namespace const defaultStorageKey = `sb-${baseUrl.hostname.split('.')[0]}-auth-token`; const DEFAULTS = { db: constants_1.DEFAULT_DB_OPTIONS, realtime: constants_1.DEFAULT_REALTIME_OPTIONS, auth: Object.assign(Object.assign({}, constants_1.DEFAULT_AUTH_OPTIONS), { storageKey: defaultStorageKey }), global: constants_1.DEFAULT_GLOBAL_OPTIONS, }; const settings = (0, helpers_1.applySettingDefaults)(options !== null && options !== void 0 ? options : {}, DEFAULTS); this.storageKey = (_a = settings.auth.storageKey) !== null && _a !== void 0 ? _a : ''; this.headers = (_b = settings.global.headers) !== null && _b !== void 0 ? _b : {}; if (!settings.accessToken) { this.auth = this._initSupabaseAuthClient((_c = settings.auth) !== null && _c !== void 0 ? _c : {}, this.headers, settings.global.fetch); } else { this.accessToken = settings.accessToken; this.auth = new Proxy({}, { get: (_, prop) => { throw new Error(`@supabase/supabase-js: Supabase Client is configured with the accessToken option, accessing supabase.auth.${String(prop)} is not possible`); }, }); } this.fetch = (0, fetch_1.fetchWithAuth)(supabaseKey, this._getAccessToken.bind(this), settings.global.fetch); this.realtime = this._initRealtimeClient(Object.assign({ headers: this.headers, accessToken: this._getAccessToken.bind(this) }, settings.realtime)); this.rest = new postgrest_js_1.PostgrestClient(new URL('rest/v1', baseUrl).href, { headers: this.headers, schema: settings.db.schema, fetch: this.fetch, }); if (!settings.accessToken) { this._listenForAuthEvents(); } } /** * Supabase Functions allows you to deploy and invoke edge functions. */ get functions() { return new functions_js_1.FunctionsClient(this.functionsUrl.href, { headers: this.headers, customFetch: this.fetch, }); } /** * Supabase Storage allows you to manage user-generated content, such as photos or videos. */ get storage() { return new storage_js_1.StorageClient(this.storageUrl.href, this.headers, this.fetch); } /** * Perform a query on a table or a view. * * @param relation - The table or view name to query */ from(relation) { return this.rest.from(relation); } // NOTE: signatures must be kept in sync with PostgrestClient.schema /** * Select a schema to query or perform an function (rpc) call. * * The schema needs to be on the list of exposed schemas inside Supabase. * * @param schema - The schema to query */ schema(schema) { return this.rest.schema(schema); } // NOTE: signatures must be kept in sync with PostgrestClient.rpc /** * Perform a function call. * * @param fn - The function name to call * @param args - The arguments to pass to the function call * @param options - Named parameters * @param options.head - When set to `true`, `data` will not be returned. * Useful if you only need the count. * @param options.get - When set to `true`, the function will be called with * read-only access mode. * @param options.count - Count algorithm to use to count rows returned by the * function. Only applicable for [set-returning * functions](https://www.postgresql.org/docs/current/functions-srf.html). * * `"exact"`: Exact but slow count algorithm. Performs a `COUNT(*)` under the * hood. * * `"planned"`: Approximated but fast count algorithm. Uses the Postgres * statistics under the hood. * * `"estimated"`: Uses exact count for low numbers and planned count for high * numbers. */ rpc(fn, args = {}, options = {}) { return this.rest.rpc(fn, args, options); } /** * Creates a Realtime channel with Broadcast, Presence, and Postgres Changes. * * @param {string} name - The name of the Realtime channel. * @param {Object} opts - The options to pass to the Realtime channel. * */ channel(name, opts = { config: {} }) { return this.realtime.channel(name, opts); } /** * Returns all Realtime channels. */ getChannels() { return this.realtime.getChannels(); } /** * Unsubscribes and removes Realtime channel from Realtime client. * * @param {RealtimeChannel} channel - The name of the Realtime channel. * */ removeChannel(channel) { return this.realtime.removeChannel(channel); } /** * Unsubscribes and removes all Realtime channels from Realtime client. */ removeAllChannels() { return this.realtime.removeAllChannels(); } _getAccessToken() { var _a, _b; return __awaiter(this, void 0, void 0, function* () { if (this.accessToken) { return yield this.accessToken(); } const { data } = yield this.auth.getSession(); return (_b = (_a = data.session) === null || _a === void 0 ? void 0 : _a.access_token) !== null && _b !== void 0 ? _b : null; }); } _initSupabaseAuthClient({ autoRefreshToken, persistSession, detectSessionInUrl, storage, storageKey, flowType, lock, debug, }, headers, fetch) { const authHeaders = { Authorization: `Bearer ${this.supabaseKey}`, apikey: `${this.supabaseKey}`, }; return new SupabaseAuthClient_1.SupabaseAuthClient({ url: this.authUrl.href, headers: Object.assign(Object.assign({}, authHeaders), headers), storageKey: storageKey, autoRefreshToken, persistSession, detectSessionInUrl, storage, flowType, lock, debug, fetch, // auth checks if there is a custom authorizaiton header using this flag // so it knows whether to return an error when getUser is called with no session hasCustomAuthorizationHeader: 'Authorization' in this.headers, }); } _initRealtimeClient(options) { return new realtime_js_1.RealtimeClient(this.realtimeUrl.href, Object.assign(Object.assign({}, options), { params: Object.assign({ apikey: this.supabaseKey }, options === null || options === void 0 ? void 0 : options.params) })); } _listenForAuthEvents() { let data = this.auth.onAuthStateChange((event, session) => { this._handleTokenChanged(event, 'CLIENT', session === null || session === void 0 ? void 0 : session.access_token); }); return data; } _handleTokenChanged(event, source, token) { if ((event === 'TOKEN_REFRESHED' || event === 'SIGNED_IN') && this.changedAccessToken !== token) { this.changedAccessToken = token; } else if (event === 'SIGNED_OUT') { this.realtime.setAuth(); if (source == 'STORAGE') this.auth.signOut(); this.changedAccessToken = undefined; } } } exports.default = SupabaseClient; //# sourceMappingURL=SupabaseClient.js.map