diff --git a/demos/react-supabase-todolist/README.md b/demos/react-supabase-todolist/README.md index 5518cd86b..6ae7ae535 100644 --- a/demos/react-supabase-todolist/README.md +++ b/demos/react-supabase-todolist/README.md @@ -8,33 +8,42 @@ This demo uses [Sync Streams](https://docs.powersync.com/usage/sync-streams). Bo ## Run Demo -Prerequisites: -* To run this demo, you need to have properly configured Supabase and PowerSync projects. Follow the instructions in our Supabase<>PowerSync integration guide: - * [Configure Supabase](https://docs.powersync.com/integration-guides/supabase-+-powersync#configure-supabase) - * [Configure PowerSync](https://docs.powersync.com/integration-guides/supabase-+-powersync#configure-powersync) +### 1. Supabase Setup -Switch into the demo's directory: +Create a new Supabase project, then run the contents of [`database.sql`](./database.sql) in the [Supabase SQL editor](https://supabase.com/dashboard/project/_/sql). This will: + +- Create the `lists` and `todos` tables +- Enable Row Level Security (RLS) so users can only access their own data +- Create a `powersync` publication for replication + +### 2. PowerSync Setup + +Create a new PowerSync instance connected to your Supabase project ([instructions here](https://docs.powersync.com/integration-guides/supabase-+-powersync#connect-powersync-to-your-supabase)). + +In the PowerSync dashboard, go to **Sync Streams** (shown as **Sync Rules** if using legacy Sync Rules) and paste the contents of [`sync-streams.yaml`](./sync-streams.yaml). + +### 3. Install Dependencies +Switch into the demo's directory: ```bash cd demos/react-supabase-todolist ``` Use [pnpm](https://pnpm.io/installation) to install dependencies: - ```bash pnpm install ``` -Set up the Environment variables: Copy the `.env.local.template` file: +### 4. Configure Environment Variables +Copy the `.env.local.template` file: ```bash cp .env.local.template .env.local ``` -And then edit `.env.local` to insert your credentials for Supabase. - -Run the development server: +Edit `.env.local` to insert your Supabase URL, anon key, and PowerSync URL. +### 5. Run the Development Server ```bash pnpm dev ``` @@ -46,13 +55,11 @@ Open [http://localhost:5173](http://localhost:5173) with your browser to see the This demo is PWA compatible, and works fully offline. PWA is not available in development (watch) mode. The manifest and service worker is built using [vite-plugin-pwa](https://vite-pwa-org.netlify.app/). Build the production codebase: - ```bash pnpm build ``` Run the production server: - ```bash pnpm preview ``` @@ -63,4 +70,4 @@ Open a browser on the served URL and install the PWA. Check out [the PowerSync Web SDK on GitHub](https://github.com/powersync-ja/powersync-js/tree/main/packages/web) - your feedback and contributions are welcome! -To learn more about PowerSync, see the [PowerSync docs](https://docs.powersync.com). +To learn more about PowerSync, see the [PowerSync docs](https://docs.powersync.com). \ No newline at end of file diff --git a/demos/react-supabase-todolist/database.sql b/demos/react-supabase-todolist/database.sql new file mode 100644 index 000000000..8321ccf6b --- /dev/null +++ b/demos/react-supabase-todolist/database.sql @@ -0,0 +1,68 @@ +-- Create the lists table +CREATE TABLE IF NOT EXISTS public.lists ( + id uuid NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY, + created_at timestamp with time zone NOT NULL DEFAULT now(), + name text NOT NULL, + owner_id uuid NOT NULL REFERENCES auth.users (id) ON DELETE CASCADE +); + +-- Create the todos table +CREATE TABLE IF NOT EXISTS public.todos ( + id uuid NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY, + created_at timestamp with time zone NOT NULL DEFAULT now(), + completed_at timestamp with time zone, + description text NOT NULL, + completed boolean NOT NULL DEFAULT false, + list_id uuid NOT NULL REFERENCES public.lists (id) ON DELETE CASCADE, + created_by uuid REFERENCES auth.users (id), + completed_by uuid REFERENCES auth.users (id) +); + +-- Enable Row Level Security +ALTER TABLE public.lists ENABLE ROW LEVEL SECURITY; +ALTER TABLE public.todos ENABLE ROW LEVEL SECURITY; + +-- RLS policies for lists: users can only access their own lists +CREATE POLICY "Users can view their own lists" ON public.lists + FOR SELECT USING (auth.uid() = owner_id); + +CREATE POLICY "Users can insert their own lists" ON public.lists + FOR INSERT WITH CHECK (auth.uid() = owner_id); + +CREATE POLICY "Users can update their own lists" ON public.lists + FOR UPDATE USING (auth.uid() = owner_id); + +CREATE POLICY "Users can delete their own lists" ON public.lists + FOR DELETE USING (auth.uid() = owner_id); + +-- RLS policies for todos: users can only access todos in their own lists +CREATE POLICY "Users can view todos in their lists" ON public.todos + FOR SELECT USING ( + list_id IN (SELECT id FROM public.lists WHERE owner_id = auth.uid()) + ); + +CREATE POLICY "Users can insert todos in their lists" ON public.todos + FOR INSERT WITH CHECK ( + list_id IN (SELECT id FROM public.lists WHERE owner_id = auth.uid()) + ); + +CREATE POLICY "Users can update todos in their lists" ON public.todos + FOR UPDATE USING ( + list_id IN (SELECT id FROM public.lists WHERE owner_id = auth.uid()) + ); + +CREATE POLICY "Users can delete todos in their lists" ON public.todos + FOR DELETE USING ( + list_id IN (SELECT id FROM public.lists WHERE owner_id = auth.uid()) + ); + +-- Create PowerSync role for replication access +-- Note: After creating this role, set a secure password in the Supabase dashboard +-- or run: ALTER ROLE powersync_role WITH PASSWORD 'your-secure-password'; +CREATE ROLE powersync_role REPLICATION LOGIN; +GRANT SELECT ON public.lists TO powersync_role; +GRANT SELECT ON public.todos TO powersync_role; + +-- Create PowerSync publication +-- Note: FOR ALL TABLES is simplest for dev. In production, specify tables explicitly. +CREATE PUBLICATION powersync FOR TABLE public.lists, public.todos; \ No newline at end of file diff --git a/demos/react-supabase-todolist/sync-streams.yaml b/demos/react-supabase-todolist/sync-streams.yaml new file mode 100644 index 000000000..788f30e46 --- /dev/null +++ b/demos/react-supabase-todolist/sync-streams.yaml @@ -0,0 +1,10 @@ +config: + edition: 3 + +streams: + user_data: + auto_subscribe: true + queries: + # Scoped to the authenticated user + - SELECT * FROM lists WHERE owner_id = auth.user_id() + - SELECT todos.* FROM todos INNER JOIN lists ON todos.list_id = lists.id WHERE lists.owner_id = auth.user_id() \ No newline at end of file