Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/bright-beans-dream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@powersync/capacitor': patch
'@powersync/nuxt': patch
'@powersync/web': patch
---

Make `@journeyapps/wa-sqlite` a regular dependency instead of a dev-dependency.
When upgrading, you can remove that package from your dependencies if you don't import it directly in your project.
12 changes: 12 additions & 0 deletions .changeset/core-extension-0-5-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'@powersync/web': patch
'@powersync/adapter-sql-js': patch
'@powersync/node': patch
'@powersync/react-native': patch
'@powersync/shared-internals': patch
'@powersync/tauri-plugin': patch
'@powersync/nuxt': patch
'tauri-plugin-powersync': patch
---

Update PowerSync SQLite core extension to version 0.5.2.
1 change: 0 additions & 1 deletion demos/angular-supabase-todolist/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
"@angular/platform-browser-dynamic": "^19.2.4",
"@angular/router": "^19.2.4",
"@angular/service-worker": "^19.2.4",
"@journeyapps/wa-sqlite": "^1.7.0",
"@powersync/web": "^2.0.0",
"@supabase/supabase-js": "^2.44.4",
"rxjs": "~7.8.1",
Expand Down
1 change: 0 additions & 1 deletion demos/example-capacitor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
"@capacitor/core": "^8.0.0",
"@capacitor/ios": "^8.0.0",
"@capacitor/splash-screen": "^8.0.0",
"@journeyapps/wa-sqlite": "^1.7.0",
"@powersync/capacitor": "^0.8.0",
"@powersync/react": "^2.0.0",
"@powersync/web": "^2.0.0",
Expand Down
1 change: 0 additions & 1 deletion demos/example-electron/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
"dependencies": {
"@emotion/react": "^11.13.0",
"@emotion/styled": "^11.13.0",
"@journeyapps/wa-sqlite": "^1.7.0",
"@mui/icons-material": "^5.15.16",
"@mui/material": "^5.15.16",
"@mui/x-data-grid": "^6.19.11",
Expand Down
1 change: 0 additions & 1 deletion demos/example-nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"test:build": "pnpm build"
},
"dependencies": {
"@journeyapps/wa-sqlite": "^1.7.0",
"@powersync/react": "^2.0.0",
"@powersync/web": "^2.0.0",
"@tailwindcss/postcss": "^4.2.2",
Expand Down
1 change: 0 additions & 1 deletion demos/example-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
"test:build": "pnpm build && vitest run"
},
"dependencies": {
"@journeyapps/wa-sqlite": "^1.7.0",
"@powersync/web": "^2.0.0"
},
"devDependencies": {
Expand Down
1 change: 0 additions & 1 deletion demos/react-multi-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"test:build": "pnpm build"
},
"dependencies": {
"@journeyapps/wa-sqlite": "^1.7.0",
"@powersync/react": "^2.0.0",
"@powersync/web": "^2.0.0",
"@supabase/supabase-js": "^2.43.1",
Expand Down
1 change: 0 additions & 1 deletion demos/react-native-web-supabase-todolist/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"@dr.pogodin/react-native-fs": "2.37.0",
"@expo/metro-runtime": "~57.0.2",
"@expo/vector-icons": "^15.1.1",
"@journeyapps/wa-sqlite": "^1.7.0",
"@op-engineering/op-sqlite": "^17.0.0",
"@powersync/attachments-storage-react-native": "^0.0.3",
"@powersync/common": "^2.0.0",
Expand Down
1 change: 0 additions & 1 deletion demos/react-neon-tanstack-query-notes/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"db:generate": "drizzle-kit generate"
},
"dependencies": {
"@journeyapps/wa-sqlite": "^1.7.0",
"@neondatabase/neon-js": "^0.1.0-alpha.6",
"@neondatabase/serverless": "^1.0.2",
"@powersync/drizzle-driver": "^0.8.0",
Expand Down
1 change: 0 additions & 1 deletion demos/react-supabase-time-based-sync/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
"@powersync/web": "^2.0.0",
"@emotion/react": "11.11.4",
"@emotion/styled": "11.11.5",
"@journeyapps/wa-sqlite": "^1.7.0",
"@mui/icons-material": "^5.15.12",
"@mui/material": "^5.15.12",
"@supabase/supabase-js": "^2.39.7",
Expand Down
1 change: 0 additions & 1 deletion demos/react-supabase-todolist-optional-sync/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"@powersync/web": "^2.0.0",
"@emotion/react": "11.11.4",
"@emotion/styled": "11.11.5",
"@journeyapps/wa-sqlite": "^1.7.0",
"@mui/icons-material": "^5.15.12",
"@mui/material": "^5.15.12",
"@mui/x-data-grid": "^6.19.6",
Expand Down
1 change: 0 additions & 1 deletion demos/react-supabase-todolist-sync-streams/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"@powersync/web": "^2.0.0",
"@emotion/react": "11.11.4",
"@emotion/styled": "11.11.5",
"@journeyapps/wa-sqlite": "^1.7.0",
"@mui/icons-material": "^5.15.12",
"@mui/material": "^5.15.12",
"@mui/x-data-grid": "^6.19.6",
Expand Down
1 change: 0 additions & 1 deletion demos/react-supabase-todolist-tanstackdb/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"dependencies": {
"@emotion/react": "11.11.4",
"@emotion/styled": "11.11.5",
"@journeyapps/wa-sqlite": "^1.7.0",
"@mui/icons-material": "^5.15.12",
"@mui/material": "^5.15.12",
"@mui/x-data-grid": "^6.19.6",
Expand Down
1 change: 0 additions & 1 deletion demos/react-supabase-todolist/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"@powersync/web": "^2.0.0",
"@emotion/react": "11.11.4",
"@emotion/styled": "11.11.5",
"@journeyapps/wa-sqlite": "^1.7.0",
"@mui/icons-material": "^5.15.12",
"@mui/material": "^5.15.12",
"@mui/x-data-grid": "^6.19.6",
Expand Down
1 change: 0 additions & 1 deletion demos/yjs-react-supabase-text-collab/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
"dependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@journeyapps/wa-sqlite": "^1.7.0",
"@mui/material": "^5.15.12",
"@mui/x-data-grid": "^6.19.6",
"@powersync/react": "^2.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/adapter-sql-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"@powersync/shared-internals": "workspace:*"
},
"devDependencies": {
"@powersync/sql-js": "0.0.9",
"@powersync/sql-js": "0.0.11",
"@powersync/web": "workspace:*",
"@rollup/plugin-alias": "catalog:",
"@rollup/plugin-commonjs": "catalog:",
Expand Down
63 changes: 23 additions & 40 deletions packages/adapter-sql-js/src/SQLJSAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import {
BaseObserver,
BaseListener,
BatchedUpdateNotification,
createConsoleLogger,
DBAdapter,
Expand Down Expand Up @@ -42,32 +40,13 @@ export class SQLJSOpenFactory implements SQLOpenFactory {
}
}

(globalThis as any).onSqliteUpdate = (
dbP: number,
operation: string,
database: string,
table: string,
rowId: number
) => {
SQLJSDBAdapter.sharedObserver.iterateListeners((l) => l.tablesUpdated?.(dbP, operation, database, table, rowId));
};

interface TableObserverListener extends BaseListener {
tablesUpdated?: (dpP: number, operation: string, database: string, table: string, rowId: number) => void;
}
class TableObserver extends BaseObserver<TableObserverListener> {}

export class SQLJSDBAdapter extends DBAdapter {
protected initPromise: Promise<SQLJs.Database>;
protected _db: SQLJs.Database | null;
protected tableUpdateCache: Set<string>;
protected dbP: number | null;
protected writeScheduler: ControlledExecutor<SQLJs.Database>;
protected options: ResolvedSQLJSOpenOptions;

static sharedObserver = new TableObserver();
protected disposeListener: () => void;

protected mutex: Mutex;

protected getDB(): Promise<SQLJs.Database> {
Expand All @@ -83,25 +62,19 @@ export class SQLJSDBAdapter extends DBAdapter {
this.options = this.resolveOptions(options);
this.initPromise = this.init();
this._db = null;
this.tableUpdateCache = new Set<string>();
this.mutex = new Mutex();
this.dbP = null;
this.disposeListener = SQLJSDBAdapter.sharedObserver.registerListener({
tablesUpdated: (dbP: number, operation: string, database: string, table: string, rowId: number) => {
if (this.dbP !== dbP) {
// Ignore updates from other databases.
return;
}
this.tableUpdateCache.add(table);
}
});

this.writeScheduler = new ControlledExecutor(async (db: SQLJs.Database) => {
if (!this.options.persister) {
const persister = this.options.persister;
if (!persister) {
return;
}

await this.options.persister.writeFile(db.export());
const blob = db.export();
// Calling export() closes and re-opens the database, so we need to re-install update hooks.
this.setup(db);
await persister.writeFile(blob);
});
}

Expand All @@ -128,12 +101,16 @@ export class SQLJSDBAdapter extends DBAdapter {
const db = new SQL.Database(existing);
this.dbP = (db as any)['db'] as number;
this._db = db;
this.setup(db);
return db;
}

private setup(db: SQLJs.Database) {
db.exec("SELECT powersync_update_hooks('install')");
}

async close() {
const db = await this.getDB();
this.disposeListener();
db.close();
}

Expand All @@ -147,18 +124,24 @@ export class SQLJSDBAdapter extends DBAdapter {
writeLock<T>(fn: (tx: LockContext) => Promise<T>, options?: DBLockOptions): Promise<T> {
return this.mutex.runExclusive(async () => {
const db = await this.getDB();
const result = await fn(new SqlJsLockContext(db));
const context = new SqlJsLockContext(db);
const result = await fn(context);

const { rawRows: rawUpdates } = await context.executeRaw("SELECT powersync_update_hooks('get')");
const updatedTables = JSON.parse(rawUpdates[0][0] as string);

if (updatedTables.length) {
const notification: BatchedUpdateNotification = {
tables: updatedTables
};
this.iterateListeners((l) => l.tablesUpdated?.(notification));
}

// No point to schedule a write if there's no persister.
if (this.options.persister) {
this.writeScheduler.schedule(db);
}

const notification: BatchedUpdateNotification = {
tables: Array.from(this.tableUpdateCache)
};
this.tableUpdateCache.clear();
this.iterateListeners((l) => l.tablesUpdated?.(notification));
return result;
}, timeoutSignal(options?.timeoutMs));
}
Expand Down
2 changes: 1 addition & 1 deletion packages/capacitor/PowersyncCapacitor.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Pod::Spec.new do |s|
s.ios.deployment_target = '15.0'
s.dependency 'Capacitor'
s.swift_version = '5.1'
s.dependency "powersync-sqlite-core", "~> 0.4.12"
s.dependency "powersync-sqlite-core", "~> 0.5.2"
s.xcconfig = {
'OTHER_CFLAGS' => '$(inherited) -DSQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION=1',
'HEADER_SEARCH_PATHS' => '$(inherited) "$(PODS_ROOT)/SQLCipher"'
Expand Down
2 changes: 1 addition & 1 deletion packages/capacitor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ This package uses `@powersync/web` as a peer dependency. For additional `@powers
You must also install the following peer dependencies:

```bash
npm install @capacitor-community/sqlite @powersync/web @journeyapps/wa-sqlite
npm install @capacitor-community/sqlite @powersync/web
```

See the [Capacitor Community SQLite](https://github.com/capacitor-community/sqlite?tab=readme-ov-file#installation) repository for additional instructions.
Expand Down
2 changes: 1 addition & 1 deletion packages/capacitor/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ ext {
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.1'
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.3.0'
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.7.0'
powerSyncCoreVersion = project.hasProperty('powerSyncCoreVersion') ? rootProject.ext.powerSyncCoreVersion : '0.4.12'
powerSyncCoreVersion = project.hasProperty('powerSyncCoreVersion') ? rootProject.ext.powerSyncCoreVersion : '0.5.2'
}

buildscript {
Expand Down
22 changes: 11 additions & 11 deletions packages/node/download_core.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ import { Readable } from 'node:stream';
import { finished } from 'node:stream/promises';

// When changing this version, run node download_core.js update_hashes
const version = '0.4.12';
const version = '0.5.2';
const versionHashes = {
'powersync_x64.dll': 'efc095c2dff5194c1dbf4943012ae8bb5349e8aaac481d18cb0d3a49fa6a1255',
'powersync_x86.dll': '147ef50acdab8dc27075f29ae6f86dd26fb574f373e3a186492ca7d55d0b867c',
'powersync_aarch64.dll': '90fbce6a22bc7fcde0ee62ed52eec821afa86b1bacff4597ddc9cea2f7203cb1',
'libpowersync_x86.linux.so': '89b8b7451a01e533a5736a7025d13f0bd0640c1df40025cf8a90d6d2e7e8b1ee',
'libpowersync_x64.linux.so': 'c15d5a069200c823c95435bbad38a9dc12743deca42b30b0c40557b2bc32ac5d',
'libpowersync_aarch64.linux.so': 'acbf2a1b27f413d8a83e5efc91f0531c6989519203eaf2814c52942f1a445649',
'libpowersync_armv7.linux.so': 'e262fcf4c1509d96a692f159af572a09fad781d4cc3ba885d3de276926526432',
'libpowersync_riscv64gc.linux.so': '46101c885b4ff23e4a7059a5eb9f3fc697762455e6d296815a8ccece8eeacd41',
'libpowersync_x64.macos.dylib': 'e0b2402702bd744d65a2c8aba4d7242f5cefd67c33926d92567ee4e02b13e20d',
'libpowersync_aarch64.macos.dylib': 'cfbfa86a0b8203619059be4bf4cf3078f122866dcc4896b07f7b412a41628abe'
'powersync_x64.dll': '95b1aa81b5307793fcf5ef4d0982f38076e14cdd7b97ea1a84faa545af0b74db',
'powersync_x86.dll': '215d4aa2a08972dea7cbc91c316c111c2968ec47bd40865a78237b649d8d2e9a',
'powersync_aarch64.dll': '42a66fff06b2c927c60c78941ff8c069ad878761a46802a13dc33b9d503f6589',
'libpowersync_x86.linux.so': '3be78268b546796c5e8983d37b3c4b28e2c6d2a5c4ec21757164c0d6b7bc11f8',
'libpowersync_x64.linux.so': 'e3288d3e1e2bfc5ccee4fb66d5afb9c691e7da7010b3a561892857a922659819',
'libpowersync_aarch64.linux.so': '50817891679aa5598009119aa6cf00561e28c04078c6045c109281cf32bcf747',
'libpowersync_armv7.linux.so': 'c0028d3536fdd8684c6be20988d7edf91eb290da0b53a6f3b6752c3f0462daa7',
'libpowersync_riscv64gc.linux.so': 'c636d46f0e591953e37e306efd8c055b44216fb019733cbdae718d70387b6042',
'libpowersync_x64.macos.dylib': '53359ad66f31160795cf2728b1125567593bb00bd62197372fca8e461040abce',
'libpowersync_aarch64.macos.dylib': 'a3a37b9f346a7d12717149209f01c5f580a2ee3471b37bcdfa59a324834fd698'
};

const assets = Object.keys(versionHashes);
Expand Down
2 changes: 1 addition & 1 deletion packages/node/tests/sync.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ describe('Sync', () => {

// Replicate what we'd see on the web when switching connections in the shared sync worker: The sync client would
// suddenly see a database without an active sync iteration.
await database.execute('SELECT powersync_control(?, null)', ['stop']);
await database.writeTransaction((tx) => tx.execute('SELECT powersync_control(?, null)', ['stop']));
(database as BasePowerSyncDatabase).syncStreamImplementation!.markConnectionMayHaveChanged();
await database.waitForStatus((s) => !s.connected);
await vi.waitFor(() => expect(syncService.connectedListeners).toHaveLength(1));
Expand Down
1 change: 0 additions & 1 deletion packages/nuxt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@
"bson": "catalog:"
},
"peerDependencies": {
"@journeyapps/wa-sqlite": "^1.7.0",
"@powersync/kysely-driver": "workspace:^2.0.0",
"@powersync/vue": "workspace:^0.6.0",
"@powersync/web": "workspace:^2.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { ref, computed, readonly, onMounted, onUnmounted } from 'vue';
import { computedAsync } from '@vueuse/core';
import { usePowerSyncInspector } from './usePowerSyncInspector';
import type { NuxtDatabaseImplementation } from '../utils/NuxtPowerSyncDatabase';
import { SyncStatusSnapshot } from '@powersync/shared-internals';

// queries
const BUCKETS_QUERY = `
Expand Down Expand Up @@ -308,17 +309,21 @@ export function usePowerSyncInspectorDiagnostics(): UsePowerSyncInspectorDiagnos

async function refreshState() {
if (db.value) {
const { synced_at } = await db.value.get<{ synced_at: string | null }>(
'SELECT powersync_last_synced_at() as synced_at'
// FIXME: This relies on internal core extension APIs, why can't this use the
// current sync status?
const { status: rawStatus } = await db.value.get<{ status: string }>(
'SELECT powersync_offline_sync_status() as status'
);
const status = new SyncStatusSnapshot(JSON.parse(rawStatus), null);
const hasSyned = status.hasSynced;

uploadQueueStats.value = await db.value?.getUploadQueueStats(true);
uploadQueueStats.value = await db.value.getUploadQueueStats(true);

if (synced_at != null && !syncStatus.value?.downloading) {
if (hasSyned && !syncStatus.value.downloading) {
// These are potentially expensive queries - do not run during initial sync
bucketRows.value = await db.value.getAll(BUCKETS_QUERY);
tableRows.value = await db.value.getAll(TABLES_QUERY);
} else if (synced_at != null) {
} else if (hasSyned) {
// Busy downloading, but have already synced once
bucketRows.value = await db.value.getAll(BUCKETS_QUERY_FAST);
// Load tables if we haven't yet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ describe('usePowerSyncInspectorDiagnostics', () => {

// Verify refreshState was called (it queries synced_at and bucket data)
const getCalls = getSpy.mock.calls;
const hasSyncedAtQuery = getCalls.some((call) => call[0]?.includes('powersync_last_synced_at'));
expect(hasSyncedAtQuery).toBe(true);
const hasStatusQuery = getCalls.some((call) => call[0]?.includes('powersync_offline_sync_status'));
expect(hasStatusQuery).toBe(true);
});

it('should trigger refreshState when onChangeWithCallback fires', async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ repositories {
def kotlin_version = getExtOrDefault("kotlinVersion")

dependencies {
implementation 'com.powersync:powersync-sqlite-core:0.4.12'
implementation 'com.powersync:powersync-sqlite-core:0.5.2'
// For < 0.71, this will be from the local maven repo
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
//noinspection GradleDynamicVersion
Expand Down
Loading
Loading