alfy 0,1 editorconfig travis-ci npm

Create Alfred workflows with ease

Alfy

Create Alfred workflows with ease

Build Status

Highlights

  • Easy input↔output.
  • Config and cache handling built-in.
  • Fetching remote files with optional caching.
  • Publish your workflow to npm.
  • Automatic update notifications.
  • Easily testable workflows.
  • Finds the node binary.
  • Presents uncaught exceptions and unhandled Promise rejections to the user.
    No need to manually .catch() top-level promises.

Prerequisites

You need Node.js 4+ and Alfred 3 with the paid Powerpack upgrade.

Install

$ npm install --save alfy

Usage

Create a new Alfred workflow and add a Script Filter with the following script:

./node_modules/.bin/run-node index.js "$1"

We can’t call node directly as GUI apps on macOS doesn’t inherit the $PATH.

In the workflow directory, create a index.js file, import alfy, and do your thing.

Tip: you can use generator-alfred to scaffold out an alfy based workflow.

Example

Here we fetch some JSON from a placeholder API and present matching items to the user:

const alfy = require('alfy');

alfy.fetch('jsonplaceholder.typicode.com/posts').then(data => {
	const items = alfy
		.inputMatches(data, 'title')
		.map(x => ({
			title: x.title,
			subtitle: x.body,
			arg: x.id
		}));

	alfy.output(items);
});

More

Some example usage in the wild: alfred-npms, alfred-emoj, alfred-ng2.

Update notifications

Alfy uses alfred-notifier in the background to show a notification when an update for your workflow is available.

Publish to npm

By adding alfy-init as postinstall script, you can publish your package to npm instead of to Packal. This way, your packages are only one simple npm install command away.

{
  "name": "alfred-unicorn",
  "version": "1.0.0",
  "description": "My awesome unicorn workflow",
  "author": {
    "name": "Sindre Sorhus",
    "email": "[email protected]",
    "url": "sindresorhus.com"
  },
  "scripts": {
    "postinstall": "alfy-init"
  },
  "dependencies": {
    "alfy": "*"
  }
}

Tip: Prefix your workflow with alfred- to make them easy searchable through npm.

You can remove these properties from your info.plist file as they are being added automatically at install time.

After publishing your workflow to npm, your users can easily install or update the workflow.

$ npm install --global alfred-unicorn

Tip: instead of manually updating every workflow yourself, use the alfred-updater workflow to do that for you.

Testing

Workflows can easily be tested with alfy-test. Here is a small example.

import test from 'ava';
import alfyTest from 'alfy-test';

test(async t => {
    const alfy = alfyTest();

    const result = await alfy('workflow input');

    t.deepEqual(result, [
        {
            title: 'foo',
            subtitle: 'bar'
        }
    ]);
});

API

alfy

input

Type: string

Input from Alfred. What the user wrote in the input box.

output(list)

Return output to Alfred.

list

Type: Array

List of Object with any of the supported properties.

Example:

alfy.output([{
	title: 'Unicorn'
}, {
	title: 'Rainbow'
}]);

matches(input, list, [item])

Returns an Array of items in list that case-insensitively contains input.

alfy.matches('Corn', ['foo', 'unicorn']);
//=> ['unicorn']
input

Type: string

Text to match against the list items.

list

Type: Array

List to be matched against.

item

Type: string Function

By default it will match against the list items.

Specify a string to match against an object property:

const list = [{
	title: 'foo'
}, {
	title: 'unicorn'
}];

alfy.matches('Unicorn', list, 'title');
//=> [{title: 'unicorn'}]

Or nested property:

const list = [{
	name: {
		first: 'John',
		last: 'Doe'
	}
}, {
	name: {
		first: 'Sindre',
		last: 'Sorhus'
	}
}];

alfy.matches('sindre', list, 'name.first');
//=> [{name: {first: 'Sindre', last: 'Sorhus'}}]

Specify a function to handle the matching yourself. The function receives the list item and input, both lowercased, as arguments, and is expected to return a boolean whether it matches:

const list = ['foo', 'unicorn'];

// here we do an exact match
// `Foo` matches the item since it's lowercased for you
alfy.matches('Foo', list, (item, input) => item === input);
//=> ['foo']

inputMatches(list, [item])

Same as matches(), but with alfy.input as input.

log(text)

text

Type: string

Text to be logged to the debug panel. Only logs when alfred.debug is true, so not to interfere with the normal output.

error(err)

Display an error or error message in Alfred.

Note: You don’t need to .catch() top-level promises. Alfy handles that for you.

err

Type: Error string

Error or error message to be displayed.

fetch(url, [options])

Returns a Promise that returns the body of the response.

url

Type: string

URL to fetch.

options

Type: Object

Any of the got options.

json

Type: boolean
Default: true

Parse response body with JSON.parse and set accept header to application/json.

maxAge

Type: number

Number of milliseconds this request should be cached.

transform

Type: Function

Transform the response before it gets cached.

alfy.fetch('https://api.foo.com', {
	transform: body => {
		body.foo = 'bar';
		return body;
	}
})

You can also return a Promise.

const xml2js = require('xmls2js');
const pify = require('pify');

const parseString = pify(xml2js.parseString);

alfy.fetch('https://api.foo.com', {
	transform: body => parseString(body)
})

config

Type: Object

Persist config data.

Exports a conf instance with the correct config path set.

Example:

”`js alfy.config.set(‘unicorn’, ‘

Related Repositories

alfy

alfy

Create Alfred workflows with ease ...

alfy-test

alfy-test

Test your Alfy workflows ...

Alfy-TokenSwapService

Alfy-TokenSwapService

Heroku hosted token swap service to enable Spotify login ...


Top Contributors

sindresorhus SamVerschueren importre spinscale sotojuan mafredri

Dependencies

package version
alfred-link ^0.2.0
alfred-notifier ^0.2.0
cache-conf ^0.5.0
clean-stack ^1.0.0
conf ^1.1.2
dot-prop ^4.0.0
execa ^0.7.0
got ^7.0.0
hook-std ^0.4.0
loud-rejection ^1.6.0
npm-run-path ^2.0.2
read-pkg-up ^2.0.0
dev ava *
delay ^2.0.0
nock ^9.0.2
tempfile ^2.0.0
xo *

Releases

-   v0.4.0 zip tar
-   v0.3.0 zip tar
-   v0.2.1 zip tar
-   v0.2.0 zip tar
-   v0.1.1 zip tar
-   v0.1.0 zip tar