I have a question that perhaps some of the JXA gurus can help me with.
@8isnothing is helping me to write an API to access DT3 via the web and via Zapier. (I will post details here to share when done.). We have the download API endpoint working and are very close to having the upload endpoint working. But the uploaded documents are going into the root of the desired database instead of into the Group identified by UUID.
This is Python code which calls JXA inside the API:
We know that this script correctly receives data from Python since it can identify the correct database and can also correctly add tags and custom metadata. But the problem is that DT is recognizing the UUID but importing the files to the root folder of the desired Group instead of to the desired Group itself.
Interestingly however this is a standalone JXA script which uses the same logic. If we run this script from Terminal or Keyboard Maestro or Textexpander, then the file does go to the correct Group. It only fails to go to the correct Group when the process is initiated from Python to JXA.
It would have been advantageous to include the script code verbatim (i.e. included in code fences ```) here, so that others could run it easily.
Apart from the spelling mistake @cgrunenberg noted already, Iâd suggest to write the data you pass into the script to console.log or to a file or something. The only reason I can see that this is not working is that myDestUUID != "" is in fact true.
How do you know that DT is recognizing the UUID? And is that UUID really a group? On a related note, wouldnât it be easier to use group names (or hierachies) instead of UUIDs (in terms of readability and maintainability)?
Yes the UUID is really for a group - not only is this something I can personally verify in the database, but also it works in the standalone script to add the document to the group.
We know DT is recognizing the UUID because when we run the script in the API (using Python), it adds the document to the Inbox of the database which contains the desired destination group. If I try it with a different UUID representing a group in a different database, then it adds the document to the inbox of the corresponding database.
The reason to use a UUID rather than a group name is that names are not unique. For example if this is a database of client cases then I might have a main case group of âDoe, Johnâ with subgroups of âDoe, John Urgent to Reviewâ and âDoe, John Completed.â
Although the API will be usable on its own if desired, I am working on a web app front end using www.retool.com which displays the group names so for regular use I will not need to reference UUIDs if I choose not to do so.
I will let @8isnothing respond to your other specific questions on coding technique.
Thatâs why I said âgroup name (or hierarchies)â. âDoe, John/Doe, John Urgent to Reviewâ should be unique.
That might just be a coincidence (this database being the âcurrentDatabaseâ, for example). I still suggest to console.log(theUUID)and to check that getRecordWithUuid(theUUID).type() === "group"
If I use the UUID, then it is easy to do âCopy Item Linkâ and paste that into the appropriate query in the app (which actually accepts either pure UUID or an x-devonthink link). If I have to enter the group hierarchy, then there is no simple way to grab that.
Agreed - we will try this if the other suggestions do not work. Thanks.
As an aside, the use of exceptions for control flow tends to be seen as an anti-pattern. Google, for example, the discussion on:
anti patterns - Are exceptions as control flow considered a serious antipattern? If so, Why? - Software Engineering Stack Exchange
Here, I think the .length typo was probably harder to notice inside the black hole of a try ... throw error exception wrapping, where it would create the impression that the UUID was never being found.
(usually best to reserve exceptions for interactions with IO)
I have a minimal example (which is always! the way to go) here:
function doIt(args) {
dt = Application("DEVONthink 3");
const file = args[0];
const uuid = args[1];
var tags = args[2];
var meta = args[3];
var params = {};
if (uuid != "") {
var destGroup = dt.getRecordWithUuid(uuid);
if (destGroup.type() === "group") {
params.to = destGroup;
}
}
const record = dt.import(file, params);
console.log(`record ${record.name()} created in group ${record.parents()[0].uuid()}`);
}
doIt(["/Users/ck/Fotos ohne Location.scpt"), "FFC907C5-EF78-4934-B063-A6DA61061E39", "",""]);
that works ok. I didnât do anything about the tags and metadata stuff, since you mentioned that your problem is the import.
Now that thatâs out of the way, I suppose that the UUID is not passed from your Python code to the JXA script as you expect it.
Indeed, DEVONthink could be importing to the active database. It may be a coincidence. Great insight!
We had console.log before. It was stripped out after my personal tests, but it may be a good idea to bring it back.
Object.keys(myDestGroup).length === 0 is used to check if the return of getRecordWithUuid is not empty. As far as I tested, without it the code wonât return an error.
The most important and curious detail about this problem is that it happens in @rkaplan 's computer, but it works perfectly on mine. We are using exactly the same code (using github as source) and somehow software behaves differently. Also, as pointed out by @rkaplan, the standalone version of the script (Iâve made it just to debug the import feature) works flawlessly on both my and @rkaplan 's ends.
Iâll post the code again (as code, not as images) if that helps.
We have some other API endpoints that passes UUID from Python to JXA using the same logic as the code posted, and it works fine.
Question:
I was wondering: if this problem could be related to some DEVONthink configuration. Since the standalone script to import files work, we can discard this possibility, right?
We have different databases. So the group UUID is definitely different.
Groups by path wonât be practical for this use case. We should really go with UUID. As I said, that method per se is not problematic. We are only facing issues with this import being called from Python.
Very, very stupid question: Is the group in question may be âlockedâ or in some other way protected for writing?
The bad thing is that import is apparently not raising any error. It was driving me mad, because I tried to import a file that never appeared in DT and everything seemed to be ok. In fact, Iâd forgotten the file extension, so what I passed to import did not exist in the filesystem⌠@cgrunenberg: Maybe import could throw a error if the file canât be imported, possibly indicating the reason for it? I know that I can check the returned record (which is null if something went wrong), but that does not tell me anything about the possible problem.
Interesting, not stupid - but no it is not locked. And I have the same problem when I try it with various groups in different databases. And it works when we do the standalone script; the problem is only when Python is calling the scriptâŚ
(the last two empty strings are just the tags and metadata, which are not needed, I think). If that works, Iâd go and fiddle around with the Python stuff.