From 136663795be01192d9a3f3c49a4529bf1b4e4658 Mon Sep 17 00:00:00 2001 From: Mike Barnes Date: Thu, 20 Nov 2025 23:38:21 -0700 Subject: [PATCH 1/3] Fixed the linting error and removed use of deprecated function in the lint config --- eslint.config.js | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index d94e7de..aac8eec 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -3,21 +3,28 @@ import globals from 'globals' import reactHooks from 'eslint-plugin-react-hooks' import reactRefresh from 'eslint-plugin-react-refresh' import tseslint from 'typescript-eslint' -import { globalIgnores } from 'eslint/config' +import { defineConfig, globalIgnores } from 'eslint/config' -export default tseslint.config([ +export default defineConfig([ globalIgnores(['dist']), + js.configs.recommended, + ...tseslint.configs.recommended, { files: ['**/*.{ts,tsx}'], - extends: [ - js.configs.recommended, - tseslint.configs.recommended, - reactHooks.configs['recommended-latest'], - reactRefresh.configs.vite, - ], + plugins: { + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, languageOptions: { ecmaVersion: 2020, globals: globals.browser, }, + rules: { + ...reactHooks.configs.recommended.rules, + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, }, ]) From 21ddd81db1b129a07b9b680aa82232bbef6e5126 Mon Sep 17 00:00:00 2001 From: Mike Barnes Date: Thu, 20 Nov 2025 23:41:00 -0700 Subject: [PATCH 2/3] Implemented the Rust sync client and implemented OPFSCoopSyncVFS --- src/powersync/System.ts | 49 ++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/powersync/System.ts b/src/powersync/System.ts index 9548933..9140b5b 100644 --- a/src/powersync/System.ts +++ b/src/powersync/System.ts @@ -2,6 +2,9 @@ import { createBaseLogger, LogLevel, PowerSyncDatabase, + SyncClientImplementation, + WASQLiteOpenFactory, + WASQLiteVFS } from "@powersync/web"; import { AppSchema } from "./AppSchema"; import { connector } from "./SupabaseConnector"; @@ -11,17 +14,17 @@ logger.useDefaults(); logger.setLevel(LogLevel.DEBUG); /** - * Default configuration - uses IndexedDB storage + * Default configuration AccessHandlePoolVFS - uses IndexedDB * ✅ Use this for: Simple setup, most browsers * ❌ Avoid if: You need Safari support or have stability issues */ -export const powerSync = new PowerSyncDatabase({ - schema: AppSchema, - database: { - dbFilename: 'example.db' - }, - logger: logger -}); +// export const powerSync = new PowerSyncDatabase({ +// schema: AppSchema, +// database: { +// dbFilename: 'example.db' +// }, +// logger: logger +// }); /** * Alternative configuration with OPFS storage (Origin Private File System) @@ -41,20 +44,20 @@ export const powerSync = new PowerSyncDatabase({ * * 📚 Learn more: https://docs.powersync.com/client-sdk-references/javascript-web#sqlite-virtual-file-systems */ -// export const powerSync = new PowerSyncDatabase({ -// database: new WASQLiteOpenFactory({ -// dbFilename: "exampleVFS.db", -// vfs: WASQLiteVFS.OPFSCoopSyncVFS, // Use AccessHandlePoolVFS for single-tab only -// flags: { -// enableMultiTabs: typeof SharedWorker !== "undefined", -// }, -// }), -// flags: { -// enableMultiTabs: typeof SharedWorker !== "undefined", -// }, -// schema: AppSchema, -// logger: logger, -// }); +export const powerSync = new PowerSyncDatabase({ + database: new WASQLiteOpenFactory({ + dbFilename: "exampleVFS.db", + vfs: WASQLiteVFS.OPFSCoopSyncVFS, // Use AccessHandlePoolVFS for single-tab only + flags: { + enableMultiTabs: typeof SharedWorker !== "undefined", + }, + }), + flags: { + enableMultiTabs: typeof SharedWorker !== "undefined", + }, + schema: AppSchema, + logger: logger, +}); /** * Quick Decision Guide: @@ -69,4 +72,4 @@ export const powerSync = new PowerSyncDatabase({ await connector.signInAnonymously(); // Establish connection between PowerSync and the Supabase connector -powerSync.connect(connector); +powerSync.connect(connector, { clientImplementation: SyncClientImplementation.RUST }); From 81fb2349a537d9618c476ffdd6ab7c1dc8ff7c44 Mon Sep 17 00:00:00 2001 From: Mike Barnes Date: Thu, 20 Nov 2025 23:50:32 -0700 Subject: [PATCH 3/3] Added the Caddyfile and a Dockerfile so we can containerize it and serve the app --- Caddyfile | 37 +++++++++++++++++++++++++++++++++++++ Dockerfile | 40 ++++++++++++++++++++++++++++++++++++++++ src/powersync/System.ts | 2 +- 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 Caddyfile create mode 100644 Dockerfile diff --git a/Caddyfile b/Caddyfile new file mode 100644 index 0000000..1df1edc --- /dev/null +++ b/Caddyfile @@ -0,0 +1,37 @@ +# global options +{ + admin off # there's no need for the admin api in railway's environment + persist_config off # storage isn't persistent anyway + auto_https off # railway handles https for us, this would cause issues if left enabled + # runtime logs + log { + format json # set runtime log format to json mode + } + # server options + servers { + trusted_proxies static private_ranges 100.0.0.0/8 # trust railway's proxy + } +} + +# site block, listens on the $PORT environment variable, automatically assigned by railway +:{$PORT:3000} { + # access logs + log { + format json # set access log format to json mode + } + + # health check for railway + rewrite /health /* + + # serve from the 'dist' folder (Vite builds into the 'dist' folder) + root * dist + + # enable gzipping responses + encode gzip + + # serve files from 'dist' + file_server + + # if path doesn't exist, redirect it to 'index.html' for client side routing + try_files {path} /index.html +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3da15c3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,40 @@ +# Use the Node alpine official image +# https://hub.docker.com/_/node +FROM node:lts-alpine AS build + +# Set config +ENV NPM_CONFIG_UPDATE_NOTIFIER=false +ENV NPM_CONFIG_FUND=false + +# Create and change to the app directory. +WORKDIR /app + +# Copy the files to the container image +COPY package*.json ./ + +# Install packages +RUN npm ci + +# Copy local code to the container image. +COPY . ./ + +# Build the app. +RUN npm run build + +# Use the Caddy image +FROM caddy + +# Create and change to the app directory. +WORKDIR /app + +# Copy Caddyfile to the container image. +COPY Caddyfile ./ + +# Copy local code to the container image. +RUN caddy fmt Caddyfile --overwrite + +# Copy files to the container image. +COPY --from=build /app/dist ./dist + +# Use Caddy to run/serve the app +CMD ["caddy", "run", "--config", "Caddyfile", "--adapter", "caddyfile"] \ No newline at end of file diff --git a/src/powersync/System.ts b/src/powersync/System.ts index 9140b5b..5c0fcd7 100644 --- a/src/powersync/System.ts +++ b/src/powersync/System.ts @@ -72,4 +72,4 @@ export const powerSync = new PowerSyncDatabase({ await connector.signInAnonymously(); // Establish connection between PowerSync and the Supabase connector -powerSync.connect(connector, { clientImplementation: SyncClientImplementation.RUST }); +powerSync.connect(connector, { clientImplementation: SyncClientImplementation.RUST }); \ No newline at end of file