From 0c4da7607fb069cf4f7888da5d9e1ecac2b12e71 Mon Sep 17 00:00:00 2001 From: benitav Date: Mon, 16 Sep 2024 11:34:59 +0200 Subject: [PATCH 1/2] Readme polish --- demos/react-native-web-supabase-todolist/README.md | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/demos/react-native-web-supabase-todolist/README.md b/demos/react-native-web-supabase-todolist/README.md index 8a08700d..56fd6383 100644 --- a/demos/react-native-web-supabase-todolist/README.md +++ b/demos/react-native-web-supabase-todolist/README.md @@ -12,7 +12,7 @@ To run this demo, follow these instructions: ### Install dependencies -In the repo directory, use [pnpm](https://pnpm.io/installation) to install dependencies: +In the repo root, use [pnpm](https://pnpm.io/installation) to install dependencies: ```bash pnpm install @@ -68,14 +68,6 @@ This is required for the React Native Web implementation. Learn more in [Configu mkdir -p public/@powersync && cp -r node_modules/@powersync/web/dist/* public/@powersync/ ``` -### EAS Build configuration - -Take note that you will need an [Expo](https://expo.dev/) account if you want to use EAS for your builds. The Expo project ID should then also be configured in the environment file. - -For secret/sensitive environment variables which shouldn't be checked into source control, you can configure them as EAS secrets. They can be added via either the Expo website or the EAS CLI, both are explained [here](https://docs.expo.dev/build-reference/variables/#using-secrets-in-environment-variables). - -General information on defining environment variables with Expo can be found here [here](https://docs.expo.dev/build-reference/variables/#can-eas-build-use-env-files). - ### Run the app Run on Web: From 97c285a438d2a9c778635bcb858058a972e90dc6 Mon Sep 17 00:00:00 2001 From: benitav Date: Mon, 16 Sep 2024 13:08:34 +0200 Subject: [PATCH 2/2] Simplify readme - migrate config instructions to docs --- .../README.md | 220 +----------------- 1 file changed, 2 insertions(+), 218 deletions(-) diff --git a/demos/react-native-web-supabase-todolist/README.md b/demos/react-native-web-supabase-todolist/README.md index 56fd6383..50f7aac3 100644 --- a/demos/react-native-web-supabase-todolist/README.md +++ b/demos/react-native-web-supabase-todolist/README.md @@ -4,7 +4,7 @@ This demo app is an extension of the [Supabase Todo List App](../react-native-supabase-todolist/) and demonstrates the use of the PowerSync SDKs for [React Native](https://www.npmjs.com/package/@powersync/react-native) and [Web](https://www.npmjs.com/package/@powersync/web) in a [React Native Web](https://necolas.github.io/react-native-web/) project. This configuration allows developers to use one React Native codebase to target mobile and well as web platforms. -To use PowerSync in your own React Native for Web project, additional config is required. This is detailed in the [Configuring PowerSync for React Native for Web](#configuring-powersync-for-react-native-for-web) section further below. +To use PowerSync in your own React Native for Web project, additional config is required. This is detailed in our docs [here](https://docs.powersync.com/client-sdk-references/react-native-and-expo/react-native-web-support). To run this demo, follow these instructions: @@ -62,7 +62,7 @@ Then edit `.env.local` to insert your Supabase and PowerSync project credentials #### 2. Configure web workers -This is required for the React Native Web implementation. Learn more in [Configuring PowerSync for React Native for Web](#configuring-powersync-for-react-native-for-web). +This is required for the React Native Web implementation. Learn more in [our docs](https://docs.powersync.com/client-sdk-references/react-native-and-expo/react-native-web-support). ```bash mkdir -p public/@powersync && cp -r node_modules/@powersync/web/dist/* public/@powersync/ @@ -88,220 +88,4 @@ Run on Android: ```sh pnpm android -``` - -## Configuring PowerSync in React Native for Web projects - -To ensure that PowerSync features are fully supported in your React Native Web project, follow the below steps. This documentation covers necessary web worker configurations, database instantiation, and multi-platform implementations. - -### 1. Install Web SDK - -The PowerSync Web SDK, alongside the PowerSync React Native SDK, is required for Web support. - -See installation instructions [here](https://www.npmjs.com/package/@powersync/web). - -### 2. Configure Web Workers - -For React Native for Web, workers need to be configured when instantiating `PowerSyncDatabase`. An example of this is avaiable [here](./library/powersync/system.ts). - -To do this, copy the contents of `node_modules/@powersync/web/dist` to the root of your project (typically in the `public ` directory). To make it easier to manage these files in the `public` directory, it is recommended to place the contents in a nested directory like `@powersync`. - -You can run the following bash command to automate the copying process. It will create copy the contents to `/public/@powersync`. - -``` -mkdir -p public/@powersync && cp -r node_modules/@powersync/web/dist/* public/@powersync/ -``` - -### 3. Instantiate Web Workers -The example below demonstrates how to instantiate the workers (PowerSync requires a database and a sync worker) when instantiating `PowerSyncDatabase`. You can either specify a path to the worker (they are available in the `worker` directory of the `dist` contents), or provide a factory function to create the worker. - -```javascript -const factory = new WASQLiteOpenFactory({ - dbFilename: 'sqlite.db', - - // Option 1: Specify a path to the database worker - worker: '/@powersync/worker/WASQLiteDB.umd.js' - - // Option 2: Or provide a factory function to create the worker. - // The worker name should be unique for the database filename to avoid conflicts if multiple clients with different databases are present. - // worker: (options) => { - // if (options?.flags?.enableMultiTabs) { - // return new SharedWorker(`/@powersync/worker/WASQLiteDB.umd.js`, { - // name: `shared-DB-worker-${options?.dbFilename}` - // }); - // } else { - // return new Worker(`/@powersync/worker/WASQLiteDB.umd.js`, { - // name: `DB-worker-${options?.dbFilename}` - // }); - // } - // } -}); - -this.powersync = new PowerSyncDatabaseWeb({ - schema: AppSchema, - database: factory, - sync: { - // Option 1: You can specify a path to the sync worker - worker: '/@powersync/worker/SharedSyncImplementation.umd.js' - - //Option 2: Or provide a factory function to create the worker. - // The worker name should be unique for the database filename to avoid conflicts if multiple clients with different databases are present. - // worker: (options) => { - // return new SharedWorker(`/@powersync/worker/SharedSyncImplementation.umd.js`, { - // name: `shared-sync-${options?.dbFilename}` - // }); - // } - } -}); -``` - -This `PowerSyncDatabaseWeb` database will be used alongside the native `PowerSyncDatabase` to support platform-specific implementations. See the [Instantiating PowerSync](#instantiating-powersync) below for more details. - -### 4. Enable multiple platforms - -To target both mobile and web platforms, you need to adjust the Metro configuration and handle platform-specific libraries accordingly. - -#### Metro config - -Refer to the example [here](./metro.config.js). -Setting `config.resolver.resolveRequest` allows Metro to behave differently based on the platform. - -```javascript -config.resolver.resolveRequest = (context, moduleName, platform) => { - if (platform === 'web') { - // Depending on `@powersync/web` for functionality, ignore mobile specific dependencies. - if (['react-native-prompt-android', '@powersync/react-native'].includes(moduleName)) { - return { - type: 'empty' - }; - } - const mapping = { 'react-native': 'react-native-web', '@powersync/web': '@powersync/web/dist/index.umd.js' }; - if (mapping[moduleName]) { - console.log('remapping', moduleName); - return context.resolveRequest(context, mapping[moduleName], platform); - } - } else { - // Depending on `@powersync/react-native` for functionality, ignore `@powersync/web` dependencies. - if (['@powersync/web'].includes(moduleName)) { - return { - type: 'empty' - }; - } - } - - // Ensure you call the default resolver. - return context.resolveRequest(context, moduleName, platform); -}; -``` - -#### Implementations - -Many `react-native` and `web` packages are implemented with only their specific platform in mind, as such there may be times where you will need to evaluate the platform and provide alternative implementations. - -##### Instantiating PowerSync - -The following snippet constructs the correct `PowerSyncDatabase` depending on the platform that the code is executing on. - -```javascript -import React from 'react'; -import { PowerSyncDatabase as PowerSyncDatabaseNative } from '@powersync/react-native'; -import { PowerSyncDatabase as PowerSyncDatabaseWeb } from '@powersync/web'; - -if (PowerSyncDatabaseNative) { - this.powersync = new PowerSyncDatabaseNative({ - schema: AppSchema, - database: { - dbFilename: 'sqlite.db' - } - }); -} else { - const factory = new WASQLiteOpenFactory({ - dbFilename: 'sqlite.db', - worker: '/@powersync/worker/WASQLiteDB.umd.js' - }); - this.powersync = new PowerSyncDatabaseWeb({ - schema: AppSchema, - database: factory, - sync: { - worker: '/@powersync/worker/SharedSyncImplementation.umd.js' - } - }); -} -``` - -##### Implementations that don't support both mobile and web - -```javascript -import { Platform } from 'react-native'; - -import { Platform } from 'react-native'; -import rnPrompt from 'react-native-prompt-android'; - -// Example conditional implementation -export async function prompt( - title = '', - description = '', - onInput = (_input: string | null): void | Promise => {}, - options: { placeholder: string | undefined } = { placeholder: undefined } -) { - const isWeb = Platform.OS === 'web'; - let name: string | null = null; - - if (isWeb) { - name = window.prompt(`${title}\n${description}`, options.placeholder); - } else { - name = await new Promise((resolve) => { - rnPrompt( - title, - description, - (input) => { - resolve(input); - }, - { placeholder: options.placeholder, style: 'shimo' } - ); - }); - } - - await onInput(name); -} - -``` - -Which can then be used agnostically in a component. - -```jsx -import { Button } from 'react-native'; -import { prompt } from 'util/prompt'; - -