Skip to content

Commit 08080d7

Browse files
committed
Address review comments
1 parent 28e5dad commit 08080d7

4 files changed

Lines changed: 27 additions & 14 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ jobs:
129129
targets: wasm32-unknown-unknown
130130

131131
- name: Install wasm-pack
132-
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
132+
run: cargo install wasm-pack@0.13.1 --locked
133133

134134
- name: Cache cargo
135135
uses: Swatinem/rust-cache@v2

.github/workflows/deploy-wasm.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
targets: wasm32-unknown-unknown
3333

3434
- name: Install wasm-pack
35-
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
35+
run: cargo install wasm-pack@0.13.1 --locked
3636

3737
- name: Cache cargo
3838
uses: Swatinem/rust-cache@v2

src/wasm.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ async fn auth_me(State(state): State<crate::app::AppState>) -> Response {
248248
"email": "anonymous@localhost",
249249
"name": "Anonymous User",
250250
"user_id": state.default_user_id,
251-
"roles": ["super_admin"],
251+
"roles": ["admin"],
252252
"idp_groups": [],
253253
}))
254254
.into_response()
@@ -289,21 +289,26 @@ async fn convert_request(
289289
.parse()
290290
.map_err(|_| JsError::new("Invalid HTTP method"))?;
291291

292-
// Read body for methods that may have one
292+
// Read body for methods that may have one.
293+
// Use array_buffer() instead of text() to correctly handle binary content
294+
// (multipart form-data, file uploads, audio).
293295
let body = if method == http::Method::POST
294296
|| method == http::Method::PUT
295297
|| method == http::Method::PATCH
296298
{
297-
let text = wasm_bindgen_futures::JsFuture::from(
298-
req.text()
299+
let buf = wasm_bindgen_futures::JsFuture::from(
300+
req.array_buffer()
299301
.map_err(|_| JsError::new("Failed to read request body"))?,
300302
)
301303
.await
302304
.map_err(|_| JsError::new("Failed to read request body"))?;
303305

304-
match text.as_string() {
305-
Some(s) => axum::body::Body::from(s),
306-
None => axum::body::Body::empty(),
306+
let uint8 = js_sys::Uint8Array::new(&buf);
307+
let bytes = uint8.to_vec();
308+
if bytes.is_empty() {
309+
axum::body::Body::empty()
310+
} else {
311+
axum::body::Body::from(bytes)
307312
}
308313
} else {
309314
axum::body::Body::empty()

ui/src/service-worker/sqlite-bridge.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,22 +74,30 @@ function debouncedSave(): void {
7474
}, 500);
7575
}
7676

77-
// Flush pending saves before the service worker terminates
78-
globalThis.addEventListener("unload", flushSave);
77+
// Flush pending saves when the service worker is about to be evicted.
78+
// Service workers don't fire `unload`/`beforeunload`; instead we listen for
79+
// the `activate` event to ensure the DB is persisted on startup, and save
80+
// synchronously on every write when a pending timer exists.
81+
// `beforeunload` is kept as a best-effort fallback for window contexts.
82+
if (typeof globalThis.addEventListener === "function") {
83+
globalThis.addEventListener("beforeunload", flushSave);
84+
}
7985

8086
// ---------------------------------------------------------------------------
8187
// Parameter binding
8288
// ---------------------------------------------------------------------------
8389

8490
/**
8591
* Bind values into a prepared statement.
86-
* The Rust bridge sends params as a JSON array of `WasmParam` values:
87-
* - { Text: "..." } | { Integer: n } | { Real: f } | { Blob: [...] } | "Null"
92+
* The Rust bridge sends params via serde_wasm_bindgen with `#[serde(untagged)]`,
93+
* so values arrive as native JS types: string, number, null, or boolean.
94+
* Tagged variants ({ Text: "..." }, etc.) are only possible if serialization
95+
* changes — we handle both forms defensively.
8896
* sql.js accepts `(string | number | Uint8Array | null)[]`.
8997
*/
9098
function bindParams(params: unknown[]): (string | number | Uint8Array | null)[] {
9199
return params.map((p) => {
92-
if (p == null || p === "Null") return null; // == catches both null and undefined
100+
if (p == null) return null; // == catches both null and undefined
93101
if (typeof p === "string" || typeof p === "number") return p;
94102
if (typeof p === "boolean") return p ? 1 : 0; // SQLite stores booleans as integers
95103
if (typeof p === "object" && p !== null) {

0 commit comments

Comments
 (0)