Skip to main content

Supabase JS SDK

JavaScript Client Library : https://supabase.com/docs/reference/javascript/introduction

Next actions + supabase client

supabase client

  • 기본적으로 public 스키마를 디폴트로 가르키고 있다.

Next actions

주의점

  • 서버 액션은 서버 컴포넌트를 포함한 미들웨어, 다른 서버 액션, 라우터 핸들러에서 호출될 수 있다.
  • 이때 서버 컴포넌트에서 SSR 중에 서버 액션을 부르게 되면 쿠키에 대한 조작을 금지 해야 한다.
  • 그래서 액션한테 어떠한 곳에서 서버 액션을 불렀는지 알려주어야 한다.

Select

let { data: chat, error } = await supabase
.from('chat') // 'chat' 테이블을 선택
.select("*") // 테이블의 모든 컬럼을 조회
// Filters (필터 조건 설정)
.eq('column', 'Equal to') // NULL 외 값을 비교한다.
.gt('column', 'Greater than') //
.lt('column', 'Less than') //
.gte('column', 'Greater than or equal to') //
.lte('column', 'Less than or equal to') //
.like('column', '%CaseSensitive%') // CaseSensitive
.ilike('column', '%CaseInsensitive%') // CaseInsensitive
.is('column', null) // IS NULL
.in('column', ['Array', 'Values']) //
.neq('column', 'Not equal to') // 'column' 값이 'Not equal to'와 일치하지 않는 행 필터
// Arrays (배열 관련 조건 설정)
.contains('array_column', ['array', 'contains']) // 'array_column'이 배열 ['array', 'contains']를 포함하는 행 필터
.containedBy('array_column', ['contained', 'by']) // 'array_column'이 배열 ['contained', 'by']에 완전히 포함되는 행 필터
---
.eq('column', 'Equal to')
SELECT * FROM chat WHERE column = 'Equal to';

.neq('column', 'Not equal to')
SELECT * FROM chat WHERE column != 'Not equal to';

.gt('column', 'Greater than')
SELECT * FROM chat WHERE column > 'Greater than';

.lt('column', 'Less than')
SELECT * FROM chat WHERE column < 'Less than';

.gte('column', 'Greater than or equal to')
SELECT * FROM chat WHERE column >= 'Greater than or equal to';

.lte('column', 'Less than or equal to')
SELECT * FROM chat WHERE column <= 'Less than or equal to';

.like('column', '%CaseSensitive%')
SELECT * FROM chat WHERE column LIKE '%CaseSensitive%';

.ilike('column', '%CaseInsensitive%')
SELECT * FROM chat WHERE column ILIKE '%CaseInsensitive%';

.is('column', null)
SELECT * FROM chat WHERE column IS NULL;

.in('column', ['Array', 'Values'])
SELECT * FROM chat WHERE column IN ('Array', 'Values');

.contains('array_column', ['array', 'contains'])
SELECT * FROM chat WHERE array_column @> ARRAY['array', 'contains'];

.containedBy('array_column', ['contained', 'by'])
SELECT * FROM chat WHERE array_column <@ ARRAY['contained', 'by'];

Select Example Todo

"use server";
import { createServerSideClient } from "@/lib/supabase";

interface ContextProps {
serverComponent?: boolean;
}

export const getTodosPublic = async (ctx?: ContextProps) => {
const supabase = await createServerSideClient(ctx?.serverComponent);
const result = await supabase
.from("todos-public")
.select("*")
.is("deleted_at", null)
.order("id", { ascending: false });

return result.data;
};

export const getTodosPublicById = async (id: number, ctx?: ContextProps) => {
const supabase = await createServerSideClient(ctx?.serverComponent);
const result = await supabase
.from("todos-public")
.select("*")
.is("deleted_at", null)
.eq("id", id);

return result.data?.[0];
};

export const getTodosPublicBySearch = async (
terms: string,
ctx?: ContextProps
) => {
const supabase = await createServerSideClient(ctx?.serverComponent);
const result = await supabase
.from("todos-public")
.select("*")
.is("deleted_at", null)
.ilike("content", `%${terms}%`);

return result.data;
};

Select With Join

// 1.
// countries와 cities는 1:N 관계
// - 자식 테이블 조회
const { data, error } = await supabase
.from('countries')
.select(`
name,
cities (
name
)
`)


// 1.1
// 갯수만 구하기
const { data, error } = await supabase
.from('countries')
.select(`*, cities(count)`)


// 2.
// users와 teams는 N:M 관계
// - join table 자동으로 알고 조회 해준다.
const { data, error } = await supabase
.from('users')
.select(`
name,
teams (
name
)
`)

// 3.
// users와 messages는 1:N관계 - 1 sender
// users와 messages는 1:N관계 - 2 receiver
// - from:users!messages_sender_id_fkey(name),
// - 별칭:테이블!외래키제약(필드선태)
const { data, error } = await supabase
.from('messages')
.select(`
content,
from:users!messages_sender_id_fkey(name),
to:users!messages_receiver_id_fkey(name)
`)

Mutation

  • update는 eq로 선택 + update안에는 업데이트 할 내용을 적어준다.
  • softDelete는 string타입(ISO)으로 삭제된 날짜를 넘겨주면서 구현한다.
// single insert  
const result = await supabase
.from("todos-public")
.insert({ content })
.select();


// multiple insert
const rows = [
{ column1: 'value1', column2: 'value2' },
{ column1: 'value3', column2: 'value4' },
{ column1: 'value5', column2: 'value6' },
];

const { data, error } = await supabase
.from('your_table_name')
.insert(rows);

// single update
const result = await supabase
.from("todos-public")
.update({ content, updated_at: new Date().toISOString() })
.eq("id", id)
.select();

// multiple update
const { data, error } = await supabase
.from('your_table_name')
.update({ column_name: 'new_value' }) // 업데이트할 값
.in('id', [1, 2, 3]); // 조건: id가 1, 2, 3인 행들

// soft delete
const result = await supabase
.from("todos-public")
.update({ deleted_at: new Date().toISOString() })
.eq("id", id)
.select();

// hard delete
const result = await supabase.from("todos-public").delete().eq("id", id);