diff --git a/.changeset/serious-rice-buy.md b/.changeset/serious-rice-buy.md
new file mode 100644
index 000000000..aefcd913d
--- /dev/null
+++ b/.changeset/serious-rice-buy.md
@@ -0,0 +1,5 @@
+---
+'@powersync/node': minor
+---
+
+Initial version
diff --git a/README.md b/README.md
index 68c46913d..51ed617ec 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,10 @@ _[PowerSync](https://www.powersync.com) is a sync engine for building local-firs
- JS Web SDK implementation (extension of `packages/common`)
+- [packages/node](./packages/node/README.md)
+
+ - Node.js client implementation (extension of `packages/common`)
+
- [packages/react](./packages/react/README.md)
- React integration for PowerSync.
@@ -80,6 +84,10 @@ Demo applications are located in the [`demos/`](./demos/) directory. Also see ou
- [demos/example-capacitor](./demos/example-capacitor/README.md) A Capacitor example app using the PowerSync Web SDK.
+### Node
+
+- [demos/example-node](./demos/example-node/README.md) A small CLI example built using the PowerSync SDK for Node.js.
+
## Tools
- [tools/diagnostics-app](./tools/diagnostics-app): A standalone web app that presents stats about a user's local database (incl. tables and sync buckets).
diff --git a/demos/example-node/.env b/demos/example-node/.env
new file mode 100644
index 000000000..170d91d37
--- /dev/null
+++ b/demos/example-node/.env
@@ -0,0 +1,2 @@
+BACKEND=http://localhost:6060
+SYNC_SERVICE=http://localhost:8080
diff --git a/demos/example-node/README.md b/demos/example-node/README.md
new file mode 100644
index 000000000..85b16e181
--- /dev/null
+++ b/demos/example-node/README.md
@@ -0,0 +1,16 @@
+## Node.js Demo
+
+This demonstrates a small Node.js client opening a database and connecting PowerSync.
+
+This demo is configured to talk to an example backend [you can host yourself](https://github.com/powersync-ja/self-host-demo). To get started:
+
+1. Start one of the Node.js backend examples from [the self-host-demo repository](https://github.com/powersync-ja/self-host-demo).
+2. If necessary, change `.env` to point to the started backend and sync service.
+3. Run `pnpm install` and `pnpm build:packages` in the root of this repo.
+4. In this directory, run `pnpm run start`.
+
+This opens the local database, connects to PowerSync, waits for a first sync and then runs a simple query.
+Results from the query are printed every time it changes. Try:
+
+1. Updating a row in the backend database and see changes reflected in the running client.
+2. Enter `add('my list')` and see the new list show up in the backend database.
diff --git a/demos/example-node/package.json b/demos/example-node/package.json
new file mode 100644
index 000000000..cdabd63ce
--- /dev/null
+++ b/demos/example-node/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "example-node",
+ "version": "1.0.0",
+ "description": "",
+ "type": "module",
+ "private": true,
+ "scripts": {
+ "build": "tsc -b",
+ "watch": "tsc -b -w",
+ "start": "node --loader ts-node/esm -r dotenv/config src/main.ts"
+ },
+ "dependencies": {
+ "@powersync/node": "workspace:*",
+ "dotenv": "^16.4.7"
+ },
+ "devDependencies": {
+ "ts-node": "^10.9.2",
+ "typescript": "^5.8.2"
+ }
+}
diff --git a/demos/example-node/src/main.ts b/demos/example-node/src/main.ts
new file mode 100644
index 000000000..04e13dedd
--- /dev/null
+++ b/demos/example-node/src/main.ts
@@ -0,0 +1,65 @@
+import repl_factory from 'node:repl';
+import { once } from 'node:events';
+
+import { PowerSyncDatabase, SyncStreamConnectionMethod } from '@powersync/node';
+import Logger from 'js-logger';
+import { AppSchema, DemoConnector } from './powersync.js';
+import { exit } from 'node:process';
+
+const main = async () => {
+ Logger.useDefaults({ defaultLevel: Logger.WARN });
+
+ if (!('BACKEND' in process.env) || !('SYNC_SERVICE' in process.env)) {
+ console.warn(
+ 'Set the BACKEND and SYNC_SERVICE environment variables to point to a sync service and a running demo backend.'
+ );
+ return;
+ }
+
+ const db = new PowerSyncDatabase({
+ schema: AppSchema,
+ database: {
+ dbFilename: 'test.db'
+ },
+ logger: Logger
+ });
+ console.log(await db.get('SELECT powersync_rs_version();'));
+
+ await db.connect(new DemoConnector(), { connectionMethod: SyncStreamConnectionMethod.HTTP });
+ await db.waitForFirstSync();
+ console.log('First sync complete!');
+
+ let hasFirstRow: ((value: any) => void) | null = null;
+ const firstRow = new Promise((resolve) => (hasFirstRow = resolve));
+ const watchLists = async () => {
+ for await (const rows of db.watch('SELECT * FROM lists')) {
+ if (hasFirstRow) {
+ hasFirstRow(null);
+ hasFirstRow = null;
+ }
+ console.log('Has todo lists', rows.rows?._array);
+ }
+ };
+
+ watchLists();
+ await firstRow;
+
+ console.log('Connected to PowerSync. Try updating the lists in the database and see it reflected here.');
+ console.log("To upload a list here, enter `await add('name of new list');`");
+
+ const repl = repl_factory.start();
+ repl.context.add = async (name: string) => {
+ await db.execute(
+ "INSERT INTO lists (id, created_at, name, owner_id) VALUEs (uuid(), datetime('now'), ?, uuid());",
+ [name]
+ );
+ };
+
+ await once(repl, 'exit');
+ console.log('shutting down');
+ await db.disconnect();
+ await db.close();
+ exit(0);
+};
+
+await main();
diff --git a/demos/example-node/src/powersync.ts b/demos/example-node/src/powersync.ts
new file mode 100644
index 000000000..ee36a8e9f
--- /dev/null
+++ b/demos/example-node/src/powersync.ts
@@ -0,0 +1,77 @@
+import { AbstractPowerSyncDatabase, column, PowerSyncBackendConnector, Schema, Table } from '@powersync/node';
+
+export class DemoConnector implements PowerSyncBackendConnector {
+ async fetchCredentials() {
+ const response = await fetch(`${process.env.BACKEND}/api/auth/token`);
+ if (response.status != 200) {
+ throw 'Could not fetch token';
+ }
+
+ const { token } = await response.json();
+
+ return {
+ endpoint: process.env.SYNC_SERVICE!,
+ token: token
+ };
+ }
+
+ async uploadData(database: AbstractPowerSyncDatabase) {
+ const batch = await database.getCrudBatch();
+ if (batch == null) {
+ return;
+ }
+
+ const entries: any[] = [];
+ for (const op of batch.crud) {
+ entries.push({
+ table: op.table,
+ op: op.op,
+ id: op.id,
+ data: op.opData
+ });
+ }
+
+ const response = await fetch(`${process.env.BACKEND}/api/data/`, {
+ method: 'POST',
+ headers: {'Content-Type': 'application/json'},
+ body: JSON.stringify({batch: entries}),
+ });
+ if (response.status !== 200) {
+ throw new Error(`Server returned HTTP ${response.status}: ${await response.text()}`);
+ }
+
+ await batch?.complete();
+ }
+}
+
+export const LIST_TABLE = 'lists';
+export const TODO_TABLE = 'todos';
+
+const todos = new Table(
+ {
+ list_id: column.text,
+ created_at: column.text,
+ completed_at: column.text,
+ description: column.text,
+ created_by: column.text,
+ completed_by: column.text,
+ completed: column.integer,
+ photo_id: column.text
+ },
+ { indexes: { list: ['list_id'] } }
+);
+
+const lists = new Table({
+ created_at: column.text,
+ name: column.text,
+ owner_id: column.text
+});
+
+export const AppSchema = new Schema({
+ lists,
+ todos
+});
+
+export type Database = (typeof AppSchema)['types'];
+export type TodoRecord = Database['todos'];
+export type ListRecord = Database['lists'];
diff --git a/demos/example-node/tsconfig.json b/demos/example-node/tsconfig.json
new file mode 100644
index 000000000..9d2259b00
--- /dev/null
+++ b/demos/example-node/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "extends": "../../tsconfig.base",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "rootDir": "src",
+ "outDir": "lib",
+ "strictNullChecks": true
+ },
+ "references": [
+ {
+ "path": "../../packages/node"
+ }
+ ]
+}
diff --git a/docs/utils/packageMap.ts b/docs/utils/packageMap.ts
index 01b83fed0..daf9aab1c 100644
--- a/docs/utils/packageMap.ts
+++ b/docs/utils/packageMap.ts
@@ -6,7 +6,8 @@ enum Packages {
VueSdk = 'vue-sdk',
AttachmentsSdk = 'attachments-sdk',
WebSdk = 'web-sdk',
- TanstackReactQuerySdk = 'tanstack-react-query-sdk'
+ TanstackReactQuerySdk = 'tanstack-react-query-sdk',
+ NodeSdk = 'node-sdk',
}
interface Package {
@@ -63,5 +64,12 @@ export const packageMap: PackageMap = {
entryPoints: ['../packages/attachments/src/index.ts'],
tsconfig: '../packages/attachments/tsconfig.json',
id: Packages.AttachmentsSdk
- }
+ },
+ [Packages.NodeSdk]: {
+ name: 'Node SDK',
+ dirName: Packages.NodeSdk,
+ entryPoints: ['../packages/node/src/index.ts'],
+ tsconfig: '../packages/node/tsconfig.json',
+ id: Packages.NodeSdk
+ },
};
diff --git a/packages/node/CHANGELOG.md b/packages/node/CHANGELOG.md
new file mode 100644
index 000000000..3906dd8d3
--- /dev/null
+++ b/packages/node/CHANGELOG.md
@@ -0,0 +1 @@
+# @powersync/node
diff --git a/packages/node/LICENSE b/packages/node/LICENSE
new file mode 100644
index 000000000..c61b66391
--- /dev/null
+++ b/packages/node/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/packages/node/README.md b/packages/node/README.md
new file mode 100644
index 000000000..22783a38c
--- /dev/null
+++ b/packages/node/README.md
@@ -0,0 +1,44 @@
+
+
+
+
+# PowerSync SDK for Node.js
+
+_[PowerSync](https://www.powersync.com) is a sync engine for building local-first apps with instantly-responsive UI/UX and simplified state transfer. Syncs between SQLite on the client-side and Postgres, MongoDB or MySQL on the server-side._
+
+This package (`packages/node`) is the PowerSync SDK for Node.js clients. It is an extension of `packages/common`.
+Using this package is not necessary for PowerSync on servers, see [our documentation](https://docs.powersync.com/installation/app-backend-setup) for more details on that.
+
+This package has an API similar to the PowerSync web SDK, for which a summary of features is available [here](https://docs.powersync.com/client-sdk-references/js-web).
+
+# Installation
+
+## Install Package
+
+```bash
+npm install @powersync/node
+```
+
+Both `@powersync/node` and the `better-sqlite3` packages have install scripts that need to run to compile
+or download sqlite3 and PowerSync binaries.
+
+# Getting Started
+
+You can follow along our [web SDK reference](https://docs.powersync.com/client-sdk-references/js-web)
+which contains everything you need to know to get started implementing PowerSync in your project.
+Replace imports of `@powersync/web` with `@powersync/node` where necessary.
+
+# Examples
+
+A simple example using `@powersync/node` is available in the [`demos/example-node/`](../demos/example-node) directory.
+
+# Found a bug or need help?
+
+- Join our [Discord server](https://discord.gg/powersync) where you can browse topics from our community, ask questions, share feedback, or just say hello :)
+- Please open a [GitHub issue](https://github.com/powersync-ja/powersync-js/issues) when you come across a bug.
+- Have feedback or an idea? [Submit an idea](https://roadmap.powersync.com/tabs/5-roadmap/submit-idea) via our public roadmap or [schedule a chat](https://calendly.com/powersync-product/powersync-chat) with someone from our product team.
+
+# Thanks
+
+The PowerSync Node.js SDK relies on the work contributors and maintainers have put into the upstream better-sqlite3 package.
+In particular, we'd like to thank [@spinda](https://github.com/spinda) for contributing support for update, commit and rollback hooks!
diff --git a/packages/node/download_core.js b/packages/node/download_core.js
new file mode 100644
index 000000000..60d986894
--- /dev/null
+++ b/packages/node/download_core.js
@@ -0,0 +1,46 @@
+// TODO: Make this a pre-publish hook and just bundle everything
+import * as OS from 'node:os';
+import * as fs from 'node:fs/promises';
+import * as path from 'node:path';
+import { Readable } from 'node:stream';
+import { finished } from 'node:stream/promises';
+import { exit } from 'node:process';
+
+const version = '0.3.11';
+
+const platform = OS.platform();
+let destination;
+let asset;
+
+if (platform === 'win32') {
+ asset = 'powersync_x64.dll';
+ destination = 'powersync.dll';
+} else if (platform === 'linux') {
+ asset = OS.arch() === 'x64' ? 'libpowersync_x64.so' : 'libpowersync_aarch64.so';
+ destination = 'libpowersync.so';
+} else if (platform === 'darwin') {
+ asset = OS.arch() === 'x64' ? 'libpowersync_x64.dylib' : 'libpowersync_aarch64.dylib';
+ destination = 'libpowersync.dylib';
+}
+
+const destinationPath = path.resolve('lib', destination);
+try {
+ await fs.access(destinationPath);
+ exit(0);
+} catch {}
+
+const url = `https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v${version}/${asset}`;
+const response = await fetch(url);
+if (response.status != 200) {
+ throw `Could not download ${url}`;
+}
+
+try {
+ await fs.access('lib');
+} catch {
+ await fs.mkdir('lib');
+}
+
+const file = await fs.open(destinationPath, 'w');
+await finished(Readable.fromWeb(response.body).pipe(file.createWriteStream()));
+await file.close();
diff --git a/packages/node/package.json b/packages/node/package.json
new file mode 100644
index 000000000..cdf8b5472
--- /dev/null
+++ b/packages/node/package.json
@@ -0,0 +1,58 @@
+{
+ "name": "@powersync/node",
+ "version": "0.0.0",
+ "publishConfig": {
+ "registry": "https://registry.npmjs.org/",
+ "access": "public"
+ },
+ "description": "PowerSync - sync Postgres with SQLite in your Node.js app for offline-first and real-time data",
+ "main": "./lib/index.js",
+ "module": "./lib/index.js",
+ "types": "./lib/index.d.ts",
+ "files": [
+ "lib",
+ "dist",
+ "download_core.js"
+ ],
+ "scripts": {
+ "install": "node download_core.js",
+ "build": "tsc -b",
+ "build:prod": "tsc -b --sourceMap false",
+ "clean": "rm -rf lib dist tsconfig.tsbuildinfo dist",
+ "watch": "tsc -b -w",
+ "test": "vitest"
+ },
+ "type": "module",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/powersync-ja/powersync-js.git"
+ },
+ "author": "JOURNEYAPPS",
+ "license": "Apache-2.0",
+ "bugs": {
+ "url": "https://github.com/powersync-ja/powersync-js/issues"
+ },
+ "homepage": "https://docs.powersync.com/",
+ "peerDependencies": {
+ "@powersync/common": "workspace:^1.22.0",
+ "@powersync/better-sqlite3": "^0.1.0"
+ },
+ "dependencies": {
+ "@powersync/common": "workspace:*",
+ "async-lock": "^1.4.0",
+ "bson": "^6.6.0",
+ "comlink": "^4.4.2"
+ },
+ "devDependencies": {
+ "@types/async-lock": "^1.4.0",
+ "typescript": "^5.5.3",
+ "vitest": "^3.0.5"
+ },
+ "keywords": [
+ "data sync",
+ "offline-first",
+ "sqlite",
+ "real-time data stream",
+ "live data"
+ ]
+}
diff --git a/packages/node/src/db/AsyncDatabase.ts b/packages/node/src/db/AsyncDatabase.ts
new file mode 100644
index 000000000..61abae7ec
--- /dev/null
+++ b/packages/node/src/db/AsyncDatabase.ts
@@ -0,0 +1,23 @@
+import { QueryResult } from '@powersync/common';
+
+export type ProxiedQueryResult = Omit & {
+ rows?: {
+ _array: any[];
+ length: number;
+ };
+};
+
+export interface AsyncDatabaseOpener {
+ open(path: string, isWriter: boolean): Promise;
+}
+
+export interface AsyncDatabase {
+ execute: (query: string, params: any[]) => Promise;
+ executeBatch: (query: string, params: any[][]) => Promise;
+ close: () => Promise;
+ // Collect table updates made since the last call to collectCommittedUpdates.
+ // This happens on the worker because we otherwise get race conditions when wrapping
+ // callbacks to invoke on the main thread (we need a guarantee that collectCommittedUpdates
+ // contains entries immediately after calling COMMIT).
+ collectCommittedUpdates: () => Promise;
+}
diff --git a/packages/node/src/db/BetterSQLite3DBAdapter.ts b/packages/node/src/db/BetterSQLite3DBAdapter.ts
new file mode 100644
index 000000000..7b09557b3
--- /dev/null
+++ b/packages/node/src/db/BetterSQLite3DBAdapter.ts
@@ -0,0 +1,266 @@
+import * as path from 'node:path';
+import { Worker } from 'node:worker_threads';
+import * as Comlink from 'comlink';
+
+import {
+ BaseObserver,
+ BatchedUpdateNotification,
+ DBAdapter,
+ DBAdapterListener,
+ LockContext,
+ Transaction,
+ DBLockOptions,
+ QueryResult,
+ SQLOpenOptions
+} from '@powersync/common';
+import { Remote } from 'comlink';
+import { AsyncResource } from 'node:async_hooks';
+import { AsyncDatabase, AsyncDatabaseOpener } from './AsyncDatabase.js';
+import { RemoteConnection } from './RemoteConnection.js';
+
+export type BetterSQLite3LockContext = LockContext & {
+ executeBatch(query: string, params?: any[][]): Promise;
+};
+
+export type BetterSQLite3Transaction = Transaction & BetterSQLite3LockContext;
+
+const READ_CONNECTIONS = 5;
+
+/**
+ * Adapter for better-sqlite3
+ */
+export class BetterSQLite3DBAdapter extends BaseObserver implements DBAdapter {
+ private readonly options: SQLOpenOptions;
+ public readonly name: string;
+
+ private readConnections: RemoteConnection[];
+ private writeConnection: RemoteConnection;
+
+ private readonly readQueue: Array<(connection: RemoteConnection) => void> = [];
+ private readonly writeQueue: Array<() => void> = [];
+
+ constructor(options: SQLOpenOptions) {
+ super();
+
+ this.options = options;
+ this.name = options.dbFilename;
+ }
+
+ async initialize() {
+ let dbFilePath = this.options.dbFilename;
+ if (this.options.dbLocation !== undefined) {
+ dbFilePath = path.join(this.options.dbLocation, dbFilePath);
+ }
+
+ const openWorker = async (isWriter: boolean) => {
+ const worker = new Worker(new URL('./SqliteWorker.js', import.meta.url), {name: isWriter ? `write ${dbFilePath}` : `read ${dbFilePath}`});
+ const listeners = new WeakMap void>();
+
+ const comlink = Comlink.wrap({
+ postMessage: worker.postMessage.bind(worker),
+ addEventListener: (type, listener) => {
+ let resolved: (event: any) => void =
+ 'handleEvent' in listener ? listener.handleEvent.bind(listener) : listener;
+
+ // Comlink wants message events, but the message event on workers in Node returns the data only.
+ if (type === 'message') {
+ const original = resolved;
+
+ resolved = (data) => {
+ original({ data });
+ };
+ }
+
+ listeners.set(listener, resolved);
+ worker.addListener(type, resolved);
+ },
+ removeEventListener: (type, listener) => {
+ const resolved = listeners.get(listener);
+ if (!resolved) {
+ return;
+ }
+ worker.removeListener(type, resolved);
+ }
+ });
+
+ worker.once('error', (e) => {
+ console.error('Unexpected PowerSync database worker error', e);
+ });
+
+ const database = (await comlink.open(dbFilePath, isWriter)) as Remote;
+ return new RemoteConnection(worker, comlink, database);
+ };
+
+ // Open the writer first to avoid multiple threads enabling WAL concurrently (causing "database is locked" errors).
+ this.writeConnection = await openWorker(true);
+ const createWorkers: Promise[] = [];
+ for (let i = 0; i < READ_CONNECTIONS; i++) {
+ createWorkers.push(openWorker(false));
+ }
+ this.readConnections = await Promise.all(createWorkers);
+ }
+
+ async close() {
+ await this.writeConnection.close();
+ for (const connection of this.readConnections) {
+ await connection.close();
+ }
+ }
+
+ readLock(fn: (tx: BetterSQLite3LockContext) => Promise, _options?: DBLockOptions | undefined): Promise {
+ let resolveConnectionPromise!: (connection: RemoteConnection) => void;
+ const connectionPromise = new Promise((resolve, _reject) => {
+ resolveConnectionPromise = AsyncResource.bind(resolve);
+ });
+
+ const connection = this.readConnections.find((connection) => !connection.isBusy);
+ if (connection) {
+ connection.isBusy = true;
+ resolveConnectionPromise(connection);
+ } else {
+ this.readQueue.push(resolveConnectionPromise);
+ }
+
+ return (async () => {
+ const connection = await connectionPromise;
+
+ try {
+ return await fn(connection);
+ } finally {
+ const next = this.readQueue.shift();
+ if (next) {
+ next(connection);
+ } else {
+ connection.isBusy = false;
+ }
+ }
+ })();
+ }
+
+ writeLock(fn: (tx: BetterSQLite3LockContext) => Promise, _options?: DBLockOptions | undefined): Promise {
+ let resolveLockPromise!: () => void;
+ const lockPromise = new Promise((resolve, _reject) => {
+ resolveLockPromise = AsyncResource.bind(resolve);
+ });
+
+ if (!this.writeConnection.isBusy) {
+ this.writeConnection.isBusy = true;
+ resolveLockPromise();
+ } else {
+ this.writeQueue.push(resolveLockPromise);
+ }
+
+ return (async () => {
+ await lockPromise;
+
+ try {
+ try {
+ return await fn(this.writeConnection);
+ } finally {
+ const updates = await this.writeConnection.database.collectCommittedUpdates();
+
+ if (updates.length > 0) {
+ const event: BatchedUpdateNotification = {
+ tables: updates,
+ groupedUpdates: {},
+ rawUpdates: []
+ };
+ this.iterateListeners((cb) => cb.tablesUpdated?.(event));
+ }
+ }
+ } finally {
+ const next = this.writeQueue.shift();
+ if (next) {
+ next();
+ } else {
+ this.writeConnection.isBusy = false;
+ }
+ }
+ })();
+ }
+
+ readTransaction(
+ fn: (tx: BetterSQLite3Transaction) => Promise,
+ _options?: DBLockOptions | undefined
+ ): Promise {
+ return this.readLock((ctx) => this.internalTransaction(ctx as RemoteConnection, fn));
+ }
+
+ writeTransaction(
+ fn: (tx: BetterSQLite3Transaction) => Promise,
+ _options?: DBLockOptions | undefined
+ ): Promise {
+ return this.writeLock((ctx) => this.internalTransaction(ctx as RemoteConnection, fn));
+ }
+
+ private async internalTransaction(
+ connection: RemoteConnection,
+ fn: (tx: BetterSQLite3Transaction) => Promise
+ ): Promise {
+ let finalized = false;
+ const commit = async (): Promise => {
+ if (!finalized) {
+ finalized = true;
+ await connection.execute('COMMIT');
+ }
+ return { rowsAffected: 0 };
+ };
+ const rollback = async (): Promise => {
+ if (!finalized) {
+ finalized = true;
+ await connection.execute('ROLLBACK');
+ }
+ return { rowsAffected: 0 };
+ };
+ try {
+ await connection.execute('BEGIN');
+ const result = await fn({
+ execute: (query, params) => connection.execute(query, params),
+ executeBatch: (query, params) => connection.executeBatch(query, params),
+ get: (query, params) => connection.get(query, params),
+ getAll: (query, params) => connection.getAll(query, params),
+ getOptional: (query, params) => connection.getOptional(query, params),
+ commit,
+ rollback
+ });
+ await commit();
+ return result;
+ } catch (ex) {
+ try {
+ await rollback();
+ } catch (ex2) {
+ // In rare cases, a rollback may fail.
+ // Safe to ignore.
+ }
+ throw ex;
+ }
+ }
+
+ getAll(sql: string, parameters?: any[]): Promise {
+ return this.readLock((ctx) => ctx.getAll(sql, parameters));
+ }
+
+ getOptional(sql: string, parameters?: any[]): Promise {
+ return this.readLock((ctx) => ctx.getOptional(sql, parameters));
+ }
+
+ get(sql: string, parameters?: any[]): Promise {
+ return this.readLock((ctx) => ctx.get(sql, parameters));
+ }
+
+ execute(query: string, params?: any[] | undefined): Promise {
+ return this.writeLock((ctx) => ctx.execute(query, params));
+ }
+
+ executeBatch(query: string, params?: any[][]): Promise {
+ return this.writeTransaction((ctx) => ctx.executeBatch(query, params));
+ }
+
+ async refreshSchema() {
+ await this.writeConnection.refreshSchema();
+
+ for (const readConnection of this.readConnections) {
+ await readConnection.refreshSchema();
+ }
+ }
+}
diff --git a/packages/node/src/db/PowerSyncDatabase.ts b/packages/node/src/db/PowerSyncDatabase.ts
new file mode 100644
index 000000000..73f9ce706
--- /dev/null
+++ b/packages/node/src/db/PowerSyncDatabase.ts
@@ -0,0 +1,63 @@
+import {
+ AbstractPowerSyncDatabase,
+ AbstractStreamingSyncImplementation,
+ BucketStorageAdapter,
+ DBAdapter,
+ PowerSyncBackendConnector,
+ PowerSyncDatabaseOptionsWithSettings,
+ SqliteBucketStorage
+} from '@powersync/common';
+
+import { NodeRemote } from '../sync/stream/NodeRemote.js';
+import { NodeStreamingSyncImplementation } from '../sync/stream/NodeStreamingSyncImplementation.js';
+
+import { BetterSQLite3DBAdapter } from './BetterSQLite3DBAdapter.js';
+
+/**
+ * A PowerSync database which provides SQLite functionality
+ * which is automatically synced.
+ *
+ * @example
+ * ```typescript
+ * export const db = new PowerSyncDatabase({
+ * schema: AppSchema,
+ * database: {
+ * dbFilename: 'example.db'
+ * }
+ * });
+ * ```
+ */
+export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
+ async _initialize(): Promise {
+ await (this.database as BetterSQLite3DBAdapter).initialize();
+ }
+
+ /**
+ * Opens a DBAdapter using better-sqlite3 as the default SQLite open factory.
+ */
+ protected openDBAdapter(options: PowerSyncDatabaseOptionsWithSettings): DBAdapter {
+ return new BetterSQLite3DBAdapter(options.database);
+ }
+
+ protected generateBucketStorageAdapter(): BucketStorageAdapter {
+ return new SqliteBucketStorage(this.database, AbstractPowerSyncDatabase.transactionMutex);
+ }
+
+ protected generateSyncStreamImplementation(
+ connector: PowerSyncBackendConnector
+ ): AbstractStreamingSyncImplementation {
+ const remote = new NodeRemote(connector);
+
+ return new NodeStreamingSyncImplementation({
+ adapter: this.bucketStorageAdapter,
+ remote,
+ uploadCrud: async () => {
+ await this.waitForReady();
+ await connector.uploadData(this);
+ },
+ retryDelayMs: this.options.retryDelayMs,
+ crudUploadThrottleMs: this.options.crudUploadThrottleMs,
+ identifier: this.database.name
+ });
+ }
+}
diff --git a/packages/node/src/db/RemoteConnection.ts b/packages/node/src/db/RemoteConnection.ts
new file mode 100644
index 000000000..0a090f523
--- /dev/null
+++ b/packages/node/src/db/RemoteConnection.ts
@@ -0,0 +1,76 @@
+import { Worker } from 'node:worker_threads';
+import { LockContext, QueryResult } from '@powersync/common';
+import { releaseProxy, Remote } from 'comlink';
+import { AsyncDatabase, AsyncDatabaseOpener, ProxiedQueryResult } from './AsyncDatabase.js';
+
+/**
+ * A PowerSync database connection implemented with RPC calls to a background worker.
+ */
+export class RemoteConnection implements LockContext {
+ isBusy = false;
+
+ private readonly worker: Worker;
+ private readonly comlink: Remote;
+ readonly database: Remote;
+
+ constructor(worker: Worker, comlink: Remote, database: Remote) {
+ this.worker = worker;
+ this.comlink = comlink;
+ this.database = database;
+ }
+
+ async executeBatch(query: string, params: any[][] = []): Promise {
+ const result = await this.database.executeBatch(query, params ?? []);
+ return RemoteConnection.wrapQueryResult(result);
+ }
+
+ async execute(query: string, params?: any[] | undefined): Promise {
+ const result = await this.database.execute(query, params ?? []);
+ return RemoteConnection.wrapQueryResult(result);
+ }
+
+ async getAll(sql: string, parameters?: any[]): Promise {
+ const res = await this.execute(sql, parameters);
+ return res.rows?._array ?? [];
+ }
+
+ async getOptional(sql: string, parameters?: any[]): Promise {
+ const res = await this.execute(sql, parameters);
+ return res.rows?.item(0) ?? null;
+ }
+
+ async get(sql: string, parameters?: any[]): Promise {
+ const res = await this.execute(sql, parameters);
+ const first = res.rows?.item(0);
+ if (!first) {
+ throw new Error('Result set is empty');
+ }
+ return first;
+ }
+
+ async refreshSchema() {
+ await this.execute("pragma table_info('sqlite_master')");
+ }
+
+ async close() {
+ await this.database.close();
+ this.database[releaseProxy]();
+ this.comlink[releaseProxy]();
+ await this.worker.terminate();
+ }
+
+ static wrapQueryResult(result: ProxiedQueryResult): QueryResult {
+ let rows: QueryResult['rows'] | undefined = undefined;
+ if (result.rows) {
+ rows = {
+ ...result.rows,
+ item: (idx) => result.rows?._array[idx]
+ } satisfies QueryResult['rows'];
+ }
+
+ return {
+ ...result,
+ rows
+ };
+ }
+}
diff --git a/packages/node/src/db/SqliteWorker.ts b/packages/node/src/db/SqliteWorker.ts
new file mode 100644
index 000000000..66ac01436
--- /dev/null
+++ b/packages/node/src/db/SqliteWorker.ts
@@ -0,0 +1,116 @@
+import BetterSQLite3Database, { Database } from '@powersync/better-sqlite3';
+import * as Comlink from 'comlink';
+import { parentPort, threadId } from 'node:worker_threads';
+import OS from 'node:os';
+import url from 'node:url';
+import { AsyncDatabase, AsyncDatabaseOpener } from './AsyncDatabase.js';
+
+class BlockingAsyncDatabase implements AsyncDatabase {
+ private readonly db: Database;
+
+ private readonly uncommittedUpdatedTables = new Set();
+ private readonly committedUpdatedTables = new Set();
+
+ constructor(db: Database) {
+ this.db = db;
+
+ db.function('node_thread_id', () => threadId);
+ }
+
+ collectCommittedUpdates() {
+ const resolved = Promise.resolve([...this.committedUpdatedTables]);
+ this.committedUpdatedTables.clear();
+ return resolved;
+ }
+
+ installUpdateHooks() {
+ this.db.updateHook((_op: string, _dbName: string, tableName: string, _rowid: bigint) => {
+ this.uncommittedUpdatedTables.add(tableName);
+ });
+
+ this.db.commitHook(() => {
+ for (const tableName of this.uncommittedUpdatedTables) {
+ this.committedUpdatedTables.add(tableName);
+ }
+ this.uncommittedUpdatedTables.clear();
+ return true;
+ });
+
+ this.db.rollbackHook(() => {
+ this.uncommittedUpdatedTables.clear();
+ });
+ }
+
+ async close() {
+ this.db.close();
+ }
+
+ async execute(query: string, params: any[]) {
+ const stmt = this.db.prepare(query);
+ if (stmt.reader) {
+ const rows = stmt.all(params);
+ return {
+ rowsAffected: 0,
+ rows: {
+ _array: rows,
+ length: rows.length
+ }
+ };
+ } else {
+ const info = stmt.run(params);
+ return {
+ rowsAffected: info.changes,
+ insertId: Number(info.lastInsertRowid)
+ };
+ }
+ }
+
+ async executeBatch(query: string, params: any[][]) {
+ params = params ?? [];
+
+ let rowsAffected = 0;
+
+ const stmt = this.db.prepare(query);
+ for (const paramSet of params) {
+ const info = stmt.run(paramSet);
+ rowsAffected += info.changes;
+ }
+
+ return { rowsAffected };
+ }
+}
+
+class BetterSqliteWorker implements AsyncDatabaseOpener {
+ async open(path: string, isWriter: boolean): Promise {
+ const baseDB = new BetterSQLite3Database(path);
+ baseDB.pragma('journal_mode = WAL');
+ loadExtension(baseDB);
+ if (!isWriter) {
+ baseDB.pragma('query_only = true');
+ }
+
+ const asyncDb = new BlockingAsyncDatabase(baseDB);
+ asyncDb.installUpdateHooks();
+
+ return Comlink.proxy(asyncDb);
+ }
+}
+
+const loadExtension = (db: Database) => {
+ const platform = OS.platform();
+ let extensionPath: string;
+ if (platform === 'win32') {
+ extensionPath = 'powersync.dll';
+ } else if (platform === 'linux') {
+ extensionPath = 'libpowersync.so';
+ } else if (platform === 'darwin') {
+ extensionPath = 'libpowersync.dylib';
+ } else {
+ throw 'Unknown platform, PowerSync for Node.js currently supports Windows, Linux and macOS.';
+ }
+
+ const resolved = url.fileURLToPath(new URL(`../${extensionPath}`, import.meta.url));
+ db.loadExtension(resolved, 'sqlite3_powersync_init');
+};
+
+Comlink.expose(new BetterSqliteWorker(), parentPort! as Comlink.Endpoint);
diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts
new file mode 100644
index 000000000..aa019c363
--- /dev/null
+++ b/packages/node/src/index.ts
@@ -0,0 +1,4 @@
+// Re export to only require one import in client side code
+export * from '@powersync/common';
+
+export * from './db/PowerSyncDatabase.js';
diff --git a/packages/node/src/sync/stream/NodeRemote.ts b/packages/node/src/sync/stream/NodeRemote.ts
new file mode 100644
index 000000000..b0c147484
--- /dev/null
+++ b/packages/node/src/sync/stream/NodeRemote.ts
@@ -0,0 +1,48 @@
+import * as os from 'node:os';
+
+import { ILogger } from 'js-logger';
+
+import {
+ AbstractRemote,
+ AbstractRemoteOptions,
+ BSONImplementation,
+ DEFAULT_REMOTE_LOGGER,
+ FetchImplementation,
+ FetchImplementationProvider,
+ RemoteConnector
+} from '@powersync/common';
+import { BSON } from 'bson';
+
+export const STREAMING_POST_TIMEOUT_MS = 30_000;
+
+class NodeFetchProvider extends FetchImplementationProvider {
+ getFetch(): FetchImplementation {
+ return fetch.bind(globalThis);
+ }
+}
+
+export class NodeRemote extends AbstractRemote {
+ constructor(
+ protected connector: RemoteConnector,
+ protected logger: ILogger = DEFAULT_REMOTE_LOGGER,
+ options?: Partial
+ ) {
+ super(connector, logger, {
+ ...(options ?? {}),
+ fetchImplementation: options?.fetchImplementation ?? new NodeFetchProvider()
+ });
+ }
+
+ getUserAgent(): string {
+ return [
+ super.getUserAgent(),
+ `powersync-node`,
+ `node/${process.versions.node}`,
+ `${os.platform()}/${os.release()}`
+ ].join(' ');
+ }
+
+ async getBSON(): Promise {
+ return BSON;
+ }
+}
diff --git a/packages/node/src/sync/stream/NodeStreamingSyncImplementation.ts b/packages/node/src/sync/stream/NodeStreamingSyncImplementation.ts
new file mode 100644
index 000000000..d97849f6a
--- /dev/null
+++ b/packages/node/src/sync/stream/NodeStreamingSyncImplementation.ts
@@ -0,0 +1,54 @@
+import {
+ AbstractStreamingSyncImplementation,
+ AbstractStreamingSyncImplementationOptions,
+ LockOptions,
+ LockType
+} from '@powersync/common';
+import Lock from 'async-lock';
+
+/**
+ * Global locks which prevent multiple instances from syncing
+ * concurrently.
+ */
+const LOCKS = new Map();
+
+const lockTypes = new Set(Object.values(LockType));
+
+export class NodeStreamingSyncImplementation extends AbstractStreamingSyncImplementation {
+ locks: Lock;
+
+ constructor(options: AbstractStreamingSyncImplementationOptions) {
+ super(options);
+ this.initLocks();
+ }
+
+ /**
+ * Configures global locks on sync process
+ */
+ initLocks() {
+ const { identifier } = this.options;
+ if (identifier && LOCKS.has(identifier)) {
+ this.locks = LOCKS.get(identifier)!;
+ return;
+ }
+
+ this.locks = new Lock();
+
+ if (identifier) {
+ LOCKS.set(identifier, this.locks);
+ }
+ }
+
+ obtainLock(lockOptions: LockOptions): Promise {
+ if (!lockTypes.has(lockOptions.type)) {
+ throw new Error(`Lock type ${lockOptions.type} not found`);
+ }
+ return this.locks.acquire(lockOptions.type, async () => {
+ if (lockOptions.signal?.aborted) {
+ throw new Error('Aborted');
+ }
+
+ return lockOptions.callback();
+ });
+ }
+}
diff --git a/packages/node/tests/PowerSyncDatabase.test.ts b/packages/node/tests/PowerSyncDatabase.test.ts
new file mode 100644
index 000000000..3857ab368
--- /dev/null
+++ b/packages/node/tests/PowerSyncDatabase.test.ts
@@ -0,0 +1,79 @@
+import { vi, expect, test } from 'vitest';
+import { databaseTest } from './utils';
+
+databaseTest('links powersync', async ({ database }) => {
+ await database.get('select powersync_rs_version();');
+});
+
+databaseTest('runs queries on multiple threads', async ({ database }) => {
+ const threads = new Set();
+
+ const collectWorkerThreadId = async () => {
+ const row = await database.get<{ r: number }>('SELECT node_thread_id() AS r');
+ threads.add(row.r);
+ return row.r;
+ };
+
+ const queryTasks: Promise[] = [];
+ for (let i = 0; i < 10; i++) {
+ queryTasks.push(collectWorkerThreadId());
+ }
+
+ const res = await Promise.all(queryTasks);
+ expect(res).toHaveLength(10);
+ expect([...threads]).toHaveLength(5);
+});
+
+databaseTest('can watch tables', async ({ database }) => {
+ const fn = vi.fn();
+ const disposeWatch = database.onChangeWithCallback(
+ {
+ onChange: () => {
+ fn();
+ }
+ },
+ { tables: ['todos'], throttleMs: 0 }
+ );
+
+ await database.execute('INSERT INTO todos (id, content) VALUES (uuid(), ?)', ['first']);
+ await expect.poll(() => fn).toHaveBeenCalledOnce();
+
+ await database.writeTransaction(async (tx) => {
+ await tx.execute('INSERT INTO todos (id, content) VALUES (uuid(), ?)', ['second']);
+ });
+ await expect.poll(() => fn).toHaveBeenCalledTimes(2);
+
+ await database.writeTransaction(async (tx) => {
+ await tx.execute('DELETE FROM todos;');
+ await tx.rollback();
+ });
+ await expect.poll(() => fn).toHaveBeenCalledTimes(2);
+
+ disposeWatch();
+ await database.execute('INSERT INTO todos (id, content) VALUES (uuid(), ?)', ['fourth']);
+ await expect.poll(() => fn).toHaveBeenCalledTimes(2);
+});
+
+databaseTest.skip('can watch queries', async ({ database }) => {
+ const query = await database.watch('SELECT * FROM todos;', [])[Symbol.asyncIterator]();
+ expect((await query.next()).value.rows).toHaveLength(0);
+
+ await database.execute('INSERT INTO todos (id, content) VALUES (uuid(), ?)', ['first']);
+ // TODO: There is a race condition somewhere, this reports now rows sometimes.
+ expect((await query.next()).value.rows).toHaveLength(1);
+
+ await database.writeTransaction(async (tx) => {
+ await tx.execute('INSERT INTO todos (id, content) VALUES (uuid(), ?)', ['second']);
+ await tx.execute('INSERT INTO todos (id, content) VALUES (uuid(), ?)', ['third']);
+ });
+
+ expect((await query.next()).value.rows).toHaveLength(3);
+
+ await database.writeTransaction(async (tx) => {
+ await tx.execute('DELETE FROM todos;');
+ await tx.rollback();
+ });
+
+ await database.execute('INSERT INTO todos (id, content) VALUES (uuid(), ?)', ['fourth']);
+ expect((await query.next()).value.rows).toHaveLength(4);
+});
diff --git a/packages/node/tests/utils.ts b/packages/node/tests/utils.ts
new file mode 100644
index 000000000..c8ce4345e
--- /dev/null
+++ b/packages/node/tests/utils.ts
@@ -0,0 +1,39 @@
+import os from 'node:os';
+import fs from 'node:fs/promises';
+import path from 'node:path';
+import { test } from 'vitest';
+import { column, PowerSyncDatabase, Schema, Table } from '../lib';
+
+async function createTempDir() {
+ const ostmpdir = os.tmpdir();
+ const tmpdir = path.join(ostmpdir, 'powersync-node-test-');
+ return await fs.mkdtemp(tmpdir);
+}
+
+export const LIST_TABLE = 'lists';
+export const TODO_TABLE = 'todos';
+
+const todos = new Table({
+ content: column.text
+});
+
+export const AppSchema = new Schema({
+ todos
+});
+
+export type Database = (typeof AppSchema)['types'];
+
+export const databaseTest = test.extend<{ database: PowerSyncDatabase }>({
+ database: async ({}, use) => {
+ const directory = await createTempDir();
+ const database = new PowerSyncDatabase({
+ schema: AppSchema,
+ database: {
+ dbFilename: 'test.db',
+ dbLocation: directory
+ }
+ });
+ await use(database);
+ await fs.rm(directory, { recursive: true });
+ }
+});
diff --git a/packages/node/tsconfig.json b/packages/node/tsconfig.json
new file mode 100644
index 000000000..2cb0b7091
--- /dev/null
+++ b/packages/node/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "extends": "../../tsconfig.base",
+ "compilerOptions": {
+ "baseUrl": "./",
+ "jsx": "react",
+ "types": ["node"],
+ "rootDir": "src",
+ "outDir": "./lib",
+ "lib": ["esnext"],
+ "declaration": true,
+ "module": "nodenext",
+ "moduleResolution": "nodenext",
+ "preserveConstEnums": true,
+ "esModuleInterop": true,
+ "skipLibCheck": false,
+ "strictNullChecks": true
+ },
+ "include": ["src/**/*"],
+ "references": [
+ {
+ "path": "../common"
+ }
+ ]
+}
diff --git a/packages/node/vitest.config.ts b/packages/node/vitest.config.ts
new file mode 100644
index 000000000..94ec60f24
--- /dev/null
+++ b/packages/node/vitest.config.ts
@@ -0,0 +1,4 @@
+import { defineConfig } from 'vitest/config';
+
+// We need to define an empty config to be part of the vitest works
+export default defineConfig({});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5b42746ca..1157a8e38 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -19,7 +19,7 @@ importers:
version: 4.0.11(@pnpm/logger@5.2.0)
'@vitest/browser':
specifier: ^3.0.8
- version: 3.0.8(@testing-library/dom@10.4.0)(@types/node@22.7.4)(playwright@1.51.0)(typescript@5.7.2)(vite@5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1))(vitest@3.0.8)(webdriverio@9.8.0)
+ version: 3.0.8(@testing-library/dom@10.4.0)(@types/node@22.7.4)(playwright@1.51.0)(typescript@5.7.2)(vite@6.1.0(@types/node@22.7.4)(jiti@1.21.6)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1)(yaml@2.6.1))(vitest@3.0.8)(webdriverio@9.8.0)
husky:
specifier: ^9.0.11
version: 9.1.6
@@ -137,7 +137,7 @@ importers:
version: 0.1.11(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
'@react-navigation/drawer':
specifier: ^6.6.15
- version: 6.7.2(yaao3llbshooz2bjipuf6mkduy)
+ version: 6.7.2(de9b7caae7cef38a32afa5b76a3c9d54)
'@react-navigation/native':
specifier: ^6.1.17
version: 6.1.18(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
@@ -161,7 +161,7 @@ importers:
version: 1.11.3
expo-router:
specifier: 3.5.21
- version: 3.5.21(gtohwu5bdvnl7tvlmjhokmubum)
+ version: 3.5.21(49b2fd6c45ca81e2d20f2f5a4be05a3e)
expo-splash-screen:
specifier: ~0.27.4
version: 0.27.6(encoding@0.1.13)(expo-modules-autolinking@1.11.3)(expo@51.0.27(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(encoding@0.1.13))
@@ -215,7 +215,7 @@ importers:
version: 10.2.0
react-navigation-stack:
specifier: ^2.10.4
- version: 2.10.4(ei6zhj5w65kzzp3jt27w3zu7ea)
+ version: 2.10.4(b5d6035dfb87b14e0677db2e89c1e7ef)
typed-async-storage:
specifier: ^3.1.2
version: 3.1.2
@@ -495,7 +495,7 @@ importers:
version: 8.57.1
eslint-config-next:
specifier: 14.0.0
- version: 14.0.0(eslint@8.57.1)(typescript@5.7.2)
+ version: 14.0.0(eslint@8.57.1)(typescript@5.8.2)
postcss:
specifier: ^8.4.35
version: 8.4.47
@@ -510,7 +510,23 @@ importers:
version: 3.3.4(webpack@5.95.0(@swc/core@1.10.1(@swc/helpers@0.5.5)))
tailwindcss:
specifier: ^3.4.3
- version: 3.4.13(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.5))(@types/node@20.16.10)(typescript@5.7.2))
+ version: 3.4.13(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.5))(@types/node@20.16.10)(typescript@5.8.2))
+
+ demos/example-node:
+ dependencies:
+ '@powersync/node':
+ specifier: workspace:*
+ version: link:../../packages/node
+ dotenv:
+ specifier: ^16.4.7
+ version: 16.4.7
+ devDependencies:
+ ts-node:
+ specifier: ^10.9.2
+ version: 10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.5))(@types/node@22.7.4)(typescript@5.8.2)
+ typescript:
+ specifier: ^5.8.2
+ version: 5.8.2
demos/example-vite:
dependencies:
@@ -702,7 +718,7 @@ importers:
version: 6.3.1(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(encoding@0.1.13))
expo-router:
specifier: ^3.5.15
- version: 3.5.21(j6qjh2jsuy2ozdtd6girxrw3ky)
+ version: 3.5.21(988d822f9e58e176bb73f45e8e45eb4a)
expo-splash-screen:
specifier: ~0.27.4
version: 0.27.6(encoding@0.1.13)(expo-modules-autolinking@1.11.1)(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(encoding@0.1.13))
@@ -799,7 +815,7 @@ importers:
version: 0.1.11(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
'@react-navigation/drawer':
specifier: ^6.6.3
- version: 6.7.2(f5uupuoecme7pb3346nlwm73my)
+ version: 6.7.2(fe8cd8328c484d4e3eaed8eea351852b)
'@react-navigation/native':
specifier: ^6.0.0
version: 6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
@@ -838,7 +854,7 @@ importers:
version: 6.3.1(expo@51.0.37(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13))
expo-router:
specifier: 3.5.23
- version: 3.5.23(x45f6tg66eoafhyrv4brrngbdm)
+ version: 3.5.23(2f86f7434a59b644ba234fab7be01c9e)
expo-secure-store:
specifier: ~13.0.1
version: 13.0.2(expo@51.0.37(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13))
@@ -886,7 +902,7 @@ importers:
version: 3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
react-navigation-stack:
specifier: ^2.10.4
- version: 2.10.4(b23yjknfeew5kcy4o5zrlfz5ae)
+ version: 2.10.4(cf0911ea264205029347060226fe0d29)
devDependencies:
'@babel/core':
specifier: ^7.24.5
@@ -950,7 +966,7 @@ importers:
version: 0.1.11(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
'@react-navigation/drawer':
specifier: ^6.6.3
- version: 6.7.2(f5uupuoecme7pb3346nlwm73my)
+ version: 6.7.2(fe8cd8328c484d4e3eaed8eea351852b)
'@react-navigation/native':
specifier: ^6.0.0
version: 6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
@@ -983,7 +999,7 @@ importers:
version: 6.3.1(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13))
expo-router:
specifier: 3.5.21
- version: 3.5.21(qrxjjyxvihi5xb6jovt7bb6fjy)
+ version: 3.5.21(43cc03a7fb538f7aef105856925492f6)
expo-secure-store:
specifier: ~13.0.1
version: 13.0.2(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13))
@@ -1043,7 +1059,7 @@ importers:
version: 0.19.12(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
react-navigation-stack:
specifier: ^2.10.4
- version: 2.10.4(b23yjknfeew5kcy4o5zrlfz5ae)
+ version: 2.10.4(cf0911ea264205029347060226fe0d29)
devDependencies:
'@babel/core':
specifier: ^7.24.5
@@ -1630,7 +1646,7 @@ importers:
version: 20.17.6
drizzle-orm:
specifier: ^0.35.2
- version: 0.35.2(@op-engineering/op-sqlite@11.2.13(react-native@0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2))(react@18.3.1))(@types/react@18.3.12)(kysely@0.27.4)(react@18.3.1)
+ version: 0.35.2(@op-engineering/op-sqlite@11.2.13(react-native@0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2))(react@18.3.1))(@types/better-sqlite3@7.6.12)(@types/react@18.3.12)(better-sqlite3@11.7.2)(kysely@0.27.4)(react@18.3.1)
vite:
specifier: ^6.1.0
version: 6.1.0(@types/node@20.17.6)(jiti@1.21.6)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1)(yaml@2.6.1)
@@ -1669,6 +1685,34 @@ importers:
specifier: ^3.3.0
version: 3.3.0(vite@6.1.0(@types/node@20.17.6)(jiti@1.21.6)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1)(yaml@2.6.1))
+ packages/node:
+ dependencies:
+ '@powersync/better-sqlite3':
+ specifier: ^0.1.0
+ version: 0.1.0
+ '@powersync/common':
+ specifier: workspace:*
+ version: link:../common
+ async-lock:
+ specifier: ^1.4.0
+ version: 1.4.1
+ bson:
+ specifier: ^6.6.0
+ version: 6.8.0
+ comlink:
+ specifier: ^4.4.2
+ version: 4.4.2
+ devDependencies:
+ '@types/async-lock':
+ specifier: ^1.4.0
+ version: 1.4.2
+ typescript:
+ specifier: ^5.5.3
+ version: 5.7.2
+ vitest:
+ specifier: ^3.0.5
+ version: 3.0.8(@types/debug@4.1.12)(@types/node@22.7.4)(@vitest/browser@3.0.8)(jsdom@24.1.3)(less@4.2.0)(lightningcss@1.28.2)(msw@2.7.3(@types/node@22.7.4)(typescript@5.7.2))(sass@1.79.4)(terser@5.34.1)
+
packages/powersync-op-sqlite:
dependencies:
'@powersync/common':
@@ -1680,10 +1724,10 @@ importers:
devDependencies:
'@op-engineering/op-sqlite':
specifier: ^11.2.13
- version: 11.2.13(react-native@0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2))(react@18.3.1)
+ version: 11.2.13(react-native@0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2))(react@18.3.1)
'@react-native/eslint-config':
specifier: ^0.73.1
- version: 0.73.2(eslint@8.57.1)(prettier@3.3.3)(typescript@5.7.2)
+ version: 0.73.2(eslint@8.57.1)(prettier@3.3.3)(typescript@5.8.2)
'@types/async-lock':
specifier: ^1.4.0
version: 1.4.2
@@ -1710,10 +1754,10 @@ importers:
version: 18.3.1
react-native:
specifier: 0.75.3
- version: 0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2)
+ version: 0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2)
react-native-builder-bob:
specifier: ^0.30.2
- version: 0.30.2(typescript@5.7.2)
+ version: 0.30.2(typescript@5.8.2)
turbo:
specifier: ^1.10.7
version: 1.13.4
@@ -1841,7 +1885,7 @@ importers:
version: 24.1.3
vue:
specifier: 3.4.21
- version: 3.4.21(typescript@5.7.2)
+ version: 3.4.21(typescript@5.8.2)
packages/web:
dependencies:
@@ -6287,6 +6331,9 @@ packages:
'@popperjs/core@2.11.8':
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
+ '@powersync/better-sqlite3@0.1.0':
+ resolution: {integrity: sha512-DKiLB8Fk5FrkjxknZYTAvWwLmXf40qlWJb6iQGXQOx4VAu3ZInhYHc0n/msTqPcrBLNHStteuOmiy7h7XvtbcQ==}
+
'@promptbook/utils@0.70.0-1':
resolution: {integrity: sha512-qd2lLRRN+sE6UuNMi2tEeUUeb4zmXnxY5EMdfHVXNE+bqBDpUC7/aEfXgA3jnUXEr+xFjQ8PTFQgWvBMaKvw0g==}
@@ -8526,6 +8573,9 @@ packages:
'@types/babel__traverse@7.20.6':
resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==}
+ '@types/better-sqlite3@7.6.12':
+ resolution: {integrity: sha512-fnQmj8lELIj7BSrZQAdBMHEHX8OZLYIHXqAKT1O7tDfLxaINzf00PMjw22r3N/xXh0w/sGHlO6SVaCQ2mj78lg==}
+
'@types/body-parser@1.19.5':
resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==}
@@ -9775,6 +9825,9 @@ packages:
resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==}
engines: {node: '>=4'}
+ better-sqlite3@11.7.2:
+ resolution: {integrity: sha512-10a57cHVDmfNQS4jrZ9AH2t+2ekzYh5Rhbcnb4ytpmYweoLdogDmyTt5D+hLiY9b44Mx9foowb/4iXBTO2yP3Q==}
+
big-integer@1.6.52:
resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==}
engines: {node: '>=0.6'}
@@ -9790,6 +9843,9 @@ packages:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
+ bindings@1.5.0:
+ resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
+
bl@4.1.0:
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
@@ -10128,6 +10184,9 @@ packages:
resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==}
engines: {node: '>= 14.16.0'}
+ chownr@1.1.4:
+ resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
+
chownr@2.0.0:
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
engines: {node: '>=10'}
@@ -11928,6 +11987,10 @@ packages:
resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
engines: {node: '>=16.17'}
+ expand-template@2.0.3:
+ resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
+ engines: {node: '>=6'}
+
expand-tilde@2.0.2:
resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==}
engines: {node: '>=0.10.0'}
@@ -12216,6 +12279,9 @@ packages:
peerDependencies:
webpack: ^4.0.0 || ^5.0.0
+ file-uri-to-path@1.0.0:
+ resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==}
+
filelist@1.0.4:
resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==}
@@ -12405,6 +12471,9 @@ packages:
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
engines: {node: '>= 0.6'}
+ fs-constants@1.0.0:
+ resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
+
fs-extra@10.1.0:
resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
engines: {node: '>=12'}
@@ -12561,6 +12630,9 @@ packages:
resolution: {integrity: sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg==}
engines: {node: '>=6'}
+ github-from-package@0.0.0:
+ resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
+
github-slugger@1.5.0:
resolution: {integrity: sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==}
@@ -14855,6 +14927,9 @@ packages:
resolution: {integrity: sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q==}
engines: {node: '>= 8.0.0'}
+ mkdirp-classic@0.5.3:
+ resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
+
mkdirp@0.5.6:
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
hasBin: true
@@ -14951,6 +15026,9 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
+ napi-build-utils@2.0.0:
+ resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==}
+
native-run@2.0.1:
resolution: {integrity: sha512-XfG1FBZLM50J10xH9361whJRC9SHZ0Bub4iNRhhI61C8Jv0e1ud19muex6sNKB51ibQNUJNuYn25MuYET/rE6w==}
engines: {node: '>=16.0.0'}
@@ -16211,6 +16289,11 @@ packages:
engines: {node: '>=14.0.0'}
hasBin: true
+ prebuild-install@7.1.3:
+ resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==}
+ engines: {node: '>=10'}
+ hasBin: true
+
preferred-pm@3.1.4:
resolution: {integrity: sha512-lEHd+yEm22jXdCphDrkvIJQU66EuLojPPtvZkpKIkiD+l0DMThF/niqZKJSoU8Vl7iuvtmzyMhir9LdVy5WMnA==}
engines: {node: '>=10'}
@@ -17598,6 +17681,12 @@ packages:
resolution: {integrity: sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==}
engines: {node: ^16.14.0 || >=18.0.0}
+ simple-concat@1.0.1:
+ resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
+
+ simple-get@4.0.1:
+ resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
+
simple-plist@1.3.1:
resolution: {integrity: sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==}
@@ -18122,9 +18211,16 @@ packages:
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
engines: {node: '>=6'}
+ tar-fs@2.1.2:
+ resolution: {integrity: sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==}
+
tar-fs@3.0.6:
resolution: {integrity: sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==}
+ tar-stream@2.2.0:
+ resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
+ engines: {node: '>=6'}
+
tar-stream@3.1.7:
resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==}
@@ -18589,6 +18685,11 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
+ typescript@5.8.2:
+ resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
ua-parser-js@1.0.39:
resolution: {integrity: sha512-k24RCVWlEcjkdOxYmVJgeD/0a1TiSpqLg+ZalVGV9lsnr4yqu0w7tX/x2xX6G4zpkgQnRf89lxuZ1wsbjXM8lw==}
hasBin: true
@@ -29430,15 +29531,15 @@ snapshots:
'@oclif/screen@3.0.8': {}
- '@op-engineering/op-sqlite@11.2.13(react-native@0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2))(react@18.3.1)':
+ '@op-engineering/op-sqlite@11.2.13(react-native@0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2))(react@18.3.1)':
dependencies:
react: 18.3.1
- react-native: 0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2)
+ react-native: 0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2)
- '@op-engineering/op-sqlite@11.2.13(react-native@0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2))(react@18.3.1)':
+ '@op-engineering/op-sqlite@11.2.13(react-native@0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2))(react@18.3.1)':
dependencies:
react: 18.3.1
- react-native: 0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2)
+ react-native: 0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2)
optional: true
'@open-draft/deferred-promise@2.2.0': {}
@@ -29743,6 +29844,10 @@ snapshots:
'@popperjs/core@2.11.8': {}
+ '@powersync/better-sqlite3@0.1.0':
+ dependencies:
+ bindings: 1.5.0
+
'@promptbook/utils@0.70.0-1':
dependencies:
spacetrim: 0.11.39
@@ -29867,11 +29972,11 @@ snapshots:
transitivePeerDependencies:
- typescript
- '@react-native-community/cli-config@14.1.0(typescript@5.7.2)':
+ '@react-native-community/cli-config@14.1.0(typescript@5.8.2)':
dependencies:
'@react-native-community/cli-tools': 14.1.0
chalk: 4.1.2
- cosmiconfig: 9.0.0(typescript@5.7.2)
+ cosmiconfig: 9.0.0(typescript@5.8.2)
deepmerge: 4.3.1
fast-glob: 3.3.2
joi: 17.13.3
@@ -29990,9 +30095,9 @@ snapshots:
transitivePeerDependencies:
- typescript
- '@react-native-community/cli-doctor@14.1.0(typescript@5.7.2)':
+ '@react-native-community/cli-doctor@14.1.0(typescript@5.8.2)':
dependencies:
- '@react-native-community/cli-config': 14.1.0(typescript@5.7.2)
+ '@react-native-community/cli-config': 14.1.0(typescript@5.8.2)
'@react-native-community/cli-platform-android': 14.1.0
'@react-native-community/cli-platform-apple': 14.1.0
'@react-native-community/cli-platform-ios': 14.1.0
@@ -30400,12 +30505,12 @@ snapshots:
- typescript
- utf-8-validate
- '@react-native-community/cli@14.1.0(typescript@5.7.2)':
+ '@react-native-community/cli@14.1.0(typescript@5.8.2)':
dependencies:
'@react-native-community/cli-clean': 14.1.0
- '@react-native-community/cli-config': 14.1.0(typescript@5.7.2)
+ '@react-native-community/cli-config': 14.1.0(typescript@5.8.2)
'@react-native-community/cli-debugger-ui': 14.1.0
- '@react-native-community/cli-doctor': 14.1.0(typescript@5.7.2)
+ '@react-native-community/cli-doctor': 14.1.0(typescript@5.8.2)
'@react-native-community/cli-server-api': 14.1.0
'@react-native-community/cli-tools': 14.1.0
'@react-native-community/cli-types': 14.1.0
@@ -31171,18 +31276,18 @@ snapshots:
- supports-color
- utf-8-validate
- '@react-native/eslint-config@0.73.2(eslint@8.57.1)(prettier@3.3.3)(typescript@5.7.2)':
+ '@react-native/eslint-config@0.73.2(eslint@8.57.1)(prettier@3.3.3)(typescript@5.8.2)':
dependencies:
'@babel/core': 7.24.5
'@babel/eslint-parser': 7.25.8(@babel/core@7.25.7)(eslint@8.57.1)
'@react-native/eslint-plugin': 0.73.1
- '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)
- '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.7.2)
+ '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1)(typescript@5.8.2)
+ '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.8.2)
eslint: 8.57.1
eslint-config-prettier: 8.10.0(eslint@8.57.1)
eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.1)
eslint-plugin-ft-flow: 2.0.3(@babel/eslint-parser@7.25.8(@babel/core@7.24.5)(eslint@8.57.1))(eslint@8.57.1)
- eslint-plugin-jest: 26.9.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)
+ eslint-plugin-jest: 26.9.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1)(typescript@5.8.2)
eslint-plugin-prettier: 4.2.1(eslint-config-prettier@8.10.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.3.3)
eslint-plugin-react: 7.37.1(eslint@8.57.1)
eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1)
@@ -31321,12 +31426,12 @@ snapshots:
optionalDependencies:
'@types/react': 18.2.79
- '@react-native/virtualized-lists@0.75.3(@types/react@18.3.11)(react-native@0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2))(react@18.3.1)':
+ '@react-native/virtualized-lists@0.75.3(@types/react@18.3.11)(react-native@0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2))(react@18.3.1)':
dependencies:
invariant: 2.2.4
nullthrows: 1.1.1
react: 18.3.1
- react-native: 0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2)
+ react-native: 0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2)
optionalDependencies:
'@types/react': 18.3.11
@@ -31339,12 +31444,12 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.12
- '@react-native/virtualized-lists@0.75.3(@types/react@18.3.12)(react-native@0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2))(react@18.3.1)':
+ '@react-native/virtualized-lists@0.75.3(@types/react@18.3.12)(react-native@0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2))(react@18.3.1)':
dependencies:
invariant: 2.2.4
nullthrows: 1.1.1
react: 18.3.1
- react-native: 0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2)
+ react-native: 0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2)
optionalDependencies:
'@types/react': 18.3.12
optional: true
@@ -31400,7 +31505,7 @@ snapshots:
react-is: 16.13.1
use-latest-callback: 0.2.1(react@18.2.0)
- '@react-navigation/drawer@6.7.2(bmedeebhe3ixiqe753c2r26xfi)':
+ '@react-navigation/drawer@6.7.2(038ae2d2ed70d2cde1afeae3252026e4)':
dependencies:
'@react-navigation/elements': 1.3.31(@react-navigation/native@6.1.18(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
'@react-navigation/native': 6.1.18(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
@@ -31414,20 +31519,7 @@ snapshots:
warn-once: 0.1.1
optional: true
- '@react-navigation/drawer@6.7.2(f5uupuoecme7pb3346nlwm73my)':
- dependencies:
- '@react-navigation/elements': 1.3.31(@react-navigation/native@6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- '@react-navigation/native': 6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- color: 4.2.3
- react: 18.2.0
- react-native: 0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0)
- react-native-gesture-handler: 2.16.2(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- react-native-reanimated: 3.10.1(@babel/core@7.24.5)(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- react-native-safe-area-context: 4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- warn-once: 0.1.1
-
- '@react-navigation/drawer@6.7.2(yaao3llbshooz2bjipuf6mkduy)':
+ '@react-navigation/drawer@6.7.2(de9b7caae7cef38a32afa5b76a3c9d54)':
dependencies:
'@react-navigation/elements': 1.3.31(@react-navigation/native@6.1.18(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
'@react-navigation/native': 6.1.18(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
@@ -31440,6 +31532,19 @@ snapshots:
react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
warn-once: 0.1.1
+ '@react-navigation/drawer@6.7.2(fe8cd8328c484d4e3eaed8eea351852b)':
+ dependencies:
+ '@react-navigation/elements': 1.3.31(@react-navigation/native@6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ '@react-navigation/native': 6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ color: 4.2.3
+ react: 18.2.0
+ react-native: 0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0)
+ react-native-gesture-handler: 2.16.2(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ react-native-reanimated: 3.10.1(@babel/core@7.24.5)(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ react-native-safe-area-context: 4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ warn-once: 0.1.1
+
'@react-navigation/elements@1.3.31(@react-navigation/native@6.1.18(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)':
dependencies:
'@react-navigation/native': 6.1.18(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
@@ -33694,6 +33799,11 @@ snapshots:
dependencies:
'@babel/types': 7.25.7
+ '@types/better-sqlite3@7.6.12':
+ dependencies:
+ '@types/node': 20.17.12
+ optional: true
+
'@types/body-parser@1.19.5':
dependencies:
'@types/connect': 3.4.38
@@ -34077,22 +34187,22 @@ snapshots:
'@types/node': 20.17.6
optional: true
- '@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)':
+ '@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1)(typescript@5.8.2)':
dependencies:
'@eslint-community/regexpp': 4.11.1
- '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.7.2)
+ '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.8.2)
'@typescript-eslint/scope-manager': 5.62.0
- '@typescript-eslint/type-utils': 5.62.0(eslint@8.57.1)(typescript@5.7.2)
- '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.7.2)
+ '@typescript-eslint/type-utils': 5.62.0(eslint@8.57.1)(typescript@5.8.2)
+ '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.8.2)
debug: 4.3.7(supports-color@8.1.1)
eslint: 8.57.1
graphemer: 1.4.0
ignore: 5.3.2
natural-compare-lite: 1.4.0
semver: 7.6.3
- tsutils: 3.21.0(typescript@5.7.2)
+ tsutils: 3.21.0(typescript@5.8.2)
optionalDependencies:
- typescript: 5.7.2
+ typescript: 5.8.2
transitivePeerDependencies:
- supports-color
@@ -34116,15 +34226,15 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.7.2)':
+ '@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.2)':
dependencies:
'@typescript-eslint/scope-manager': 5.62.0
'@typescript-eslint/types': 5.62.0
- '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.7.2)
+ '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.8.2)
debug: 4.3.7(supports-color@8.1.1)
eslint: 8.57.1
optionalDependencies:
- typescript: 5.7.2
+ typescript: 5.8.2
transitivePeerDependencies:
- supports-color
@@ -34141,16 +34251,16 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2)':
+ '@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2)':
dependencies:
'@typescript-eslint/scope-manager': 6.21.0
'@typescript-eslint/types': 6.21.0
- '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.7.2)
+ '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.8.2)
'@typescript-eslint/visitor-keys': 6.21.0
debug: 4.3.7(supports-color@8.1.1)
eslint: 8.57.1
optionalDependencies:
- typescript: 5.7.2
+ typescript: 5.8.2
transitivePeerDependencies:
- supports-color
@@ -34164,15 +34274,15 @@ snapshots:
'@typescript-eslint/types': 6.21.0
'@typescript-eslint/visitor-keys': 6.21.0
- '@typescript-eslint/type-utils@5.62.0(eslint@8.57.1)(typescript@5.7.2)':
+ '@typescript-eslint/type-utils@5.62.0(eslint@8.57.1)(typescript@5.8.2)':
dependencies:
- '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.7.2)
- '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.7.2)
+ '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.8.2)
+ '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.8.2)
debug: 4.4.0(supports-color@8.1.1)
eslint: 8.57.1
- tsutils: 3.21.0(typescript@5.7.2)
+ tsutils: 3.21.0(typescript@5.8.2)
optionalDependencies:
- typescript: 5.7.2
+ typescript: 5.8.2
transitivePeerDependencies:
- supports-color
@@ -34192,7 +34302,7 @@ snapshots:
'@typescript-eslint/types@6.21.0': {}
- '@typescript-eslint/typescript-estree@5.62.0(typescript@5.7.2)':
+ '@typescript-eslint/typescript-estree@5.62.0(typescript@5.8.2)':
dependencies:
'@typescript-eslint/types': 5.62.0
'@typescript-eslint/visitor-keys': 5.62.0
@@ -34200,9 +34310,9 @@ snapshots:
globby: 11.1.0
is-glob: 4.0.3
semver: 7.6.3
- tsutils: 3.21.0(typescript@5.7.2)
+ tsutils: 3.21.0(typescript@5.8.2)
optionalDependencies:
- typescript: 5.7.2
+ typescript: 5.8.2
transitivePeerDependencies:
- supports-color
@@ -34221,7 +34331,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/typescript-estree@6.21.0(typescript@5.7.2)':
+ '@typescript-eslint/typescript-estree@6.21.0(typescript@5.8.2)':
dependencies:
'@typescript-eslint/types': 6.21.0
'@typescript-eslint/visitor-keys': 6.21.0
@@ -34230,20 +34340,20 @@ snapshots:
is-glob: 4.0.3
minimatch: 9.0.3
semver: 7.6.3
- ts-api-utils: 1.3.0(typescript@5.7.2)
+ ts-api-utils: 1.3.0(typescript@5.8.2)
optionalDependencies:
- typescript: 5.7.2
+ typescript: 5.8.2
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@5.7.2)':
+ '@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@5.8.2)':
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1)
'@types/json-schema': 7.0.15
'@types/semver': 7.5.8
'@typescript-eslint/scope-manager': 5.62.0
'@typescript-eslint/types': 5.62.0
- '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.7.2)
+ '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.8.2)
eslint: 8.57.1
eslint-scope: 5.1.1
semver: 7.6.3
@@ -34351,6 +34461,29 @@ snapshots:
- typescript
- utf-8-validate
- vite
+ optional: true
+
+ '@vitest/browser@3.0.8(@testing-library/dom@10.4.0)(@types/node@22.7.4)(playwright@1.51.0)(typescript@5.7.2)(vite@6.1.0(@types/node@22.7.4)(jiti@1.21.6)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1)(yaml@2.6.1))(vitest@3.0.8)(webdriverio@9.8.0)':
+ dependencies:
+ '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.0)
+ '@vitest/mocker': 3.0.8(msw@2.7.3(@types/node@22.7.4)(typescript@5.7.2))(vite@6.1.0(@types/node@22.7.4)(jiti@1.21.6)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1)(yaml@2.6.1))
+ '@vitest/utils': 3.0.8
+ magic-string: 0.30.17
+ msw: 2.7.3(@types/node@22.7.4)(typescript@5.7.2)
+ sirv: 3.0.1
+ tinyrainbow: 2.0.0
+ vitest: 3.0.8(@types/debug@4.1.12)(@types/node@22.7.4)(@vitest/browser@3.0.8)(jsdom@24.1.3)(less@4.2.0)(lightningcss@1.28.2)(msw@2.7.3(@types/node@22.7.4)(typescript@5.7.2))(sass@1.79.4)(terser@5.34.1)
+ ws: 8.18.1
+ optionalDependencies:
+ playwright: 1.51.0
+ webdriverio: 9.8.0
+ transitivePeerDependencies:
+ - '@testing-library/dom'
+ - '@types/node'
+ - bufferutil
+ - typescript
+ - utf-8-validate
+ - vite
'@vitest/expect@3.0.8':
dependencies:
@@ -34368,6 +34501,15 @@ snapshots:
msw: 2.7.3(@types/node@22.7.4)(typescript@5.7.2)
vite: 5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1)
+ '@vitest/mocker@3.0.8(msw@2.7.3(@types/node@22.7.4)(typescript@5.7.2))(vite@6.1.0(@types/node@22.7.4)(jiti@1.21.6)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1)(yaml@2.6.1))':
+ dependencies:
+ '@vitest/spy': 3.0.8
+ estree-walker: 3.0.3
+ magic-string: 0.30.17
+ optionalDependencies:
+ msw: 2.7.3(@types/node@22.7.4)(typescript@5.7.2)
+ vite: 6.1.0(@types/node@22.7.4)(jiti@1.21.6)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1)(yaml@2.6.1)
+
'@vitest/pretty-format@3.0.8':
dependencies:
tinyrainbow: 2.0.0
@@ -34509,11 +34651,11 @@ snapshots:
'@vue/shared': 3.4.21
vue: 3.4.21(typescript@5.5.4)
- '@vue/server-renderer@3.4.21(vue@3.4.21(typescript@5.7.2))':
+ '@vue/server-renderer@3.4.21(vue@3.4.21(typescript@5.8.2))':
dependencies:
'@vue/compiler-ssr': 3.4.21
'@vue/shared': 3.4.21
- vue: 3.4.21(typescript@5.7.2)
+ vue: 3.4.21(typescript@5.8.2)
'@vue/shared@3.4.21': {}
@@ -35535,6 +35677,12 @@ snapshots:
dependencies:
is-windows: 1.0.2
+ better-sqlite3@11.7.2:
+ dependencies:
+ bindings: 1.5.0
+ prebuild-install: 7.1.3
+ optional: true
+
big-integer@1.6.52: {}
big.js@5.2.2: {}
@@ -35548,6 +35696,10 @@ snapshots:
binary-extensions@2.3.0: {}
+ bindings@1.5.0:
+ dependencies:
+ file-uri-to-path: 1.0.0
+
bl@4.1.0:
dependencies:
buffer: 5.7.1
@@ -36005,6 +36157,9 @@ snapshots:
dependencies:
readdirp: 4.0.2
+ chownr@1.1.4:
+ optional: true
+
chownr@2.0.0: {}
chownr@3.0.0: {}
@@ -36390,14 +36545,14 @@ snapshots:
optionalDependencies:
typescript: 5.5.4
- cosmiconfig@9.0.0(typescript@5.7.2):
+ cosmiconfig@9.0.0(typescript@5.8.2):
dependencies:
env-paths: 2.2.1
import-fresh: 3.3.0
js-yaml: 4.1.0
parse-json: 5.2.0
optionalDependencies:
- typescript: 5.7.2
+ typescript: 5.8.2
crc-32@1.2.2:
optional: true
@@ -37202,7 +37357,7 @@ snapshots:
dotenv-expand@11.0.6:
dependencies:
- dotenv: 16.4.5
+ dotenv: 16.4.7
dotenv@16.3.1: {}
@@ -37210,10 +37365,12 @@ snapshots:
dotenv@16.4.7: {}
- drizzle-orm@0.35.2(@op-engineering/op-sqlite@11.2.13(react-native@0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2))(react@18.3.1))(@types/react@18.3.12)(kysely@0.27.4)(react@18.3.1):
+ drizzle-orm@0.35.2(@op-engineering/op-sqlite@11.2.13(react-native@0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2))(react@18.3.1))(@types/better-sqlite3@7.6.12)(@types/react@18.3.12)(better-sqlite3@11.7.2)(kysely@0.27.4)(react@18.3.1):
optionalDependencies:
- '@op-engineering/op-sqlite': 11.2.13(react-native@0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2))(react@18.3.1)
+ '@op-engineering/op-sqlite': 11.2.13(react-native@0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2))(react@18.3.1)
+ '@types/better-sqlite3': 7.6.12
'@types/react': 18.3.12
+ better-sqlite3: 11.7.2
kysely: 0.27.4
react: 18.3.1
@@ -37758,20 +37915,20 @@ snapshots:
source-map: 0.6.1
optional: true
- eslint-config-next@14.0.0(eslint@8.57.1)(typescript@5.7.2):
+ eslint-config-next@14.0.0(eslint@8.57.1)(typescript@5.8.2):
dependencies:
'@next/eslint-plugin-next': 14.0.0
'@rushstack/eslint-patch': 1.10.4
- '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.7.2)
+ '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.8.2)
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1)
- eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
+ eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1)
+ eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
eslint-plugin-jsx-a11y: 6.10.0(eslint@8.57.1)
eslint-plugin-react: 7.37.1(eslint@8.57.1)
eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1)
optionalDependencies:
- typescript: 5.7.2
+ typescript: 5.8.2
transitivePeerDependencies:
- eslint-import-resolver-webpack
- eslint-plugin-import-x
@@ -37817,19 +37974,19 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1):
+ eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.3.7(supports-color@8.1.1)
enhanced-resolve: 5.17.1
eslint: 8.57.1
- eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
+ eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
fast-glob: 3.3.2
get-tsconfig: 4.8.1
is-bun-module: 1.2.1
is-glob: 4.0.3
optionalDependencies:
- eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
+ eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
transitivePeerDependencies:
- '@typescript-eslint/parser'
- eslint-import-resolver-node
@@ -37846,14 +38003,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1):
+ eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1):
dependencies:
debug: 3.2.7
optionalDependencies:
- '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.7.2)
+ '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.8.2)
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1)
+ eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1)
transitivePeerDependencies:
- supports-color
@@ -37905,7 +38062,7 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1):
+ eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.8
@@ -37916,7 +38073,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
+ eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
hasown: 2.0.2
is-core-module: 2.15.1
is-glob: 4.0.3
@@ -37928,18 +38085,18 @@ snapshots:
string.prototype.trimend: 1.0.8
tsconfig-paths: 3.15.0
optionalDependencies:
- '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.7.2)
+ '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.8.2)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-jest@26.9.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2):
+ eslint-plugin-jest@26.9.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1)(typescript@5.8.2):
dependencies:
- '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.7.2)
+ '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.8.2)
eslint: 8.57.1
optionalDependencies:
- '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)
+ '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1)(typescript@5.8.2)
transitivePeerDependencies:
- supports-color
- typescript
@@ -38295,6 +38452,9 @@ snapshots:
signal-exit: 4.1.0
strip-final-newline: 3.0.0
+ expand-template@2.0.3:
+ optional: true
+
expand-tilde@2.0.2:
dependencies:
homedir-polyfill: 1.0.3
@@ -38570,7 +38730,35 @@ snapshots:
dependencies:
invariant: 2.2.4
- expo-router@3.5.21(gtohwu5bdvnl7tvlmjhokmubum):
+ expo-router@3.5.21(43cc03a7fb538f7aef105856925492f6):
+ dependencies:
+ '@expo/metro-runtime': 3.2.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))
+ '@expo/server': 0.4.4(typescript@5.5.4)
+ '@radix-ui/react-slot': 1.0.1(react@18.2.0)
+ '@react-navigation/bottom-tabs': 6.5.20(@react-navigation/native@6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ '@react-navigation/native': 6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ '@react-navigation/native-stack': 6.9.26(@react-navigation/native@6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ expo: 51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13)
+ expo-constants: 16.0.2(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13))
+ expo-linking: 6.3.1(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13))
+ expo-splash-screen: 0.27.5(encoding@0.1.13)(expo-modules-autolinking@1.11.3)(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13))
+ expo-status-bar: 1.12.1
+ react-native-helmet-async: 2.0.4(react@18.2.0)
+ react-native-safe-area-context: 4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ schema-utils: 4.2.0
+ optionalDependencies:
+ '@react-navigation/drawer': 6.7.2(fe8cd8328c484d4e3eaed8eea351852b)
+ react-native-reanimated: 3.10.1(@babel/core@7.24.5)(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ transitivePeerDependencies:
+ - encoding
+ - expo-modules-autolinking
+ - react
+ - react-native
+ - supports-color
+ - typescript
+
+ expo-router@3.5.21(49b2fd6c45ca81e2d20f2f5a4be05a3e):
dependencies:
'@expo/metro-runtime': 3.2.1(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))
'@expo/server': 0.4.4(typescript@5.5.4)
@@ -38588,7 +38776,7 @@ snapshots:
react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
schema-utils: 4.2.0
optionalDependencies:
- '@react-navigation/drawer': 6.7.2(yaao3llbshooz2bjipuf6mkduy)
+ '@react-navigation/drawer': 6.7.2(de9b7caae7cef38a32afa5b76a3c9d54)
react-native-reanimated: 3.10.1(@babel/core@7.26.0)(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
transitivePeerDependencies:
- encoding
@@ -38598,7 +38786,7 @@ snapshots:
- supports-color
- typescript
- expo-router@3.5.21(j6qjh2jsuy2ozdtd6girxrw3ky):
+ expo-router@3.5.21(988d822f9e58e176bb73f45e8e45eb4a):
dependencies:
'@expo/metro-runtime': 3.2.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))
'@expo/server': 0.4.4(typescript@5.3.3)
@@ -38616,7 +38804,7 @@ snapshots:
react-native-screens: 3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
schema-utils: 4.2.0
optionalDependencies:
- '@react-navigation/drawer': 6.7.2(bmedeebhe3ixiqe753c2r26xfi)
+ '@react-navigation/drawer': 6.7.2(038ae2d2ed70d2cde1afeae3252026e4)
react-native-reanimated: 3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
transitivePeerDependencies:
- encoding
@@ -38626,35 +38814,7 @@ snapshots:
- supports-color
- typescript
- expo-router@3.5.21(qrxjjyxvihi5xb6jovt7bb6fjy):
- dependencies:
- '@expo/metro-runtime': 3.2.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))
- '@expo/server': 0.4.4(typescript@5.5.4)
- '@radix-ui/react-slot': 1.0.1(react@18.2.0)
- '@react-navigation/bottom-tabs': 6.5.20(@react-navigation/native@6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- '@react-navigation/native': 6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- '@react-navigation/native-stack': 6.9.26(@react-navigation/native@6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- expo: 51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13)
- expo-constants: 16.0.2(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13))
- expo-linking: 6.3.1(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13))
- expo-splash-screen: 0.27.5(encoding@0.1.13)(expo-modules-autolinking@1.11.3)(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13))
- expo-status-bar: 1.12.1
- react-native-helmet-async: 2.0.4(react@18.2.0)
- react-native-safe-area-context: 4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- schema-utils: 4.2.0
- optionalDependencies:
- '@react-navigation/drawer': 6.7.2(f5uupuoecme7pb3346nlwm73my)
- react-native-reanimated: 3.10.1(@babel/core@7.24.5)(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- transitivePeerDependencies:
- - encoding
- - expo-modules-autolinking
- - react
- - react-native
- - supports-color
- - typescript
-
- expo-router@3.5.23(x45f6tg66eoafhyrv4brrngbdm):
+ expo-router@3.5.23(2f86f7434a59b644ba234fab7be01c9e):
dependencies:
'@expo/metro-runtime': 3.2.3(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))
'@expo/server': 0.4.4(typescript@5.5.4)
@@ -38672,7 +38832,7 @@ snapshots:
react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
schema-utils: 4.2.0
optionalDependencies:
- '@react-navigation/drawer': 6.7.2(f5uupuoecme7pb3346nlwm73my)
+ '@react-navigation/drawer': 6.7.2(fe8cd8328c484d4e3eaed8eea351852b)
react-native-reanimated: 3.10.1(@babel/core@7.24.5)(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
transitivePeerDependencies:
- encoding
@@ -39041,6 +39201,8 @@ snapshots:
schema-utils: 3.3.0
webpack: 5.95.0(@swc/core@1.10.1(@swc/helpers@0.5.5))
+ file-uri-to-path@1.0.0: {}
+
filelist@1.0.4:
dependencies:
minimatch: 5.1.6
@@ -39260,6 +39422,9 @@ snapshots:
fresh@0.5.2: {}
+ fs-constants@1.0.0:
+ optional: true
+
fs-extra@10.1.0:
dependencies:
graceful-fs: 4.2.11
@@ -39446,6 +39611,9 @@ snapshots:
getenv@1.0.0: {}
+ github-from-package@0.0.0:
+ optional: true
+
github-slugger@1.5.0: {}
glob-parent@5.1.2:
@@ -42644,6 +42812,9 @@ snapshots:
mixme@0.5.10: {}
+ mkdirp-classic@0.5.3:
+ optional: true
+
mkdirp@0.5.6:
dependencies:
minimist: 1.2.8
@@ -42747,6 +42918,9 @@ snapshots:
nanoid@3.3.8: {}
+ napi-build-utils@2.0.0:
+ optional: true
+
native-run@2.0.1:
dependencies:
'@ionic/utils-fs': 3.1.7
@@ -43757,13 +43931,13 @@ snapshots:
'@csstools/utilities': 2.0.0(postcss@8.4.47)
postcss: 8.4.47
- postcss-load-config@4.0.2(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.5))(@types/node@20.16.10)(typescript@5.7.2)):
+ postcss-load-config@4.0.2(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.5))(@types/node@20.16.10)(typescript@5.8.2)):
dependencies:
lilconfig: 3.1.2
yaml: 2.6.1
optionalDependencies:
postcss: 8.4.47
- ts-node: 10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.5))(@types/node@20.16.10)(typescript@5.7.2)
+ ts-node: 10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.5))(@types/node@20.16.10)(typescript@5.8.2)
postcss-load-config@4.0.2(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.5))(@types/node@22.7.4)(typescript@5.5.4)):
dependencies:
@@ -44112,6 +44286,22 @@ snapshots:
dependencies:
commander: 9.5.0
+ prebuild-install@7.1.3:
+ dependencies:
+ detect-libc: 2.0.3
+ expand-template: 2.0.3
+ github-from-package: 0.0.0
+ minimist: 1.2.8
+ mkdirp-classic: 0.5.3
+ napi-build-utils: 2.0.0
+ node-abi: 3.68.0
+ pump: 3.0.2
+ rc: 1.2.8
+ simple-get: 4.0.1
+ tar-fs: 2.1.2
+ tunnel-agent: 0.6.0
+ optional: true
+
preferred-pm@3.1.4:
dependencies:
find-up: 5.0.0
@@ -44538,7 +44728,7 @@ snapshots:
react-loadable: '@docusaurus/react-loadable@6.0.0(react@18.2.0)'
webpack: 5.95.0(@swc/core@1.10.1(@swc/helpers@0.5.5))
- react-native-builder-bob@0.30.2(typescript@5.7.2):
+ react-native-builder-bob@0.30.2(typescript@5.8.2):
dependencies:
'@babel/core': 7.25.7
'@babel/plugin-transform-strict-mode': 7.25.7(@babel/core@7.25.7)
@@ -44548,7 +44738,7 @@ snapshots:
'@babel/preset-typescript': 7.25.7(@babel/core@7.25.7)
babel-plugin-module-resolver: 5.0.2
browserslist: 4.24.0
- cosmiconfig: 9.0.0(typescript@5.7.2)
+ cosmiconfig: 9.0.0(typescript@5.8.2)
cross-spawn: 7.0.3
dedent: 0.7.0
del: 6.1.1
@@ -45074,10 +45264,10 @@ snapshots:
- supports-color
- utf-8-validate
- react-native@0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2):
+ react-native@0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2):
dependencies:
'@jest/create-cache-key-function': 29.7.0
- '@react-native-community/cli': 14.1.0(typescript@5.7.2)
+ '@react-native-community/cli': 14.1.0(typescript@5.8.2)
'@react-native-community/cli-platform-android': 14.1.0
'@react-native-community/cli-platform-ios': 14.1.0
'@react-native/assets-registry': 0.75.3
@@ -45086,7 +45276,7 @@ snapshots:
'@react-native/gradle-plugin': 0.75.3
'@react-native/js-polyfills': 0.75.3
'@react-native/normalize-colors': 0.75.3
- '@react-native/virtualized-lists': 0.75.3(@types/react@18.3.11)(react-native@0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2))(react@18.3.1)
+ '@react-native/virtualized-lists': 0.75.3(@types/react@18.3.11)(react-native@0.75.3(@babel/core@7.25.7)(@babel/preset-env@7.26.0(@babel/core@7.25.7))(@types/react@18.3.11)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2))(react@18.3.1)
abort-controller: 3.0.0
anser: 1.4.10
ansi-regex: 5.0.1
@@ -45180,10 +45370,10 @@ snapshots:
- typescript
- utf-8-validate
- react-native@0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2):
+ react-native@0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2):
dependencies:
'@jest/create-cache-key-function': 29.7.0
- '@react-native-community/cli': 14.1.0(typescript@5.7.2)
+ '@react-native-community/cli': 14.1.0(typescript@5.8.2)
'@react-native-community/cli-platform-android': 14.1.0
'@react-native-community/cli-platform-ios': 14.1.0
'@react-native/assets-registry': 0.75.3
@@ -45192,7 +45382,7 @@ snapshots:
'@react-native/gradle-plugin': 0.75.3
'@react-native/js-polyfills': 0.75.3
'@react-native/normalize-colors': 0.75.3
- '@react-native/virtualized-lists': 0.75.3(@types/react@18.3.12)(react-native@0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.7.2))(react@18.3.1)
+ '@react-native/virtualized-lists': 0.75.3(@types/react@18.3.12)(react-native@0.75.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(encoding@0.1.13)(react@18.3.1)(typescript@5.8.2))(react@18.3.1)
abort-controller: 3.0.0
anser: 1.4.10
ansi-regex: 5.0.1
@@ -45234,19 +45424,7 @@ snapshots:
- utf-8-validate
optional: true
- react-navigation-stack@2.10.4(b23yjknfeew5kcy4o5zrlfz5ae):
- dependencies:
- '@react-native-community/masked-view': 0.1.11(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- color: 3.2.1
- react: 18.2.0
- react-native: 0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0)
- react-native-gesture-handler: 2.16.2(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- react-native-iphone-x-helper: 1.3.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))
- react-native-safe-area-context: 4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
- react-navigation: 4.4.4(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
-
- react-navigation-stack@2.10.4(ei6zhj5w65kzzp3jt27w3zu7ea):
+ react-navigation-stack@2.10.4(b5d6035dfb87b14e0677db2e89c1e7ef):
dependencies:
'@react-native-community/masked-view': 0.1.11(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
color: 3.2.1
@@ -45258,6 +45436,18 @@ snapshots:
react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
react-navigation: 4.4.4(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ react-navigation-stack@2.10.4(cf0911ea264205029347060226fe0d29):
+ dependencies:
+ '@react-native-community/masked-view': 0.1.11(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ color: 3.2.1
+ react: 18.2.0
+ react-native: 0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0)
+ react-native-gesture-handler: 2.16.2(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ react-native-iphone-x-helper: 1.3.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))
+ react-native-safe-area-context: 4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+ react-navigation: 4.4.4(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)
+
react-navigation@4.4.4(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0):
dependencies:
'@react-navigation/core': 3.7.9(react@18.2.0)
@@ -46312,6 +46502,16 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ simple-concat@1.0.1:
+ optional: true
+
+ simple-get@4.0.1:
+ dependencies:
+ decompress-response: 6.0.0
+ once: 1.4.0
+ simple-concat: 1.0.1
+ optional: true
+
simple-plist@1.3.1:
dependencies:
bplist-creator: 0.1.0
@@ -46867,7 +47067,7 @@ snapshots:
tabbable@6.2.0: {}
- tailwindcss@3.4.13(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.5))(@types/node@20.16.10)(typescript@5.7.2)):
+ tailwindcss@3.4.13(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.5))(@types/node@20.16.10)(typescript@5.8.2)):
dependencies:
'@alloc/quick-lru': 5.2.0
arg: 5.0.2
@@ -46886,7 +47086,7 @@ snapshots:
postcss: 8.4.47
postcss-import: 15.1.0(postcss@8.4.47)
postcss-js: 4.0.1(postcss@8.4.47)
- postcss-load-config: 4.0.2(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.5))(@types/node@20.16.10)(typescript@5.7.2))
+ postcss-load-config: 4.0.2(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.5))(@types/node@20.16.10)(typescript@5.8.2))
postcss-nested: 6.2.0(postcss@8.4.47)
postcss-selector-parser: 6.1.2
resolve: 1.22.8
@@ -46987,6 +47187,14 @@ snapshots:
tapable@2.2.1: {}
+ tar-fs@2.1.2:
+ dependencies:
+ chownr: 1.1.4
+ mkdirp-classic: 0.5.3
+ pump: 3.0.2
+ tar-stream: 2.2.0
+ optional: true
+
tar-fs@3.0.6:
dependencies:
pump: 3.0.2
@@ -46996,6 +47204,15 @@ snapshots:
bare-path: 2.1.3
optional: true
+ tar-stream@2.2.0:
+ dependencies:
+ bl: 4.1.0
+ end-of-stream: 1.4.4
+ fs-constants: 1.0.0
+ inherits: 2.0.4
+ readable-stream: 3.6.2
+ optional: true
+
tar-stream@3.1.7:
dependencies:
b4a: 1.6.7
@@ -47259,13 +47476,13 @@ snapshots:
dependencies:
typescript: 5.3.3
- ts-api-utils@1.3.0(typescript@5.7.2):
+ ts-api-utils@1.3.0(typescript@5.8.2):
dependencies:
- typescript: 5.7.2
+ typescript: 5.8.2
ts-interface-checker@0.1.13: {}
- ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.5))(@types/node@20.16.10)(typescript@5.7.2):
+ ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.5))(@types/node@20.16.10)(typescript@5.8.2):
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.11
@@ -47279,7 +47496,7 @@ snapshots:
create-require: 1.1.1
diff: 4.0.2
make-error: 1.3.6
- typescript: 5.7.2
+ typescript: 5.8.2
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
optionalDependencies:
@@ -47326,6 +47543,26 @@ snapshots:
optionalDependencies:
'@swc/core': 1.10.1(@swc/helpers@0.5.5)
+ ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.5))(@types/node@22.7.4)(typescript@5.8.2):
+ dependencies:
+ '@cspotcode/source-map-support': 0.8.1
+ '@tsconfig/node10': 1.0.11
+ '@tsconfig/node12': 1.0.11
+ '@tsconfig/node14': 1.0.3
+ '@tsconfig/node16': 1.0.4
+ '@types/node': 22.7.4
+ acorn: 8.12.1
+ acorn-walk: 8.3.4
+ arg: 4.1.3
+ create-require: 1.1.1
+ diff: 4.0.2
+ make-error: 1.3.6
+ typescript: 5.8.2
+ v8-compile-cache-lib: 3.0.1
+ yn: 3.1.1
+ optionalDependencies:
+ '@swc/core': 1.10.1(@swc/helpers@0.5.5)
+
ts-node@10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.16.10)(typescript@4.5.5):
dependencies:
'@cspotcode/source-map-support': 0.8.1
@@ -47373,10 +47610,10 @@ snapshots:
tslib@2.7.0: {}
- tsutils@3.21.0(typescript@5.7.2):
+ tsutils@3.21.0(typescript@5.8.2):
dependencies:
tslib: 1.14.1
- typescript: 5.7.2
+ typescript: 5.8.2
tty-table@4.2.3:
dependencies:
@@ -47543,6 +47780,8 @@ snapshots:
typescript@5.7.2: {}
+ typescript@5.8.2: {}
+
ua-parser-js@1.0.39: {}
uc.micro@2.1.0: {}
@@ -48175,15 +48414,15 @@ snapshots:
optionalDependencies:
typescript: 5.5.4
- vue@3.4.21(typescript@5.7.2):
+ vue@3.4.21(typescript@5.8.2):
dependencies:
'@vue/compiler-dom': 3.4.21
'@vue/compiler-sfc': 3.4.21
'@vue/runtime-dom': 3.4.21
- '@vue/server-renderer': 3.4.21(vue@3.4.21(typescript@5.7.2))
+ '@vue/server-renderer': 3.4.21(vue@3.4.21(typescript@5.8.2))
'@vue/shared': 3.4.21
optionalDependencies:
- typescript: 5.7.2
+ typescript: 5.8.2
vuetify@3.6.8(typescript@5.5.4)(vite-plugin-vuetify@2.0.4)(vue@3.4.21(typescript@5.5.4)):
dependencies:
diff --git a/verdaccio-config.yaml b/verdaccio-config.yaml
index e58226111..b354099c7 100644
--- a/verdaccio-config.yaml
+++ b/verdaccio-config.yaml
@@ -2,7 +2,15 @@ storage: /tmp/storage
auth:
htpasswd:
file: /tmp/htpasswd
+uplinks:
+ npmjs:
+ url: https://registry.npmjs.org/
packages:
+ # Our better-sqlite3 fork is published under @powersync without being part of this repository.
+ '@powersync/better-sqlite3':
+ access: $all
+ publish: false
+ proxy: npmjs
'@powersync/*':
access: $all
publish: $all
diff --git a/vitest.workspace.ts b/vitest.workspace.ts
new file mode 100644
index 000000000..8e6c09dda
--- /dev/null
+++ b/vitest.workspace.ts
@@ -0,0 +1,4 @@
+export default [
+ // Consider all packages with a vitest configuration file as part of the test workspace.
+ 'packages/*/vitest.config.ts'
+];