@supabase/supabase-js
Version:
Isomorphic Javascript client for Supabase
233 lines • 10.7 kB
JavaScript
"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-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