UNPKG

@dill-pixel/storage-adapter-supabase

Version:

Supabase Storage Adapter

149 lines (128 loc) 5.2 kB
import type { SupabaseClient } from '@supabase/supabase-js'; import { createClient } from '@supabase/supabase-js'; import { GenericSchema } from '@supabase/supabase-js/dist/module/lib/types'; import { IApplication, IStorageAdapter, Logger, StorageAdapter } from 'dill-pixel'; import { supabasePostgresVersion, supabaseVersion, version } from './version'; type SaveMethod = 'insert' | 'update' | 'upsert'; type DeleteData = { [key: string]: any; }; interface ISupabaseAdapterOptions { supabaseUrl?: string; anonKey?: string; debug?: boolean; } export interface ISupabaseAdapter<Database extends GenericSchema = any> extends IStorageAdapter<ISupabaseAdapterOptions, Database> { client: SupabaseClient<Database>; initialize(options: Partial<ISupabaseAdapterOptions>, _app: IApplication): void; save(tableId: string, data: any, method?: SaveMethod): Promise<any>; load<T = any>(tableId: string, selectors?: string[]): Promise<T>; delete(tableId: string, data: DeleteData): Promise<any>; } /** * A class representing a storage adapter that uses Supabase. */ export class SupabaseAdapter<Database extends GenericSchema = any> extends StorageAdapter<ISupabaseAdapterOptions, Database> implements ISupabaseAdapter<Database> { private _options: ISupabaseAdapterOptions; private _supabase: SupabaseClient<Database>; /** * Returns the Supabase client. * @returns {SupabaseClient<Database>} The Supabase client. */ get client(): SupabaseClient<Database> { return this._supabase as SupabaseClient<Database>; } private hello() { const hello = `%c Dill Pixel Supabase Adapter v${version} | %cSupabase v${supabaseVersion} | %cSupabase Postgres v${supabasePostgresVersion}`; console.log( hello, 'background: rgba(31, 41, 55, 1);color: #74b64c', 'background: rgba(31, 41, 55, 1);color: #e91e63', 'background: rgba(31, 41, 55, 1);color: #e91e63', 'background: rgba(31, 41, 55, 1);color: #74b64c', 'background: rgba(31, 41, 55, 1);color: #74b64c', ); if (this._options.debug) { Logger.log(this._options); } } /** * Initializes the adapter. * @param {IApplication} _app The application that the adapter belongs to. * @param {ISupabaseAdapterOptions} options The options to initialize the adapter with. * @returns {void} */ public initialize(options: Partial<ISupabaseAdapterOptions> = {}, _app: IApplication): void { Logger.log('SupabaseAdapter initialized'); const defaultConfig: ISupabaseAdapterOptions = { supabaseUrl: _app.env.VITE_SUPABASE_URL || _app.env.SUPABASE_URL, anonKey: _app.env.VITE_SUPABASE_ANON_KEY || _app.env.SUPABASE_ANON_KEY, }; this._options = { ...defaultConfig, ...options }; this.hello(); if (!this._options.supabaseUrl) { throw new Error('Supabase URL is not set'); } if (!this._options.anonKey) { throw new Error('Supabase anon key is not set'); } this._supabase = createClient<Database>(this._options.supabaseUrl, this._options.anonKey); } /** * Saves data to a specified table in the Supabase database. * @param {string} tableId The table to save the data to. * @param {any} data The data to save. * @param {SaveMethod} method The method to use for saving the data. * @returns {Promise<any>} The saved data. * * @example * await this.app.supabase.save('scores', { username: 'relish', score: 50 }) */ async save(tableId: string, data: any, method: SaveMethod = 'upsert'): Promise<any> { if (!Array.isArray(data)) { data = [data]; } const table = this.client.from(tableId); switch (method) { case 'insert': return await table.insert(data).select(); case 'update': return await table.update(data).select(); case 'upsert': return await table.upsert(data).select(); } } /** * Loads data from a specified table in the Supabase database. * @param {string} tableId The table from which to load the data. * @param {string[]} selectors The columns to select. Default is '*'. * @returns {PostgrestFilterBuilder<any, any, any>} PostgrestFilterBuilder // TODO * * @example * await this.app.supabase.load('scores', ['score', 'username']).order('score', { ascending: false }).limit(5) */ async load<TExpectedLoadResult = any>(tableId: string, selectors?: string[]): Promise<TExpectedLoadResult> { const query = this.client.from(tableId).select(selectors?.join(',')); const { data, error } = await query; if (error) throw error; return data as TExpectedLoadResult; } /** * Deletes data from a specified table in the Supabase database. * @param {string} tableId The table from which to load the data. * @param {DeleteData} data The data to delete. * @returns {Promise<any>} The deleted data. * * @example * await this.app.supabase.delete('scores', { username: 'relish', score: 50 }) */ async delete(tableId: string, data: DeleteData): Promise<any> { const column = Object.keys(data)[0]; const value = data[column]; return await this.client.from(tableId).delete().eq(column, value).select(); } }