Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Create Alfred workflows with ease
node
binary..catch()
top-level promises.You need Node.js 4+ and Alfred 3 with the paid Powerpack upgrade.
$ npm install alfy
Create a new blank Alfred workflow.
Add a Script Filter
(right-click the canvas → Inputs
→ Script Filter
), set Language
to /bin/bash
, and add 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.
Tip: You can use generator-alfred to scaffold out an
alfy
based workflow. If so, you can skip the rest of the steps, go straight to theindex.js
and do your thing.
Set the Keyword
by which you want to invoke your workflow.
Go to your new workflow directory (right-click on the workflow in the sidebar → Open in Finder
).
Initialize a repo with npm init
.
Install Alfy with npm install alfy
.
In the workflow directory, create a index.js
file, import alfy
, and do your thing.
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);
});
Some example usage in the wild: alfred-npms
, alfred-emoj
, alfred-ng
.
Alfy uses alfred-notifier in the background to show a notification when an update for your workflow is available.
Alfy offers the possibility of caching data, either with the fetch or directly through the cache object.
An important thing to note is that the cached data gets invalidated automatically when you update your workflow. This offers the flexibility for developers to change the structure of the cached data between workflows without having to worry about invalid older data.
By adding alfy-init
as postinstall
and alfy-cleanup
as preuninstall
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": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"scripts": {
"postinstall": "alfy-init",
"preuninstall": "alfy-cleanup"
},
"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.
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'
}
]);
});
When developing your workflow it can be useful to be able to debug it when something is not working. This is when the workflow debugger comes in handy. You can find it in your workflow view in Alfred. Press the insect icon to open it. It will show you the plain text output of alfy.output()
and anything you log with alfy.log()
:
const unicorn = getUnicorn();
alfy.log(unicorn);
Alfred lets users set environment variables for a workflow which can then be used by that workflow. This can be useful if you, for example, need the user to specify an API token for a service. You can access the workflow environment variables from process.env
. For example process.env.apiToken
.
Type: string
Input from Alfred. What the user wrote in the input box.
Return output to Alfred.
Type: Array
List of Object
with any of the supported properties.
Example:
alfy.output([{
title: 'Unicorn'
}, {
title: 'Rainbow'
}]);
Log value
to the Alfred workflow debugger.
Returns an Array
of items in list
that case-insensitively contains input
.
alfy.matches('Corn', ['foo', 'unicorn']);
//=> ['unicorn']
Type: string
Text to match against the list
items.
Type: Array
List to be matched against.
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']
Same as matches()
, but with alfy.input
as input
.
Display an error or error message in Alfred.
Note: You don't need to .catch()
top-level promises. Alfy handles that for you.
Type: Error
string
Error or error message to be displayed.
Returns a Promise
that returns the body of the response.
Type: string
URL to fetch.
Type: Object
Any of the got
options.
Type: boolean
Default: true
Parse response body with JSON.parse
and set accept
header to application/json
.
Type: number
Number of milliseconds this request should be cached.
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)
})
Type: Object
Persist config data.
Exports a conf
instance with the correct config path set.
Example:
alfy.config.set('unicorn', '🦄');
alfy.config.get('unicorn');
//=> '🦄'
Type: Object
Persist cache data.
Exports a modified conf
instance with the correct cache path set.
Example:
alfy.cache.set('unicorn', '🦄');
alfy.cache.get('unicorn');
//=> '🦄'
The set
method of this instance accepts an optional third argument where you can provide a maxAge
option. maxAge
is
the number of milliseconds the value is valid in the cache.
Example:
const delay = require('delay');
alfy.cache.set('foo', 'bar', {maxAge: 5000});
alfy.cache.get('foo');
//=> 'bar'
// Wait 5 seconds
await delay(5000);
alfy.cache.get('foo');
//=> undefined
Type: boolean
Whether the user currently has the workflow debugger open.
Type: Object
Keys: info
warning
error
alert
like
delete
Get various default system icons.
The most useful ones are included as keys. The rest you can get with icon.get()
. Go to /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources
in Finder to see them all.
Example:
console.log(alfy.icon.error);
//=> '/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/AlertStopIcon.icns'
console.log(alfy.icon.get('Clock'));
//=> '/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/Clock.icns'
Type: Object
Example:
{
name: 'Emoj',
version: '0.2.5',
uid: 'user.workflow.B0AC54EC-601C-479A-9428-01F9FD732959',
bundleId: 'com.sindresorhus.emoj'
}
Type: Object
Alfred metadata.
Example: '3.0.2'
Find out which version the user is currently running. This may be useful if your workflow depends on a particular Alfred version's features.
Example: 'alfred.theme.yosemite'
Current theme used.
Example: 'rgba(255,255,255,0.98)'
If you're creating icons on the fly, this allows you to find out the color of the theme background.
Example: 'rgba(255,255,255,0.98)'
The color of the selected result.
Example: 3
Find out what subtext mode the user has selected in the Appearance preferences.
Usability note: This is available so developers can tweak the result text based on the user's selected mode, but a workflow's result text should not be bloated unnecessarily based on this, as the main reason users generally hide the subtext is to make Alfred look cleaner.
Example: '/Users/sindresorhus/Library/Application Support/Alfred 3/Workflow Data/com.sindresorhus.npms'
Recommended location for non-volatile data. Just use alfy.data
which uses this path.
Example: '/Users/sindresorhus/Library/Caches/com.runningwithcrayons.Alfred-3/Workflow Data/com.sindresorhus.npms'
Recommended location for volatile data. Just use alfy.cache
which uses this path.
Example: '/Users/sindresorhus/Dropbox/Alfred/Alfred.alfredpreferences'
This is the location of the Alfred.alfredpreferences
. If a user has synced their settings, this will allow you to find out where their settings are regardless of sync state.
Example: 'adbd4f66bc3ae8493832af61a41ee609b20d8705'
Non-synced local preferences are stored within Alfred.alfredpreferences
under …/preferences/local/${preferencesLocalHash}/
.
Alfred workflows using Alfy
MIT
FAQs
Create Alfred workflows with ease
The npm package alfy receives a total of 89 weekly downloads. As such, alfy popularity was classified as not popular.
We found that alfy demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.