Skip to content

Instantly share code, notes, and snippets.

@touhidrahman
Last active March 5, 2022 02:42
Show Gist options
  • Save touhidrahman/af0382da3f66c3b9cd9850422c3194fb to your computer and use it in GitHub Desktop.
Save touhidrahman/af0382da3f66c3b9cd9850422c3194fb to your computer and use it in GitHub Desktop.
base.service.ts (supabase)
export class BaseService<T> {
protected resource: string // table name
constructor(protected supabase: SupabaseService, resource: string) {
this.resource = resource
}
findById(id: number, select = '*'): Observable<T> {
const query = this.supabase.table(this.resource).select(select).match({ id }).single()
return from(query).pipe(map((res) => res.body as T))
}
find(filters: FindFilter[], select = '*', range = [0, 10], orders: FindOrder[] = []): Observable<T[]> {
const query = this.supabase.table(this.resource).select(select)
// filters is an array of FindFilters, so we chain each filter to the query builder
filters.forEach(([column, op, value]) => {
query.filter(column, op, value)
})
// same as filters, chaining multiple order by queries is possible
orders.forEach(([column, ascending]) => {
query.order(column, { ascending })
})
// use range for pagination
query.range(range[0], range[1])
return from(query).pipe(map((res) => res.body as T[]))
}
count(filters: FindFilter[]) {
// providing the option `head: true` will only return the count, otherwise results too.
const query = this.supabase.table(this.resource).select('*', {
count: 'exact', head: true
})
filters.forEach(([column, op, value]) => {
query.filter(column, op, value)
})
return from(query).pipe(map((res) => res.count))
}
create(model: Partial<T>): Observable<T> {
const query = this.supabase
.table(this.resource)
.insert({ ...model })
.single()
return from(query).pipe(map((res) => res.body as T))
}
createMany(models: Partial<T>[]): Observable<T[]> {
const query = this.supabase.table(this.resource).insert(models)
return from(query).pipe(map((res) => res.body as T[]))
}
delete(id: number): Observable<T> {
const query = this.supabase.table(this.resource).delete().eq('id', id).single()
return from(query).pipe(map((res) => res.body as T))
}
deleteMany(filters: FindFilter[]): Observable<T[]> {
const query = this.supabase.table(this.resource).delete()
filters.forEach(([column, op, value]) => {
query.filter(column, op, value)
})
return from(query).pipe(map((res) => res.body as T[]))
}
update(id: number, data: Partial<T>): Observable<T> {
const query = this.supabase
.table(this.resource)
.update({ ...data })
.eq('id', id)
.single()
return from(query).pipe(map((res) => res.body as T))
}
// helpers for other custom methods you might write in the service. Returns typed result.
protected returnList(query: any): Observable<T[]> {
return from(query).pipe(map((res: any) => res.body as T[]))
}
protected returnSingle(query: any): Observable<T> {
return from(query).pipe(map((res: any) => res.body?.[0] as T))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment