sqlite_wasm_example/
lib.rs
1pub mod models;
2pub mod schema;
3
4use std::sync::Mutex;
5use std::sync::Once;
6
7use crate::models::{NewPost, Post};
8use diesel::prelude::*;
9use diesel_migrations::embed_migrations;
10use diesel_migrations::EmbeddedMigrations;
11use diesel_migrations::MigrationHarness;
12use wasm_bindgen::prelude::*;
13
14const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations");
15
16#[wasm_bindgen]
17extern "C" {
18 #[wasm_bindgen(js_namespace = console)]
21 fn log(s: &str);
22}
23
24macro_rules! console_log {
29 ($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
32}
33
34static VFS: Mutex<(i32, Once)> = Mutex::new((0, Once::new()));
35
36pub fn establish_connection() -> SqliteConnection {
37 let (vfs, once) = &*VFS.lock().unwrap();
38 let url = match vfs {
39 0 => "post.db",
40 1 => "file:post.db?vfs=opfs-sahpool",
41 _ => unreachable!(),
42 };
43 let mut conn =
44 SqliteConnection::establish(url).unwrap_or_else(|_| panic!("Error connecting to post.db"));
45 once.call_once(|| {
46 conn.run_pending_migrations(MIGRATIONS).unwrap();
47 });
48 conn
49}
50
51#[cfg(all(target_family = "wasm", target_os = "unknown"))]
52#[wasm_bindgen]
53pub async fn install_opfs_sahpool() {
54 sqlite_wasm_rs::export::install_opfs_sahpool(None, false)
55 .await
56 .unwrap();
57}
58
59#[wasm_bindgen]
60pub fn switch_vfs(id: i32) {
61 *VFS.lock().unwrap() = (id, Once::new());
62}
63
64#[wasm_bindgen]
65pub fn create_post(title: &str, body: &str) -> JsValue {
66 use crate::schema::posts;
67
68 let new_post = NewPost { title, body };
69
70 let post = diesel::insert_into(posts::table)
71 .values(&new_post)
72 .returning(Post::as_returning())
73 .get_result(&mut establish_connection())
74 .expect("Error saving new post");
75
76 serde_wasm_bindgen::to_value(&post).unwrap()
77}
78
79#[wasm_bindgen]
80pub fn delete_post(pattern: &str) {
81 let connection = &mut establish_connection();
82 let num_deleted = diesel::delete(
83 schema::posts::dsl::posts.filter(schema::posts::title.like(pattern.to_string())),
84 )
85 .execute(connection)
86 .expect("Error deleting posts");
87
88 console_log!("Deleted {num_deleted} posts");
89}
90
91#[wasm_bindgen]
92pub fn get_post(post_id: i32) -> JsValue {
93 use schema::posts::dsl::posts;
94
95 let connection = &mut establish_connection();
96
97 let post = posts
98 .find(post_id)
99 .select(Post::as_select())
100 .first(connection)
101 .optional(); match &post {
104 Ok(Some(post)) => console_log!("Post with id: {} has a title: {}", post.id, post.title),
105 Ok(None) => console_log!("Unable to find post {}", post_id),
106 Err(_) => console_log!("An error occurred while fetching post {}", post_id),
107 }
108 serde_wasm_bindgen::to_value(&post.ok().flatten()).unwrap()
109}
110
111#[wasm_bindgen]
112pub fn publish_post(id: i32) {
113 let connection = &mut establish_connection();
114
115 let post = diesel::update(schema::posts::dsl::posts.find(id))
116 .set(schema::posts::dsl::published.eq(true))
117 .returning(Post::as_returning())
118 .get_result(connection)
119 .unwrap();
120
121 console_log!("Published post {}", post.title);
122}
123
124#[wasm_bindgen]
125pub fn show_posts() -> Vec<JsValue> {
126 let connection = &mut establish_connection();
127 let results = schema::posts::dsl::posts
128 .filter(schema::posts::dsl::published.eq(true))
129 .limit(5)
130 .select(Post::as_select())
131 .load(connection)
132 .expect("Error loading posts");
133
134 console_log!("Displaying {} posts", results.len());
135 for post in &results {
136 console_log!("{}", post.title);
137 console_log!("----------\n");
138 console_log!("{}", post.body);
139 }
140
141 results
142 .into_iter()
143 .map(|x| serde_wasm_bindgen::to_value(&x).unwrap())
144 .collect()
145}