I decided to try to port this to Logseq.
The first issue I ran into was despite being written in ClojureScript and one of the reasons I was drawn to logseq, the plugin libs are not ClojureScript friendly and could not be imported with shadow-cljs in the traditional manner requiring use of js interop. But there are some good cljs libraries for interop that it was easy enough to use interop syntax.
The next issue I ran into was that plugins are sandboxed and I could not directly query the Things 3 sqlite database as is done in the obsidian plugin. So to work around Things 3 not having an API I decided to spin up an HTTP server on my local machine to dump all the data. At first, this seemed a bit unnecessary work (and a potential security issue at the moment as anyone on the local network can potentially access my things db while the service is running), but this may prove to be useful when mobile comes out as I could potentially still have it connect to my computer. I’m not sure yet how to improve discoverability other than manually inputting the computer IP address and port if anyone has thoughts on that I’d be interested in how one might be able to discover if the service is running on the local network without the need for some internet service to serve as a registry (although I guess if needed I could create one).
The implementation as of yet is coming along okay. Few things in API not working quite as expected.
insertBlock on an empty page didn’t seem to work for me… I would expect that given a page block as srcBlock it would insert the block on the page, but it seemed to do nothing or create an orphan block. After asking in discord I discovered I needed to specify isPageBlock. I think this is potentially something the API could figure out if the given block is a page insert it on the page, but it works well enough if inserting relative to getCurrentBlock.
getCurrentPage sometimes returned nil even when getCurrentBlock worked and included page ref so I created helper function to use getPage(getCurrentBlock().page) if getCurentPage returned nil.
datascriptQuery expects a raw string and doesn’t take any parameters or rules, for now, I just build the values into the query, but not being able to specify rules may significantly limit potential queries particularly recursive queries which seem particularly useful in this context.
If you use Things 3 and are interested in the ability to sync with Logseq let me know.
Mostly I’m interested in syncing the logbook to reflect and organize the notes I take on tasks (mostly because it has a good mobile app so I take notes there and sync using obsidian). But logseq works way better for me Obsidian when it comes to mining my notes for relationships. I have some ideas on how to make the sync bidirectional using apple script (updating the sqlite database directly unfortunately does not push updates to mobile app), but it is a lot more work so I may not do it for myself.
You can find the first draft of the plugin here