Create Alfred workflows with ease
- 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. - Support for top-level
await
. - Presents uncaught exceptions and unhandled Promise rejections to the user.
No need to manually.catch()
top-level promises.
You need Node.js 18+ and Alfred 4 or later with the paid Powerpack upgrade.
npm install alfy
IMPORTANT: Your script will be run as ESM.
-
Create a new blank Alfred workflow.
-
Add a
Script Filter
(right-click the canvas →Inputs
→Script Filter
), setLanguage
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
. -
Add
"type": "module"
to package.json. -
Install Alfy with
npm install alfy
. -
In the workflow directory, create a
index.js
file, importalfy
, and do your thing.
Here we fetch some JSON from a placeholder API and present matching items to the user:
import alfy from 'alfy';
const data = await alfy.fetch('https://jsonplaceholder.typicode.com/posts');
const items = alfy
.inputMatches(data, 'title')
.map(element => ({
title: element.title,
subtitle: element.body,
arg: element.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": "[email protected]",
"url": "https://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('main', 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()
:
import alfy from 'alfy';
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: object[]
List of object
with any of the supported properties.
Example:
import alfy from 'alfy';
alfy.output([
{
title: 'Unicorn'
},
{
title: 'Rainbow'
}
]);
Type: object
Type: number
(seconds)
Values: 0.1...5.0
A script can be set to re-run automatically after some interval. The script will only be re-run if the script filter is still active and the user hasn't changed the state of the filter by typing and triggering a re-run. More info.
For example, it could be used to update the progress of a particular task:
import alfy from 'alfy';
alfy.output(
[
{
title: 'Downloading Unicorns…',
subtitle: `${progress}%`,
}
],
{
// Re-run and update progress every 3 seconds.
rerunInterval: 3
}
);
Log value
to the Alfred workflow debugger.
Returns an string[]
of items in list
that case-insensitively contains input
.
import alfy from 'alfy';
alfy.matches('Corn', ['foo', 'unicorn']);
//=> ['unicorn']
Type: string
Text to match against the list
items.
Type: string[]
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:
import alfy from 'alfy';
const list = [
{
title: 'foo'
},
{
title: 'unicorn'
}
];
alfy.matches('Unicorn', list, 'title');
//=> [{title: 'unicorn'}]
Or nested property:
import alfy from 'alfy';
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 of whether it matches:
import alfy from 'alfy';
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
.
If you want to match against multiple items, you must define your own matching function (as shown here). Let’s extend the example from the beginning to search for a keyword that appears either within the title
or body
property or both.
import alfy from 'alfy';
const data = await alfy.fetch('https://jsonplaceholder.typicode.com/posts');
const items = alfy
.inputMatches(
data,
(item, input) =>
item.title?.toLowerCase().includes(input) ||
item.body?.toLowerCase().includes(input)
)
.map((element) => ({
title: element.title,
subtitle: element.body,
arg: element.id,
}));
alfy.output(items);
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 and the below 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: boolean
Default: true
Whether to resolve with only body or a full response.
import alfy from 'alfy';
await alfy.fetch('https://api.foo.com');
//=> {foo: 'bar'}
await alfy.fetch('https://api.foo.com', {
resolveBodyOnly: false
});
/*
{
body: {
foo: 'bar'
},
headers: {
'content-type': 'application/json'
}
}
*/
Type: Function
Transform the response body before it gets cached.
import alfy from 'alfy';
await alfy.fetch('https://api.foo.com', {
transform: body => {
body.foo = 'bar';
return body;
}
})
Transform the response.
import alfy from 'alfy';
await alfy.fetch('https://api.foo.com', {
resolveBodyOnly: false,
transform: response => {
response.body.foo = 'bar';
return response;
}
})
You can also return a Promise.
import alfy from 'alfy';
import xml2js from 'xml2js';
import pify from 'pify';
const parseString = pify(xml2js.parseString);
await 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:
import alfy from 'alfy';
alfy.config.set('unicorn', '🦄');
alfy.config.get('unicorn');
//=> '🦄'
Type: Map
Exports a Map with the user workflow configuration. A workflow configuration allows your users to provide configuration information for the workflow. For instance, if you are developing a GitHub workflow, you could let your users provide their own API tokens.
See alfred-config
for more details.
Example:
import alfy from 'alfy';
alfy.userConfig.get('apiKey');
//=> '16811cad1b8547478b3e53eae2e0f083'
Type: object
Persist cache data.
Exports a modified conf
instance with the correct cache path set.
Example:
import alfy from 'alfy';
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:
import alfy from 'alfy';
import delay from '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:
import alfy from 'alfy';
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/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/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
- alfred-emoj - Find relevant emoji from text
- alfred-npms - Search for npm packages with npms.io
- alfred-dark-mode - Toggle the system dark mode
- alfred-xcode - Open Xcode projects and workspaces
- alfred-lock - Lock your Mac
- alfred-fkill - Fabulously search and kill processes
- alfred-ng - Search through the Angular documentation on angular.io
- alfred-ionic - Search through the Ionic documentation
- alfred-react-native - Access the React Native documentation
- alfred-hl - Syntax highlight code in the clipboard
- alfred-workflow-docs-elastic - Search the Elastic.co documentation
- alfredinary - Capture screenshots and upload to Cloudinary
- alfred-keycode - Get JavaScript keycodes
- alfred-vue - Search the Vue.js API docs
- alfred-meteor-docs - Search the Meteor docs
- alfred-meteor-packages - Meteor package search
- alfred-climbing-grades-converter - Convert between climbing grading systems
- alfred-hotel - Quickly start, stop and open Hotel apps
- alfred-coolors - Find relevant color names
- alfred-postico-favorites-workflow - Open postico favorites
- alfred-messages - Message your contacts through iMessage
- alfred-bitbucket - List you and your teams public and private Bitbucket repositories
- alfred-asana - Search your Asana tasks
- alfred-cacher - Find a code snippet from Cacher and copy it to the clipboard
- alfred-loremipsum - Generate placeholder text
- alfred-packagist - Search for PHP packages with Packagist
- alfred-vpn - Connect/disconnect from VPNs
- alfred-yandex-translate - Translate words and text with Yandex Translate
- alfred-now - Use Now commands within Alfred to access deployments and aliases
- alfred-chuck-norris-jokes - Get Chuck Norris jokes
- alfred-show-network-info - See network info and discover local devices
- alfred-currency-conversion - See foreign exchange rates and currency conversion
- alfred-polyglot - Translate text with Google Translate
- alfred-stock-price - Show real time stock price in US market
- alfred-jira - Convert clipboard text between Markdown and Jira markup
- alfred-network-location-switch - Switch macOS network location
- alfred-cool - Find cool words
- alfred-google-books - Search for Google Books
- alfred-ip - Find your public IP
- alfred-figma – Quick links and search Figma teams, projects and files
- alfred-flutter-docs – Quickly search and preview Flutter docs
- alfred-title – Capitalize your titles
- alfred-trello - Search your boards, quickly add cards, and view list of cards for Trello
- alfred-npm-versions - Lookup the latest 15 versions for an npm package
- alfred-github-trending - Search trending repositories on GitHub
- alfred-elm - Browse Elm packages documentation
- alfred-imagemin - Minify images with Imagemin
- alfred-evernote-workflow - Search Evernote with keywords and tags
- alfred-deno-doc - Access the Deno documentation
- alfred-fly - Search Google Chrome bookmarks
- alfred-simple-email-fetcher - Show unseen emails from multiple accounts using IMAP
- alfred-chrome-workflow - Search Chrome's bookmarks, history and download logs
- alfred-code - Quickly open a file in Visual Studio Code
- alfred-amphetamine - Start and end sessions quickly in the Amphetamine app
- alfred-ids - Generate various types of IDs.
- alfred-awesome-stars - Search starred GitHub repos through awesome-stars.
- alfred-pwgen - Generate random and secure passwords.
- alfred-bear - Use dynamic templates with the Bear app.
- alfred-color-converter - Convert colors between RGB and Hex.
- alfred-simple - Simple theme for Alfred (Used in the screenshots)
- alfred-updater - Workflow updater
- alfred-notifier - Update notifications for your workflow
- generator-alfred - Scaffold out an Alfred workflow
alfy's People
Forkers
mafredri importre spinscale vutran ninjakttty adnasa frog79 jhilker urre lleonardl radibit wolasss luca-aurelia xiaomaisu autostu denistsoi exah tirams ericksahara danielbayley nicklayb cacherapp antonniklasson alexlafroscia mkalygin robjtede rsify parinck wei-xia colinf navpreetsamra abdul hiwangyeah imagineagents nguyenvanduocit calpa dameck crazyrex heypoom kaicorp victorkolb chris-nicol kikobeats adamkiss phantomk stanleyyylau litomore best199101 w0ng jonicious antonisin zwhgithub keyz mikqi automatethings badibadiola 3diq zhangaz1 kawamataryo raykle jopemachine hhhhhosx stdavis chancock09 sbusso jacobjohansen houxianxin pvinis syedpeer guanlinwu adambudzik afzalive currybob shaodahong demartini fitnesses jacke brunoss8 gil 0xblockchainx0 cipengxu commonjs-bot lisaross rchl davidmondok webcomeon alexrogalskiy wisinfun extirpate jmeischner tofrankie liangshen001 all-forks nativeit-dev gksander tranquocthien boraseoksoon avatararts geekwolverine mfrank2016alfy's Issues
Use `String#normalize()` in `alfy.matches()`
Extract and open source `run-node.sh`?
This would help with an issue we've had for a long time on ghooks
.
I'd be happy to do it. I notice there's some specific Alfred stuff in there. Do you have any tips on how to make it in a way that works cross-platform and agnostic of Alfred?
ERROR: alfred.workflow.input.scriptfilter
[ERROR: alfred.workflow.input.scriptfilter] XML Parse Error 'The operation couldn’t be completed. (NSXMLParserErrorDomain error 4.)'. Row (null), Col (null): 'Document is empty' in XML:
index.js code:
const alfy = require('alfy');
alfy.output([{
title: 'Unicorn'
}, {
title: 'Rainbow'
}]);
[ERROR: input.scriptfilter] JSON error: JSON text did not start with array or object and option to allow fragments not set. in JSON:
I'm getting the following error when just trying to log a string with alfy.log
:
[ERROR: input.scriptfilter] JSON error: JSON text did not start with array or object and option to allow fragments not set. in JSON:
Project built with yo alfred
and development linked with alfred-link
There is a $20.00 open bounty on this issue. Add more on Issuehunt.
- Checkout the Issuehunt explorer to discover more funded issues.
- Need some help from other developers? Add your repositories on Issuehunt to raise funds.
Support the `rerun` parameter
https://www.alfredapp.com/help/workflows/inputs/script-filter/json/
// @mdeboer
IssueHunt Summary
jopemachine has been rewarded.
Backers (Total: $20.00)
- issuehunt ($20.00)
Submitted pull Requests
Tips
- Checkout the Issuehunt explorer to discover more funded issues.
- Need some help from other developers? Add your repositories on IssueHunt to raise funds.
RerunInterval option documentation need to be modified
Issue
I think the range of rerun-interval value should be 0.1...5.0 according to this document., not to 0.1...0.5
Screenshot
ERR_INPUT_TYPE_NOT_ALLOWED with example script
Using:
Alfred version 4.5.1 with Powerpack
Node version 14.17.5
After following all steps as described under Usage, when running the example workflow I get the following error in Alfred debugger:
Alfy[Script Filter] Queuing argument 'h'
Alfy[Script Filter] Script with argv 'h' finished
ERROR: Alfy[Script Filter] Code 1: internal/process/esm_loader.js:74
internalBinding('errors').triggerUncaughtException(
^
Error [ERR_INPUT_TYPE_NOT_ALLOWED]: --input-type can only be used with string input via --eval, --print, or STDIN
at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:813:13)
at Loader.resolve (internal/modules/esm/loader.js:89:40)
at Loader.getModuleJob (internal/modules/esm/loader.js:242:28)
at Loader.import (internal/modules/esm/loader.js:177:28)
at internal/modules/run_main.js:50:28
at Object.loadESM (internal/process/esm_loader.js:68:11) {
code: 'ERR_INPUT_TYPE_NOT_ALLOWED'
}
When I navigate to the workflow folder in terminal and run the javascript file with node index.js {query}
I do get the expected result (JSON is returned).
Logging prevents results from appearing
If I use alfy.log
in my script, I can't get any valid results in the workflow. I get an error like this when trying to log some results during development:
[2017-12-07 15:27:10][ERROR: input.scriptfilter] JSON error: No string key for value in object around character 4. in JSON:
I know that alfy.log
just goes to STDOUT
(though console.error
); is the issue that Alfred is reading that and trying to parse it for results? Or something in the way that my workflow is configured?
Access environment variables
#36 will likely resolve my issue so I can gather the users token to use to make API calls but for the short term is there a way to I can access the users system env variables?
Add alfy-init script
Original comment: #24 (comment)
Basically it would just be a proxy to alfred-link. This would make the dev experience much better because it doesn't require installing alfred-link
separately (assuming they know about alfred-link
in the first place). Hopefully this encourages people to publish their workflows to npm instead of to Packal. Publishing to npm has much more benefits (which should be all described in my to-do blogpost :)).
How can i output a function?
Hello! How can i run a function (for example execa) when user select an item from list?
That's my code:
alfy.output([
{
title: 'Random',
body: 'Get random photo'
}, {
title: 'ID',
body: 'Pick photo by id'
}
])
Maybe not quite understand how it works
Getting alfy-init: command not found
I was about to make an update to my Alfredinary, but now getting alfy-init: command not found
. I have "postinstall": "alfy-init",
in my package.json
.
Using Node.js v14.8.0, Alfred 4.3.2 and these are my dependencies to the Alfred workflow
"dependencies": {
"alfy": "^0.10.0",
"cloudinary": "^1.25.0",
"dotenv": "^8.2.0"
}
Question: how to package .workflow file?
What is the process to create a proper release with .workflow
filename? Thanks.
GraphQL Support?
As more and more sites and services are using graphql it would be great if alfy
would support graphql queries & mutations.
// edit: saw that alfy used got
under the hood. So you can make POST requests to the graphq api 🙈
Prevent cache failures on workflow update
I was implementing the transform
function of the alfy.fetch
method in alfred-ng2
and noticed a subtle area that could cause your workflow from failing a certain amount of time due to the cache being invalid.
Let me give you an example first to make it easier to understand. Let's assume I was calling an XML API that I transformed to JSON. At first (pre-transform), it would look like this.
alfy.fetch(`https://my-api.com/resources.xml`, {maxAge: ONE_WEEK})
.then(result => xml2js(result))
.then(jsonResult => {
// transform the jsonResult to alfred items
});
The XML data is cached for one day. Now let's assume I upgrade to the transform function. This could be beneficiel because it only has to run the xml2js
call once before caching.
alfy.fetch(`https://my-api.com/resources.xml`, {
maxAge: ONE_WEEK,
transform: result => xml2js(result)
})
.then(jsonResult => {
// transform the jsonResult to alfred items
});
An important thing to notice here is that in the second example, not the XML result is cached, but the result of the transform function and thus the JSON result is being cached. Pretty straightforward.
BUT, without knowing it, we could break everyones workflow now for one day. The thing is that if I had used this workflow quite recently, the XML data would still be cached and the fetch
promise will not return JSON but XML. Boom, workflow explodes! Adding a function to (transform
in this case), doesn't change anything to the cache key.
How did I solve this? By adding a version
property to the options object.
alfy.fetch(`https://my-api.com/resources.xml`, {
maxAge: ONE_WEEK,
version: pkg.version,
transform: result => xml2js(result)
})
.then(jsonResult => {
// transform the jsonResult to alfred items
});
This will make sure that my cache key is different on every release and will invalidate the old cache.
Is this something we could add in alfy
? Could we detect the callers package.json version number? In my case alfred-ng2
so that the developer doesn't have to worry about this issue? I'm quite sure that this issue will be overlooked by almost everyone if it was not tested properly.
A downside of this is that the cache could grow quite rapidly depending on the release cycles of the workflow.
Running basic script takes 5s and throws error
Hey,
I've created a new workflow with yeoman generator:
'use strict';
const alfy = require('alfy');
alfy.output([
{
title: 'Unicorn',
subtitle: alfy.input
}
]);
output
[00:16:30.984] alfy-pkc[Script Filter] Script with argv 'test' finished
[00:16:30.990] STDERR: alfy-pkc[Script Filter] /Users/pk/Library/Caches/com.runningwithcrayons.Alfred/Workflow Data/com.google.alfy-pkc/node_path: line 1: unexpected EOF while looking for matching `"'
/Users/pk/Library/Caches/com.runningwithcrayons.Alfred/Workflow Data/com.google.alfy-pkc/node_path: line 2: syntax error: unexpected end of file
[00:16:30.991] alfy-pkc[Script Filter] {
"items": [
{
"title": "Unicorn",
"subtitle": "test"
}
]
I'm using node 14 from nvm. Symlinked it to /usr/local/bin. Content of 'node_path' file:
PATH="/usr/local/opt/coreutils/libexec/gnubin
(missing " is not a typo)
Install it globally
Hi there,
I'm quite new to node.js / npm so please excuse my rookie question.
Are there any drawbacks to install it with --global?
Alfy eats errors from Run Script action
Alfred's workflow debugger only shows output from stderr
. These lines redirect all output from stderr
to alfy.error()
, which then uses console.log()
to print it to stdout
:
loudRejection(alfy.error);
process.on('uncaughtException', alfy.error);
hookStd.stderr(alfy.error);
This means that any errors that occur inside a Run Script action are never displayed in the workflow debugger.
IssueHunt Summary
Backers (Total: $20.00)
- issuehunt ($20.00)
Submitted pull Requests
Become a backer now!
Or submit a pull request to get the deposits!
Tips
- Checkout the Issuehunt explorer to discover more funded issues.
- Need some help from other developers? Add your repositories on IssueHunt to raise funds.
IssueHunt has been backed by the following sponsors. Become a sponsor
"Couldn't find binary node" error in two packages using alfy
Hey @sindresorhus,
On a 1h fresh Mac OS setup, I cannot use any alfred workflow relying on alfy.
Here's my setup:
- Iterm with
zsh
andoh-my-zshrc
yarn
installed throughbrew install yarn --without-node
nvm
with version 9 and 10 installed.
I've tried command -v node
from zsh
, bash
and sh
and they all return the path to the nvm installed binary.
I think installing yarn
without node, and using nvm
as the only way to install node
breaks something with how alfy calls the scripts.
Issue Updating Alfy Workflow
Yesterday we released a new version of the alfred-packagist
. When we tried to update the package locally with npm i -g alfred-packagist
we get the following error:
> [email protected] preuninstall /usr/local/lib/node_modules/alfred-packagist
> alfy-cleanup
{ Error: Command failed: alfred-unlink
module.js:529
throw err;
^
Error: Cannot find module './'
at Function.Module._resolveFilename (module.js:527:15)
at Function.Module._load (module.js:476:23)
at Module.require (module.js:568:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (/usr/local/lib/node_modules/alfred-packagist/node_modules/.bin/alfred-unlink:3:20)
at Module._compile (module.js:624:30)
at Object.Module._extensions..js (module.js:635:10)
at Module.load (module.js:545:32)
at tryModuleLoad (module.js:508:12)
at Function.Module._load (module.js:500:3)
at Promise.all.then.arr (/usr/local/lib/node_modules/alfred-packagist/node_modules/execa/index.js:201:11)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
code: 1,
killed: false,
stdout: '',
stderr: 'module.js:529\n throw err;\n ^\n\nError: Cannot find module \'./\'\n at Function.Module._resolveFilename (module.js:527:15)\n at Function.Module._load (module.js:476:23)\n at Module.require (module.js:568:17)\n at require (internal/module.js:11:18)\n at Object.<anonymous> (/usr/local/lib/node_modules/alfred-packagist/node_modules/.bin/alfred-unlink:3:20)\n at Module._compile (module.js:624:30)\n at Object.Module._extensions..js (module.js:635:10)\n at Module.load (module.js:545:32)\n at tryModuleLoad (module.js:508:12)\n at Function.Module._load (module.js:500:3)\n',
failed: true,
signal: null,
cmd: 'alfred-unlink',
timedOut: false }
npm WARN lifecycle [email protected]~preuninstall: continuing anyway [email protected] preuninstall: `alfy-cleanup`
npm WARN lifecycle Exit status 1
npm ERR! path /usr/local/lib/node_modules/alfred-packagist/node_modules/.bin/rimraf
npm ERR! code EEXIST
npm ERR! Refusing to delete /usr/local/lib/node_modules/alfred-packagist/node_modules/.bin/rimraf: is outside /usr/local/lib/node_modules/alfred-packagist/node_modules/rimraf and not a link
npm ERR! File exists: /usr/local/lib/node_modules/alfred-packagist/node_modules/.bin/rimraf
npm ERR! Move it away, and try again.
We're using node
v8.7.0 and npm
v5.5.1 on macOS.
Is this something we have done wrong when we implemented Alfy into alfred-packagist
? What is your thoughts on this issue?
How to copy output to clipboard?
This repo hasn't gotten a commit in a month so I'm assuming it won't get a response, but I might as well try.
alfy.output(
[{
title: `👏🏻 ${alfy.input.replace(/ /g, ' 👏🏻 ')} 👏🏻 `,
}]);
This is my code. How do I copy the title
to the clipboard?
That's my workflow. What am I doing wrong?
Configuring workflows
So, a couple of weeks back I thought we could make much more powerfull workflows if there was a way to configure them individually per user.
For instance, if someone creates a git workflow, the user installing that workflow should be able to put an API key somewhere. It's very dirty if he needs to change the workflow in that visual workflow editor and put the API key somewhere.
I have a couple of ideas for this, not sure if all that easy to do.
Configure script
We could allow a user to create a configure.js
script which could use Inquirer.js or something to ask questions to the user. In the git
workflow example for instance, either we create a new activation keyword, for instance configure-git
which opens the terminal and executes configure.js
. Or git configure
for instance.
The name of that script could be set via package.json
{
"name": "alfred-git",
"alfy": {
"configure": "configure.js"
}
}
Configure questions
A second approach would be easier to add for the user. This would allow someone to define the questions in package.json
and will store them in the config of the workflow. This way, in your workflow, you could just grab them from the config.
{
"name": "alfred-git",
"alfy": {
"configure": {
"api_key": {
"type": "input",
"message": "GitHub API key?"
},
"foo": {
"type": "list",
"message": "Some list here?",
"choices": ["foo", "bar"]
}
}
}
}
The first option offers the most flexibility in terms of the package you use to ask your questions (although 2 would offer more consistency).
The second one would definitely be easier for the developer, though less flexible. This would also mean every workflow is packaged with Inquirer.js
, not sure how "heavy" it is. Although, it might be an idea to extract this in a separate package called alfy-configure
and keep this the core. Something like alfy-test
.
Note: This issue has a bounty, so it's expected that you are an experienced programmer and that you give it your best effort if you intend to tackle this. Don't forget, if applicable, to add tests, docs (double-check for typos), and update TypeScript definitions. And don't be sloppy. Review your own diff multiple times and try to find ways to improve and simplify your code. Instead of asking too many questions, present solutions. The point of an issue bounty is to reduce my workload, not give me more. Include a 🦄 in your PR description to indicate that you've read this. Thanks for helping out 🙌 - @sindresorhus
IssueHunt Summary
samverschueren has been rewarded.
Backers (Total: $100.00)
- issuehunt ($100.00)
Submitted pull Requests
Tips
- Checkout the Issuehunt explorer to discover more funded issues.
- Need some help from other developers? Add your repositories on IssueHunt to raise funds.
Is Typescript declaration provided for alfy?
Add TypeScript definition
If anyone wants to contribute, keep this in mind:
- It should adhere to https://github.com/sindresorhus/typescript-definition-style-guide
- You should have a lot of TypeScript experience.
- The pull request should be high-quality. Not sloppy.
- Docs can be copy-pasted from the readme.
Embed alfred-notifier
It would totally make sense to embed alfred-notifier. It's easy to miss the possibility of notifying your users when you have a new version, no one reads the docs (entirely). Notifying your users of a new version is best practice after all and I always want to know if a new version is available.
However, there should always be a way to turn this feature off. The question is, how? Some ways I can think off.
alfy.disableUpdateNotification()
alfy.configure({updateNotification: false});
Support Alfred 4
npm install --global alfred-lock
Errors:
> [email protected] postinstall /Users/vivaxy/.npm-packages/lib/node_modules/alfred-lock
> alfy-init
{ Error: Command failed: alfred-link
Error: Alfred preferences not found at location /Users/vivaxy/Library/Preferences/com.runningwithcrayons.Alfred-Preferences-3.plist
at pathExists.then.exists (/Users/vivaxy/.npm-packages/lib/node_modules/alfred-lock/node_modules/resolve-alfred-prefs/index.js:15:10)
at makeError (/Users/vivaxy/.npm-packages/lib/node_modules/alfred-lock/node_modules/execa/index.js:174:9)
at Promise.all.then.arr (/Users/vivaxy/.npm-packages/lib/node_modules/alfred-lock/node_modules/execa/index.js:278:16)
at processTicksAndRejections (internal/process/next_tick.js:81:5)
code: 1,
stdout: '',
stderr:
'Error: Alfred preferences not found at location /Users/vivaxy/Library/Preferences/com.runningwithcrayons.Alfred-Preferences-3.plist\n at pathExists.then.exists (/Users/vivaxy/.npm-packages/lib/node_modules/alfred-lock/node_modules/resolve-alfred-prefs/index.js:15:10)\n',
failed: true,
signal: null,
cmd: 'alfred-link',
timedOut: false,
killed: false }
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] postinstall: `alfy-init`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/vivaxy/.npm/_logs/2019-05-31T14_25_10_280Z-debug.log
Add `maxAge` option for `alfy.cache`
Error: workflows directory does not exist
When installing a workflow for the first time with Alfy (when no other workflows have been installed yet), I get an error saying that the workflows directory in Alfred.alfredpreferences
doesn't exist yet.
Error: Command failed: alfred-link
Error: Workflow directory `/Users/adriaan/stack/share/backups/Alfred 3/Alfred.alfredpreferences/workflows` does not exist
at pathExists.then.exists (/Users/adriaan/.npm-packages/lib/node_modules/alfred-google-translate/node_modules/alfred-link/index.js:19:10)
at <anonymous>
at Promise.all.then.arr (/Users/adriaan/.npm-packages/lib/node_modules/alfred-google-translate/node_modules/execa/index.js:201:11)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:160:7)
code: 1,
killed: false,
stdout: '',
stderr: 'Error: Workflow directory `/Users/adriaan/stack/share/backups/Alfred 3/Alfred.alfredpreferences/workflows` does not exist\n at pathExists.then.exists (/Users/adriaan/.npm-packages/lib/node_modules/alfred-google-translate/node_modules/alfred-link/index.js:19:10)\n at <anonymous>\n',
failed: true,
signal: null,
cmd: 'alfred-link',
timedOut: false
The solution would be simple: just create the workflows
directory when it does not exist yet.
How do I install a workflow into Alfred?
Sorry for the dumb question, but how do I then add a project into Alfred? I'm sure I'm missing something obvious.
Using `npm-registry-client` with alfy
I don't think this is an alfy issue but since this was the only way to reach you, I thought I'd post my question here.
To clarify, npm registry client is built to work with the browser only and I can't use their request methods?
Easiest to just highlight the work -- I've marked out most of it but this method is trying to fetch npm starred repos: https://github.com/artivilla/alfred-starred/blob/master/index.js#L28
Using postman, I get this response:
{"rows":[{"value":"basscss"},{"value":"bl"},{"value":"bluebird"},{"value":"fetch"},{"value":"jest-serializer-enzyme"},{"value":"json-web-token"},{"value":"kue"},{"value":"longjohn"},{"value":"mongoose-softdelete"},{"value":"nconf"},{"value":"nib"},{"value":"nodemon"},{"value":"v8-profiler"},{"value":"vinyl-source-stream"}]}
[ERROR: input.scriptfilter] JSON error: JSON text did not start with array or object and option to allow fragments not set.
Alfred v3.5 [876]
Having this in my index.js
,
"use strict";
const alfy = require("alfy");
const myConfig = require("./src/config.js");
alfy.output([
{
title: "Unicorn"
},
{
title: "Rainbow"
}
]);
I'm getting an error in Alfred debugger:
[ERROR: input.scriptfilter] JSON error: JSON text did not start with array or object and option to allow fragments not set. in JSON:
called
{
"items": [
{
"title": "Unicorn"
},
{
"title": "Rainbow"
}
]
}
If I require custom file const myConfig = require("./src/config.js");
, error does show up.
If I require npm package (for example const notifier = require("node-notifier");
), error does not show up.
Content of my config.js
:
const alfy = require('alfy');
const config = alfy.config;
const getTimerObject = () => {
return config.get('timerObject') || null;
};
const setTimerObject = newTimerObject => {
config.set('timerObject', newTimerObject);
return getTimerObject();
};
console.log('called');
module.exports = {
setTimerObject,
getTimerObject
};
Any way I can solve this?
The search will be more quik without wifi
here is the code , the url is a visual host
I wonder why , when I shut down the wifi , the alfred will return the result more quickly?
If turn on the wifi,will be more slow, I have logged the url in alfy.fetch function,which shows
they both use the cached data .
alfy.fetch('http://linuxcmd.com/data.json',
{maxAge: 86400000}).then(result => {
var commands = [];
var e = 0;
for(var a in result){
++e;
result[a]['id'] = e;
commands.push(result[a]);
}
var i=0,
page_size = commands.length,
arrResult = [],
query=alfy.input;
if(commands&&commands.length&&toString.call(commands).indexOf('Array')>-1){
var count = 0
for (; i < page_size; i++) {
if(isSreachIndexOF(commands[i].n,query)
|| isSreachIndexOF(commands[i].d,query)
){
if(count < page_size){
arrResult.push(commands[i]);
++count;
}
}
}
}
var items = [];
for(var i = 0;i< arrResult.length;i++){
items.push({
title: arrResult[i].n,
subtitle: arrResult[i].d,
arg: arrResult[i].n
})
}
if(items.length < 1){
items.push({
title: "没有搜素到内容",
subtitle: "请尝试其它关键字",
})
}
alfy.output(items);
});
Cannot read property 'alfy' of undefined
the index.js is
const alfy = require('alfy');
alfy.output([{
title: 'Unicorn'
}, {
title: 'Rainbow'
}]);
and the console outputs the error:
[ERROR: input.scriptfilter] Code 1: {
"items": [
{
"title": "Unicorn"
},
{
"title": "Rainbow"
}
]
}
{
"items": [
{
"title": "TypeError: Cannot read property 'alfy' of undefined\n at readPkgUp.then.result (/Users/pro/Library/Application Support/Alfred 3/Alfred.alfredpreferences/workflows/user.workflow.0408C61C-45B8-474D-B77D-B3C6691E4024/node_modules/alfy/lib/update-notification.js:7:26)",
"subtitle": "Press ⌘L to see the full error and ⌘C to copy it.",
"valid": false,
"text": {
"copy": "```\nTypeError: Cannot read property 'alfy' of undefined\n at readPkgUp.then.result (/Users/pro/Library/Application Support/Alfred 3/Alfred.alfredpreferences/workflows/user.workflow.0408C61C-45B8-474D-B77D-B3C6691E4024/node_modules/alfy/lib/update-notification.js:7:26)\n```\n\n-\nregurl undefined\nAlfred 3.3.2\ndarwin x64 15.6.0",
"largetype": "TypeError: Cannot read property 'alfy' of undefined\n at readPkgUp.then.result (/Users/pro/Library/Application Support/Alfred 3/Alfred.alfredpreferences/workflows/user.workflow.0408C61C-45B8-474D-B77D-B3C6691E4024/node_modules/alfy/lib/update-notification.js:7:26)"
},
"icon": {
"path": "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/AlertStopIcon.icns"
}
}
]
}
[2017-06-03 16:11:59][ERROR: input.scriptfilter] JSON error: Garbage at end. in JSON:
{
"items": [
{
"title": "Unicorn"
},
{
"title": "Rainbow"
}
]
}
{
"items": [
{
"title": "TypeError: Cannot read property 'alfy' of undefined\n at readPkgUp.then.result (/Users/pro/Library/Application Support/Alfred 3/Alfred.alfredpreferences/workflows/user.workflow.0408C61C-45B8-474D-B77D-B3C6691E4024/node_modules/alfy/lib/update-notification.js:7:26)",
"subtitle": "Press ⌘L to see the full error and ⌘C to copy it.",
"valid": false,
"text": {
"copy": "```\nTypeError: Cannot read property 'alfy' of undefined\n at readPkgUp.then.result (/Users/pro/Library/Application Support/Alfred 3/Alfred.alfredpreferences/workflows/user.workflow.0408C61C-45B8-474D-B77D-B3C6691E4024/node_modules/alfy/lib/update-notification.js:7:26)\n```\n\n-\nregurl undefined\nAlfred 3.3.2\ndarwin x64 15.6.0",
"largetype": "TypeError: Cannot read property 'alfy' of undefined\n at readPkgUp.then.result (/Users/pro/Library/Application Support/Alfred 3/Alfred.alfredpreferences/workflows/user.workflow.0408C61C-45B8-474D-B77D-B3C6691E4024/node_modules/alfy/lib/update-notification.js:7:26)"
},
"icon": {
"path": "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/AlertStopIcon.icns"
}
}
]
}
require("alfy") takes ~120ms
I noticed that a very simple script of mine (just returning a query from a JSON file) was much slower than expected.
It turns out that just require('alfy')
adds about 120ms to a script's execution time.
Since I only used alfy for outputs I replaced
const alfy = require('alfy');
with
const alfy = {
output: (items) => {
console.log(JSON.stringify({items}, null, '\t'));
}
}
Now Alfred feels snappy again. :-)
Plist Error
I've made a copy of the alfred-npms
package and I'm trying to use the same workflow for another API. Though, the error below is thrown.
TypeError: Cannot read property '1' of null
return /<key>version<\/key>[\s\S]*<string>([\d.]+)<\/string>/.exec(fs.readFileSync(infoPlist, 'utf8'))[1];
^
If I take the line below and remove the [1]
in the end…
return /<key>version<\/key>[\s\S]*<string>([\d.]+)<\/string>/.exec(fs.readFileSync(infoPlist, 'utf8'))[1];
…it works. Then my package is executed as expected. What am I doing wrong? Any thoughts?
non-bundlable with webpack
I've tried webpack, parcel, rollup and they all seem to fail at some stage.
I've gotten webpack to work by altering the way conf
and cache-conf
are given parentDir. By passing this explicitly in the constructor instead of relying on the module.parent
object, webpack can resolve almost* all of the dependencies.
From conf/index.js:21
opts = Object.assign({
projectName: pkgPath && JSON.parse(fs.readFileSync(pkgPath, 'utf8')).name
}, opts);
to
opts = Object.assign({
projectName: opts.name
}, opts);
almost* refers to a dynamic require of electron
in the got
package. got/index.js:91
Allow top-level await
Would be a nice convenience as a lot of Alfy workflows use promises.
We could use esm
for this.
IssueHunt Summary
[
<
i
m
g
s
r
c
'
h
t
t
p
s
:
/
/
a
v
a
t
a
r
s
3
.
g
i
t
h
u
b
u
s
e
r
c
o
n
t
e
n
t
.
c
o
m
/
u
/
1
4
0
2
2
4
1
?
v
4
'
a
l
t
'
b
f
r
e
d
i
t
'
w
i
d
t
h
2
4
h
e
i
g
h
t
2
4
b
f
r
e
d
i
t
]
(
h
t
t
p
s
:
/
/
i
s
s
u
e
h
u
n
t
.
i
o
/
u
/
b
f
r
e
d
i
t
)
h
a
s
b
e
e
n
r
e
w
a
r
d
e
d
.
Backers (Total: $40.00)
- issuehunt ($40.00)
Submitted pull Requests
Tips
- Checkout the Issuehunt explorer to discover more funded issues.
- Need some help from other developers? Add your repositories on IssueHunt to raise funds.
IssueHunt has been backed by the following sponsors. Become a sponsor
Support setting Alfred variables with alfy.output
You can set variables in Alfred by writing to stdout using a special JSON format. It would be handy if alfy.output
supported this, perhaps in a special variables
key:
alfy.output([
{ title: 'Google', arg: 'https://www.google.com', variables: { browser: 'Chrome' },
{ title: 'Mozilla', arg: 'https://www.mozilla.org', variables: { browser: 'Firefox' } }
])
Or as a second argument:
// backwards compatible, but less elegant
alfy.output([
{ title: 'Google', arg: 'https://www.google.com' },
{ title: 'Mozilla', arg: 'https://www.mozilla.org' }
], [
{ browser: 'Chrome' },
{ browser: 'Firefox' }
])
I'm happy to write a pull request if this seems worthwhile.
JSON Format
The format for emitting variables isn't complicated, but life would be easier if Alfy handled it.
Emit a string and set variables
// The root `alfredworkflow` key is required.
// Without it, Alfred will pass the object to the next node in the workflow like normal.
{
"alfredworkflow": {
"arg": "https://www.google.com",
"variables": {"browser": "Chrome"}
}
}
Emit multiple items and set variables
// `arg` is a stringified `alfredworkflow` object
{
"items": [{
"title": "Google",
"arg": "{\"alfredworkflow\": {\"arg\": \"https://www.google.com\", \"variables\": {\"browser\": \"Chrome\"}}}"
}]
}
Note, you can access Alfred variables through the environment:
const browser = process.env.browser
IssueHunt Summary
Backers (Total: $60.00)
- issuehunt ($60.00)
Submitted pull Requests
Become a backer now!
Or submit a pull request to get the deposits!
Tips
- Checkout the Issuehunt explorer to discover more funded issues.
- Need some help from other developers? Add your repositories on IssueHunt to raise funds.
add `transform` function to `fetch` method
alfy.fetch
allows someone to cache network requests for some time. An example is my alfred-ng2 workflow.
The json returned from the endpoint looks like this
{
"@angular/common": [
{
"title": "APP_BASE_HREF",
"path": "common/index/APP_BASE_HREF-let.html",
"docType": "let",
"stability": "stable",
"secure": "false",
"howToUse": "",
"whatItDoes": "Not Done",
"barrel" : "@angular/common"
}
],
"@angular/core": [
{
"title": "APPLICATION_COMMON_PROVIDERS",
"path": "core/index/APPLICATION_COMMON_PROVIDERS-let.html",
"docType": "let",
"stability": "stable",
"secure": "false",
"howToUse": "",
"whatItDoes": "Not Done",
"barrel" : "@angular/core"
}
]
}
I transform that data into one single list of items. Instead of doing the transformation every time a user searches through the packages, it could be done once before caching the data and directly work with the cached data instead. This could be very useful for large datasets or even for APIs returning xml
and transform them to json
before caching.
My suggestion is to add a transform
option to the alfy.fetch
options object.
alfy.fetch('https://my-xml-api.com/some-feed.xml', {
maxAge: 86400000, // 24 hours
transform: result => xml2js.parseString(result)
}).then(jsonResult => {
console.log(jsonResult);
//=> some best-effort xml-2-json converted json
});
Feel free to provide (useful) feedback of any kind.
npm can not install
npm install alfy -S -D
npm ERR! code E404
npm ERR! 404 Not Found: resolve-alfred-prefs@^1.0.0
What's the recommended way to test my workflow?
I can't find any test script in the linked packages.
Maybe calling alfy.debug()
to simulate the alfred environment?
Flaky tests
The tests are flaky because of these two lines
They are both working on the same instance of CacheConf
. Is there anyway we can work around this problem without merging everything in one test file or run the test serially?
Built version caching into CacheConf
Currently, alfy.fetch
will invalidate the cache if you update your workflow which is pretty nice. But maybe we should built this into cache-conf. The reason I'm thinking about this is because I'm creating a new workflow that does not fetch the data from a server, but from different files in a dependency. Reading all those files and transforming the data takes some time and I want to cache it. But if I want to do it correctly, I will have to write the versioned caching myself. So maybe we should add an optional version
property to cache-conf
which will invalidate older caches and just overwrite them.
Another suggestion of fixing this is if we would allow to read local files with alfy.fetch
as well.
alfy.fetch('my-file.json', {
maxAge: ONE_DAY,
transform: data => {
return {data};
}
});
This way you will have the same benefits as URLs but for local files, as well as the transform function. Maybe this suggestion is a separate enhancement from the initial idea. But either one of them would solve my use case.
when i publish a new alfy workflow , they did't show a update notify
when i npm publish a new version, after that, the my alfy workflow not notify me to update..
i don't understand what happen, so i need you help please, i m english so bad, hope you know that.
slow to exit
While testing I've found that there's a noticable lag after the script outputs the final JSON. My solution was to add a .then(() => process.exit(0))
which speeded up results being outputted since Alfed seems to wait for the script to exit before returning anything.
Remove broken links in Users section
There are 5 broken links in Users section.
I think it is good to remove these lines in Users section if possible to avoid misclicks.
> blc https://github.com/sindresorhus/alfy | grep HTTP_404
├─BROKEN─ https://github.com/vinkla/alfred-kaomoji (HTTP_404)
├─BROKEN─ https://github.com/jacc/alfred-clap (HTTP_404)
├─BROKEN─ https://github.com/vinkla/alfred-reference (HTTP_404)
├─BROKEN─ https://github.com/vinkla/alfred-homebrew (HTTP_404)
├─BROKEN─ https://github.com/adriantombu/alfred-travis-ci (HTTP_404)
FYI: I used blc to check broken links
Error: Alfred preferences not found at location
Tried:
npm install --global alfred-npms
Got:
> [email protected] postinstall /usr/local/lib/node_modules/alfred-npms
> alfy-init
{ Error: Command failed: alfred-link
Error: Alfred preferences not found at location /Users/velocityzen/Library/Preferences/com.runningwithcrayons.Alfred-Preferences-3.plist
at pathExists.then.exists (/usr/local/lib/node_modules/alfred-npms/node_modules/resolve-alfred-prefs/index.js:15:10)
at <anonymous>
at Promise.all.then.arr (/usr/local/lib/node_modules/alfred-npms/node_modules/execa/index.js:201:11)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:160:7)
code: 1,
killed: false,
stdout: '',
stderr: 'Error: Alfred preferences not found at location /Users/velocityzen/Library/Preferences/com.runningwithcrayons.Alfred-Preferences-3.plist\n at pathExists.then.exists (/usr/local/lib/node_modules/alfred-npms/node_modules/resolve-alfred-prefs/index.js:15:10)\n at <anonymous>\n',
failed: true,
signal: null,
cmd: 'alfred-link',
timedOut: false }
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] postinstall: `alfy-init`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/velocityzen/.npm/_logs/2018-03-01T04_44_12_239Z-debug.log
My preferences file is in dropbox for synchronization.
run failed if index.js is esm module
error
[ERR_REQUIRE_ESM]: Must use import to load ES Module: /Users/jiangwei/.nvm/versions/node/v14.17.3/lib/node_modules/@ifu/emoji/index.js
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1102:13) {
code: 'ERR_REQUIRE_ESM'
}
node: v14.17.3
alfy: 0.11.1
i try to remove --require esm
in run-node.sh
, will not throw this error anymore. so what --require esm
doing
When use nvm,got `Couldn\'t find the `node` binary`
Add possibility to fetch from network with caching
We already discussed something like this here #4 (comment).
Here's a small wrap-up. We want to add got
to alfy
by default in order to make network requests. But not only that, it should be possible to cache the network requests. If later on, the same network request is performed and the cache is still valid, the cache will be returned. If the cache is not valid, a new network request is performed and the cache is updated.
Bonus feature: If the cache is not valid BUT the network request fails (user might be working offline), the cached data is still returned.
alfy.fetch('https://myapi.com/foo/bar.json', {maxAge: 5000}).then(res => {
console.log(res.body);
// {foo: 'bar'}
});
Some extra notes: fetch
is just calling got
. So you can just pass the method
property with value POST
if a post request has to be performed.
@sindresorhus Did I cover everything?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.