Download supabase_schema.sql from simikkk/EtsyListingGenerator: direct link, hf CLI and curl.
- Browser
- Download file 6.15 kB
-
https://huggingface.co/spaces/simikkk/EtsyListingGenerator/resolve/main/supabase_schema.sql
- Command line
-
hf download hf://spaces/simikkk/EtsyListingGenerator/supabase_schema.sql
-
curl -L -o supabase_schema.sql https://huggingface.co/spaces/simikkk/EtsyListingGenerator/resolve/main/supabase_schema.sql
6.15 kB
| -- Etsy Listing Optimizer - Supabase (Postgres) schema | |
| -- Run this in the Supabase SQL editor for your project (see DEPLOY.md). | |
| -- Assumes Supabase Auth is enabled; auth.users is Supabase's built-in table. | |
| -- --------------------------------------------------------------------------- | |
| -- profiles: one row per auth user, holds subscription/tier state | |
| -- --------------------------------------------------------------------------- | |
| create table if not exists public.profiles ( | |
| user_id uuid primary key references auth.users (id) on delete cascade, | |
| email text not null, | |
| tier text not null default 'free' check (tier in ('free', 'starter', 'pro', 'business')), | |
| stripe_customer_id text, | |
| stripe_subscription_id text, | |
| stripe_subscription_status text, | |
| created_at timestamptz not null default now(), | |
| updated_at timestamptz not null default now() | |
| ); | |
| alter table public.profiles enable row level security; | |
| create policy "profiles_select_own" on public.profiles | |
| for select using (auth.uid() = user_id); | |
| create policy "profiles_update_own" on public.profiles | |
| for update using (auth.uid() = user_id); | |
| -- Inserts happen via a service-role backend call on signup, not directly by | |
| -- the client, so no client-facing insert policy is defined here. | |
| -- --------------------------------------------------------------------------- | |
| -- generation_counters: one row per user per calendar month | |
| -- --------------------------------------------------------------------------- | |
| create table if not exists public.generation_counters ( | |
| user_id uuid not null references auth.users (id) on delete cascade, | |
| year_month text not null, -- e.g. '2026-07' | |
| count integer not null default 0, | |
| updated_at timestamptz not null default now(), | |
| primary key (user_id, year_month) | |
| ); | |
| alter table public.generation_counters enable row level security; | |
| create policy "counters_select_own" on public.generation_counters | |
| for select using (auth.uid() = user_id); | |
| -- Writes to counters go through the backend (service role) so quota can't | |
| -- be tampered with by the client; no client insert/update policy. | |
| -- --------------------------------------------------------------------------- | |
| -- brand_voice_profiles | |
| -- --------------------------------------------------------------------------- | |
| create table if not exists public.brand_voice_profiles ( | |
| id uuid primary key default gen_random_uuid(), | |
| user_id uuid not null references auth.users (id) on delete cascade, | |
| name text not null, | |
| tone text, | |
| target_audience text, | |
| favorite_words text, | |
| created_at timestamptz not null default now() | |
| ); | |
| alter table public.brand_voice_profiles enable row level security; | |
| create policy "brand_voice_select_own" on public.brand_voice_profiles | |
| for select using (auth.uid() = user_id); | |
| create policy "brand_voice_insert_own" on public.brand_voice_profiles | |
| for insert with check (auth.uid() = user_id); | |
| create policy "brand_voice_update_own" on public.brand_voice_profiles | |
| for update using (auth.uid() = user_id); | |
| create policy "brand_voice_delete_own" on public.brand_voice_profiles | |
| for delete using (auth.uid() = user_id); | |
| -- --------------------------------------------------------------------------- | |
| -- listings: generation history | |
| -- --------------------------------------------------------------------------- | |
| create table if not exists public.listings ( | |
| id uuid primary key default gen_random_uuid(), | |
| user_id uuid not null references auth.users (id) on delete cascade, | |
| brand_voice_profile_id uuid references public.brand_voice_profiles (id) on delete set null, | |
| product_description text not null, | |
| target_keywords text, | |
| titles jsonb not null, | |
| tags jsonb not null, | |
| description text not null, | |
| category_hints jsonb, | |
| provider_used text, | |
| created_at timestamptz not null default now() | |
| ); | |
| alter table public.listings enable row level security; | |
| create policy "listings_select_own" on public.listings | |
| for select using (auth.uid() = user_id); | |
| create policy "listings_insert_own" on public.listings | |
| for insert with check (auth.uid() = user_id); | |
| create policy "listings_delete_own" on public.listings | |
| for delete using (auth.uid() = user_id); | |
| create index if not exists listings_user_created_idx on public.listings (user_id, created_at desc); | |
| -- --------------------------------------------------------------------------- | |
| -- shops: for Business tier "multiple shops/clients" | |
| -- --------------------------------------------------------------------------- | |
| create table if not exists public.shops ( | |
| id uuid primary key default gen_random_uuid(), | |
| user_id uuid not null references auth.users (id) on delete cascade, | |
| name text not null, | |
| created_at timestamptz not null default now() | |
| ); | |
| alter table public.shops enable row level security; | |
| create policy "shops_select_own" on public.shops | |
| for select using (auth.uid() = user_id); | |
| create policy "shops_insert_own" on public.shops | |
| for insert with check (auth.uid() = user_id); | |
| create policy "shops_delete_own" on public.shops | |
| for delete using (auth.uid() = user_id); | |
| -- --------------------------------------------------------------------------- | |
| -- helper: touch updated_at on profiles | |
| -- --------------------------------------------------------------------------- | |
| create or replace function public.set_updated_at() | |
| returns trigger as $$ | |
| begin | |
| new.updated_at = now(); | |
| return new; | |
| end; | |
| $$ language plpgsql; | |
| drop trigger if exists profiles_set_updated_at on public.profiles; | |
| create trigger profiles_set_updated_at | |
| before update on public.profiles | |
| for each row execute function public.set_updated_at(); | |
| -- --------------------------------------------------------------------------- | |
| -- Reminder (see DEPLOY.md): | |
| -- - Enable "Leaked password protection" under Auth > Policies in the Supabase | |
| -- dashboard - this is a project setting, not a SQL statement. | |
| -- - Provision this project in an EU region (e.g. Frankfurt) at creation time | |
| -- for GDPR data residency - also a dashboard setting, not SQL. | |
| -- --------------------------------------------------------------------------- | |