@tursodatabase/vercel-experimental 0.0.3 → 0.0.4
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 +15 -12
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,11 +35,13 @@
|
|
|
35
35
|
</a>
|
|
36
36
|
</p>
|
|
37
37
|
|
|
38
|
+
> **⚠️ Warning:** This software is in BETA. It may still contain bugs and unexpected behavior. Use caution with production data and ensure you have backups.
|
|
39
|
+
|
|
38
40
|
## Features
|
|
39
41
|
|
|
40
42
|
- **Zero-config databases** — Databases are created automatically on first use
|
|
41
43
|
- **Local SQLite** — Fast reads from a local database copy in the serverless function
|
|
42
|
-
- **Automatic sync** — Writes are automatically pushed to Turso
|
|
44
|
+
- **Automatic sync** — Writes are automatically pushed to Turso when the database connection is closed
|
|
43
45
|
- **Partial sync** — Sync only the data you need for efficient cold starts
|
|
44
46
|
|
|
45
47
|
## Install
|
|
@@ -64,15 +66,18 @@ npm install @tursodatabase/vercel-experimental
|
|
|
64
66
|
```
|
|
65
67
|
TURSO_API_TOKEN=your-api-token
|
|
66
68
|
TURSO_ORG=your-org-slug
|
|
69
|
+
TURSO_DATABASE=your-database-name
|
|
67
70
|
```
|
|
68
71
|
|
|
72
|
+
> **Important:** Store `TURSO_DATABASE` as a secret environment variable in Vercel, just like your API token. The API token grants access to your entire Turso organization, so if an attacker can control the database name passed to `createDb()`, they could access any database in your org. By keeping the database name in a secret environment variable, you ensure it cannot be injected or tampered with.
|
|
73
|
+
|
|
69
74
|
## Quickstart
|
|
70
75
|
|
|
71
76
|
```ts
|
|
72
77
|
import { createDb } from "@tursodatabase/vercel-experimental";
|
|
73
78
|
|
|
74
|
-
// Get or create a database
|
|
75
|
-
const db = await createDb(
|
|
79
|
+
// Get or create a database using the secret database name from environment
|
|
80
|
+
const db = await createDb(process.env.TURSO_DATABASE!);
|
|
76
81
|
|
|
77
82
|
// Create tables
|
|
78
83
|
await db.execute(`
|
|
@@ -89,8 +94,6 @@ await db.execute(
|
|
|
89
94
|
["Alice", "alice@example.com"]
|
|
90
95
|
);
|
|
91
96
|
|
|
92
|
-
// Changes sync automatically via waitUntil - no manual push needed!
|
|
93
|
-
|
|
94
97
|
// Query data
|
|
95
98
|
const result = await db.query("SELECT * FROM users");
|
|
96
99
|
console.log(result.rows);
|
|
@@ -103,7 +106,7 @@ console.log(result.rows);
|
|
|
103
106
|
Creates or retrieves a database instance.
|
|
104
107
|
|
|
105
108
|
```ts
|
|
106
|
-
const db = await createDb(
|
|
109
|
+
const db = await createDb(process.env.TURSO_DATABASE!, {
|
|
107
110
|
group: "default", // Database group (optional)
|
|
108
111
|
partialSync: true, // Enable partial sync (optional)
|
|
109
112
|
});
|
|
@@ -136,11 +139,11 @@ await db.execute(
|
|
|
136
139
|
|
|
137
140
|
### `db.push()`
|
|
138
141
|
|
|
139
|
-
Manually push local changes to the remote Turso database.
|
|
142
|
+
Manually push local changes to the remote Turso database.
|
|
140
143
|
|
|
141
144
|
```ts
|
|
142
145
|
await db.execute("INSERT INTO users (name) VALUES (?)", ["Charlie"]);
|
|
143
|
-
await db.push();
|
|
146
|
+
await db.push();
|
|
144
147
|
```
|
|
145
148
|
|
|
146
149
|
### `db.pull()`
|
|
@@ -159,7 +162,7 @@ await db.pull(); // Get latest data from Turso
|
|
|
159
162
|
import { createDb } from "@tursodatabase/vercel-experimental";
|
|
160
163
|
|
|
161
164
|
async function getUsers() {
|
|
162
|
-
const db = await createDb(
|
|
165
|
+
const db = await createDb(process.env.TURSO_DATABASE!);
|
|
163
166
|
const result = await db.query("SELECT * FROM users");
|
|
164
167
|
return result.rows;
|
|
165
168
|
}
|
|
@@ -187,7 +190,7 @@ async function addUser(formData: FormData) {
|
|
|
187
190
|
"use server";
|
|
188
191
|
|
|
189
192
|
const name = formData.get("name") as string;
|
|
190
|
-
const db = await createDb(
|
|
193
|
+
const db = await createDb(process.env.TURSO_DATABASE!);
|
|
191
194
|
|
|
192
195
|
await db.execute("INSERT INTO users (name) VALUES (?)", [name]);
|
|
193
196
|
await db.push();
|
|
@@ -203,7 +206,7 @@ import { createDb } from "@tursodatabase/vercel-experimental";
|
|
|
203
206
|
import { NextResponse } from "next/server";
|
|
204
207
|
|
|
205
208
|
export async function GET() {
|
|
206
|
-
const db = await createDb(
|
|
209
|
+
const db = await createDb(process.env.TURSO_DATABASE!);
|
|
207
210
|
const result = await db.query("SELECT * FROM users");
|
|
208
211
|
|
|
209
212
|
return NextResponse.json(result.rows);
|
|
@@ -211,7 +214,7 @@ export async function GET() {
|
|
|
211
214
|
|
|
212
215
|
export async function POST(request: Request) {
|
|
213
216
|
const { name } = await request.json();
|
|
214
|
-
const db = await createDb(
|
|
217
|
+
const db = await createDb(process.env.TURSO_DATABASE!);
|
|
215
218
|
|
|
216
219
|
await db.execute("INSERT INTO users (name) VALUES (?)", [name]);
|
|
217
220
|
await db.push();
|
package/dist/index.d.ts
CHANGED
|
@@ -11,15 +11,16 @@ export interface CreateDbOptions extends DatabaseOptions {
|
|
|
11
11
|
group?: string;
|
|
12
12
|
}
|
|
13
13
|
export declare class TursoDatabase {
|
|
14
|
+
readonly name: string;
|
|
14
15
|
private db;
|
|
15
16
|
private dirty;
|
|
16
17
|
private constructor();
|
|
17
|
-
static open(localPath: string, url: string, authToken: string, options?: DatabaseOptions): Promise<TursoDatabase>;
|
|
18
|
+
static open(name: string, localPath: string, url: string, authToken: string, options?: DatabaseOptions): Promise<TursoDatabase>;
|
|
18
19
|
query(sql: string, params?: unknown[]): Promise<QueryResult>;
|
|
19
20
|
execute(sql: string, params?: unknown[]): Promise<void>;
|
|
20
21
|
push(): Promise<void>;
|
|
21
22
|
pull(): Promise<void>;
|
|
22
|
-
|
|
23
|
+
close(): Promise<void>;
|
|
23
24
|
}
|
|
24
25
|
export declare function createDb(name: string, options?: CreateDbOptions): Promise<TursoDatabase>;
|
|
25
26
|
export { TursoDatabase as VercelDatabase };
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAOhF,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,WAAW,CAAC,YAAY,CAAC,yBAAyB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;CAC/F;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAuBD,qBAAa,aAAa;IACxB,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,KAAK,CAAS;IAEtB,OAAO;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAOhF,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,WAAW,CAAC,YAAY,CAAC,yBAAyB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;CAC/F;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAuBD,qBAAa,aAAa;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,KAAK,CAAS;IAEtB,OAAO;WAKM,IAAI,CACf,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,aAAa,CAAC;IAYnB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IAW5D,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAUvD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAMrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAW7B;AAMD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC,CA2BxF;AA8DD,OAAO,EAAE,aAAa,IAAI,cAAc,EAAE,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -8,27 +8,29 @@ import { waitUntil } from "@vercel/functions";
|
|
|
8
8
|
// ============================================================================
|
|
9
9
|
const instances = new Map();
|
|
10
10
|
const credentials = new Map();
|
|
11
|
-
const
|
|
11
|
+
const connections = new Set();
|
|
12
|
+
const closeChecks = new Map();
|
|
12
13
|
let apiClient = null;
|
|
13
14
|
let apiClientOrg = null;
|
|
14
|
-
let flushScheduled = false;
|
|
15
15
|
// ============================================================================
|
|
16
16
|
// Database Class
|
|
17
17
|
// ============================================================================
|
|
18
18
|
export class TursoDatabase {
|
|
19
|
+
name;
|
|
19
20
|
db;
|
|
20
21
|
dirty = false;
|
|
21
|
-
constructor(db) {
|
|
22
|
+
constructor(name, db) {
|
|
23
|
+
this.name = name;
|
|
22
24
|
this.db = db;
|
|
23
25
|
}
|
|
24
|
-
static async open(localPath, url, authToken, options) {
|
|
26
|
+
static async open(name, localPath, url, authToken, options) {
|
|
25
27
|
const opts = { path: localPath, url, authToken };
|
|
26
28
|
if (options?.partialSync) {
|
|
27
29
|
opts.partialSyncExperimental = {
|
|
28
30
|
bootstrapStrategy: options.bootstrapStrategy ?? { kind: "prefix", length: 128 * 1024 },
|
|
29
31
|
};
|
|
30
32
|
}
|
|
31
|
-
return new TursoDatabase(await connect(opts));
|
|
33
|
+
return new TursoDatabase(name, await connect(opts));
|
|
32
34
|
}
|
|
33
35
|
async query(sql, params) {
|
|
34
36
|
const stmt = this.db.prepare(sql);
|
|
@@ -45,11 +47,7 @@ export class TursoDatabase {
|
|
|
45
47
|
const stmt = this.db.prepare(sql);
|
|
46
48
|
try {
|
|
47
49
|
await stmt.run(...(params ?? []));
|
|
48
|
-
|
|
49
|
-
this.dirty = true;
|
|
50
|
-
pendingFlush.add(this);
|
|
51
|
-
scheduleFlush();
|
|
52
|
-
}
|
|
50
|
+
this.dirty = true;
|
|
53
51
|
}
|
|
54
52
|
finally {
|
|
55
53
|
stmt.close();
|
|
@@ -60,13 +58,21 @@ export class TursoDatabase {
|
|
|
60
58
|
return;
|
|
61
59
|
await this.db.push();
|
|
62
60
|
this.dirty = false;
|
|
63
|
-
pendingFlush.delete(this);
|
|
64
61
|
}
|
|
65
62
|
async pull() {
|
|
66
63
|
await this.db.pull();
|
|
67
64
|
}
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
async close() {
|
|
66
|
+
connections.delete(this);
|
|
67
|
+
closeChecks.get(this)?.();
|
|
68
|
+
closeChecks.delete(this);
|
|
69
|
+
try {
|
|
70
|
+
await this.push();
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
instances.delete(this.name);
|
|
74
|
+
await this.db.close();
|
|
75
|
+
}
|
|
70
76
|
}
|
|
71
77
|
}
|
|
72
78
|
// ============================================================================
|
|
@@ -79,6 +85,19 @@ export function createDb(name, options) {
|
|
|
79
85
|
const promise = initDb(name, options);
|
|
80
86
|
instances.set(name, promise);
|
|
81
87
|
promise.catch(() => instances.delete(name));
|
|
88
|
+
promise.then((db) => {
|
|
89
|
+
connections.add(db);
|
|
90
|
+
waitUntil(new Promise((resolve) => {
|
|
91
|
+
closeChecks.set(db, resolve);
|
|
92
|
+
setTimeout(resolve, 5000);
|
|
93
|
+
}).then(() => {
|
|
94
|
+
closeChecks.delete(db);
|
|
95
|
+
if (connections.has(db)) {
|
|
96
|
+
console.warn(`Database "${db.name}" was not closed. ` +
|
|
97
|
+
"Call db.close() to ensure writes are pushed and errors are surfaced.");
|
|
98
|
+
}
|
|
99
|
+
}));
|
|
100
|
+
});
|
|
82
101
|
return promise;
|
|
83
102
|
}
|
|
84
103
|
// ============================================================================
|
|
@@ -87,7 +106,7 @@ export function createDb(name, options) {
|
|
|
87
106
|
async function initDb(name, options) {
|
|
88
107
|
const creds = await ensureDb(name, options?.group);
|
|
89
108
|
const localPath = join(tmpdir(), `${name}.db`);
|
|
90
|
-
return TursoDatabase.open(localPath, creds.url, creds.authToken, options);
|
|
109
|
+
return TursoDatabase.open(name, localPath, creds.url, creds.authToken, options);
|
|
91
110
|
}
|
|
92
111
|
async function ensureDb(name, group) {
|
|
93
112
|
const cached = credentials.get(name);
|
|
@@ -122,18 +141,6 @@ function getClient() {
|
|
|
122
141
|
}
|
|
123
142
|
return apiClient;
|
|
124
143
|
}
|
|
125
|
-
function scheduleFlush() {
|
|
126
|
-
if (flushScheduled)
|
|
127
|
-
return;
|
|
128
|
-
flushScheduled = true;
|
|
129
|
-
waitUntil((async () => {
|
|
130
|
-
await Promise.resolve();
|
|
131
|
-
flushScheduled = false;
|
|
132
|
-
const dbs = Array.from(pendingFlush);
|
|
133
|
-
pendingFlush.clear();
|
|
134
|
-
await Promise.all(dbs.map((db) => db.push().catch((err) => console.error("Failed to push database:", err))));
|
|
135
|
-
})());
|
|
136
|
-
}
|
|
137
144
|
function requireEnv(name) {
|
|
138
145
|
const value = process.env[name];
|
|
139
146
|
if (!value)
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAoC,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAyB9C,+EAA+E;AAC/E,QAAQ;AACR,+EAA+E;AAE/E,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkC,CAAC;AAC5D,MAAM,WAAW,GAAG,IAAI,GAAG,EAAuB,CAAC;AACnD,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|