233 lines
10 KiB
JavaScript
233 lines
10 KiB
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/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
|