clojurescript

Kodinak 2025-09-26T07:51:13.310039Z

I have a cross-platform (Initially iPad) re-frame app running on Tauri. I'm now considering implementing a rehydration mechanism which I have never done before. That means UI state and content, which includes datascript, should be persisted somehow. I'm thinking of using the Rust core to play that role. Has anyone implemented something similar? What would be a sensible way to do it? Thanks!

πŸ™Œ 1
cormacc 2025-09-27T09:20:50.333739Z

You shouldn't need to use Tauri-specific plugins to read/write your native filesystem. Browser APIs let you pop up a native dialog to grant file/folder access. Once granted I think you can save the directory handle to indexed-db so you don't need to re-grant per session, though I haven't actually needed to do this as yet. I've used this for a data import function in a current project and it's pretty straightforward

πŸ‘ 1
Kodinak 2025-09-27T10:58:00.534619Z

I was wondering if there's a systematic way to do it, like datasync or such. You want to maintain your datascript state and potentially more

cormacc 2025-09-27T11:11:32.967119Z

If it's just local persistence, it's pretty straightforward. Sounds like you may have a datascript dB and a separate state atom you want to persist? The simplest solution there would be to add watches to both that write the current state to localStorage on every update, then reload on app load. You could do something similar to an EDN file using one of the FileSystem APIs with a little bit of extra effort. If you want to get clever, your datascript DB watch can write a transaction log to indexed-db, giving you a poor-man's local datomic. Your mention of datasync though suggests you're thinking about client <-> server sync? That's a different problem / can of worms...

Chris McCormick 2025-09-27T13:05:12.860269Z

> Once granted I think you can save the directory handle to indexed-db so you don't need to re-grant per session Whaaaat really?

Chris McCormick 2025-09-27T13:05:29.514029Z

Does this work in normal browsers or only Tauri?

Ada Des Etages 2025-09-27T13:26:58.088679Z

I might be missing something, but although tauri uses the platform's webview, your frontend code does not have the same filesystem access as a Progressive Web App/website. They add extra security barriers so you'd need to go through the tauri.conf permissions system at least. For example, the browser's upload worked without modification, but the browser's download did not automatically work when compiled as a tauri application.

cormacc 2025-09-27T13:34:53.604299Z

I have no experience with tauri - just using those APIs in a standard SPA running in chrome/chromium/edge

cormacc 2025-09-27T13:37:26.423369Z

@chris358 don't take that as gospel - haven't tried it yet, but it was something that stuck with me during a recent read of (I think) MDN API docs. I'll see if I can dig out the reference and report back to you

cormacc 2025-09-27T14:00:26.727329Z

... I've now fact checked myself πŸ™‚ Can't find the original source (it wasn't the MDN docs) - but that included an example of writing the handle to indexed-db. Reading the specification here https://wicg.github.io/file-system-access/ , it's alluded to indirectly in section 2.3.1 - my reading of it is that there's some wiggle room in the implementation - on load from indexed DB, you'll probably be prompted for confirmation that it's still OK, but not necessarily. I'll report back again if I can find the original source again. All of that said - you have a local file bucket without any permissions concerns using the OPFS API, which should be fine for most use cases. You won't see the files on your local FS, but easy to implement an export function using the file system access API for episodic use...

πŸ‘ 1
πŸ’œ 1
Kodinak 2025-09-27T14:06:29.931229Z

@cormacc, the datasync idea is just a rough parallel - not literal implementation. The underlying mechanism should allow for an efficient, potentially incremental, sync within datascript, not with server. But then gain, much of this is armchair. I haven't experimented much in this space. On a different note, the platform specific considerations, like ios file access and so on are making me wonder whether I should go Rust-first. Ideally, the solution will have to be as platform-agnostic as possible.

cormacc 2025-09-27T17:13:07.395089Z

The nice thing about the browser APIs is that they are platform agnostic. I'm using them for native filesystem and USB port access across Linux, Windows and MacOS. Haven't played with iPad/iPhone though. Re. incremental sync, the datascript / indexed-db transaction log gives you that by definition, though you do have to re-run your transactions to rebuild the DB at the start of a session

πŸ‘ 2
Kodinak 2025-09-28T02:11:22.895809Z

Tried to research a bit. Here's one thing I found: "... Web APIs (localStorage/IndexedDB) are fine for β€œhot” UI state, quick resume, and small blobs. But on iOS/WKWebView they’re subject to quota/eviction policies, so don’t treat them as durable. Apple/WebKit have documented eviction behavior and quota caps; IndexedDB is supported but not guaranteed to stick around forever if the OS needs space." https://webkit.org/blog/14403/updates-to-storage-policy

Kodinak 2025-09-28T02:22:54.711699Z

I wonder about the performance implications of using tauri's official KV store as the primary rehydration driver. But it's durable and platform-agnostic. https://v2.tauri.app/plugin/store

Ada Des Etages 2025-09-28T20:39:10.895619Z

my intuition is that it'll be a fast part of your system if your intention is to store blobs of data that you then read into the application. The only way to know for sure is measuring though :) in my personal app something I ran into is that rehydration seemed 2-3 times slower while in the dev mode compared to when it's built for release because the most intensive part of my rehydration steps were the actual reading into the system, not the retrieval from disk/decompression. I think the rehydration steps benefitted from the cljs build optimizations.

πŸ‘ 1
cormacc 2025-09-26T08:46:23.731219Z

Don't know about rehydration, but if you want to persist data between sessions you should be able to manage that fine using just the filesystem, localStorage and/or indexed-db web APIs provided by the webview2 engine Tauri (I think) uses?

πŸ‘ 1
Roman Liutikov 2025-09-26T09:21:55.063489Z

+1 on using existing web storage APIs

πŸ‘ 1
Ada Des Etages 2025-09-26T09:38:48.925849Z

i literally implemented that this week!

Ada Des Etages 2025-09-26T09:41:09.071809Z

localstorage is the easiest for persisting local state that's non-essential, but if it's data that needs to be backed up you can consider the tauri-fs extension. On ios it's limited to the Applications folder though.

πŸ‘ 1
Ada Des Etages 2025-09-26T09:51:36.649529Z

The general workflow is using the tauri-dialog extension to prompt the user for a file path (dialog/save) and then you take the result of that call and use it with the fs extension's writeFile or writeTextFile to persist data. Don't forget to serialize your data properly and use clojure.edn to parse it when reading it back in. (https://stackoverflow.com/questions/24661655/clojure-clojurescript-clojure-core-read-string-clojure-edn-read-string-and-c)

πŸ‘ 1
Ada Des Etages 2025-09-26T10:00:06.785479Z

you'll also need to update your file (src-tauri/capabilities/tauri.conf) with the right permissions. I'd suggest calling the functions from the repl, and then checking the application's console log for the error message. It'll show you exactly which permissions can allow the action so you can select the most restrictive options and not give the program any more access than necessary :)

πŸ‘ 1
Kodinak 2025-09-26T10:02:14.154409Z

Thanks @ada. On a related note, you're using exactly this stack (cljs + Tauri)? I'm betting my production app on it, with capacitor as potential fallback should any deal breaker turn up. So far so good though. Any gotchas you faced?

Ada Des Etages 2025-09-26T10:18:53.084369Z

I'm using that stack, but my targets are desktop apps. My binaries are < 30mb and I've been able to do everything I need using the plugins. I'd try them before jumping to rust although the inter-process-communication between cljs and the rust backend worked great for me... my current roadblock is the cost of code-signing for distribution, but that should already be covered by your Apple Developer fee and is not a Tauri specific challenge.

Kodinak 2025-09-26T12:07:21.878599Z

You're right, Apple developer solves the signing issue. Tauri is solid on desktop, but mobile is less trodden path. Surprisingly smooth to me for a new tech. Hopefully, there won't be any deal-breakers down the road.

🀞 1
cormacc 2025-09-29T13:21:29.710839Z

Re. persistent file access permissions -- seems it is a thing, on chromium-based browsers at least --- found a detailed write-up here: https://developer.chrome.com/blog/persistent-permissions-for-the-file-system-access-api

πŸ‘ 1
πŸ‘ 1