This is pretty hairy, because we're relying on the LEFT JOIN feature
to give us the root node when we need it. That's kinda ugly, but
it seems to work just fine. It also gives us the list in the
*correct* order, so the only thing we need to do is go to the last
item in the returned vector, make sure it's a root node, then go
fetch the page so we can decorate the list with the *right* root.
We'll pass this as a JSON object { [notes-in-reverse], page }.
Well, as complete as it could be without proper automated testing.
I think there'll be some more testing soon, as it doesn't make sense
for it to hang out so blatantly like this.
Both a fmt and clippy pass have shaken all the lint off, and right
now it builds without warnings or lintings. Wheee!
This features all of the reference types that I commonly use,
including the ORG mode [[Title]], #CamelCase, #lisp-case, and #colon:case.
There are still edge cases around capitalization and the mixing of symbols
and numbers, and I'll have to hack on those until I'm satisfied.
This code now uses the ParentId/NoteId dichotomy supported with
Shrinkwrap. It's actually very nice.
* refs/remotes/origin/reboot-20201004:
FEAT: Move note now works.
This is mostly an exercise to understand the derive_builder pattern.
It required a few tips to get it working, but in the end, it's
actually what I want.
I also learned a lot about how the Executor pattern, the Results<> object,
error mapping, and futures interact in this code. This is going to be
incredibly useful long-term, as long as I still keep this project "live"
in my head.
Since both `insert_page` and `insert_note` need to insert a note,
having that code twice in the same block was annoying, especially
since discovering that my oh-so-clever use of `include_str!`
precludes me from using the `query!` macros, which want the strings
included *before* doing analysis.
All that wrestling with the Transaction type turned out to be much
simpler when I was able to just devolve it into an Executor.
In the great tradition of TPP, this is a win. We've gone through
the test driven development, and there is so much *learning* here:
- tokio::test NEEDS the threaded_schedular feature to report errors correctly
- thiserror can't do enum variants the way I expected
- Different error types for different returns is not kosher
- Serde's configuration NEEDS a type, such as JSON, to work,
- Rust has include_str!(), to embed text in a Rust program from an external source
- SQLX is still a pain, but it's managable.