diff --git a/README.md b/README.md index d8b8552..a48ec6b 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ A templated Vite, TS, React, PowerSync and Supabase project to get you started quickly with building offline-first applications with PowerSync and Supabase. +🚀 [Live Demo](https://vite-react-ts-powersync-supabase.up.railway.app/) 🚀 + # Usage ## Install dependencies 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 }, + ], + }, }, ]) diff --git a/package-lock.json b/package-lock.json index f7d750a..42c4d83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,9 @@ "name": "vite-react-ts-powersync-supabase", "version": "0.0.0", "dependencies": { - "@journeyapps/wa-sqlite": "^1.3.2", - "@powersync/react": "^1.8.1", - "@powersync/web": "^1.27.1", + "@journeyapps/wa-sqlite": "^1.3.3", + "@powersync/react": "^1.8.2", + "@powersync/web": "^1.29.0", "@supabase/supabase-js": "^2.76.1", "react": "^19.2.0", "react-dom": "^19.2.0", @@ -62,6 +62,7 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -952,10 +953,11 @@ } }, "node_modules/@journeyapps/wa-sqlite": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@journeyapps/wa-sqlite/-/wa-sqlite-1.3.2.tgz", - "integrity": "sha512-zZ0KF01an940DV2jJHHzeTvGlXZ8il/sWnI6a2hH3eV/LHtb5H0c6TB7WursE3c8BvNLifXre3R0mLM5OyNhgw==", - "hasInstallScript": true + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@journeyapps/wa-sqlite/-/wa-sqlite-1.3.3.tgz", + "integrity": "sha512-LwekcI0eSLVwNTt6r5j2GdYfA4aCCRnRmVhnrIRz6Tet8Ih6OPqQ4ae6xYXFBGTpw54jexHqwMcOQFTOOvTNIw==", + "hasInstallScript": true, + "peer": true }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", @@ -1046,33 +1048,35 @@ } }, "node_modules/@powersync/common": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/@powersync/common/-/common-1.40.0.tgz", - "integrity": "sha512-0pJ9UK4Hhunxk0YSWEQ6V0YvjDVVbOv7/GcqmOyZ+vKYzTztnzDA8n+rcbCN1x3NFm69Y5V19yDwuNYoM+MH9A==", + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@powersync/common/-/common-1.43.0.tgz", + "integrity": "sha512-WNllgjVQCLQZ80B97PVJE9y5yCRDag1crFk+J7pNryijA/CCGdvHCI47t3FJxcgMHdE3Cqlr1UVDXvsTyxLuPA==", "license": "Apache-2.0", + "peer": true, "dependencies": { - "js-logger": "^1.6.1" + "async-mutex": "^0.5.0", + "event-iterator": "^2.0.0" } }, "node_modules/@powersync/react": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@powersync/react/-/react-1.8.1.tgz", - "integrity": "sha512-ITrHeXahrsqe1IA6WRoaIGIVYg5gZpDiSNZqjO6jvXoS2hTTYhCShNfn5t38lor9mpooISBjxTFHLy/k7Nh5yQ==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@powersync/react/-/react-1.8.2.tgz", + "integrity": "sha512-15z8JKt66dq2bqX2P7QQ71eUIx3DWLc5WMdB/PDc9MIAHf1SERqKfzbzWGxKplQGHC/GogDA7G8IDoRadhNXOA==", "license": "Apache-2.0", "peerDependencies": { - "@powersync/common": "^1.40.0", + "@powersync/common": "^1.41.1", "react": "*" } }, "node_modules/@powersync/web": { - "version": "1.27.1", - "resolved": "https://registry.npmjs.org/@powersync/web/-/web-1.27.1.tgz", - "integrity": "sha512-O8divcVgBxakBTxW7C6nw57sDGnpZYe9je9kM9C15WSt5jVkzgHQmbZCWjaDz06rVUx8IYUHbcxfneTHJoZKyQ==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@powersync/web/-/web-1.29.0.tgz", + "integrity": "sha512-Yv4GuV7TqD2qympekDOUodMGxCn7haDY5mzESoiChy07SQLr3Ol+X7xQ0z4zFgtmnBjd69QcIuy7oSY9Lo1fIQ==", "license": "Apache-2.0", "dependencies": { - "@powersync/common": "1.40.0", - "async-mutex": "^0.4.0", - "bson": "^6.6.0", + "@powersync/common": "1.43.0", + "async-mutex": "^0.5.0", + "bson": "^6.10.4", "comlink": "^4.4.2", "commander": "^12.1.0" }, @@ -1081,7 +1085,7 @@ }, "peerDependencies": { "@journeyapps/wa-sqlite": "^1.3.2", - "@powersync/common": "^1.40.0" + "@powersync/common": "^1.43.0" } }, "node_modules/@rolldown/pluginutils": { @@ -1535,6 +1539,7 @@ "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -1604,6 +1609,7 @@ "integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/types": "8.46.2", @@ -1856,6 +1862,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1924,9 +1931,9 @@ "license": "Python-2.0" }, "node_modules/async-mutex": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.4.1.tgz", - "integrity": "sha512-WfoBo4E/TbCX1G95XTjbWTE3X2XLG0m1Xbv2cwOtuPdyH9CZvnaA5nCt1ucjaKEgW2A5IF71hxrRhr83Je5xjA==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz", + "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==", "license": "MIT", "dependencies": { "tslib": "^2.4.0" @@ -2010,6 +2017,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.19", "caniuse-lite": "^1.0.30001751", @@ -2284,6 +2292,7 @@ "integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -2462,6 +2471,12 @@ "node": ">=0.10.0" } }, + "node_modules/event-iterator": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/event-iterator/-/event-iterator-2.0.0.tgz", + "integrity": "sha512-KGft0ldl31BZVV//jj+IAIGCxkvvUkkON+ScH6zfoX+l+omX6001ggyRSpI0Io2Hlro0ThXotswCtfzS8UkIiQ==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2799,12 +2814,6 @@ "dev": true, "license": "ISC" }, - "node_modules/js-logger": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/js-logger/-/js-logger-1.6.1.tgz", - "integrity": "sha512-yTgMCPXVjhmg28CuUH8CKjU+cIKL/G+zTu4Fn4lQxs8mRFH/03QTNvEFngcxfg/gRDiQAOoyCKmMTOm9ayOzXA==", - "license": "MIT" - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3264,6 +3273,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -3558,6 +3568,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -3622,6 +3633,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3706,6 +3718,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.12.tgz", "integrity": "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==", "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -3806,6 +3819,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -3926,6 +3940,7 @@ "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "dev": true, "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index aadaf7a..5f549f2 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,9 @@ "type-check": "tsc --noEmit" }, "dependencies": { - "@journeyapps/wa-sqlite": "^1.3.2", - "@powersync/react": "^1.8.1", - "@powersync/web": "^1.27.1", + "@journeyapps/wa-sqlite": "^1.3.3", + "@powersync/react": "^1.8.2", + "@powersync/web": "^1.29.0", "@supabase/supabase-js": "^2.76.1", "react": "^19.2.0", "react-dom": "^19.2.0", diff --git a/src/powersync/System.ts b/src/powersync/System.ts index 9548933..4f43813 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,8 @@ export const powerSync = new PowerSyncDatabase({ await connector.signInAnonymously(); // Establish connection between PowerSync and the Supabase connector -powerSync.connect(connector); +powerSync.connect(connector, { + // Rust based implementation is more efficient and faster than the JavaScript implementation + clientImplementation: SyncClientImplementation.RUST, + crudUploadThrottleMs: 5000 +}); \ No newline at end of file