Custom Assets

You can declare custom assets to use if they are not already included in the defaults.

Why use the Bundler for custom assets?

If you are using a utility that might need to be whitelisted by Gatekeeper, then the Bundler will take care of that headache for you. If an application is not whitelisted, then opening it in a script will fail silently. Gatekeeper is a pain. Trust us on that, and let us handle it for you.

If the asset that you want to use is large then it might live in the users' Dropbox folder (if the user is set to use Dropbox to sync workflows). This will take up valuable space, but the Bundler will put it in a different directory that is not synced with Dropbox.

If you happen to reuse the same asset between workflows, then the Bundler will make it so that only one copy of the asset lives on the users' computers, cutting down code duplication.

If you think that there is a good asset that should be included in the Bundler's defaults, then put in a pull request in the Bundler's Github repo, and we might include it.

To define a custom asset, you need to make a json file that the bundler can read. Look at the template below.

{
    "name": "ASSETNAME",
    "type": "TYPE",
    "gatekeeper": "false",
    "message": "what it does",
    "versions": {
        "latest": {
            "invoke": "COMMAND",
            "files": [
                {
                    "url": "URL",
                    "method": "METHOD"
                }
            ],
            "install": [
                "cp -f '__CACHE__/FILE' '__DATA__'"
            ]
        }
    }
}

There are a few things to know about the bundler. First, everything is case sensitive. Second, it stores assets dynamically named directories:

{bundler-data-directory}/data/assets/TYPE/NAME/VERSION/

Name

Any asset file needs to have the same name as the name attribute set within the file. So, if the name of the asset is mYweIdly_nameD-assEt, then the file will need to be named mYweIdly_nameD-assEt.json, and you will have to call the file with that case.

Type

Utilities (applications or other executables) should have the type utility. A library for a language should have the language name as the type (applescript for an AppleScript library, bash for a Bash library). The type should be lowercase.

The gatekeeper entry is needed only when the asset is a utility and it needs Gatekeeper approval to run. The message entry is needed only in the same circumstance. If you do not need to set gatekeeper to true, then omit it and message.
Versions

The versions value is a hash. Each key in the hash should be the version's name. You'll notice that all of the defaults have a latest version that might duplicate a version below. The bundler, in the absence of a version argument when loading an asset with fallback to latest. Otherwise, you should name the version however it will be called (3.1.2-rc3).

Invoke

The invoke value should be set to whatever is necessary to use the asset. So, when you are calling a utility, you need to execute the utility via the path. However, some utilities want you to run the binary within the .app directory. So, the invoke should be the remainder of the path to that binary. Here is CocoaDialog's invoke: cocoaDialog.app/Contents/MacOS/cocoaDialog. However, if it is a library that needs to be included, then it should just be the filename. For instance, here is David Ferguson's PHP Workflows library's invoke line: workflows.php.

Files

The files entry is an array of hashes of files that need to be downloaded. Each hash within the array needs a value for url and method. url is the URL from where the file will be downloaded, and the method describes what kind of download it is.

Methods

Currently, there are three valid methods. Choose the appropriate one for each file.

Install

The install array is a list of shell commands that need to be executed in order to install the asset. All paths should be quoted with single quotes. You'll see that there are some funky flags that are used within this array. Those flags are dynamic values that the bundler will interpret.

If you use the tgz or zip methods, then you should not need the the __FILE__ flag.

Here is an example of how to deal with a dmg file. The example comes from the Pashua.json file.

"install": [
            "hdiutil attach -nobrowse -quiet '__FILE__'",
            "cp -f /Volumes/Pashua/Documentation.html '__DATA__'",
            "cp -fR /Volumes/Pashua/Pashua.app '__DATA__'",
            "hdiutil detach -quiet /Volumes/Pashua"
        ]
        

Here __FILE__ refers to the actual dmg file that was downloaded. __DATA__ evaluates to {bundler-data-directory}/data/assets/utility/Pashua/latest/.

Always use single quotes when dealing with files. Many users' directories have spaces in them, so, if you do not quote the path, the asset installation will fail.

For more examples asset JSON files, look in the bundler/meta/defaults directory.

Questions?

Post on the Alfred Forum thread.

Bug Reports?

Open an issue in the Github queue.