Skip to content

Commit 757ce9f

Browse files
authored
Merge pull request silvermine#9 from 1Cor125/complete_plugin_api
feat: complete the plugin commands
2 parents 07592a0 + d5a0b01 commit 757ce9f

21 files changed

Lines changed: 690 additions & 122 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 9 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pooling, write serialization, and proper resource management.
1717
* **Optimized Connection Pooling**: Separate read and write pools for concurrent reads,
1818
even while writing
1919
* **Write Serialization**: Exclusive write access through connection manager
20-
* **Migration Support**: Uses SQLx's database migration system (runs during preload)
20+
* **Migration Support**: Uses SQLx's database migration system
2121
* **Custom Configuration**: Configure read pool size and idle timeouts
2222
* **Type Safety**: Full TypeScript bindings
2323
* **Resource Management**: Proper cleanup on application exit
@@ -332,7 +332,7 @@ console.log(`Transfer ID: ${results[2].lastInsertId}`);
332332

333333
**How it works:**
334334

335-
* Automatically executes `BEGIN` before running statements
335+
* Automatically executes `BEGIN IMMEDIATE` before running statements
336336
* Executes all statements in order
337337
* Commits with `COMMIT` if all statements succeed
338338
* Rolls back with `ROLLBACK` if any statement fails
@@ -360,85 +360,8 @@ await db.remove()
360360

361361
## Migrations
362362

363-
Migrations run automatically during database preload at application startup.
364-
365-
### Setting Up Migrations
366-
367-
`src-tauri/src/lib.rs`
368-
369-
```rust
370-
use tauri_plugin_sqlite::{Builder, Migration, MigrationKind};
371-
372-
fn main() {
373-
let migrations = vec![
374-
// Version 1: Create initial schema
375-
Migration {
376-
version: 1,
377-
description: "create_users_table",
378-
sql: vec!["CREATE TABLE users (
379-
id INTEGER PRIMARY KEY AUTOINCREMENT,
380-
name TEXT NOT NULL,
381-
email TEXT NOT NULL UNIQUE,
382-
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
383-
)"],
384-
kind: MigrationKind::Up,
385-
},
386-
// Version 2: Add new column
387-
Migration {
388-
version: 2,
389-
description: "add_users_role",
390-
sql: vec!["ALTER TABLE users ADD COLUMN role TEXT DEFAULT 'user'"],
391-
kind: MigrationKind::Up,
392-
},
393-
// Version 3: Create index and add trigger (multiple statements)
394-
Migration {
395-
version: 3,
396-
description: "create_email_index_and_trigger",
397-
sql: vec![
398-
"CREATE INDEX idx_users_email ON users(email)",
399-
"CREATE TRIGGER update_timestamp AFTER UPDATE ON users
400-
BEGIN
401-
UPDATE users SET created_at = strftime('%s', 'now') WHERE id = NEW.id;
402-
END",
403-
],
404-
kind: MigrationKind::Up,
405-
},
406-
];
407-
408-
tauri::Builder::default()
409-
.plugin(
410-
Builder::new()
411-
.add_migrations("mydb.db", migrations)
412-
.build(),
413-
)
414-
.run(tauri::generate_context!())
415-
.expect("error while running tauri application");
416-
}
417-
```
418-
419-
### Preloading Databases
420-
421-
Add databases to `tauri.conf.json` to connect and run migrations at startup:
422-
423-
```json
424-
{
425-
"plugins": {
426-
"sqlite": {
427-
"preload": ["mydb.db", "cache.db"]
428-
}
429-
}
430-
}
431-
```
432-
433-
When preloaded:
434-
435-
1. The plugin connects to each database
436-
2. Runs any pending migrations defined in `add_migrations()`
437-
3. Keeps the connection open and ready for use
438-
439-
> **Important:** Migrations only run during preload. If you load a database
440-
> dynamically with `Database.load()`, migrations will not run unless it was
441-
> preloaded.
363+
> **Note:** Database migration support is a planned feature and will be added in a
364+
> future release. It will be based on SQLx's migration framework.
442365
443366
## Query Parameter Binding
444367

@@ -526,7 +449,7 @@ const db = Database.get('mydb.db')
526449
// Connection happens on first query
527450
```
528451

529-
##### `Database.closeAll(): Promise<boolean>`
452+
##### `Database.closeAll(): Promise<void>`
530453

531454
Close all database connections.
532455

@@ -578,15 +501,17 @@ if (user) {
578501

579502
##### `close(): Promise<boolean>`
580503

581-
Close this database connection.
504+
Close this database connection. Returns `true` if the database was loaded and closed,
505+
`false` if it wasn't loaded.
582506

583507
```typescript
584508
await db.close()
585509
```
586510

587511
##### `remove(): Promise<boolean>`
588512

589-
Close the connection and permanently delete database file(s).
513+
Close the connection and permanently delete database file(s). Returns `true` if
514+
the database was loaded and removed, `false` if it wasn't loaded.
590515

591516
> ⚠️ **Warning:** This cannot be undone!
592517

api-iife.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
fn main() {
2-
// TODO: Add commands to the plugin
3-
tauri_plugin::Builder::new(&["hello"]).build();
2+
tauri_plugin::Builder::new(&[
3+
"load",
4+
"execute",
5+
"execute_transaction",
6+
"fetch_all",
7+
"fetch_one",
8+
"close",
9+
"close_all",
10+
"remove",
11+
])
12+
.build();
413
}

crates/sqlx-sqlite-conn-mgr/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ sqlx = { version = "0.8.6", features = ["runtime-tokio", "sqlite"] }
1111
thiserror = "2.0.17"
1212
tokio = { version = "1.48.0", features = ["full"] }
1313
tracing = { version = "0.1.41", default-features = false, features = ["std", "release_max_level_off"] }
14+
serde = { version = "1.0.228", features = ["derive"] }
Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
//! Configuration for SQLite database connection pools
22
3-
use std::time::Duration;
3+
use serde::{Deserialize, Serialize};
44

55
/// Configuration for SqliteDatabase connection pools
66
///
77
/// # Examples
88
///
99
/// ```
1010
/// use sqlx_sqlite_conn_mgr::SqliteDatabaseConfig;
11-
/// use std::time::Duration;
1211
///
1312
/// // Use defaults
1413
/// let config = SqliteDatabaseConfig::default();
1514
///
1615
/// // Customize specific fields
1716
/// let config = SqliteDatabaseConfig {
1817
/// max_read_connections: 3,
19-
/// idle_timeout: Duration::from_secs(60),
18+
/// idle_timeout_secs: 60,
2019
/// };
2120
///
2221
/// // Override just one field
@@ -25,7 +24,7 @@ use std::time::Duration;
2524
/// ..Default::default()
2625
/// };
2726
/// ```
28-
#[derive(Debug, Clone)]
27+
#[derive(Debug, Clone, Serialize, Deserialize)]
2928
pub struct SqliteDatabaseConfig {
3029
/// Maximum number of concurrent read connections
3130
///
@@ -35,20 +34,20 @@ pub struct SqliteDatabaseConfig {
3534
/// Default: 6
3635
pub max_read_connections: u32,
3736

38-
/// Idle timeout for both read and write connections
37+
/// Idle timeout for both read and write connections (in seconds)
3938
///
4039
/// Connections that remain idle for this duration will be closed automatically.
4140
/// This helps prevent resource exhaustion from idle threads.
4241
///
43-
/// Default: 30 seconds
44-
pub idle_timeout: Duration,
42+
/// Default: 30
43+
pub idle_timeout_secs: u64,
4544
}
4645

4746
impl Default for SqliteDatabaseConfig {
4847
fn default() -> Self {
4948
Self {
5049
max_read_connections: 6,
51-
idle_timeout: Duration::from_secs(30),
50+
idle_timeout_secs: 30,
5251
}
5352
}
5453
}

crates/sqlx-sqlite-conn-mgr/src/database.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,13 @@ impl SqliteDatabase {
9292
///
9393
/// ```no_run
9494
/// use sqlx_sqlite_conn_mgr::{SqliteDatabase, SqliteDatabaseConfig};
95-
/// use std::time::Duration;
9695
/// use std::sync::Arc;
9796
///
9897
/// # async fn example() -> Result<(), sqlx_sqlite_conn_mgr::Error> {
9998
/// // Customize configuration when defaults don't meet your requirements
10099
/// let custom_config = SqliteDatabaseConfig {
101100
/// max_read_connections: 10,
102-
/// idle_timeout: Duration::from_secs(60),
101+
/// idle_timeout_secs: 60,
103102
/// };
104103
/// let db = SqliteDatabase::connect("test.db", Some(custom_config)).await?;
105104
/// # Ok(())
@@ -151,7 +150,9 @@ impl SqliteDatabase {
151150
let read_pool = SqlitePoolOptions::new()
152151
.max_connections(config.max_read_connections)
153152
.min_connections(0)
154-
.idle_timeout(Some(config.idle_timeout))
153+
.idle_timeout(Some(std::time::Duration::from_secs(
154+
config.idle_timeout_secs,
155+
)))
155156
.connect_with(read_options)
156157
.await?;
157158

@@ -161,7 +162,9 @@ impl SqliteDatabase {
161162
let write_conn = SqlitePoolOptions::new()
162163
.max_connections(1)
163164
.min_connections(0)
164-
.idle_timeout(Some(config.idle_timeout))
165+
.idle_timeout(Some(std::time::Duration::from_secs(
166+
config.idle_timeout_secs,
167+
)))
165168
.connect_with(write_options)
166169
.await?;
167170

@@ -529,15 +532,13 @@ mod tests {
529532

530533
#[tokio::test]
531534
async fn test_custom_config() {
532-
use std::time::Duration;
533-
534535
let test_path = std::env::current_dir()
535536
.unwrap()
536537
.join("test_custom_config.db");
537538

538539
let custom_config = SqliteDatabaseConfig {
539540
max_read_connections: 10,
540-
idle_timeout: Duration::from_secs(60),
541+
idle_timeout_secs: 60,
541542
};
542543

543544
// Verify custom config is accepted and connection works

guest-js/index.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,17 @@ export default class Database {
265265
*
266266
* Closes the database connection pool(s) for this specific database.
267267
*
268+
* @returns `true` if the database was loaded and successfully closed,
269+
* `false` if the database was not loaded (nothing to close)
270+
*
268271
* @example
269272
* ```ts
270-
* const success = await db.close()
273+
* const wasClosed = await db.close()
274+
* if (wasClosed) {
275+
* console.log('Database closed successfully')
276+
* } else {
277+
* console.log('Database was not loaded')
278+
* }
271279
* ```
272280
*/
273281
async close(): Promise<boolean> {
@@ -284,12 +292,11 @@ export default class Database {
284292
*
285293
* @example
286294
* ```ts
287-
* const success = await Database.closeAll()
295+
* await Database.closeAll()
288296
* ```
289297
*/
290-
static async closeAll(): Promise<boolean> {
291-
const success = await invoke<boolean>('plugin:sqlite|close_all')
292-
return success
298+
static async closeAll(): Promise<void> {
299+
await invoke<void>('plugin:sqlite|close_all')
293300
}
294301

295302
/**
@@ -300,9 +307,17 @@ export default class Database {
300307
*
301308
* **Warning:** This permanently deletes the database files from disk. Use with caution!
302309
*
310+
* @returns `true` if the database was loaded and successfully removed,
311+
* `false` if the database was not loaded (nothing to remove)
312+
*
303313
* @example
304314
* ```ts
305-
* const success = await db.remove()
315+
* const wasRemoved = await db.remove()
316+
* if (wasRemoved) {
317+
* console.log('Database deleted successfully')
318+
* } else {
319+
* console.log('Database was not loaded')
320+
* }
306321
* ```
307322
*/
308323
async remove(): Promise<boolean> {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Automatically generated - DO NOT EDIT!
2+
3+
"$schema" = "../../schemas/schema.json"
4+
5+
[[permission]]
6+
identifier = "allow-close"
7+
description = "Enables the close command without any pre-configured scope."
8+
commands.allow = ["close"]
9+
10+
[[permission]]
11+
identifier = "deny-close"
12+
description = "Denies the close command without any pre-configured scope."
13+
commands.deny = ["close"]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Automatically generated - DO NOT EDIT!
2+
3+
"$schema" = "../../schemas/schema.json"
4+
5+
[[permission]]
6+
identifier = "allow-close-all"
7+
description = "Enables the close_all command without any pre-configured scope."
8+
commands.allow = ["close_all"]
9+
10+
[[permission]]
11+
identifier = "deny-close-all"
12+
description = "Denies the close_all command without any pre-configured scope."
13+
commands.deny = ["close_all"]

0 commit comments

Comments
 (0)