{"_id":"@bullet./paraql","_rev":"4-0e80b8b3dd60a69922d6779b9b9cb32b","name":"@bullet./paraql","dist-tags":{"latest":"0.3.0"},"versions":{"0.1.0":{"name":"@bullet./paraql","version":"0.1.0","keywords":["sql","autobase","vector-search"],"author":{"url":"https://tomasrav.me/","name":"Tomas Ravinskas","email":"tomas@tomasrav.me"},"license":"Apache-2.0","_id":"@bullet./paraql@0.1.0","maintainers":[{"name":"ozymandiasthegreat","email":"tomas@tomasrav.me"}],"homepage":"https://github.com/getbullet-app/paraql","bugs":{"url":"https://github.com/getbullet-app/paraql/issues"},"dist":{"shasum":"e64baad111e7348f5748641791797b8bbeb720c1","tarball":"https://registry.npmjs.org/@bullet./paraql/-/paraql-0.1.0.tgz","fileCount":16,"integrity":"sha512-X6rB5CcxsB4kPGCABW8KN5ZnJAc2x79xKp0AgCp9lfHM3RPqhNmj+2kQn4YQVDwUOWAkOwgs2gF1BeH0I7kpqA==","signatures":[{"sig":"MEQCIDgdOadiTynXZ51famkg9NBRLOO6NzND6U3UyK4OVWoxAiBwD0bf5OQGLrSihu+Xd64Awu0uDXe5QEafShzf93D9cA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":108879},"addon":true,"types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./package":"./package.json"},"funding":[{"url":"https://github.com/sponsors/OzymandiasTheGreat","type":"github"}],"gitHead":"eae1159821fb5dfa0a44d9a80628a8dbd846a956","imports":{"fs":{"bare":"bare-fs","default":"fs"},"path":{"bare":"bare-path","default":"path"},"zlib":{"bare":"bare-zlib","default":"zlib"},"buffer":{"bare":"bare-buffer","default":"buffer"},"fs/promises":{"bare":"bare-fs/promises","default":"fs/promises"}},"scripts":{"test":"npm run test:bare && npm run test:node","bench":"brittle-bare test/bench.js","test:bare":"brittle-bare test/all.js","test:node":"brittle-node test/all.js","test:manual":"bare test/manual.js"},"_npmUser":{"name":"ozymandiasthegreat","email":"tomas@tomasrav.me"},"repository":{"url":"git+https://github.com/getbullet-app/paraql.git","type":"git"},"_npmVersion":"12.0.1","description":"Parallel multi-writer relational database with SQL syntax. Native support for encryption, compression, and vector search.","directories":{},"_nodeVersion":"24.18.0","dependencies":{"autobee":"^1.0.10","bare-fs":"^4.7.4","bare-path":"^3.1.1","bare-zlib":"^1.4.1","bare-buffer":"^3.6.2","index-encoder":"^3.5.0","require-addon":"^1.2.0","sodium-native":"^5.1.0","ready-resource":"^1.2.0","rocksdb-native":"^3.17.2","compact-encoding":"^3.3.0"},"_hasShrinkwrap":false,"devDependencies":{"brittle":"^4.0.2","prettier":"^3.9.4","test-tmp":"^1.4.0","cmake-npm":"^1.1.2","corestore":"^7.11.0","cmake-bare":"^1.8.0","cmake-napi":"^1.2.2","cmake-fetch":"^1.5.2","bare-compat-napi":"^1.3.9"},"_npmOperationalInternal":{"tmp":"tmp/paraql_0.1.0_1785820503335_0.23018783883266947","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@bullet./paraql","version":"0.1.2","keywords":["sql","autobase","vector-search"],"author":{"url":"https://tomasrav.me/","name":"Tomas Ravinskas","email":"tomas@tomasrav.me"},"license":"Apache-2.0","_id":"@bullet./paraql@0.1.2","maintainers":[{"name":"ozymandiasthegreat","email":"tomas@tomasrav.me"}],"homepage":"https://github.com/getbullet-app/paraql","bugs":{"url":"https://github.com/getbullet-app/paraql/issues"},"dist":{"shasum":"576822234f399764b91bf6fe140d5762c48a9449","tarball":"https://registry.npmjs.org/@bullet./paraql/-/paraql-0.1.2.tgz","fileCount":39,"integrity":"sha512-fRlLtDAHWxDwdaz7gXB3Zi9oaqZgIfu3bmy3cK7lr3dv01eLtFPexUYjMrgKZlok5yXLqflct6fQxaW6zfCPoA==","signatures":[{"sig":"MEYCIQCqcWZGvhZlW5C5g3yJPvF5uryKY1QN9/0HoqTKdEGbxgIhAJHjtEux7fnrCoX0JMELCuE2/c12/Iel24IFzJ+fcpoP","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bullet.%2fparaql@0.1.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":32493443},"addon":true,"types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./package":"./package.json"},"funding":[{"url":"https://github.com/sponsors/OzymandiasTheGreat","type":"github"}],"gitHead":"876308890e3cec6ed4d919766c1ebf0f1708f029","imports":{"fs":{"bare":"bare-fs","default":"fs"},"path":{"bare":"bare-path","default":"path"},"zlib":{"bare":"bare-zlib","default":"zlib"},"buffer":{"bare":"bare-buffer","default":"buffer"},"fs/promises":{"bare":"bare-fs/promises","default":"fs/promises"}},"scripts":{"test":"npm run test:bare && npm run test:node","bench":"brittle-bare test/bench.js","test:bare":"brittle-bare test/all.js","test:node":"brittle-node test/all.js","test:manual":"bare test/manual.js"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f18ecc83-d5c8-4e10-9534-ac21d9300b04"}},"repository":{"url":"git+https://github.com/getbullet-app/paraql.git","type":"git"},"_npmVersion":"11.16.0","description":"Parallel multi-writer relational database with SQL syntax. Native support for encryption, compression, and vector search.","directories":{},"_nodeVersion":"24.18.0","dependencies":{"autobee":"^1.0.10","bare-fs":"^4.7.4","bare-path":"^3.1.1","bare-zlib":"^1.4.1","bare-buffer":"^3.6.2","index-encoder":"^3.5.0","require-addon":"^1.2.0","sodium-native":"^5.1.0","ready-resource":"^1.2.0","rocksdb-native":"^3.17.2","compact-encoding":"^3.3.0"},"_hasShrinkwrap":false,"devDependencies":{"brittle":"^4.0.2","prettier":"^3.9.4","test-tmp":"^1.4.0","cmake-npm":"^1.1.2","corestore":"^7.11.0","cmake-bare":"^1.8.0","cmake-napi":"^1.2.2","cmake-fetch":"^1.5.2","bare-compat-napi":"^1.3.9"},"_npmOperationalInternal":{"tmp":"tmp/paraql_0.1.2_1785823863149_0.44067519755656304","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@bullet./paraql","version":"0.2.0","keywords":["sql","autobase","vector-search"],"author":{"url":"https://tomasrav.me/","name":"Tomas Ravinskas","email":"tomas@tomasrav.me"},"license":"Apache-2.0","_id":"@bullet./paraql@0.2.0","maintainers":[{"name":"ozymandiasthegreat","email":"tomas@tomasrav.me"}],"homepage":"https://github.com/getbullet-app/paraql","bugs":{"url":"https://github.com/getbullet-app/paraql/issues"},"dist":{"shasum":"a80f4e430efbd2792ecb471df54fc5f13dd3b987","tarball":"https://registry.npmjs.org/@bullet./paraql/-/paraql-0.2.0.tgz","fileCount":39,"integrity":"sha512-k0mW8/PtWfOYpDhuDm99xUOaMWWwcqbXmdaQ2oAKPxiknGS9kYuVKg6niHcm6AjvAnVjr3/AYLaHTJ81YynoYg==","signatures":[{"sig":"MEQCIFCXqzWLh3ulwEuCDTe6grvArLvG7BGdI+QXUnbQSYDEAiAzjz3HyAE2Ntg1JIHcFLhxCLF5Li8pJIR1V3rNdlxyPw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bullet.%2fparaql@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":32240922},"addon":true,"types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./package":"./package.json"},"funding":[{"url":"https://github.com/sponsors/OzymandiasTheGreat","type":"github"}],"gitHead":"13d2c04635d9ed5715b9ad91508d617f50ce8522","imports":{"fs":{"bare":"bare-fs","default":"fs"},"path":{"bare":"bare-path","default":"path"},"zlib":{"bare":"bare-zlib","default":"zlib"},"buffer":{"bare":"bare-buffer","default":"buffer"},"fs/promises":{"bare":"bare-fs/promises","default":"fs/promises"}},"scripts":{"test":"npm run test:bare && npm run test:node","bench":"brittle-bare test/bench.js","test:bare":"brittle-bare test/all.js","test:node":"brittle-node test/all.js","test:manual":"bare test/manual.js"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f18ecc83-d5c8-4e10-9534-ac21d9300b04"}},"repository":{"url":"git+https://github.com/getbullet-app/paraql.git","type":"git"},"_npmVersion":"11.16.0","description":"Parallel multi-writer relational database with SQL syntax. Native support for encryption, compression, and vector search.","directories":{},"_nodeVersion":"24.18.0","dependencies":{"autobee":"^1.0.10","bare-fs":"^4.7.4","bare-path":"^3.1.1","bare-zlib":"^1.4.1","bare-buffer":"^3.6.2","index-encoder":"^3.5.0","require-addon":"^1.2.0","sodium-native":"^5.1.0","ready-resource":"^1.2.0","rocksdb-native":"^3.17.2","compact-encoding":"^3.3.0"},"_hasShrinkwrap":false,"devDependencies":{"brittle":"^4.0.2","prettier":"^3.9.4","test-tmp":"^1.4.0","cmake-npm":"^1.1.2","corestore":"^7.11.0","cmake-bare":"^1.8.0","cmake-napi":"^1.2.2","cmake-fetch":"^1.5.2","bare-compat-napi":"^1.3.9"},"_npmOperationalInternal":{"tmp":"tmp/paraql_0.2.0_1786215744465_0.970239099995474","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@bullet./paraql","version":"0.3.0","description":"Fast, parallel, multi-writer relational database with SQL syntax. Native support for encryption, compression, and vector search.","author":{"name":"Tomas Ravinskas","email":"tomas@tomasrav.me","url":"https://tomasrav.me/"},"license":"Apache-2.0","addon":true,"scripts":{"test":"npm run test:bare && npm run test:node","test:bare":"brittle-bare test/all.js","test:node":"brittle-node test/all.js","test:manual":"bare test/manual.js","bench":"brittle-bare test/bench.js"},"exports":{"./package":"./package.json",".":{"types":"./index.d.ts","default":"./index.js"}},"imports":{"buffer":{"bare":"bare-buffer","default":"buffer"},"fs":{"bare":"bare-fs","default":"fs"},"fs/promises":{"bare":"bare-fs/promises","default":"fs/promises"},"path":{"bare":"bare-path","default":"path"}},"homepage":"https://github.com/getbullet-app/paraql","repository":{"type":"git","url":"git+https://github.com/getbullet-app/paraql.git"},"funding":[{"type":"github","url":"https://github.com/sponsors/OzymandiasTheGreat"}],"keywords":["sql","autobase","vector-search"],"dependencies":{"autobee":"^2.7.2","bare-buffer":"^3.6.2","bare-fs":"^4.7.4","bare-path":"^3.1.1","compact-encoding":"^3.3.0","index-encoder":"^3.5.0","ready-resource":"^1.2.0","require-addon":"^1.2.0","rocksdb-native":"^3.17.2","sodium-native":"^5.1.0"},"devDependencies":{"bare-compat-napi":"^1.3.9","brittle":"^4.0.2","cmake-bare":"^1.8.0","cmake-fetch":"^1.5.2","cmake-napi":"^1.2.2","cmake-npm":"^1.1.2","corestore":"^7.11.0","prettier":"^3.9.4","test-tmp":"^1.4.0"},"gitHead":"9cb6190019fe8f249274c375ca16e5b1a5db99f2","types":"./index.d.ts","_id":"@bullet./paraql@0.3.0","bugs":{"url":"https://github.com/getbullet-app/paraql/issues"},"_nodeVersion":"24.20.0","_npmVersion":"11.19.0","dist":{"integrity":"sha512-QSVyWdeJ4SOHV9E6XozCpOBLI5ihGM5ofqwrivHhmi54XSeJEcde1yKXusTZ46VkBLxM7Na8HkwhiC7j/+nTrQ==","shasum":"90cc6e222bc0aaae6b886334ffd4dcefd7f19d1e","tarball":"https://registry.npmjs.org/@bullet./paraql/-/paraql-0.3.0.tgz","fileCount":39,"unpackedSize":32239222,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bullet.%2fparaql@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDmzDVvoaL7KCuim/z7fteAHl2Ilk67zHLEjaKTZK5TzwIhAKdD0r8hRFBPps0TqHqvRidVwlHMJqfA612B2QlmQn2g"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f18ecc83-d5c8-4e10-9534-ac21d9300b04"}},"directories":{},"maintainers":[{"name":"ozymandiasthegreat","email":"tomas@tomasrav.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/paraql_0.3.0_1789324387654_0.23515578659293523"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-04T05:15:03.167Z","modified":"2026-09-13T18:33:08.323Z","0.1.0":"2026-08-04T05:15:03.463Z","0.1.2":"2026-08-04T06:11:03.573Z","0.2.0":"2026-08-08T19:02:24.841Z","0.3.0":"2026-09-13T18:33:08.012Z"},"bugs":{"url":"https://github.com/getbullet-app/paraql/issues"},"author":{"name":"Tomas Ravinskas","email":"tomas@tomasrav.me","url":"https://tomasrav.me/"},"license":"Apache-2.0","homepage":"https://github.com/getbullet-app/paraql","keywords":["sql","autobase","vector-search"],"repository":{"type":"git","url":"git+https://github.com/getbullet-app/paraql.git"},"description":"Fast, parallel, multi-writer relational database with SQL syntax. Native support for encryption, compression, and vector search.","maintainers":[{"name":"ozymandiasthegreat","email":"tomas@tomasrav.me"}],"readme":"# ParaQL\n\nParaQL is a mad-science experiment combining [libSQL](https://github.com/tursodatabase/libsql) (an open-contribution [SQLite](https://github.com/sqlite/sqlite) fork with native vector support) with [Autobase](https://github.com/holepunchto/autobase) (or to be more precise, it's next-gen iteration [Autobee](https://github.com/holepunchto/autobee)) for massively-parallel multi-writer access.\n\nIt logs every write in a per-instance append-only log (oplog) and applies them in deterministic order to a shared view (the database) ensuring no corruption can occur. Performance is impressive, it blows vanilla SQLite out of the water, in part due to flushing to disk less often. That's not an issue though, because by the time database write occurs the operation is already in the oplog, so in case crashes or corruption it can simply be reapplied. Peers who haven't written to the database simply fast-forward (download) the latest database version which on a good connection is even faster.\n\nThe oplog based design means that disk space used is roughly double (after compaction) that of vanilla SQLite. Operating requirements are considerably higher, because Autobee uses RocksDB as the storage backend and RocksDB doesn't free deleted data immediately as a performance optimization. Periodic compaction, both automatic, and manual, makes this an easily solvable issue.\n\nFor a better idea of how ParaQL performs and compares to other solutions see [the benchmark](./BENCHMARK.md).\n\nParaQL is developed on [Bare](https://github.com/holepunchto/bare) but it's also tested on Node. Because Bare is multi-platform and supports mobile operating systems as first class citizens, ParaQL runs on recent versions of Android, iOS, macOS, Linux, and Windows.\n\nParaQL supports encrypting the database with a 256-bit key, both on disk and in transport (meaning remote peers need to know the key to read or write into the database). The local-only temporary files are currently encrypted with unique but not random nonces. This is something we're still working on.\n\nParaQL has native support for vector data types and vector search functions with optional indexing. This is courtesy of libSQL and one of the primary reasons ParaQL was made: to support vector similarity search in P2P context.\n\n## Install\n\n```shell\nnpm i @bullet./paraql\n```\n\n## Usage\n\n```javascript\nconst Corestore = require(\"corestore\")\nconst ParaQL = require(\"@bullet./paraql\")\n\nconst store = new Corestore(\"./paraql\")\nconst db = new ParaQL(store)\n\nawait db.exec(`\n  CREATE TABLE people (id INTEGER PRIMARY KEY, name TEXT);\n  INSERT INTO people (name) VALUES ('Alice'), ('Bob');\n`)\n\nconst select = await db.prepare(\"SELECT id, name FROM people ORDER BY id\")\n\nfor await (const row of select.iterate()) {\n  console.log(row)\n}\n\nawait select.finalize()\nawait db.close()\n```\n\nPrints:\n\n```json\n{ id: 1, name: \"Alice\" }\n{ id: 2, name: \"Bob\" }\n```\n\n## API\n\n### `const db = new ParaQL(store[, key][, options])`\n\nCreates a new database or an instance of an existing database if key is provided. `store` is an instance of [Corestore](https://github.com/holepunchto/corestore) used for storage. `key` is either null or 32-byte key of the database.\n\n`options` include:\n\n```javascript\noptions = {\n  name: \"paraql.db\",\n  authorize: null,\n  keyPair: null,\n  encrypted: false,\n  encryptionKey: null,\n}\n```\n\nThese options should only be used at database creation and set for every instance of the database. Option mismatch may lead to database corruption and/or sync issues.\n\n`name` is the name of the database file, also used as a prefix for temporary files.\n\n`authorize` is either null or an (asynchronous) authorizer callback with the following signature:\n\n```typescript\n;(\n  key: Buffer,\n  action: ParaQL.AUTHORIZE_ACTION,\n  param1: string | null,\n  param2: string | null,\n  param3: string | null,\n  param4: string | null,\n) => Promise<boolean>\n```\n\nwhere `key` is the local key of the writer attempting the operation, `action` is numeric action code defined in `ParaQL.AUTHORIZE_ACTION` enum, and params 1 through 4 are [action specific strings (e.g. table name) or null](https://sqlite.org/c3ref/c_alter_table.html).\n\nDo note that operations initiated by initial instance (root node) and all read-only operations are always allowed and authorizer callback is **NOT** invoked for them.\n\n`keyPair`, if provided, is the signing key pair for the local writer in the form `{ publicKey: <32-byte Buffer>, secretKey: <32-byte Buffer> }` .\n\nIf `encrypted` is true and `encryptionKey` is provided as 32-byte buffer, it is used to encrypt the database.\n\n### `db.name`\n\nThe name of the database file.\n\n### `db.key`\n\nThe database key used for replication. `null` before `db.ready()` is called.\n\n### `db.local`\n\nThe key of the local writer. Pass this to `db.addWriter()` to grant write access. `null` before `db.ready()` is called.\n\n### `db.discoveryKey`\n\nThe discovery key of the database, can be used e.g. as the topic for replicating over [Hyperswarm](https://github.com/holepunchto/hyperswarm). `null` before `db.ready()` is called.\n\n### `encryptionKey`\n\nThe key used to encrypt the database or `null`. `null` before `db.ready()` is called.\n\n### `writable`\n\nWhether this instance has write access to the database. `false` if `db.addWriter()` hasn't been called with this instances local key or if `db.ready()` hasn't been called.\n\n### `encrypted`\n\nWhether this database is encrypted.\n\n### `await db.ready()`\n\nInitialized the database. All methods call this implicitly, so unless you need to access some instance property early, there's no need to call this yourself.\n\n### `await db.close()`\n\nCloses the database and cleans up all used resources. Does not close the Corestore instance.\n\n### `await db.addWriter(key)`\n\nGrant another instance of the database write access. `key` should be the local key of the remote instance. `db` needs to be writable.\n\n### `await db.removeWriter(key)`\n\nRevoke write access from another instance of the database. `key` should be the local key of the remote instance. `db` needs to be writable.\n\n### `db.replicate(isInitiatorOrStream)`\n\nCreates a replication stream that can be piped over any streamable transport. `isInitiatorOrStream` can be a boolean indicating whether this instance initiated Noise handshake, or another replication stream.\n\n### `await db.compact()`\n\nCompacts database and removes stale data. This operation is local only and can reduce disk space usage by up to 30x or more depending on the data stored and settings of the database. Compaction happens automatically but you might want to run this periodically, when idle.\n\n### `const info = await db.info()`\n\nGet information about disk space usage. Returned object has all properties in bytes and looks like this:\n\n```javascript\n{\n    database: number,\n    temporary: number,\n    total: number,\n}\n```\n\n### `await db.exec(sql)`\n\nExecute given SQL statement(s) without checking return values.\n\nThis is a convenience method.\n\n### `const stmt = await db.prepare(sql)`\n\nPrepare SQL statement `stmt` from the first statement in `sql`. If `sql` contains more than one statement tailing statements are discarded.\n\n### `stmt.sourceSQL`\n\nThe SQL string used to initialize this prepared statement.\n\n### `await stmt.finalize()`\n\nFinalize a statement freeing up resources used.\n\n### `const rows = await stmt.all(...params)`\n\nExecute a statement with given positional params. First param may optionally be an object containing named params.\n\nReturns an array of row objects keyed by column name.\n\n### `const row = await stmt.get(...params)`\n\nSame as `stmt.all()` except it only returns the first row.\n\n### `const result = await stmt.run(...params)`\n\nExecute a statement with given params and return an object in the form `{ changes: number, lastInsertRowid: number }`.\n\n### `for await (const row of stmt.iterate(...params))`\n\nExecute a statement with given params and return rows one by one.\n\n### `const buffer = await db.serialize()`\n\nReturn an unencrypted, uncompressed, serialized version of the database that can be (re-)used with any SQLite3 compatible application or library.\n\n### `const db = await ParaQL.deserialize(buffer)`\n\nInitiate a new ParaQL instance with any SQLite3 compatible database contained in the buffer.\n\n## License\n\nApache-2.0\n","readmeFilename":"README.md"}