tutorbookapp/tutorbook

View on GitHub
lib/api/db/org.ts

Summary

Maintainability
B
6 hrs
Test Coverage
import { DBOrg, DBRelationMember, DBRelationOrgSubject, DBViewOrg, Org } from 'lib/model/org';
import { APIError } from 'lib/model/error';
import handle from 'lib/api/db/error';
import logger from 'lib/api/logger';
import supabase from 'lib/api/supabase';

export async function createOrg(org: Org): Promise<Org> {
  logger.debug(`Inserting org (${org.toString()}) row...`);
  const { data, error } = await supabase.from<DBOrg>('orgs').insert(org.toDB());
  handle('creating', 'org', org, error);
  const o = data ? Org.fromDB(data[0]) : org;
  if (org.subjects) {
    const subjects: DBRelationOrgSubject[] = org.subjects.map((s) => ({
      subject: s.id,
      org: o.id,
    }));
    logger.debug(`Inserting subjects (${JSON.stringify(subjects)}) rows...`);
    const { error: err } = await supabase
      .from<DBRelationOrgSubject>('relation_org_subjects')
      .insert(subjects);
    handle('creating', 'org subjects', subjects, err);
  }
  const members = org.members.map((m) => ({ user: m, org: o.id }));
  logger.debug(`Inserting org members (${JSON.stringify(members)}) rows...`);
  const { error: err } = await supabase
    .from<DBRelationMember>('relation_members')
    .insert(members);
  handle('creating', 'members', members, err);
  return new Org({ ...o, members: org.members });
}

export async function updateOrg(org: Org): Promise<Org> {
  logger.debug(`Updating org (${org.toString()}) row...`);
  const { data, error } = await supabase
    .from<DBOrg>('orgs')
    .update(org.toDB())
    .eq('id', org.id);
  handle('updating', 'org', org, error);
  const o = data ? Org.fromDB(data[0]) : org;

  const subjects: DBRelationOrgSubject[] = (org.subjects || []).map((s) => ({
    subject: s.id,
    org: o.id,
  }));
  logger.debug(`Replacing org subjects (${JSON.stringify(subjects)}) rows...`);
  const { error: deleteSubjectsErr } = await supabase
    .from<DBRelationOrgSubject>('relation_org_subjects')
    .delete()
    .eq('org', o.id);
  handle('deleting', 'org subjects', subjects, deleteSubjectsErr);
  const { error: insertSubjectsErr } = await supabase
    .from<DBRelationOrgSubject>('relation_org_subjects')
    .insert(subjects);
  handle('inserting', 'org subjects', subjects, insertSubjectsErr);
  
  const members = org.members.map((m) => ({ user: m, org: o.id }));
  logger.debug(`Replacing org members (${JSON.stringify(members)}) rows...`);
  const { error: deleteMembersErr } = await supabase
    .from<DBRelationMember>('relation_members')
    .delete()
    .eq('org', o.id);
  handle('deleting', 'members', members, deleteMembersErr);
  const { error: insertMembersErr } = await supabase
    .from<DBRelationMember>('relation_members')
    .insert(members);
  handle('inserting', 'members', members, insertMembersErr);
  
  return new Org({ ...o, members: org.members });
}

export async function getOrg(id: string): Promise<Org> {
  const { data, error } = await supabase
    .from<DBViewOrg>('view_orgs')
    .select()
    .eq('id', id);
  handle('getting', 'org', id, error);
  if (!data?.length) throw new APIError(`Org (${id}) does not exist`, 404);
  return Org.fromDB(data[0]);
}

export async function getOrgs(): Promise<Org[]> {
  const { data, error } = await supabase.from<DBViewOrg>('view_orgs').select();
  // TODO: Remove this weird edge case workaround for no results.
  // @see {@link https://github.com/supabase/postgrest-js/issues/202}
  if (error instanceof Array) return [];
  handle('getting', 'orgs', {}, error);
  return (data || []).map((d) => Org.fromDB(d));
}

export async function getOrgsByAdminId(adminId: string): Promise<Org[]> {
  const { data, error } = await supabase
    .from<DBViewOrg>('view_orgs')
    .select()
    .contains('members', [adminId]);
  // TODO: Remove this weird edge case workaround for no results.
  // @see {@link https://github.com/supabase/postgrest-js/issues/202}
  if (error instanceof Array) return [];
  handle('getting', 'orgs by admin', adminId, error);
  return (data || []).map((d) => Org.fromDB(d));
}