@tursodatabase/sync 0.1.5 → 0.2.0-pre.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -18
- package/dist/promise.d.ts +43 -0
- package/dist/promise.d.ts.map +1 -0
- package/dist/promise.js +137 -0
- package/dist/promise.test.d.ts +2 -0
- package/dist/promise.test.d.ts.map +1 -0
- package/dist/promise.test.js +454 -0
- package/index.js +166 -50
- package/package.json +37 -48
- package/browser.js +0 -1
- package/dist/sync_engine.d.ts +0 -24
- package/dist/sync_engine.js +0 -152
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<h1 align="center">Turso
|
|
2
|
+
<h1 align="center">Turso Database for JavaScript in Node</h1>
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
|
-
<a title="JavaScript" target="_blank" href="https://www.npmjs.com/package/@tursodatabase/
|
|
6
|
+
<a title="JavaScript" target="_blank" href="https://www.npmjs.com/package/@tursodatabase/database"><img alt="npm" src="https://img.shields.io/npm/v/@tursodatabase/database"></a>
|
|
7
7
|
<a title="MIT" target="_blank" href="https://github.com/tursodatabase/turso/blob/main/LICENSE.md"><img src="http://img.shields.io/badge/license-MIT-orange.svg?style=flat-square"></a>
|
|
8
8
|
</p>
|
|
9
9
|
<p align="center">
|
|
@@ -14,40 +14,105 @@
|
|
|
14
14
|
|
|
15
15
|
## About
|
|
16
16
|
|
|
17
|
-
This package is
|
|
17
|
+
This package is the Turso embedded database library for JavaScript in Node.
|
|
18
18
|
|
|
19
19
|
> **⚠️ Warning:** This software is ALPHA, only use for development, testing, and experimentation. We are working to make it production ready, but do not use it for critical data right now.
|
|
20
20
|
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- **SQLite compatible:** SQLite query language and file format support ([status](https://github.com/tursodatabase/turso/blob/main/COMPAT.md)).
|
|
24
|
+
- **In-process**: No network overhead, runs directly in your Node.js process
|
|
25
|
+
- **TypeScript support**: Full TypeScript definitions included
|
|
26
|
+
- **Cross-platform**: Supports Linux (x86 and arm64), macOS, Windows (browser is supported in the separate package `@tursodatabase/database-browser` package)
|
|
27
|
+
|
|
21
28
|
## Installation
|
|
22
29
|
|
|
23
30
|
```bash
|
|
24
|
-
npm install @tursodatabase/
|
|
31
|
+
npm install @tursodatabase/database
|
|
25
32
|
```
|
|
26
33
|
|
|
27
34
|
## Getting Started
|
|
28
35
|
|
|
29
|
-
|
|
36
|
+
### In-Memory Database
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
import { connect } from '@tursodatabase/database';
|
|
40
|
+
|
|
41
|
+
// Create an in-memory database
|
|
42
|
+
const db = await connect(':memory:');
|
|
43
|
+
|
|
44
|
+
// Create a table
|
|
45
|
+
await db.exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)');
|
|
46
|
+
|
|
47
|
+
// Insert data
|
|
48
|
+
const insert = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
|
|
49
|
+
await insert.run('Alice', 'alice@example.com');
|
|
50
|
+
await insert.run('Bob', 'bob@example.com');
|
|
51
|
+
|
|
52
|
+
// Query data
|
|
53
|
+
const users = await db.prepare('SELECT * FROM users').all();
|
|
54
|
+
console.log(users);
|
|
55
|
+
// Output: [
|
|
56
|
+
// { id: 1, name: 'Alice', email: 'alice@example.com' },
|
|
57
|
+
// { id: 2, name: 'Bob', email: 'bob@example.com' }
|
|
58
|
+
// ]
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### File-Based Database
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
import { connect } from '@tursodatabase/database';
|
|
30
65
|
|
|
31
|
-
|
|
32
|
-
|
|
66
|
+
// Create or open a database file
|
|
67
|
+
const db = await connect('my-database.db');
|
|
33
68
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
69
|
+
// Create a table
|
|
70
|
+
await db.exec(`
|
|
71
|
+
CREATE TABLE IF NOT EXISTS posts (
|
|
72
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
73
|
+
title TEXT NOT NULL,
|
|
74
|
+
content TEXT,
|
|
75
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
76
|
+
)
|
|
77
|
+
`);
|
|
78
|
+
|
|
79
|
+
// Insert a post
|
|
80
|
+
const insertPost = db.prepare('INSERT INTO posts (title, content) VALUES (?, ?)');
|
|
81
|
+
const result = await insertPost.run('Hello World', 'This is my first blog post!');
|
|
82
|
+
|
|
83
|
+
console.log(`Inserted post with ID: ${result.lastInsertRowid}`);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Transactions
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
import { connect } from '@tursodatabase/database';
|
|
90
|
+
|
|
91
|
+
const db = await connect('transactions.db');
|
|
92
|
+
|
|
93
|
+
// Using transactions for atomic operations
|
|
94
|
+
const transaction = db.transaction(async (users) => {
|
|
95
|
+
const insert = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
|
|
96
|
+
for (const user of users) {
|
|
97
|
+
await insert.run(user.name, user.email);
|
|
98
|
+
}
|
|
39
99
|
});
|
|
40
100
|
|
|
41
|
-
//
|
|
42
|
-
await
|
|
43
|
-
|
|
44
|
-
|
|
101
|
+
// Execute transaction
|
|
102
|
+
await transaction([
|
|
103
|
+
{ name: 'Alice', email: 'alice@example.com' },
|
|
104
|
+
{ name: 'Bob', email: 'bob@example.com' }
|
|
105
|
+
]);
|
|
45
106
|
```
|
|
46
107
|
|
|
108
|
+
## API Reference
|
|
109
|
+
|
|
110
|
+
For complete API documentation, see [JavaScript API Reference](../../../../docs/javascript-api-reference.md).
|
|
111
|
+
|
|
47
112
|
## Related Packages
|
|
48
113
|
|
|
49
|
-
* The [@tursodatabase/database](https://www.npmjs.com/package/@tursodatabase/database) package provides the Turso in-memory database, compatible with SQLite.
|
|
50
114
|
* The [@tursodatabase/serverless](https://www.npmjs.com/package/@tursodatabase/serverless) package provides a serverless driver with the same API.
|
|
115
|
+
* The [@tursodatabase/sync](https://www.npmjs.com/package/@tursodatabase/sync) package provides bidirectional sync between a local Turso database and Turso Cloud.
|
|
51
116
|
|
|
52
117
|
## License
|
|
53
118
|
|
|
@@ -57,4 +122,4 @@ This project is licensed under the [MIT license](../../LICENSE.md).
|
|
|
57
122
|
|
|
58
123
|
- [GitHub Issues](https://github.com/tursodatabase/turso/issues)
|
|
59
124
|
- [Documentation](https://docs.turso.tech)
|
|
60
|
-
- [Discord Community](https://tur.so/discord)
|
|
125
|
+
- [Discord Community](https://tur.so/discord)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { DatabasePromise } from "@tursodatabase/database-common";
|
|
2
|
+
import { DatabaseOpts, EncryptionOpts, DatabaseRowMutation, DatabaseRowStatement, DatabaseRowTransformResult, DatabaseStats } from "@tursodatabase/sync-common";
|
|
3
|
+
declare class Database extends DatabasePromise {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(opts: DatabaseOpts);
|
|
6
|
+
/**
|
|
7
|
+
* connect database and initialize it in case of clean start
|
|
8
|
+
*/
|
|
9
|
+
connect(): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* pull new changes from the remote database
|
|
12
|
+
* if {@link DatabaseOpts.longPollTimeoutMs} is set - then server will hold the connection open until either new changes will appear in the database or timeout occurs.
|
|
13
|
+
* @returns true if new changes were pulled from the remote
|
|
14
|
+
*/
|
|
15
|
+
pull(): Promise<boolean>;
|
|
16
|
+
/**
|
|
17
|
+
* push new local changes to the remote database
|
|
18
|
+
* if {@link DatabaseOpts.transform} is set - then provided callback will be called for every mutation before sending it to the remote
|
|
19
|
+
*/
|
|
20
|
+
push(): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* checkpoint WAL for local database
|
|
23
|
+
*/
|
|
24
|
+
checkpoint(): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* @returns statistic of current local database
|
|
27
|
+
*/
|
|
28
|
+
stats(): Promise<DatabaseStats>;
|
|
29
|
+
/**
|
|
30
|
+
* close the database
|
|
31
|
+
*/
|
|
32
|
+
close(): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Creates a new database connection asynchronously.
|
|
36
|
+
*
|
|
37
|
+
* @param {Object} opts - Options for database behavior.
|
|
38
|
+
* @returns {Promise<Database>} - A promise that resolves to a Database instance.
|
|
39
|
+
*/
|
|
40
|
+
declare function connect(opts: DatabaseOpts): Promise<Database>;
|
|
41
|
+
export { connect, Database };
|
|
42
|
+
export type { DatabaseOpts, EncryptionOpts, DatabaseRowMutation, DatabaseRowStatement, DatabaseRowTransformResult };
|
|
43
|
+
//# sourceMappingURL=promise.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promise.d.ts","sourceRoot":"","sources":["../promise.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAChE,OAAO,EAAmB,YAAY,EAAE,cAAc,EAAW,mBAAmB,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,aAAa,EAAoB,MAAM,4BAA4B,CAAC;AAwC5M,cAAM,QAAS,SAAQ,eAAe;;gBAKtB,IAAI,EAAE,YAAY;IAmC9B;;OAEG;IACY,OAAO;IAGtB;;;;OAIG;IACG,IAAI;IAQV;;;OAGG;IACG,IAAI;IAGV;;OAEG;IACG,UAAU;IAGhB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,aAAa,CAAC;IAGrC;;OAEG;IACY,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAGxC;AAED;;;;;GAKG;AACH,iBAAe,OAAO,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAI5D;AAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAA;AAC5B,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,CAAA"}
|
package/dist/promise.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { DatabasePromise } from "@tursodatabase/database-common";
|
|
2
|
+
import { run, SyncEngineGuards } from "@tursodatabase/sync-common";
|
|
3
|
+
import { SyncEngine } from "#index";
|
|
4
|
+
import { promises } from "node:fs";
|
|
5
|
+
let NodeIO = {
|
|
6
|
+
async read(path) {
|
|
7
|
+
try {
|
|
8
|
+
return await promises.readFile(path);
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
if (error.code === 'ENOENT') {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
throw error;
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
async write(path, data) {
|
|
18
|
+
const unix = Math.floor(Date.now() / 1000);
|
|
19
|
+
const nonce = Math.floor(Math.random() * 1000000000);
|
|
20
|
+
const tmp = `${path}.tmp.${unix}.${nonce}`;
|
|
21
|
+
await promises.writeFile(tmp, new Uint8Array(data));
|
|
22
|
+
try {
|
|
23
|
+
await promises.rename(tmp, path);
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
await promises.unlink(tmp);
|
|
27
|
+
throw err;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
function memoryIO() {
|
|
32
|
+
let values = new Map();
|
|
33
|
+
return {
|
|
34
|
+
async read(path) {
|
|
35
|
+
return values.get(path);
|
|
36
|
+
},
|
|
37
|
+
async write(path, data) {
|
|
38
|
+
values.set(path, data);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
;
|
|
43
|
+
class Database extends DatabasePromise {
|
|
44
|
+
#runOpts;
|
|
45
|
+
#engine;
|
|
46
|
+
#io;
|
|
47
|
+
#guards;
|
|
48
|
+
constructor(opts) {
|
|
49
|
+
const engine = new SyncEngine({
|
|
50
|
+
path: opts.path,
|
|
51
|
+
clientName: opts.clientName,
|
|
52
|
+
useTransform: opts.transform != null,
|
|
53
|
+
protocolVersion: "v1" /* SyncEngineProtocolVersion.V1 */,
|
|
54
|
+
longPollTimeoutMs: opts.longPollTimeoutMs,
|
|
55
|
+
tracing: opts.tracing,
|
|
56
|
+
});
|
|
57
|
+
super(engine.db());
|
|
58
|
+
let headers = typeof opts.authToken === "function" ? () => ({
|
|
59
|
+
...(opts.authToken != null && { "Authorization": `Bearer ${opts.authToken()}` }),
|
|
60
|
+
...(opts.encryption != null && {
|
|
61
|
+
"x-turso-encryption-key": opts.encryption.key,
|
|
62
|
+
"x-turso-encryption-cipher": opts.encryption.cipher,
|
|
63
|
+
})
|
|
64
|
+
}) : {
|
|
65
|
+
...(opts.authToken != null && { "Authorization": `Bearer ${opts.authToken}` }),
|
|
66
|
+
...(opts.encryption != null && {
|
|
67
|
+
"x-turso-encryption-key": opts.encryption.key,
|
|
68
|
+
"x-turso-encryption-cipher": opts.encryption.cipher,
|
|
69
|
+
})
|
|
70
|
+
};
|
|
71
|
+
this.#runOpts = {
|
|
72
|
+
url: opts.url,
|
|
73
|
+
headers: headers,
|
|
74
|
+
preemptionMs: 1,
|
|
75
|
+
transform: opts.transform,
|
|
76
|
+
};
|
|
77
|
+
this.#engine = engine;
|
|
78
|
+
this.#io = this.memory ? memoryIO() : NodeIO;
|
|
79
|
+
this.#guards = new SyncEngineGuards();
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* connect database and initialize it in case of clean start
|
|
83
|
+
*/
|
|
84
|
+
async connect() {
|
|
85
|
+
await run(this.#runOpts, this.#io, this.#engine, this.#engine.connect());
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* pull new changes from the remote database
|
|
89
|
+
* if {@link DatabaseOpts.longPollTimeoutMs} is set - then server will hold the connection open until either new changes will appear in the database or timeout occurs.
|
|
90
|
+
* @returns true if new changes were pulled from the remote
|
|
91
|
+
*/
|
|
92
|
+
async pull() {
|
|
93
|
+
const changes = await this.#guards.wait(async () => await run(this.#runOpts, this.#io, this.#engine, this.#engine.wait()));
|
|
94
|
+
if (changes.empty()) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
await this.#guards.apply(async () => await run(this.#runOpts, this.#io, this.#engine, this.#engine.apply(changes)));
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* push new local changes to the remote database
|
|
102
|
+
* if {@link DatabaseOpts.transform} is set - then provided callback will be called for every mutation before sending it to the remote
|
|
103
|
+
*/
|
|
104
|
+
async push() {
|
|
105
|
+
await this.#guards.push(async () => await run(this.#runOpts, this.#io, this.#engine, this.#engine.push()));
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* checkpoint WAL for local database
|
|
109
|
+
*/
|
|
110
|
+
async checkpoint() {
|
|
111
|
+
await this.#guards.checkpoint(async () => await run(this.#runOpts, this.#io, this.#engine, this.#engine.checkpoint()));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* @returns statistic of current local database
|
|
115
|
+
*/
|
|
116
|
+
async stats() {
|
|
117
|
+
return (await run(this.#runOpts, this.#io, this.#engine, this.#engine.stats()));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* close the database
|
|
121
|
+
*/
|
|
122
|
+
async close() {
|
|
123
|
+
this.#engine.close();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Creates a new database connection asynchronously.
|
|
128
|
+
*
|
|
129
|
+
* @param {Object} opts - Options for database behavior.
|
|
130
|
+
* @returns {Promise<Database>} - A promise that resolves to a Database instance.
|
|
131
|
+
*/
|
|
132
|
+
async function connect(opts) {
|
|
133
|
+
const db = new Database(opts);
|
|
134
|
+
await db.connect();
|
|
135
|
+
return db;
|
|
136
|
+
}
|
|
137
|
+
export { connect, Database };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promise.test.d.ts","sourceRoot":"","sources":["../promise.test.ts"],"names":[],"mappings":""}
|