Skip to content
Open
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
17 changes: 17 additions & 0 deletions client-sdks/advanced/sqlite-extensions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,27 @@ To link additional extensions, you could add similar build script additions to c

Similar to Dart on the web, loading extensions with `@powersync/web` is only possible with a custom `wa-sqlite` WebAssembly build. PowerSync [forks wa-sqlite](https://github.com/powersync-ja/wa-sqlite) for this reason, loading custom extension requires patching build definitions in that repository and adding an override from your npm package manager to patch `@journeyapps/wa-sqlite`.

When you build a custom module, pin the SQLite, wa-sqlite, PowerSync core and Emscripten versions. Compile the extension into the module and register it before opening databases, for example with `sqlite3_auto_extension()`. Keep the PowerSync core extension in the build.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, "Keep the PowerSync core extension in the build." is kind of implied when we tell users to fork and override @journeyapps/wa-sqlite?


Deploy the generated JavaScript and WebAssembly files together. PowerSync's prebuilt database worker already contains wa-sqlite JavaScript, so a package override alone does not update that worker. Rebuild your database worker against the custom package and configure the SDK to use that worker. Use versioned asset filenames so a cached worker cannot load a module from a different build.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PowerSync's prebuilt database worker

FWIW, we typically rely on vite to recognize the worker as an entrypoint and bundle it, so a dependency override on wa-sqlite should actually work. Are you using react native web for this to be relevant?


Before running queries that need the extension, probe the actual PowerSync connection. For SQLite's decimal extension, this query checks scalar and aggregate functions:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the existence of decimal_cmp alone proof of the extension being bundled? I don't think we should recommend testing it.


```sql
SELECT decimal_cmp('007.5', '7.25') AS comparison,
decimal_sub('1000.00', '0.01') AS difference,
decimal_sum(amount) AS total
FROM (SELECT '9007199254740993.01' AS amount UNION ALL SELECT '-0.01');
```

The expected result is `1`, `'999.99'` and `'9007199254740993.00'`. Run the probe for each database instance, including connections opened in workers or background tasks. If you support older builds without the extension, select a compatible query before preparing SQL that calls the missing functions.

### React Native

The recommended OP-SQLite library has builtin support for custom extensions, and [excellent documentation](https://op-engineering.github.io/op-sqlite/docs/api#loading-extensions) on how to build and bundle them with your app.

For a statically linked extension, initialize it on each SQLite connection or register it with `sqlite3_auto_extension()` before creating connections. If you use SQLCipher, preserve its existing initialization hook. Adding native code requires a new native app build; a JavaScript-only update cannot add the extension to an installed binary.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that it complicates things, we should probably not recommend static extensions on native platforms (it's a different story on the web because dynamic loading isn't really a thing with wasm).


### Node.js

Loading extensions is possible with `better-sqlite3` and the [`loadExtension`](https://github.com/WiseLibs/better-sqlite3/blob/HEAD/docs/api.md#loadextensionpath-entrypoint---this) method on databases.
Expand Down