I'm releasing the first stable version (v1.0.0) where I fixed the linking between the resource and the note.
If you created some diagrams before this release you need to modify the html tag to make it work with the new version:
# Previous format
<drawio id="6a0a0fcf2b0246bca3a5b0bccbca1943"/>
# New format
<drawio id="](:/6a0a0fcf2b0246bca3a5b0bccbca1943)"/>
In the previous version the image drawn with this plugin was deleted after a while by the automatic process deleteOrphanResources.
Here is the story on how I fixed this issue that I hope can help other plugin developers with their amazing work.
Story of the fix
This was happening during the modification of a diagram where I was replacing the previous resource with the new one.
In the first implementation, I tried to use the PUT resource/:id
method documented in the Joplin Data API, but after several attempts to guess the expected input of this function (the input is not documented), I looked into the implementation and I realized it was never implemented.
My next approach was to delete the previous resource and then recreate it with the same ID in order to keep the same ID in the note body tag:
<drawio id="6a0a0fcf2b0246bca3a5b0bccbca1943"/>
this approach was working and this is what I used in my first release 0.1.0.
After some testing I realized that after a while the resources where deleted and this was caused by 2 issues:
- no linking between resource and note was generating a orphan resource that is automatically deleted after 90 days
- the delete resource I was using to replace the previous resource with the new one was done asynchronously, so instead of deleting the old resources Joplin was deleting the new one
The delete resource api DELETE /resources/:id is adding the resource to delete in the deleted_items
sqlite table
and then it is actually deleted during the next synch.
Issue #1 - Orphan resource
Jopling stores the links between resources and notes in the database table note_resource
. This table is populated automatically during the synch process.
The Joplin Data API to create a resource don't allow to link it to a note so you must follow the rules of the automatic synch process to create this link.
The synch process scans all the notes to populate the note_resource
table and uses the following rules to decide that a resource is used by a note:
- the resource id is inside a
img
tag in the src
attribute
- the resource id is inside a
a
in the href
attribute
- it matches the regular expression
/^(joplin:\/\/|:\/)([0-9a-zA-Z]{32})(|#[^\s]*)(|\s".*?")$/
For this plugin I decided to trick the resource-note linking process using the last rules and I converted the note placeholder to:
<drawio id="](:/6a0a0fcf2b0246bca3a5b0bccbca1943)"/>
Issue #2 - Asynchronous delete
To prevent the asynchronous delete of the new resources I decided to not delete it at all and create a new resource with the same ID.
I'm lucky because the code to create a resource first stores the input resource with the option { overwrite: true }
on top of the previous resource with the same ID and then tries to save the new resource in the database.
Of course the save on the database fails with a really beautiful error because the resource ID is a unique key:
but before that the resource is correctly replaced and the operation is not fallen back in case of errors.
Conclusions
To fix Issue #2, it would be really useful to have the PUT resource/:id
implemented.
Regarding Issue #1, I'm not sure what it would be the best approach. If the API to handle resources allows also to link the resource to a note, then it would be impossible to break this link in case the plugin is uninstalled.
Maybe the best approach would be for a plugin to declare what are his rules to link a resource to a note and keep those rules valid until the plugin is installed. But it looks a bit difficult to implement.