Cheap and cheerful iCloud File Sync

OK, big disclaimer here, this could really mess things up for you.

I decided to write a short action to sync one of my workspace inboxes to the file system on iCloud (so I could edit the drafts using Vim on my Mac).

I thought people may be interested in seeing the code, though I won’t publish it as an action as I don’t want everyone thinking it is a production action that’s safe for use.

The comments at the start outline the restrictions, some are due to my lack of need for the feature, others are due to the restrictions in the Drafts FileManager API.

Have fun if you are interested, and always work with a good backup of your drafts!

// A proof of concept sync of drafts to iCloud files
// Rules to lead to happy usage:
// 1. Deleting and renaming will cause duplicates. So best to sync to Drafts, make changes there, delete all files and rerun
// 2. Only create new files in drafts
// 3. Don't call your workspace Backups, Inbox or Library , this script creates a directory in Drafts' iCloud folder and that may conflict with Drafts and TADs own folders
// 4. If both files are edited then the one edited last will be in drafts - no conflict will be detected

"use strict";

// Edit this to the workspace you would like to sync
const workspaceName = 'WIP';
const fileExtension = ".md";

const fmCloud = FileManager.createCloud();
fmCloud.createDirectory(workspaceName, "/");
const ws = Workspace.find(workspaceName);



const allDrafts = ws.query('inbox'); // Just sync inbox


for (let theDraft of allDrafts) {
    let fileName = theDraft.processTemplate("[[safe_title]]").replace("  }", "").replace("{  ", "");
    fileName = (fileName.length == 0) ? fileName = theDraft.uuid + fileExtension : fileName += fileExtension;

    const draftContent = theDraft.content;
    let fileModifiedAt = fmCloud.getModificationDate(workspaceName + "/" + fileName)
    fileModifiedAt = fileModifiedAt || 0;
    console.log(`${fileName}:`);
    console.log(`${theDraft.modifiedAt} cf ${fileModifiedAt}`);
    if (theDraft.modifiedAt > fileModifiedAt) {
        // Draft is newer than File so overwrite file
        console.log("Write");
        fmCloud.writeString(workspaceName + "/" + fileName, draftContent);
        fmCloud.setModificationDate(workspaceName + "/" + fileName, theDraft.modifiedAt);
    } else {
        if (fileModifiedAt > theDraft.modifiedAt) {
            // File is newer than draft so import and replace content of draft
            console.log("Read");
            let fileContent = fmCloud.readString(workspaceName + "/" + fileName);
            theDraft.content = fileContent;
            theDraft.update();
        } else {
            console.log("No change");
        }
    }
}
3 Likes

I think you just mean Drafts’ own folders there. Backup, Inbox, and Library are all standard folders for Drafts. As a set of Drafts code, the ThoughtAsylum Drafts Library (TADpoLe/tad.js) is deployed within the standard Scripts subfolder of the Library folder. There are other standard Drafts folders you might come across in there too, including Previews, Syntaxes, Templates and Themes.

You could probably avoid the limitation by having your own unique top level folder and then creating workspace folders under that, and your draft copies in there.

Haven’t played with this yet, but thanks for making it available…