Skip to content

Commit 688265f

Browse files
authored
Node: Support using node:sqlite and encryption (#690)
1 parent 9c818dc commit 688265f

26 files changed

+1606
-840
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@powersync/node': minor
3+
---
4+
5+
Experimental support for integrating with node:sqlite.

.changeset/khaki-years-design.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@powersync/node': minor
3+
---
4+
5+
Support custom better-sqlite3 forks (see an example for encryption in the README).

.changeset/wet-cooks-dress.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@powersync/node': minor
3+
---
4+
5+
Use upstream better-sqlite3 dependency instead of the PowerSync fork.
6+
7+
After upgrading:
8+
9+
1. Ensure you no longer depend on the `@powersync/better-sqlite3` package: `npm uninstall @powersync/better-sqlite3`.
10+
2. Unlike in older versions, the upstream `better-sqlite3` dependency is marked as optional since custom forks
11+
are supported too.
12+
Use `npm install better-sqlite3` to install it.

demos/example-electron-node/config.ts

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import OS from 'node:os';
22
import path from 'node:path';
3-
import { createRequire } from 'node:module';
43

54
import type { ForgeConfig } from '@electron-forge/shared-types';
65
import { MakerSquirrel } from '@electron-forge/maker-squirrel';
@@ -14,7 +13,7 @@ import * as dotenv from 'dotenv';
1413
import type IForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
1514
import type ICopyPlugin from 'copy-webpack-plugin';
1615

17-
dotenv.config({path: '.env.local'});
16+
dotenv.config({ path: '.env.local' });
1817

1918
const ForkTsCheckerWebpackPlugin: typeof IForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
2019
const CopyPlugin: typeof ICopyPlugin = require('copy-webpack-plugin');
@@ -78,25 +77,27 @@ const mainConfig: Configuration = {
7877
entry: './src/main/index.ts',
7978
// Put your normal webpack config below here
8079
module: {
81-
rules: defaultWebpackRules(),
80+
rules: defaultWebpackRules()
8281
},
8382
plugins: [
8483
...webpackPlugins,
8584
new CopyPlugin({
86-
patterns: [{
87-
from: path.resolve(require.resolve('@powersync/node/package.json'), `../lib/${extensionPath}`),
88-
to: path.join('powersync', extensionPath),
89-
}],
85+
patterns: [
86+
{
87+
from: path.resolve(require.resolve('@powersync/node/package.json'), `../lib/${extensionPath}`),
88+
to: path.join('powersync', extensionPath)
89+
}
90+
]
9091
}),
9192
new DefinePluginImpl({
9293
POWERSYNC_URL: JSON.stringify(process.env.POWERSYNC_URL),
93-
POWERSYNC_TOKEN: JSON.stringify(process.env.POWERSYNC_TOKEN),
94-
}),
94+
POWERSYNC_TOKEN: JSON.stringify(process.env.POWERSYNC_TOKEN)
95+
})
9596
],
9697
resolve: {
9798
extensions: ['.js', '.ts', '.jsx', '.tsx', '.css', '.json']
9899
},
99-
target: "electron-main",
100+
target: 'electron-main'
100101
};
101102

102103
const rendererConfig: Configuration = {
@@ -107,7 +108,7 @@ const rendererConfig: Configuration = {
107108
test: /\.css$/,
108109
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }]
109110
}
110-
],
111+
]
111112
},
112113
plugins: webpackPlugins,
113114
resolve: {
@@ -119,10 +120,10 @@ const config: ForgeConfig = {
119120
packagerConfig: {
120121
asar: {
121122
unpack: '**/{.**,**}/**/powersync/*'
122-
},
123+
}
123124
},
124125
rebuildConfig: {
125-
force: true,
126+
force: true
126127
},
127128
makers: [
128129
new MakerSquirrel(),
@@ -142,7 +143,7 @@ const config: ForgeConfig = {
142143
html: './src/render/index.html',
143144
js: './src/render/main.ts',
144145
preload: {
145-
js: './src/render/preload.ts',
146+
js: './src/render/preload.ts'
146147
}
147148
}
148149
]

demos/example-electron-node/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@
2323
"@electron-forge/maker-zip": "^7.7.0",
2424
"@electron-forge/plugin-auto-unpack-natives": "^7.7.0",
2525
"@electron-forge/plugin-webpack": "^7.7.0",
26+
"@types/better-sqlite3": "^7.6.13",
2627
"@vercel/webpack-asset-relocator-loader": "1.7.3",
2728
"copy-webpack-plugin": "^13.0.0",
2829
"css-loader": "^6.11.0",
2930
"dotenv": "^16.4.7",
30-
"electron": "30.0.2",
31+
"electron": "37.0.0",
3132
"electron-rebuild": "^3.2.9",
3233
"fork-ts-checker-webpack-plugin": "^9.0.2",
3334
"node-loader": "^2.1.0",
@@ -40,6 +41,7 @@
4041
},
4142
"dependencies": {
4243
"@powersync/node": "workspace:*",
44+
"better-sqlite3": "^12.2.0",
4345
"electron-squirrel-startup": "^1.0.1"
4446
}
4547
}

demos/example-electron-node/src/main/worker.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as path from 'node:path';
22
import OS from 'node:os';
3+
import Database from 'better-sqlite3';
34

45
import { startPowerSyncWorker } from '@powersync/node/worker.js';
56

@@ -28,4 +29,8 @@ function resolvePowerSyncCoreExtension() {
2829
return libraryPath;
2930
}
3031

31-
startPowerSyncWorker({ extensionPath: resolvePowerSyncCoreExtension });
32+
async function resolveBetterSqlite3() {
33+
return Database;
34+
}
35+
36+
startPowerSyncWorker({ extensionPath: resolvePowerSyncCoreExtension, loadBetterSqlite3: resolveBetterSqlite3 });

demos/example-node/.env

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
BACKEND=http://localhost:6060
22
SYNC_SERVICE=http://localhost:8080
33
POWERSYNC_TOKEN=
4-
POWERSYNC_DEBUG=1
4+
POWERSYNC_DEBUG=1
5+
ENCRYPTION_KEY=

demos/example-node/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ Results from the query are printed every time it changes. Try:
1515
1. Updating a row in the backend database and see changes reflected in the running client.
1616
2. Enter `add('my list')` and see the new list show up in the backend database.
1717

18+
## Encryption
19+
20+
This demo can use encrypted databases with the `better-sqlite3-multiple-ciphers` package.
21+
To test encryption, set the `ENCRYPTION_KEY` in `.env` to a non-empty value.
22+
23+
## References
24+
1825
For more details, see the documentation for [the PowerSync node package](https://docs.powersync.com/client-sdk-references/node) and check other examples:
1926

2027
- [example-electron-node](../example-electron-node/): An Electron example that runs PowerSync in the main process using the Node.js SDK.

demos/example-node/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111
},
1212
"dependencies": {
1313
"@powersync/node": "workspace:*",
14+
"better-sqlite3": "^12.2.0",
15+
"better-sqlite3-multiple-ciphers": "^12.2.0",
1416
"dotenv": "^16.4.7",
1517
"undici": "^7.11.0"
1618
},
1719
"devDependencies": {
20+
"@types/better-sqlite3": "^7.6.13",
1821
"ts-node": "^10.9.2",
1922
"typescript": "^5.8.2"
2023
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// This worker uses bindings to sqlite3 multiple ciphers instead of the original better-sqlite3 worker.
2+
//
3+
// It is used in main.ts only when an encryption key is set.
4+
import Database from 'better-sqlite3-multiple-ciphers';
5+
6+
import { startPowerSyncWorker } from '@powersync/node/worker.js';
7+
8+
async function resolveBetterSqlite3() {
9+
return Database;
10+
}
11+
12+
startPowerSyncWorker({ loadBetterSqlite3: resolveBetterSqlite3 });

0 commit comments

Comments
 (0)