Update ping message

This commit is contained in:
2020-07-24 10:06:22 +10:00
parent 22cedd8c15
commit 83846b70ed
761 changed files with 75182 additions and 0 deletions
@@ -0,0 +1 @@
/Users/junwei.zhao/.nvm/versions/node/v10.20.1/lib/node_modules/alfred-mvns
@@ -0,0 +1,47 @@
# alfred-mvns
[![NPM](https://nodei.co/npm/alfred-mvns.png)](https://nodei.co/npm/alfred-mvns/)
## Install
```
$ npm install -g alfred-mvns
```
*Requires [Node.js](https://nodejs.org) 4+ and the Alfred [Powerpack](https://www.alfredapp.com/powerpack/).*
## Usage
In Alfred, type `mvn`, and your query, to search for java libraries at maven central repository.
Select a item and press <kbd>enter</kbd> to copy `maven dependency` to clipboard.<br>
Hold <kbd>alt</kbd> and press <kbd>enter</kbd> to copy `gradle dependency` to clipboard.<br>
## Demo
![mvn.png](mvn.png)
press <kbd>enter</kbd> get:
```
<dependency>
<groupId>org.nd4j</groupId>
<artifactId>jackson</artifactId>
<version>0.9.1</version>
</dependency>
```
Hold <kbd>alt</kbd> and press <kbd>enter</kbd> get:
```
compile 'org.nd4j:jackson:0.9.1'
```
## Related
- [alfy](https://github.com/sindresorhus/alfy) - Create Alfred workflows with ease
## License
MIT ©
Binary file not shown.

After

Width:  |  Height:  |  Size: 786 B

@@ -0,0 +1,48 @@
'use strict';
const alfy = require('alfy');
const dateFormat = require('date-format');
let q = alfy.input;
const s = q.split(':');
if (s.length > 1) {
q = 'g:'+s[0];
if (s[1]) {
q = q+' AND '+'a:'+s[1];
}
if (s.length > 2 && s[2]) {
q = q+' AND '+'v:'+s[2];
}
}
alfy.fetch('http://search.maven.org/solrsearch/select', {
query: {
q,
start: 0,
rows: 20
}
}).then(data => {
const items = data.response.docs
.map(x => {
const v = x.v?x.v:x.latestVersion;
const mvn = `<dependency>\n <groupId>${x.g}</groupId>\n <artifactId>${x.a}</artifactId>\n <version>${v}</version>\n</dependency>`;
const gradle = `compile '${x.g}:${x.a}:${v}'`;
return {
title: `${x.g}:${x.a}:${v}`,
subtitle: `updated at ${dateFormat('yyyy-dd-MM', new Date(x.timestamp))}`,
arg: mvn,
mods: {
cmd: {
arg: mvn,
subtitle: `copy maven dependency to clipboard`
},
alt: {
arg: gradle,
subtitle: `copy gradle dependency to clipboard`
}
}
};
});
alfy.output(items);
});
@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>bundleid</key>
<string>com.xfslove.mvns</string>
<key>category</key>
<string>Tools</string>
<key>connections</key>
<dict>
<key>0726E1E0-396C-4D34-BCCA-1845023FDDD8</key>
<array>
<dict>
<key>destinationuid</key>
<string>50B7B6A5-8381-4941-B19A-52654E0EFE56</string>
<key>modifiers</key>
<integer>0</integer>
<key>modifiersubtext</key>
<string></string>
<key>vitoclose</key>
<false/>
</dict>
</array>
</dict>
<key>createdby</key>
<string>hanwen.huang</string>
<key>description</key>
<string>Alfred 3 workflow to search for java libraries at central repo</string>
<key>disabled</key>
<false/>
<key>name</key>
<string>mvns</string>
<key>objects</key>
<array>
<dict>
<key>config</key>
<dict>
<key>alfredfiltersresults</key>
<false/>
<key>alfredfiltersresultsmatchmode</key>
<integer>0</integer>
<key>argumenttrimmode</key>
<integer>0</integer>
<key>argumenttype</key>
<integer>0</integer>
<key>escaping</key>
<integer>102</integer>
<key>keyword</key>
<string>mvn</string>
<key>queuedelaycustom</key>
<integer>3</integer>
<key>queuedelayimmediatelyinitially</key>
<true/>
<key>queuedelaymode</key>
<integer>0</integer>
<key>queuemode</key>
<integer>1</integer>
<key>runningsubtext</key>
<string>Searching...</string>
<key>script</key>
<string>./node_modules/.bin/run-node index.js "$1"</string>
<key>scriptargtype</key>
<integer>1</integer>
<key>scriptfile</key>
<string></string>
<key>subtext</key>
<string></string>
<key>title</key>
<string>Search for java libraries</string>
<key>type</key>
<integer>0</integer>
<key>withspace</key>
<true/>
</dict>
<key>type</key>
<string>alfred.workflow.input.scriptfilter</string>
<key>uid</key>
<string>0726E1E0-396C-4D34-BCCA-1845023FDDD8</string>
<key>version</key>
<integer>2</integer>
</dict>
<dict>
<key>config</key>
<dict>
<key>autopaste</key>
<false/>
<key>clipboardtext</key>
<string>{query}</string>
<key>transient</key>
<false/>
</dict>
<key>type</key>
<string>alfred.workflow.output.clipboard</string>
<key>uid</key>
<string>50B7B6A5-8381-4941-B19A-52654E0EFE56</string>
<key>version</key>
<integer>2</integer>
</dict>
</array>
<key>readme</key>
<string></string>
<key>uidata</key>
<dict>
<key>0726E1E0-396C-4D34-BCCA-1845023FDDD8</key>
<dict>
<key>xpos</key>
<integer>20</integer>
<key>ypos</key>
<integer>10</integer>
</dict>
<key>50B7B6A5-8381-4941-B19A-52654E0EFE56</key>
<dict>
<key>xpos</key>
<integer>170</integer>
<key>ypos</key>
<integer>10</integer>
</dict>
</dict>
<key>version</key>
<string>1.0.2</string>
<key>webaddress</key>
<string>https://github.com/xfslove/alfred-mvns#readme</string>
</dict>
</plist>
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,16 @@
#!/usr/bin/env node
'use strict';
const alfredLink = require('./');
const npmGlobal = process.env.npm_config_global;
if (npmGlobal === '') {
// Prevent linking if the script was part of a non-global npm (install) command
process.exit(0);
}
// Only transform if `alfred-link` is called from `npm -g`
alfredLink.link({transform: npmGlobal}).catch(err => {
console.error(err);
process.exit(1);
});
@@ -0,0 +1,8 @@
#!/usr/bin/env node
'use strict';
const alfredLink = require('./');
alfredLink.unlink().catch(err => {
console.error(err);
process.exit(1);
});
@@ -0,0 +1,11 @@
#!/usr/bin/env node
'use strict';
const execa = require('execa');
const npmRunPath = require('npm-run-path');
const env = npmRunPath.env({cwd: __dirname});
execa('alfred-unlink', {env}).catch(err => {
console.error(err);
process.exit(1);
});
@@ -0,0 +1,11 @@
#!/usr/bin/env node
'use strict';
const execa = require('execa');
const npmRunPath = require('npm-run-path');
const env = npmRunPath.env({cwd: __dirname});
execa('alfred-link', {env}).catch(err => {
console.error(err);
process.exit(1);
});
@@ -0,0 +1,33 @@
#!/usr/bin/env node
var mkdirp = require('../');
var minimist = require('minimist');
var fs = require('fs');
var argv = minimist(process.argv.slice(2), {
alias: { m: 'mode', h: 'help' },
string: [ 'mode' ]
});
if (argv.help) {
fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout);
return;
}
var paths = argv._.slice();
var mode = argv.mode ? parseInt(argv.mode, 8) : undefined;
(function next () {
if (paths.length === 0) return;
var p = paths.shift();
if (mode === undefined) mkdirp(p, cb)
else mkdirp(p, mode, cb)
function cb (err) {
if (err) {
console.error(err.message);
process.exit(1);
}
else next();
}
})();
@@ -0,0 +1,4 @@
#! /usr/bin/env node
var rc = require('./index')
console.log(JSON.stringify(rc(process.argv[2]), false, 2))
@@ -0,0 +1,50 @@
#!/usr/bin/env node
var rimraf = require('./')
var help = false
var dashdash = false
var noglob = false
var args = process.argv.slice(2).filter(function(arg) {
if (dashdash)
return !!arg
else if (arg === '--')
dashdash = true
else if (arg === '--no-glob' || arg === '-G')
noglob = true
else if (arg === '--glob' || arg === '-g')
noglob = false
else if (arg.match(/^(-+|\/)(h(elp)?|\?)$/))
help = true
else
return !!arg
})
if (help || args.length === 0) {
// If they didn't ask for help, then this is not a "success"
var log = help ? console.log : console.error
log('Usage: rimraf <path> [<path> ...]')
log('')
log(' Deletes all files and folders at "path" recursively.')
log('')
log('Options:')
log('')
log(' -h, --help Display this usage info')
log(' -G, --no-glob Do not expand glob patterns in arguments')
log(' -g, --glob Expand glob patterns in arguments (default)')
process.exit(help ? 0 : 1)
} else
go(0)
function go (n) {
if (n >= args.length)
return
var options = {}
if (noglob)
options = { glob: false }
rimraf(args[n], options, function (er) {
if (er)
throw er
go(n+1)
})
}
@@ -0,0 +1,49 @@
#!/bin/bash
if [[ -z "$alfred_workflow_cache" ]]; then
echo "This script must be called from Alfred, \$alfred_workflow_cache is missing. Make sure a Bundle ID is set."
exit 1
fi
if [[ ! -d "$alfred_workflow_cache" ]]; then
mkdir -p "$alfred_workflow_cache"
fi
PATH_CACHE="$alfred_workflow_cache"/node_path
get_user_path() {
eval $(/usr/libexec/path_helper -s)
echo "$($SHELL -i -l -c 'echo -e "\n"PATH=\"$PATH:\$PATH\""\n"' 2>/dev/null | grep "^PATH=")" > "$PATH_CACHE"
}
set_path() {
if [[ -f "$PATH_CACHE" ]]; then
. "$PATH_CACHE"
else
get_user_path
. "$PATH_CACHE"
fi
export PATH
}
has_node() {
command -v node >/dev/null 2>&1
}
# check if we have node, otherwise inherit path from user shell
if ! has_node; then
set_path
# retry by deleting old path cache
if ! has_node; then
rm "$PATH_CACHE"
set_path
fi
fi
if has_node; then
node "$@"
else
echo $'{"items":[{"title": "Couldn\'t find the `node` binary", "subtitle": "Symlink it to `/usr/local/bin`"}]}'
fi
@@ -0,0 +1,153 @@
#!/usr/bin/env node
// Standalone semver comparison program.
// Exits successfully and prints matching version(s) if
// any supplied version is valid and passes all tests.
var argv = process.argv.slice(2)
, versions = []
, range = []
, gt = []
, lt = []
, eq = []
, inc = null
, version = require("../package.json").version
, loose = false
, includePrerelease = false
, coerce = false
, identifier = undefined
, semver = require("../semver")
, reverse = false
, options = {}
main()
function main () {
if (!argv.length) return help()
while (argv.length) {
var a = argv.shift()
var i = a.indexOf('=')
if (i !== -1) {
a = a.slice(0, i)
argv.unshift(a.slice(i + 1))
}
switch (a) {
case "-rv": case "-rev": case "--rev": case "--reverse":
reverse = true
break
case "-l": case "--loose":
loose = true
break
case "-p": case "--include-prerelease":
includePrerelease = true
break
case "-v": case "--version":
versions.push(argv.shift())
break
case "-i": case "--inc": case "--increment":
switch (argv[0]) {
case "major": case "minor": case "patch": case "prerelease":
case "premajor": case "preminor": case "prepatch":
inc = argv.shift()
break
default:
inc = "patch"
break
}
break
case "--preid":
identifier = argv.shift()
break
case "-r": case "--range":
range.push(argv.shift())
break
case "-c": case "--coerce":
coerce = true
break
case "-h": case "--help": case "-?":
return help()
default:
versions.push(a)
break
}
}
var options = { loose: loose, includePrerelease: includePrerelease }
versions = versions.map(function (v) {
return coerce ? (semver.coerce(v) || {version: v}).version : v
}).filter(function (v) {
return semver.valid(v)
})
if (!versions.length) return fail()
if (inc && (versions.length !== 1 || range.length))
return failInc()
for (var i = 0, l = range.length; i < l ; i ++) {
versions = versions.filter(function (v) {
return semver.satisfies(v, range[i], options)
})
if (!versions.length) return fail()
}
return success(versions)
}
function failInc () {
console.error("--inc can only be used on a single version with no range")
fail()
}
function fail () { process.exit(1) }
function success () {
var compare = reverse ? "rcompare" : "compare"
versions.sort(function (a, b) {
return semver[compare](a, b, options)
}).map(function (v) {
return semver.clean(v, options)
}).map(function (v) {
return inc ? semver.inc(v, inc, options, identifier) : v
}).forEach(function (v,i,_) { console.log(v) })
}
function help () {
console.log(["SemVer " + version
,""
,"A JavaScript implementation of the http://semver.org/ specification"
,"Copyright Isaac Z. Schlueter"
,""
,"Usage: semver [options] <version> [<version> [...]]"
,"Prints valid versions sorted by SemVer precedence"
,""
,"Options:"
,"-r --range <range>"
," Print versions that match the specified range."
,""
,"-i --increment [<level>]"
," Increment a version by the specified level. Level can"
," be one of: major, minor, patch, premajor, preminor,"
," prepatch, or prerelease. Default level is 'patch'."
," Only one version may be specified."
,""
,"--preid <identifier>"
," Identifier to be used to prefix premajor, preminor,"
," prepatch or prerelease version increments."
,""
,"-l --loose"
," Interpret versions and ranges loosely"
,""
,"-p --include-prerelease"
," Always include prerelease versions in range matching"
,""
,"-c --coerce"
," Coerce a string into SemVer if possible"
," (does not imply --loose)"
,""
,"Program exits successfully if any valid version satisfies"
,"all supplied ranges, and prints all satisfying versions."
,""
,"If no satisfying versions are found, then exits failure."
,""
,"Versions are printed in ascending order, so supplying"
,"multiple versions to the utility will just sort them."
].join("\n"))
}
@@ -0,0 +1,52 @@
#!/usr/bin/env node
var which = require("../")
if (process.argv.length < 3)
usage()
function usage () {
console.error('usage: which [-as] program ...')
process.exit(1)
}
var all = false
var silent = false
var dashdash = false
var args = process.argv.slice(2).filter(function (arg) {
if (dashdash || !/^-/.test(arg))
return true
if (arg === '--') {
dashdash = true
return false
}
var flags = arg.substr(1).split('')
for (var f = 0; f < flags.length; f++) {
var flag = flags[f]
switch (flag) {
case 's':
silent = true
break
case 'a':
all = true
break
default:
console.error('which: illegal option -- ' + flag)
usage()
}
}
return false
})
process.exit(args.reduce(function (pv, current) {
try {
var f = which.sync(current, { all: all })
if (all)
f = f.join('\n')
if (!silent)
console.log(f)
return pv;
} catch (e) {
return 1;
}
}, 0))
@@ -0,0 +1,57 @@
'use strict';
const path = require('path');
const pathExists = require('path-exists');
const readPkgUp = require('read-pkg-up');
const resolveAlfredPrefs = require('resolve-alfred-prefs');
const sudoBlock = require('sudo-block');
const plistTransform = require('./lib/plist-transform');
const link = require('./lib/link');
const unlink = require('./lib/unlink');
// Prevent running as `sudo`
sudoBlock();
const getWorkflowDir = () => resolveAlfredPrefs().then(prefs => path.join(prefs, 'workflows'));
const readPkg = workflowDir => pathExists(workflowDir)
.then(exists => {
if (!exists) {
throw new Error(`Workflow directory \`${workflowDir}\` does not exist`);
}
return readPkgUp();
});
exports.link = opts => {
const options = Object.assign({
transform: true
}, opts);
let workflowDir;
return getWorkflowDir()
.then(dir => {
workflowDir = dir;
return readPkg(dir);
})
.then(result => {
const pkg = result.pkg;
const filePath = result.path;
const src = path.dirname(filePath);
const dest = path.join(workflowDir, pkg.name.replace('/', '-'));
if (!options.transform) {
return link(src, dest);
}
return plistTransform(path.dirname(filePath), pkg)
.then(() => link(src, dest));
});
};
exports.unlink = () => getWorkflowDir()
.then(dir => readPkg(dir)
.then(res => unlink(path.join(dir, res.pkg.name.replace('/', '-'))))
);
@@ -0,0 +1,8 @@
'use strict';
const fs = require('fs');
const pify = require('pify');
const del = require('del');
const fsP = pify(fs);
module.exports = (src, dest) => del(dest, {force: true}).then(() => fsP.symlink(src, dest));
@@ -0,0 +1,40 @@
'use strict';
const path = require('path');
const fs = require('fs');
const plist = require('plist');
const pify = require('pify');
const fsP = pify(fs);
// Fixes some inconsistencies when running `plist.parse`
// https://github.com/TooTallNate/plist.js/issues/75
const fix = obj => {
for (const key of Object.keys(obj)) {
const val = obj[key];
if (val === null || val === undefined) {
obj[key] = '';
} else if (Array.isArray(val)) {
obj[key] = val.map(fix);
} else if (typeof val === 'object') {
obj[key] = fix(val);
}
}
return obj;
};
module.exports = (dir, pkg) => {
const file = path.join(dir, 'info.plist');
return fsP.readFile(file, 'utf8')
.then(content => {
const data = fix(plist.parse(content));
data.version = pkg.version || '';
data.description = pkg.description || '';
data.webaddress = pkg.homepage || pkg.author.url || '';
data.createdby = pkg.author.name || '';
return fsP.writeFile(file, plist.build(data));
});
};
@@ -0,0 +1,25 @@
/* eslint-disable indent */
'use strict';
const path = require('path');
const fs = require('fs');
const del = require('del');
const pify = require('pify');
const userHome = require('user-home');
const fsP = pify(fs);
const idRegexp = /<key>bundleid<\/key>[\s]*<string>(.*?)<\/string>/;
// Remove the symlink
const unlink = dir => del(path.join(dir), {force: true});
// Cleanup config and cache data
const cleanup = dir => fsP.readFile(path.join(dir, 'info.plist'), 'utf8')
.then(content => idRegexp.exec(content)[1])
.then(bundleid => Promise.all([
unlink(path.join(userHome, 'Library/Application Support/Alfred 3/Workflow Data', bundleid)),
unlink(path.join(userHome, 'Library/Caches/com.runningwithcrayons.Alfred-3/Workflow Data', bundleid))
]));
module.exports = dir => cleanup(dir)
.then(unlink(dir));
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sam Verschueren <sam.verschueren@gmail.com> (github.com/SamVerschueren)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,16 @@
#!/usr/bin/env node
'use strict';
const alfredLink = require('./');
const npmGlobal = process.env.npm_config_global;
if (npmGlobal === '') {
// Prevent linking if the script was part of a non-global npm (install) command
process.exit(0);
}
// Only transform if `alfred-link` is called from `npm -g`
alfredLink.link({transform: npmGlobal}).catch(err => {
console.error(err);
process.exit(1);
});
@@ -0,0 +1,91 @@
{
"_from": "alfred-link@^0.2.0",
"_id": "alfred-link@0.2.1",
"_inBundle": false,
"_integrity": "sha1-RizB/M0t7dwmdqsZxX5YS4gicQo=",
"_location": "/alfred-mvns/alfred-link",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "alfred-link@^0.2.0",
"name": "alfred-link",
"escapedName": "alfred-link",
"rawSpec": "^0.2.0",
"saveSpec": null,
"fetchSpec": "^0.2.0"
},
"_requiredBy": [
"/alfred-mvns/alfy"
],
"_resolved": "https://registry.npmjs.org/alfred-link/-/alfred-link-0.2.1.tgz",
"_shasum": "462cc1fccd2deddc2676ab19c57e584b8822710a",
"_spec": "alfred-link@^0.2.0",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/alfy",
"author": {
"name": "Sam Verschueren",
"email": "sam.verschueren@gmail.com",
"url": "github.com/SamVerschueren"
},
"bin": {
"alfred-link": "link.js",
"alfred-unlink": "unlink.js"
},
"bugs": {
"url": "https://github.com/SamVerschueren/alfred-link/issues"
},
"bundleDependencies": false,
"dependencies": {
"del": "^2.2.2",
"path-exists": "^3.0.0",
"pify": "^2.3.0",
"plist": "^2.0.1",
"read-pkg-up": "^1.0.1",
"resolve-alfred-prefs": "^1.0.0",
"sudo-block": "^1.2.0",
"user-home": "^2.0.0"
},
"deprecated": false,
"description": "Make your Alfred workflows installable from npm",
"devDependencies": {
"xo": "*"
},
"engines": {
"node": ">=4"
},
"files": [
"index.js",
"link.js",
"unlink.js",
"lib"
],
"homepage": "https://github.com/SamVerschueren/alfred-link#readme",
"keywords": [
"cli-app",
"cli",
"alfred",
"link",
"symlink",
"packal"
],
"license": "MIT",
"maintainers": [
{
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
}
],
"name": "alfred-link",
"repository": {
"type": "git",
"url": "git+https://github.com/SamVerschueren/alfred-link.git"
},
"scripts": {
"test": "xo"
},
"version": "0.2.1",
"xo": {
"esnext": true
}
}
@@ -0,0 +1,70 @@
# alfred-link [![Build Status](https://travis-ci.org/SamVerschueren/alfred-link.svg?branch=master)](https://travis-ci.org/SamVerschueren/alfred-link)
> Make your [Alfred](https://www.alfredapp.com/) workflows installable from npm
## Install
```
$ npm install --save alfred-link
```
## Usage
Add the `alfred-link` command as `postinstall` script of your Alfred package and add `alfred-unlink` as `preuninstall` script to clean up the resources when the workflow gets uninstalled.
```json
{
"name": "alfred-unicorn",
"scripts": {
"postinstall": "alfred-link",
"preuninstall": "alfred-unlink"
}
}
```
You can now install the `alfred-unicorn` package like this
```
$ npm install -g alfred-unicorn.
```
This will update `info.plist` with the information from `package.json` and creates a `unicorn` symlink inside the Alfred workflows directory that points to the location of the `alfred-unicorn` module.
## info.plist
This package will update the `info.plist` file when the workflow is being installed. The following properties in `info.plist` can be safely omitted. The corresponding values in `package.json` are added to the plist file.
| info.plist | package.json |
|-------------|--------------|
| version | version |
| description | description |
| webaddress | homepage |
| createdby | author.name |
## Development
When developing an Alfred workflow, you can call `alfred-link` directly from your cli. Either by installing `alfred-link` globally or by calling `alfred-link` from your `node_modules/.bin` directory. This will create a symlink in the Alfred workflows directory pointing to your development location without transforming `info.plist`.
```
$ ./node_modules/.bin/alfred-link
```
To remove the symlink afterwards, you can call `alfred-unlink`.
```
$ ./node_modules/.bin/alfred-unlink
```
## Related
- [alfy](https://github.com/sindresorhus/alfy) - Create Alfred workflows with ease
## License
MIT © [Sam Verschueren](https://github.com/SamVerschueren)
@@ -0,0 +1,8 @@
#!/usr/bin/env node
'use strict';
const alfredLink = require('./');
alfredLink.unlink().catch(err => {
console.error(err);
process.exit(1);
});
@@ -0,0 +1,39 @@
#!/usr/bin/env node
'use strict';
const readPkg = require('read-pkg');
const latestVersion = require('latest-version');
const semver = require('semver');
const execa = require('execa');
const CacheConf = require('cache-conf');
const notify = require('./lib/notify');
const pkg = require('./package.json');
const ONE_DAY = 86400000;
const workflowPath = process.cwd();
const conf = new CacheConf({projectName: pkg.name});
const checkNpm = pkg => latestVersion(pkg.name).then(version => ({
latest: version,
current: pkg.version,
name: pkg.name
}));
readPkg(workflowPath)
.then(pkg => {
if (conf.has(pkg.name)) {
// Skip checking if a valid entry exists
return;
}
return checkNpm(pkg).then(res => {
// Store the latest version in the cache for one day
conf.set(res.name, res.latest, {maxAge: ONE_DAY});
if (!semver.eq(res.latest, res.current)) {
// Overwrite `info.plist` and reload the workflows
return notify(workflowPath, `Update available: ${res.current}${res.latest}. Run \`npm install -g ${res.name}\``)
.then(() => execa('open', ['-n', '-a', 'Alfred 3']));
}
});
});
@@ -0,0 +1,11 @@
'use strict';
const path = require('path');
const cp = require('child_process');
module.exports = () => {
const subProcess = cp.spawn(path.join(__dirname, 'check.js'), [], {
detached: true,
stdio: 'ignore'
});
subProcess.unref();
};
@@ -0,0 +1,42 @@
'use strict';
const path = require('path');
const fs = require('fs');
const plist = require('plist');
const pify = require('pify');
const fsP = pify(fs);
// Fixes some inconsistencies when running `plist.parse`
// https://github.com/TooTallNate/plist.js/issues/75
const fix = obj => {
for (const key of Object.keys(obj)) {
const val = obj[key];
if (val === null || val === undefined) {
obj[key] = '';
} else if (Array.isArray(val)) {
obj[key] = val.map(fix);
} else if (typeof val === 'object') {
obj[key] = fix(val);
}
}
return obj;
};
module.exports = (dir, message) => {
const file = path.join(dir, 'info.plist');
return fsP.readFile(file, 'utf8')
.then(content => {
const data = fix(plist.parse(content));
for (const obj of data.objects) {
if (obj.config.subtext !== undefined) {
obj.config.subtext = message;
}
}
return fsP.writeFile(file, plist.build(data));
});
};
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sam Verschueren <sam.verschueren@gmail.com> (github.com/SamVerschueren)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,86 @@
'use strict';
const path = require('path');
const Conf = require('conf');
const pkgUp = require('pkg-up');
const parentDir = path.dirname(module.parent.filename);
class CacheConf extends Conf {
constructor(options) {
const pkgPath = pkgUp.sync(parentDir);
options = Object.assign({
projectName: pkgPath && require(pkgPath).name // eslint-disable-line import/no-dynamic-require
}, options);
super(options);
this.version = options.version;
}
get(key, options) {
options = options || {};
if (options.ignoreMaxAge !== true && this.isExpired(key)) {
super.delete(key);
return;
}
const item = super.get(key);
return item && item.data;
}
set(key, val, opts) {
opts = opts || {};
if (typeof key === 'object') {
opts = val || {};
const timestamp = typeof opts.maxAge === 'number' ? Date.now() + opts.maxAge : undefined;
Object.keys(key).forEach(k => {
super.set(k, {
timestamp,
version: this.version,
data: key[k]
});
});
} else {
super.set(key, {
timestamp: typeof opts.maxAge === 'number' ? Date.now() + opts.maxAge : undefined,
version: this.version,
data: val
});
}
}
has(key) {
if (!super.has(key)) {
return false;
}
if (this.isExpired(key)) {
super.delete(key);
return false;
}
return true;
}
isExpired(key) {
const item = super.get(key);
if (!item) {
return false;
}
const invalidTimestamp = item.timestamp && item.timestamp < Date.now();
const invalidVersion = item.version !== this.version;
return Boolean(invalidTimestamp || invalidVersion);
}
}
module.exports = CacheConf;
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sam Verschueren <sam.verschueren@gmail.com> (github.com/SamVerschueren)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,86 @@
{
"_from": "cache-conf@^0.5.0",
"_id": "cache-conf@0.5.0",
"_inBundle": false,
"_integrity": "sha1-aBxC7Rdx6tK8I2MqddPNjceUXFk=",
"_location": "/alfred-mvns/alfred-notifier/cache-conf",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "cache-conf@^0.5.0",
"name": "cache-conf",
"escapedName": "cache-conf",
"rawSpec": "^0.5.0",
"saveSpec": null,
"fetchSpec": "^0.5.0"
},
"_requiredBy": [
"/alfred-mvns/alfred-notifier"
],
"_resolved": "https://registry.npmjs.org/cache-conf/-/cache-conf-0.5.0.tgz",
"_shasum": "681c42ed1771ead2bc23632a75d3cd8dc7945c59",
"_spec": "cache-conf@^0.5.0",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/alfred-notifier",
"author": {
"name": "Sam Verschueren",
"email": "sam.verschueren@gmail.com",
"url": "github.com/SamVerschueren"
},
"bugs": {
"url": "https://github.com/SamVerschueren/cache-conf/issues"
},
"bundleDependencies": false,
"dependencies": {
"conf": "^0.12.0",
"pkg-up": "^1.0.0"
},
"deprecated": false,
"description": "Simple cache config handling for your app or module",
"devDependencies": {
"ava": "*",
"delay": "^1.3.1",
"tempfile": "^1.1.1",
"xo": "*"
},
"engines": {
"node": ">=4"
},
"files": [
"index.js"
],
"homepage": "https://github.com/SamVerschueren/cache-conf#readme",
"keywords": [
"cache",
"caching",
"config",
"store",
"app",
"storage",
"conf",
"configuration",
"settings",
"preferences",
"json",
"data",
"persist",
"persistent",
"save",
"load",
"read",
"write"
],
"license": "MIT",
"name": "cache-conf",
"repository": {
"type": "git",
"url": "git+https://github.com/SamVerschueren/cache-conf.git"
},
"scripts": {
"test": "xo && ava"
},
"version": "0.5.0",
"xo": {
"esnext": true
}
}
@@ -0,0 +1,96 @@
# cache-conf [![Build Status](https://travis-ci.org/SamVerschueren/cache-conf.svg?branch=master)](https://travis-ci.org/SamVerschueren/cache-conf)
> Simple cache config handling for your app or module
If you don't need caching, you should use [conf](https://github.com/sindresorhus/conf) instead. This module extends that module and
abstracts away the caching mechanism.
## Install
```
$ npm install --save cache-conf
```
## Usage
```js
const delay = require('delay');
const CacheConf = require('cache-conf');
const config = new CacheConf();
config.set('unicorn', '🦄', {maxAge: 5000});
console.log(config.get('unicorn'));
//=> '🦄'
// Wait 5 seconds
await delay(5000);
console.log(config.get('unicorn'));
//=> undefined
```
## API
### CacheConf([options])
Returns a new instance.
#### options
Any of the [conf options](https://github.com/sindresorhus/conf#options).
### Instance
An extended [conf](https://github.com/sindresorhus/conf#instance) instance.
#### get(key, [options])
Get an item.
##### options
###### ignoreMaxAge
Type: `boolean`<br>
Default: `false`
Get the item for the `key` provided without taking the `maxAge` of the item into account.
#### set(key, value, [options])
Set an item.
#### set(object, [options])
Set multiple items at once.
##### options
###### maxAge
Type: `number`
Number of milliseconds the cached value is valid.
###### version
Type: `string`
Version number of the data. If the version provided is not the same as the version of the cached data, the data will be invalid.
#### isExpired(key)
Boolean indicating if the cached data is expired.
## Related
- [conf](https://github.com/sindresorhus/conf) - Simple config handling for your app or module
## License
MIT © [Sam Verschueren](https://github.com/SamVerschueren)
@@ -0,0 +1,105 @@
'use strict';
const fs = require('fs');
const path = require('path');
const dotProp = require('dot-prop');
const mkdirp = require('mkdirp');
const pkgUp = require('pkg-up');
const envPaths = require('env-paths');
const obj = () => Object.create(null);
// Prevent caching of this module so module.parent is always accurate
delete require.cache[__filename];
const parentDir = path.dirname(module.parent.filename);
class Conf {
constructor(opts) {
const pkgPath = pkgUp.sync(parentDir);
opts = Object.assign({
// If the package.json was not found, avoid breaking with `require(null)`
projectName: pkgPath && require(pkgPath).name // eslint-disable-line import/no-dynamic-require
}, opts);
if (!opts.projectName && !opts.cwd) {
throw new Error('Project name could not be inferred. Please specify the `projectName` option.');
}
opts = Object.assign({
configName: 'config'
}, opts);
if (!opts.cwd) {
opts.cwd = envPaths(opts.projectName).config;
}
this.path = path.resolve(opts.cwd, `${opts.configName}.json`);
this.store = Object.assign(obj(), opts.defaults, this.store);
}
get(key) {
return dotProp.get(this.store, key);
}
set(key, val) {
if (typeof key !== 'string' && typeof key !== 'object') {
throw new TypeError(`Expected \`key\` to be of type \`string\` or \`object\`, got ${typeof key}`);
}
const store = this.store;
if (typeof key === 'object') {
Object.keys(key).forEach(k => {
dotProp.set(store, k, key[k]);
});
} else {
dotProp.set(store, key, val);
}
this.store = store;
}
has(key) {
return dotProp.has(this.store, key);
}
delete(key) {
const store = this.store;
dotProp.delete(store, key);
this.store = store;
}
clear() {
this.store = obj();
}
get size() {
return Object.keys(this.store).length;
}
get store() {
try {
return Object.assign(obj(), JSON.parse(fs.readFileSync(this.path, 'utf8')));
} catch (err) {
if (err.code === 'ENOENT') {
mkdirp.sync(path.dirname(this.path));
return obj();
}
if (err.name === 'SyntaxError') {
return obj();
}
throw err;
}
}
set store(val) {
// Ensure the directory exists as it could have been deleted in the meantime
mkdirp.sync(path.dirname(this.path));
fs.writeFileSync(this.path, JSON.stringify(val, null, '\t'));
}
// TODO: Use `Object.entries()` here at some point
* [Symbol.iterator]() {
const store = this.store;
for (const key of Object.keys(store)) {
yield [key, store[key]];
}
}
}
module.exports = Conf;
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,81 @@
{
"_from": "conf@^0.12.0",
"_id": "conf@0.12.0",
"_inBundle": false,
"_integrity": "sha1-hJjFmeJIf+xwNQXRgcETh1uMMQw=",
"_location": "/alfred-mvns/alfred-notifier/conf",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "conf@^0.12.0",
"name": "conf",
"escapedName": "conf",
"rawSpec": "^0.12.0",
"saveSpec": null,
"fetchSpec": "^0.12.0"
},
"_requiredBy": [
"/alfred-mvns/alfred-notifier/cache-conf"
],
"_resolved": "https://registry.npmjs.org/conf/-/conf-0.12.0.tgz",
"_shasum": "8498c599e2487fec703505d181c113875b8c310c",
"_spec": "conf@^0.12.0",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/alfred-notifier/node_modules/cache-conf",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/conf/issues"
},
"bundleDependencies": false,
"dependencies": {
"dot-prop": "^4.1.0",
"env-paths": "^1.0.0",
"mkdirp": "^0.5.1",
"pkg-up": "^1.0.0"
},
"deprecated": false,
"description": "Simple config handling for your app or module",
"devDependencies": {
"ava": "*",
"del": "^2.2.1",
"tempfile": "^1.1.1",
"xo": "*"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/conf#readme",
"keywords": [
"config",
"store",
"app",
"storage",
"conf",
"configuration",
"settings",
"preferences",
"json",
"data",
"persist",
"persistent",
"save",
"load",
"read",
"write",
"cache"
],
"license": "MIT",
"name": "conf",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/conf.git"
},
"scripts": {
"test": "xo && ava"
},
"version": "0.12.0"
}
@@ -0,0 +1,143 @@
# conf [![Build Status: Linux and macOS](https://travis-ci.org/sindresorhus/conf.svg?branch=master)](https://travis-ci.org/sindresorhus/conf) [![Build status: Windows](https://ci.appveyor.com/api/projects/status/n88jwh3aju39i0p2/branch/master?svg=true)](https://ci.appveyor.com/project/sindresorhus/conf/branch/master)
> Simple config handling for your app or module
All you have to care about is what to persist. This module will handle all the dull details like where and how.
## Install
```
$ npm install --save conf
```
## Usage
```js
const Conf = require('conf');
const config = new Conf();
config.set('unicorn', '🦄');
console.log(config.get('unicorn'));
//=> '🦄'
// Use dot-notation to access nested properties
config.set('foo.bar', true);
console.log(config.get('foo'));
//=> {bar: true}
config.delete('unicorn');
console.log(config.get('unicorn'));
//=> undefined
```
Or [create a subclass](https://github.com/sindresorhus/electron-config/blob/master/index.js).
## API
### Conf([options])
Returns a new instance.
### options
#### defaults
Type: `Object`
Default config.
#### configName
Type: `string`<br>
Default: `config`
Name of the config file (without extension).
Useful if you need multiple config files for your app or module. For example, different config files between two major versions.
#### projectName
Type: `string`<br>
Default: The `name` field in your package.json
You only need to specify this if you don't have a package.json file in your project.
#### cwd
Type: `string`<br>
Default: System default [user config directory](https://github.com/sindresorhus/env-paths#pathsconfig)
**You most likely don't need this.**
Overrides `projectName`.
The only use-case I can think of is having the config located in the app directory or on some external storage.
### Instance
You can use [dot-notation](https://github.com/sindresorhus/dot-prop) in a `key` to access nested properties.
The instance is [`iterable`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols) so you can use it directly in a [`for…of`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of) loop.
#### .set(key, value)
Set an item.
#### .set(object)
Set multiple items at once.
#### .get(key)
Get an item.
#### .has(key)
Check if an item exists.
#### .delete(key)
Delete an item.
#### .clear()
Delete all items.
#### .size
Get the item count.
#### .store
Get all the config as an object or replace the current config with an object:
```js
conf.store = {
hello: 'world'
};
```
#### .path
Get the path to the config file.
## FAQ
### How is this different from [`configstore`](https://github.com/yeoman/configstore)?
I'm also the author of `configstore`. While it's pretty good, I did make some mistakes early on that are hard to change at this point. This module is the result of everything I learned from making `configstore`. Mainly where config is stored. In `configstore`, the config is stored in `~/.config` (which is mainly a Linux convention) on all systems, while `conf` stores config in the system default [user config directory](https://github.com/sindresorhus/env-paths#pathsconfig). The `~/.config` directory, it turns out, often have an incorrect permission on macOS and Windows, which has caused a lot of grief for users.
## Related
- [electron-config](https://github.com/sindresorhus/electron-config) - Simple config handling for your Electron app or module
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)
@@ -0,0 +1,314 @@
'use strict';
const childProcess = require('child_process');
const util = require('util');
const crossSpawn = require('cross-spawn');
const stripEof = require('strip-eof');
const npmRunPath = require('npm-run-path');
const isStream = require('is-stream');
const _getStream = require('get-stream');
const pFinally = require('p-finally');
const onExit = require('signal-exit');
const errname = require('./lib/errname');
const stdio = require('./lib/stdio');
const TEN_MEGABYTES = 1000 * 1000 * 10;
function handleArgs(cmd, args, opts) {
let parsed;
opts = Object.assign({
extendEnv: true,
env: {}
}, opts);
if (opts.extendEnv) {
opts.env = Object.assign({}, process.env, opts.env);
}
if (opts.__winShell === true) {
delete opts.__winShell;
parsed = {
command: cmd,
args,
options: opts,
file: cmd,
original: cmd
};
} else {
parsed = crossSpawn._parse(cmd, args, opts);
}
opts = Object.assign({
maxBuffer: TEN_MEGABYTES,
stripEof: true,
preferLocal: true,
localDir: parsed.options.cwd || process.cwd(),
encoding: 'utf8',
reject: true,
cleanup: true
}, parsed.options);
opts.stdio = stdio(opts);
if (opts.preferLocal) {
opts.env = npmRunPath.env(Object.assign({}, opts, {cwd: opts.localDir}));
}
return {
cmd: parsed.command,
args: parsed.args,
opts,
parsed
};
}
function handleInput(spawned, opts) {
const input = opts.input;
if (input === null || input === undefined) {
return;
}
if (isStream(input)) {
input.pipe(spawned.stdin);
} else {
spawned.stdin.end(input);
}
}
function handleOutput(opts, val) {
if (val && opts.stripEof) {
val = stripEof(val);
}
return val;
}
function handleShell(fn, cmd, opts) {
let file = '/bin/sh';
let args = ['-c', cmd];
opts = Object.assign({}, opts);
if (process.platform === 'win32') {
opts.__winShell = true;
file = process.env.comspec || 'cmd.exe';
args = ['/s', '/c', `"${cmd}"`];
opts.windowsVerbatimArguments = true;
}
if (opts.shell) {
file = opts.shell;
delete opts.shell;
}
return fn(file, args, opts);
}
function getStream(process, stream, encoding, maxBuffer) {
if (!process[stream]) {
return null;
}
let ret;
if (encoding) {
ret = _getStream(process[stream], {
encoding,
maxBuffer
});
} else {
ret = _getStream.buffer(process[stream], {maxBuffer});
}
return ret.catch(err => {
err.stream = stream;
err.message = `${stream} ${err.message}`;
throw err;
});
}
module.exports = (cmd, args, opts) => {
let joinedCmd = cmd;
if (Array.isArray(args) && args.length > 0) {
joinedCmd += ' ' + args.join(' ');
}
const parsed = handleArgs(cmd, args, opts);
const encoding = parsed.opts.encoding;
const maxBuffer = parsed.opts.maxBuffer;
let spawned;
try {
spawned = childProcess.spawn(parsed.cmd, parsed.args, parsed.opts);
} catch (err) {
return Promise.reject(err);
}
let removeExitHandler;
if (parsed.opts.cleanup) {
removeExitHandler = onExit(() => {
spawned.kill();
});
}
let timeoutId = null;
let timedOut = false;
const cleanupTimeout = () => {
if (timeoutId) {
clearTimeout(timeoutId);
timeoutId = null;
}
};
if (parsed.opts.timeout > 0) {
timeoutId = setTimeout(() => {
timeoutId = null;
timedOut = true;
spawned.kill(parsed.opts.killSignal);
}, parsed.opts.timeout);
}
const processDone = new Promise(resolve => {
spawned.on('exit', (code, signal) => {
cleanupTimeout();
resolve({code, signal});
});
spawned.on('error', err => {
cleanupTimeout();
resolve({err});
});
if (spawned.stdin) {
spawned.stdin.on('error', err => {
cleanupTimeout();
resolve({err});
});
}
});
function destroy() {
if (spawned.stdout) {
spawned.stdout.destroy();
}
if (spawned.stderr) {
spawned.stderr.destroy();
}
}
const handlePromise = () => pFinally(Promise.all([
processDone,
getStream(spawned, 'stdout', encoding, maxBuffer),
getStream(spawned, 'stderr', encoding, maxBuffer)
]).then(arr => {
const result = arr[0];
const stdout = arr[1];
const stderr = arr[2];
let err = result.err;
const code = result.code;
const signal = result.signal;
if (removeExitHandler) {
removeExitHandler();
}
if (err || code !== 0 || signal !== null) {
if (!err) {
let output = '';
if (Array.isArray(parsed.opts.stdio)) {
if (parsed.opts.stdio[2] !== 'inherit') {
output += output.length > 0 ? stderr : `\n${stderr}`;
}
if (parsed.opts.stdio[1] !== 'inherit') {
output += `\n${stdout}`;
}
} else if (parsed.opts.stdio !== 'inherit') {
output = `\n${stderr}${stdout}`;
}
err = new Error(`Command failed: ${joinedCmd}${output}`);
err.code = code < 0 ? errname(code) : code;
}
// TODO: missing some timeout logic for killed
// https://github.com/nodejs/node/blob/master/lib/child_process.js#L203
// err.killed = spawned.killed || killed;
err.killed = err.killed || spawned.killed;
err.stdout = stdout;
err.stderr = stderr;
err.failed = true;
err.signal = signal || null;
err.cmd = joinedCmd;
err.timedOut = timedOut;
if (!parsed.opts.reject) {
return err;
}
throw err;
}
return {
stdout: handleOutput(parsed.opts, stdout),
stderr: handleOutput(parsed.opts, stderr),
code: 0,
failed: false,
killed: false,
signal: null,
cmd: joinedCmd,
timedOut: false
};
}), destroy);
crossSpawn._enoent.hookChildProcess(spawned, parsed.parsed);
handleInput(spawned, parsed.opts);
spawned.then = (onfulfilled, onrejected) => handlePromise().then(onfulfilled, onrejected);
spawned.catch = onrejected => handlePromise().catch(onrejected);
return spawned;
};
module.exports.stdout = function () {
// TODO: set `stderr: 'ignore'` when that option is implemented
return module.exports.apply(null, arguments).then(x => x.stdout);
};
module.exports.stderr = function () {
// TODO: set `stdout: 'ignore'` when that option is implemented
return module.exports.apply(null, arguments).then(x => x.stderr);
};
module.exports.shell = (cmd, opts) => handleShell(module.exports, cmd, opts);
module.exports.sync = (cmd, args, opts) => {
const parsed = handleArgs(cmd, args, opts);
if (isStream(parsed.opts.input)) {
throw new TypeError('The `input` option cannot be a stream in sync mode');
}
const result = childProcess.spawnSync(parsed.cmd, parsed.args, parsed.opts);
if (result.error || result.status !== 0) {
throw (result.error || new Error(result.stderr === '' ? result.stdout : result.stderr));
}
result.stdout = handleOutput(parsed.opts, result.stdout);
result.stderr = handleOutput(parsed.opts, result.stderr);
return result;
};
module.exports.shellSync = (cmd, opts) => handleShell(module.exports.sync, cmd, opts);
module.exports.spawn = util.deprecate(module.exports, 'execa.spawn() is deprecated. Use execa() instead.');
@@ -0,0 +1,37 @@
'use strict';
// The Node team wants to deprecate `process.bind(...)`.
// https://github.com/nodejs/node/pull/2768
//
// However, we need the 'uv' binding for errname support.
// This is a defensive wrapper around it so `execa` will not fail entirely if it stops working someday.
//
// If this ever stops working. See: https://github.com/sindresorhus/execa/issues/31#issuecomment-215939939 for another possible solution.
let uv;
try {
uv = process.binding('uv');
if (typeof uv.errname !== 'function') {
throw new TypeError('uv.errname is not a function');
}
} catch (err) {
console.error('execa/lib/errname: unable to establish process.binding(\'uv\')', err);
uv = null;
}
function errname(uv, code) {
if (uv) {
return uv.errname(code);
}
if (!(code < 0)) {
throw new Error('err >= 0');
}
return `Unknown system error ${code}`;
}
module.exports = code => errname(uv, code);
// Used for testing the fallback behavior
module.exports.__test__ = errname;
@@ -0,0 +1,41 @@
'use strict';
const alias = ['stdin', 'stdout', 'stderr'];
const hasAlias = opts => alias.some(x => Boolean(opts[x]));
module.exports = opts => {
if (!opts) {
return null;
}
if (opts.stdio && hasAlias(opts)) {
throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${alias.map(x => `\`${x}\``).join(', ')}`);
}
if (typeof opts.stdio === 'string') {
return opts.stdio;
}
const stdio = opts.stdio || [];
if (!Array.isArray(stdio)) {
throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``);
}
const result = [];
const len = Math.max(stdio.length, alias.length);
for (let i = 0; i < len; i++) {
let value = null;
if (stdio[i] !== undefined) {
value = stdio[i];
} else if (opts[alias[i]] !== undefined) {
value = opts[alias[i]];
}
result[i] = value;
}
return result;
};
@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,108 @@
{
"_from": "execa@^0.8.0",
"_id": "execa@0.8.0",
"_inBundle": false,
"_integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=",
"_location": "/alfred-mvns/alfred-notifier/execa",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "execa@^0.8.0",
"name": "execa",
"escapedName": "execa",
"rawSpec": "^0.8.0",
"saveSpec": null,
"fetchSpec": "^0.8.0"
},
"_requiredBy": [
"/alfred-mvns/alfred-notifier"
],
"_resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz",
"_shasum": "d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da",
"_spec": "execa@^0.8.0",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/alfred-notifier",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/execa/issues"
},
"bundleDependencies": false,
"dependencies": {
"cross-spawn": "^5.0.1",
"get-stream": "^3.0.0",
"is-stream": "^1.1.0",
"npm-run-path": "^2.0.0",
"p-finally": "^1.0.0",
"signal-exit": "^3.0.0",
"strip-eof": "^1.0.0"
},
"deprecated": false,
"description": "A better `child_process`",
"devDependencies": {
"ava": "*",
"cat-names": "^1.0.2",
"coveralls": "^2.11.9",
"delay": "^2.0.0",
"is-running": "^2.0.0",
"nyc": "^11.0.2",
"tempfile": "^2.0.0",
"xo": "*"
},
"engines": {
"node": ">=4"
},
"files": [
"index.js",
"lib"
],
"homepage": "https://github.com/sindresorhus/execa#readme",
"keywords": [
"exec",
"child",
"process",
"execute",
"fork",
"execfile",
"spawn",
"file",
"shell",
"bin",
"binary",
"binaries",
"npm",
"path",
"local"
],
"license": "MIT",
"maintainers": [
{
"name": "James Talmage",
"email": "james@talmage.io",
"url": "github.com/jamestalmage"
}
],
"name": "execa",
"nyc": {
"reporter": [
"text",
"lcov"
],
"exclude": [
"**/fixtures/**",
"**/test.js",
"**/test/**"
]
},
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/execa.git"
},
"scripts": {
"test": "xo && nyc ava"
},
"version": "0.8.0"
}
@@ -0,0 +1,279 @@
# execa [![Build Status: Linux](https://travis-ci.org/sindresorhus/execa.svg?branch=master)](https://travis-ci.org/sindresorhus/execa) [![Build status: Windows](https://ci.appveyor.com/api/projects/status/x5ajamxtjtt93cqv/branch/master?svg=true)](https://ci.appveyor.com/project/sindresorhus/execa/branch/master) [![Coverage Status](https://coveralls.io/repos/github/sindresorhus/execa/badge.svg?branch=master)](https://coveralls.io/github/sindresorhus/execa?branch=master)
> A better [`child_process`](https://nodejs.org/api/child_process.html)
## Why
- Promise interface.
- [Strips EOF](https://github.com/sindresorhus/strip-eof) from the output so you don't have to `stdout.trim()`.
- Supports [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) binaries cross-platform.
- [Improved Windows support.](https://github.com/IndigoUnited/node-cross-spawn#why)
- Higher max buffer. 10 MB instead of 200 KB.
- [Executes locally installed binaries by name.](#preferlocal)
- [Cleans up spawned processes when the parent process dies.](#cleanup)
## Install
```
$ npm install --save execa
```
## Usage
```js
const execa = require('execa');
execa('echo', ['unicorns']).then(result => {
console.log(result.stdout);
//=> 'unicorns'
});
// pipe the child process stdout to the current stdout
execa('echo', ['unicorns']).stdout.pipe(process.stdout);
execa.shell('echo unicorns').then(result => {
console.log(result.stdout);
//=> 'unicorns'
});
// example of catching an error
execa.shell('exit 3').catch(error => {
console.log(error);
/*
{
message: 'Command failed: /bin/sh -c exit 3'
killed: false,
code: 3,
signal: null,
cmd: '/bin/sh -c exit 3',
stdout: '',
stderr: '',
timedOut: false
}
*/
});
```
## API
### execa(file, [arguments], [options])
Execute a file.
Think of this as a mix of `child_process.execFile` and `child_process.spawn`.
Returns a [`child_process` instance](https://nodejs.org/api/child_process.html#child_process_class_childprocess), which is enhanced to also be a `Promise` for a result `Object` with `stdout` and `stderr` properties.
### execa.stdout(file, [arguments], [options])
Same as `execa()`, but returns only `stdout`.
### execa.stderr(file, [arguments], [options])
Same as `execa()`, but returns only `stderr`.
### execa.shell(command, [options])
Execute a command through the system shell. Prefer `execa()` whenever possible, as it's both faster and safer.
Returns a [`child_process` instance](https://nodejs.org/api/child_process.html#child_process_class_childprocess).
The `child_process` instance is enhanced to also be promise for a result object with `stdout` and `stderr` properties.
### execa.sync(file, [arguments], [options])
Execute a file synchronously.
Returns the same result object as [`child_process.spawnSync`](https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options).
This method throws an `Error` if the command fails.
### execa.shellSync(file, [options])
Execute a command synchronously through the system shell.
Returns the same result object as [`child_process.spawnSync`](https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options).
### options
Type: `Object`
#### cwd
Type: `string`<br>
Default: `process.cwd()`
Current working directory of the child process.
#### env
Type: `Object`<br>
Default: `process.env`
Environment key-value pairs. Extends automatically from `process.env`. Set `extendEnv` to `false` if you don't want this.
#### extendEnv
Type: `boolean`<br>
Default: `true`
Set to `false` if you don't want to extend the environment variables when providing the `env` property.
#### argv0
Type: `string`
Explicitly set the value of `argv[0]` sent to the child process. This will be set to `command` or `file` if not specified.
#### stdio
Type: `Array` `string`<br>
Default: `pipe`
Child's [stdio](https://nodejs.org/api/child_process.html#child_process_options_stdio) configuration.
#### detached
Type: `boolean`
Prepare child to run independently of its parent process. Specific behavior [depends on the platform](https://nodejs.org/api/child_process.html#child_process_options_detached).
#### uid
Type: `number`
Sets the user identity of the process.
#### gid
Type: `number`
Sets the group identity of the process.
#### shell
Type: `boolean` `string`<br>
Default: `false`
If `true`, runs `command` inside of a shell. Uses `/bin/sh` on UNIX and `cmd.exe` on Windows. A different shell can be specified as a string. The shell should understand the `-c` switch on UNIX or `/d /s /c` on Windows.
#### stripEof
Type: `boolean`<br>
Default: `true`
[Strip EOF](https://github.com/sindresorhus/strip-eof) (last newline) from the output.
#### preferLocal
Type: `boolean`<br>
Default: `true`
Prefer locally installed binaries when looking for a binary to execute.<br>
If you `$ npm install foo`, you can then `execa('foo')`.
#### localDir
Type: `string`<br>
Default: `process.cwd()`
Preferred path to find locally installed binaries in (use with `preferLocal`).
#### input
Type: `string` `Buffer` `stream.Readable`
Write some input to the `stdin` of your binary.<br>
Streams are not allowed when using the synchronous methods.
#### reject
Type: `boolean`<br>
Default: `true`
Setting this to `false` resolves the promise with the error instead of rejecting it.
#### cleanup
Type: `boolean`<br>
Default: `true`
Keep track of the spawned process and `kill` it when the parent process exits.
#### encoding
Type: `string`<br>
Default: `utf8`
Specify the character encoding used to decode the `stdout` and `stderr` output.
#### timeout
Type: `number`<br>
Default: `0`
If timeout is greater than `0`, the parent will send the signal identified by the `killSignal` property (the default is `SIGTERM`) if the child runs longer than timeout milliseconds.
#### maxBuffer
Type: `number`<br>
Default: `10000000` (10MB)
Largest amount of data in bytes allowed on `stdout` or `stderr`.
#### killSignal
Type: `string` `number`<br>
Default: `SIGTERM`
Signal value to be used when the spawned process will be killed.
#### stdin
Type: `string` `number` `Stream` `undefined` `null`<br>
Default: `pipe`
Same options as [`stdio`](https://nodejs.org/dist/latest-v6.x/docs/api/child_process.html#child_process_options_stdio).
#### stdout
Type: `string` `number` `Stream` `undefined` `null`<br>
Default: `pipe`
Same options as [`stdio`](https://nodejs.org/dist/latest-v6.x/docs/api/child_process.html#child_process_options_stdio).
#### stderr
Type: `string` `number` `Stream` `undefined` `null`<br>
Default: `pipe`
Same options as [`stdio`](https://nodejs.org/dist/latest-v6.x/docs/api/child_process.html#child_process_options_stdio).
## Tips
### Save and pipe output from a child process
Let's say you want to show the output of a child process in real-time while also saving it to a variable.
```js
const execa = require('execa');
const getStream = require('get-stream');
const stream = execa('echo', ['foo']).stdout;
stream.pipe(process.stdout);
getStream(stream).then(value => {
console.log('child output:', value);
});
```
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)
@@ -0,0 +1,11 @@
'use strict';
const path = require('path');
const fs = require('graceful-fs');
const stripBom = require('strip-bom');
const parseJson = require('parse-json');
const pify = require('pify');
const parse = (data, fp) => parseJson(stripBom(data), path.relative('.', fp));
module.exports = fp => pify(fs.readFile)(fp, 'utf8').then(data => parse(data, fp));
module.exports.sync = fp => parse(fs.readFileSync(fp, 'utf8'), fp);
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,68 @@
'use strict';
var processFn = function (fn, P, opts) {
return function () {
var that = this;
var args = new Array(arguments.length);
for (var i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
return new P(function (resolve, reject) {
args.push(function (err, result) {
if (err) {
reject(err);
} else if (opts.multiArgs) {
var results = new Array(arguments.length - 1);
for (var i = 1; i < arguments.length; i++) {
results[i - 1] = arguments[i];
}
resolve(results);
} else {
resolve(result);
}
});
fn.apply(that, args);
});
};
};
var pify = module.exports = function (obj, P, opts) {
if (typeof P !== 'function') {
opts = P;
P = Promise;
}
opts = opts || {};
opts.exclude = opts.exclude || [/.+Sync$/];
var filter = function (key) {
var match = function (pattern) {
return typeof pattern === 'string' ? key === pattern : pattern.test(key);
};
return opts.include ? opts.include.some(match) : !opts.exclude.some(match);
};
var ret = typeof obj === 'function' ? function () {
if (opts.excludeMain) {
return obj.apply(this, arguments);
}
return processFn(obj, P, opts).apply(this, arguments);
} : {};
return Object.keys(obj).reduce(function (ret, key) {
var x = obj[key];
ret[key] = typeof x === 'function' && filter(key) ? processFn(x, P, opts) : x;
return ret;
}, ret);
};
pify.all = pify;
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,80 @@
{
"_from": "pify@^2.0.0",
"_id": "pify@2.3.0",
"_inBundle": false,
"_integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"_location": "/alfred-mvns/alfred-notifier/load-json-file/pify",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "pify@^2.0.0",
"name": "pify",
"escapedName": "pify",
"rawSpec": "^2.0.0",
"saveSpec": null,
"fetchSpec": "^2.0.0"
},
"_requiredBy": [
"/alfred-mvns/alfred-notifier/load-json-file"
],
"_resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"_shasum": "ed141a6ac043a849ea588498e7dca8b15330e90c",
"_spec": "pify@^2.0.0",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/alfred-notifier/node_modules/load-json-file",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/pify/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Promisify a callback-style function",
"devDependencies": {
"ava": "*",
"pinkie-promise": "^1.0.0",
"v8-natives": "0.0.2",
"xo": "*"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/pify#readme",
"keywords": [
"promise",
"promises",
"promisify",
"denodify",
"denodeify",
"callback",
"cb",
"node",
"then",
"thenify",
"convert",
"transform",
"wrap",
"wrapper",
"bind",
"to",
"async",
"es2015"
],
"license": "MIT",
"name": "pify",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/pify.git"
},
"scripts": {
"optimization-test": "node --allow-natives-syntax optimization-test.js",
"test": "xo && ava && npm run optimization-test"
},
"version": "2.3.0"
}
@@ -0,0 +1,119 @@
# pify [![Build Status](https://travis-ci.org/sindresorhus/pify.svg?branch=master)](https://travis-ci.org/sindresorhus/pify)
> Promisify a callback-style function
## Install
```
$ npm install --save pify
```
## Usage
```js
const fs = require('fs');
const pify = require('pify');
// promisify a single function
pify(fs.readFile)('package.json', 'utf8').then(data => {
console.log(JSON.parse(data).name);
//=> 'pify'
});
// or promisify all methods in a module
pify(fs).readFile('package.json', 'utf8').then(data => {
console.log(JSON.parse(data).name);
//=> 'pify'
});
```
## API
### pify(input, [promiseModule], [options])
Returns a promise wrapped version of the supplied function or module.
#### input
Type: `function`, `object`
Callback-style function or module whose methods you want to promisify.
#### promiseModule
Type: `function`
Custom promise module to use instead of the native one.
Check out [`pinkie-promise`](https://github.com/floatdrop/pinkie-promise) if you need a tiny promise polyfill.
#### options
##### multiArgs
Type: `boolean`
Default: `false`
By default, the promisified function will only return the second argument from the callback, which works fine for most APIs. This option can be useful for modules like `request` that return multiple arguments. Turning this on will make it return an array of all arguments from the callback, excluding the error argument, instead of just the second argument.
```js
const request = require('request');
const pify = require('pify');
pify(request, {multiArgs: true})('https://sindresorhus.com').then(result => {
const [httpResponse, body] = result;
});
```
##### include
Type: `array` of (`string`|`regex`)
Methods in a module to promisify. Remaining methods will be left untouched.
##### exclude
Type: `array` of (`string`|`regex`)
Default: `[/.+Sync$/]`
Methods in a module **not** to promisify. Methods with names ending with `'Sync'` are excluded by default.
##### excludeMain
Type: `boolean`
Default: `false`
By default, if given module is a function itself, this function will be promisified. Turn this option on if you want to promisify only methods of the module.
```js
const pify = require('pify');
function fn() {
return true;
}
fn.method = (data, callback) => {
setImmediate(() => {
callback(data, null);
});
};
// promisify methods but not fn()
const promiseFn = pify(fn, {excludeMain: true});
if (promiseFn()) {
promiseFn.method('hi').then(data => {
console.log(data);
});
}
```
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,75 @@
{
"_from": "load-json-file@^2.0.0",
"_id": "load-json-file@2.0.0",
"_inBundle": false,
"_integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
"_location": "/alfred-mvns/alfred-notifier/load-json-file",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "load-json-file@^2.0.0",
"name": "load-json-file",
"escapedName": "load-json-file",
"rawSpec": "^2.0.0",
"saveSpec": null,
"fetchSpec": "^2.0.0"
},
"_requiredBy": [
"/alfred-mvns/alfred-notifier/read-pkg"
],
"_resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
"_shasum": "7947e42149af80d696cbf797bcaabcfe1fe29ca8",
"_spec": "load-json-file@^2.0.0",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/alfred-notifier/node_modules/read-pkg",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/load-json-file/issues"
},
"bundleDependencies": false,
"dependencies": {
"graceful-fs": "^4.1.2",
"parse-json": "^2.2.0",
"pify": "^2.0.0",
"strip-bom": "^3.0.0"
},
"deprecated": false,
"description": "Read and parse a JSON file",
"devDependencies": {
"ava": "*",
"xo": "*"
},
"engines": {
"node": ">=4"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/load-json-file#readme",
"keywords": [
"read",
"json",
"parse",
"file",
"fs",
"graceful",
"load"
],
"license": "MIT",
"name": "load-json-file",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/load-json-file.git"
},
"scripts": {
"test": "xo && ava"
},
"version": "2.0.0",
"xo": {
"esnext": true
}
}
@@ -0,0 +1,45 @@
# load-json-file [![Build Status](https://travis-ci.org/sindresorhus/load-json-file.svg?branch=master)](https://travis-ci.org/sindresorhus/load-json-file)
> Read and parse a JSON file
[Strips UTF-8 BOM](https://github.com/sindresorhus/strip-bom), uses [`graceful-fs`](https://github.com/isaacs/node-graceful-fs), and throws more [helpful JSON errors](https://github.com/sindresorhus/parse-json).
## Install
```
$ npm install --save load-json-file
```
## Usage
```js
const loadJsonFile = require('load-json-file');
loadJsonFile('foo.json').then(json => {
console.log(json);
//=> {foo: true}
});
```
## API
### loadJsonFile(filepath)
Returns a promise for the parsed JSON.
### loadJsonFile.sync(filepath)
Returns the parsed JSON.
## Related
- [write-json-file](https://github.com/sindresorhus/write-json-file) - Stringify and write JSON to a file atomically
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)
@@ -0,0 +1,26 @@
'use strict';
const fs = require('fs');
const pify = require('pify');
function type(fn, fn2, fp) {
if (typeof fp !== 'string') {
return Promise.reject(new TypeError(`Expected a string, got ${typeof fp}`));
}
return pify(fs[fn])(fp).then(stats => stats[fn2]());
}
function typeSync(fn, fn2, fp) {
if (typeof fp !== 'string') {
throw new TypeError(`Expected a string, got ${typeof fp}`);
}
return fs[fn](fp)[fn2]();
}
exports.file = type.bind(null, 'stat', 'isFile');
exports.dir = type.bind(null, 'stat', 'isDirectory');
exports.symlink = type.bind(null, 'lstat', 'isSymbolicLink');
exports.fileSync = typeSync.bind(null, 'statSync', 'isFile');
exports.dirSync = typeSync.bind(null, 'statSync', 'isDirectory');
exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink');
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,68 @@
'use strict';
var processFn = function (fn, P, opts) {
return function () {
var that = this;
var args = new Array(arguments.length);
for (var i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
return new P(function (resolve, reject) {
args.push(function (err, result) {
if (err) {
reject(err);
} else if (opts.multiArgs) {
var results = new Array(arguments.length - 1);
for (var i = 1; i < arguments.length; i++) {
results[i - 1] = arguments[i];
}
resolve(results);
} else {
resolve(result);
}
});
fn.apply(that, args);
});
};
};
var pify = module.exports = function (obj, P, opts) {
if (typeof P !== 'function') {
opts = P;
P = Promise;
}
opts = opts || {};
opts.exclude = opts.exclude || [/.+Sync$/];
var filter = function (key) {
var match = function (pattern) {
return typeof pattern === 'string' ? key === pattern : pattern.test(key);
};
return opts.include ? opts.include.some(match) : !opts.exclude.some(match);
};
var ret = typeof obj === 'function' ? function () {
if (opts.excludeMain) {
return obj.apply(this, arguments);
}
return processFn(obj, P, opts).apply(this, arguments);
} : {};
return Object.keys(obj).reduce(function (ret, key) {
var x = obj[key];
ret[key] = typeof x === 'function' && filter(key) ? processFn(x, P, opts) : x;
return ret;
}, ret);
};
pify.all = pify;
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,80 @@
{
"_from": "pify@^2.0.0",
"_id": "pify@2.3.0",
"_inBundle": false,
"_integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"_location": "/alfred-mvns/alfred-notifier/path-type/pify",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "pify@^2.0.0",
"name": "pify",
"escapedName": "pify",
"rawSpec": "^2.0.0",
"saveSpec": null,
"fetchSpec": "^2.0.0"
},
"_requiredBy": [
"/alfred-mvns/alfred-notifier/path-type"
],
"_resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"_shasum": "ed141a6ac043a849ea588498e7dca8b15330e90c",
"_spec": "pify@^2.0.0",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/alfred-notifier/node_modules/path-type",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/pify/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Promisify a callback-style function",
"devDependencies": {
"ava": "*",
"pinkie-promise": "^1.0.0",
"v8-natives": "0.0.2",
"xo": "*"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/pify#readme",
"keywords": [
"promise",
"promises",
"promisify",
"denodify",
"denodeify",
"callback",
"cb",
"node",
"then",
"thenify",
"convert",
"transform",
"wrap",
"wrapper",
"bind",
"to",
"async",
"es2015"
],
"license": "MIT",
"name": "pify",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/pify.git"
},
"scripts": {
"optimization-test": "node --allow-natives-syntax optimization-test.js",
"test": "xo && ava && npm run optimization-test"
},
"version": "2.3.0"
}
@@ -0,0 +1,119 @@
# pify [![Build Status](https://travis-ci.org/sindresorhus/pify.svg?branch=master)](https://travis-ci.org/sindresorhus/pify)
> Promisify a callback-style function
## Install
```
$ npm install --save pify
```
## Usage
```js
const fs = require('fs');
const pify = require('pify');
// promisify a single function
pify(fs.readFile)('package.json', 'utf8').then(data => {
console.log(JSON.parse(data).name);
//=> 'pify'
});
// or promisify all methods in a module
pify(fs).readFile('package.json', 'utf8').then(data => {
console.log(JSON.parse(data).name);
//=> 'pify'
});
```
## API
### pify(input, [promiseModule], [options])
Returns a promise wrapped version of the supplied function or module.
#### input
Type: `function`, `object`
Callback-style function or module whose methods you want to promisify.
#### promiseModule
Type: `function`
Custom promise module to use instead of the native one.
Check out [`pinkie-promise`](https://github.com/floatdrop/pinkie-promise) if you need a tiny promise polyfill.
#### options
##### multiArgs
Type: `boolean`
Default: `false`
By default, the promisified function will only return the second argument from the callback, which works fine for most APIs. This option can be useful for modules like `request` that return multiple arguments. Turning this on will make it return an array of all arguments from the callback, excluding the error argument, instead of just the second argument.
```js
const request = require('request');
const pify = require('pify');
pify(request, {multiArgs: true})('https://sindresorhus.com').then(result => {
const [httpResponse, body] = result;
});
```
##### include
Type: `array` of (`string`|`regex`)
Methods in a module to promisify. Remaining methods will be left untouched.
##### exclude
Type: `array` of (`string`|`regex`)
Default: `[/.+Sync$/]`
Methods in a module **not** to promisify. Methods with names ending with `'Sync'` are excluded by default.
##### excludeMain
Type: `boolean`
Default: `false`
By default, if given module is a function itself, this function will be promisified. Turn this option on if you want to promisify only methods of the module.
```js
const pify = require('pify');
function fn() {
return true;
}
fn.method = (data, callback) => {
setImmediate(() => {
callback(data, null);
});
};
// promisify methods but not fn()
const promiseFn = pify(fn, {excludeMain: true});
if (promiseFn()) {
promiseFn.method('hi').then(data => {
console.log(data);
});
}
```
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,80 @@
{
"_from": "path-type@^2.0.0",
"_id": "path-type@2.0.0",
"_inBundle": false,
"_integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
"_location": "/alfred-mvns/alfred-notifier/path-type",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "path-type@^2.0.0",
"name": "path-type",
"escapedName": "path-type",
"rawSpec": "^2.0.0",
"saveSpec": null,
"fetchSpec": "^2.0.0"
},
"_requiredBy": [
"/alfred-mvns/alfred-notifier/read-pkg"
],
"_resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
"_shasum": "f012ccb8415b7096fc2daa1054c3d72389594c73",
"_spec": "path-type@^2.0.0",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/alfred-notifier/node_modules/read-pkg",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/path-type/issues"
},
"bundleDependencies": false,
"dependencies": {
"pify": "^2.0.0"
},
"deprecated": false,
"description": "Check if a path is a file, directory, or symlink",
"devDependencies": {
"ava": "*",
"xo": "*"
},
"engines": {
"node": ">=4"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/path-type#readme",
"keywords": [
"path",
"fs",
"type",
"is",
"check",
"directory",
"dir",
"file",
"filepath",
"symlink",
"symbolic",
"link",
"stat",
"stats",
"filesystem"
],
"license": "MIT",
"name": "path-type",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/path-type.git"
},
"scripts": {
"test": "xo && ava"
},
"version": "2.0.0",
"xo": {
"esnext": true
}
}
@@ -0,0 +1,42 @@
# path-type [![Build Status](https://travis-ci.org/sindresorhus/path-type.svg?branch=master)](https://travis-ci.org/sindresorhus/path-type)
> Check if a path is a file, directory, or symlink
## Install
```
$ npm install --save path-type
```
## Usage
```js
const pathType = require('path-type');
pathType.file('package.json').then(isFile => {
console.log(isFile);
//=> true
})
```
## API
### .file(path)
### .dir(path)
### .symlink(path)
Returns a `Promise` for a `boolean` of whether the path is the checked type.
### .fileSync(path)
### .dirSync(path)
### .symlinkSync(path)
Returns a `boolean` of whether the path is the checked type.
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)
@@ -0,0 +1,84 @@
'use strict';
const processFn = (fn, opts) => function () {
const P = opts.promiseModule;
const args = new Array(arguments.length);
for (let i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
return new P((resolve, reject) => {
if (opts.errorFirst) {
args.push(function (err, result) {
if (opts.multiArgs) {
const results = new Array(arguments.length - 1);
for (let i = 1; i < arguments.length; i++) {
results[i - 1] = arguments[i];
}
if (err) {
results.unshift(err);
reject(results);
} else {
resolve(results);
}
} else if (err) {
reject(err);
} else {
resolve(result);
}
});
} else {
args.push(function (result) {
if (opts.multiArgs) {
const results = new Array(arguments.length - 1);
for (let i = 0; i < arguments.length; i++) {
results[i] = arguments[i];
}
resolve(results);
} else {
resolve(result);
}
});
}
fn.apply(this, args);
});
};
module.exports = (obj, opts) => {
opts = Object.assign({
exclude: [/.+(Sync|Stream)$/],
errorFirst: true,
promiseModule: Promise
}, opts);
const filter = key => {
const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key);
return opts.include ? opts.include.some(match) : !opts.exclude.some(match);
};
let ret;
if (typeof obj === 'function') {
ret = function () {
if (opts.excludeMain) {
return obj.apply(this, arguments);
}
return processFn(obj, opts).apply(this, arguments);
};
} else {
ret = Object.create(Object.getPrototypeOf(obj));
}
for (const key in obj) { // eslint-disable-line guard-for-in
const x = obj[key];
ret[key] = typeof x === 'function' && filter(key) ? processFn(x, opts) : x;
}
return ret;
};
@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,83 @@
{
"_from": "pify@^3.0.0",
"_id": "pify@3.0.0",
"_inBundle": false,
"_integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
"_location": "/alfred-mvns/alfred-notifier/pify",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "pify@^3.0.0",
"name": "pify",
"escapedName": "pify",
"rawSpec": "^3.0.0",
"saveSpec": null,
"fetchSpec": "^3.0.0"
},
"_requiredBy": [
"/alfred-mvns/alfred-notifier"
],
"_resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
"_shasum": "e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176",
"_spec": "pify@^3.0.0",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/alfred-notifier",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/pify/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Promisify a callback-style function",
"devDependencies": {
"ava": "*",
"pinkie-promise": "^2.0.0",
"v8-natives": "^1.0.0",
"xo": "*"
},
"engines": {
"node": ">=4"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/pify#readme",
"keywords": [
"promise",
"promises",
"promisify",
"all",
"denodify",
"denodeify",
"callback",
"cb",
"node",
"then",
"thenify",
"convert",
"transform",
"wrap",
"wrapper",
"bind",
"to",
"async",
"await",
"es2015",
"bluebird"
],
"license": "MIT",
"name": "pify",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/pify.git"
},
"scripts": {
"optimization-test": "node --allow-natives-syntax optimization-test.js",
"test": "xo && ava && npm run optimization-test"
},
"version": "3.0.0"
}
@@ -0,0 +1,131 @@
# pify [![Build Status](https://travis-ci.org/sindresorhus/pify.svg?branch=master)](https://travis-ci.org/sindresorhus/pify)
> Promisify a callback-style function
## Install
```
$ npm install --save pify
```
## Usage
```js
const fs = require('fs');
const pify = require('pify');
// Promisify a single function
pify(fs.readFile)('package.json', 'utf8').then(data => {
console.log(JSON.parse(data).name);
//=> 'pify'
});
// Promisify all methods in a module
pify(fs).readFile('package.json', 'utf8').then(data => {
console.log(JSON.parse(data).name);
//=> 'pify'
});
```
## API
### pify(input, [options])
Returns a `Promise` wrapped version of the supplied function or module.
#### input
Type: `Function` `Object`
Callback-style function or module whose methods you want to promisify.
#### options
##### multiArgs
Type: `boolean`<br>
Default: `false`
By default, the promisified function will only return the second argument from the callback, which works fine for most APIs. This option can be useful for modules like `request` that return multiple arguments. Turning this on will make it return an array of all arguments from the callback, excluding the error argument, instead of just the second argument. This also applies to rejections, where it returns an array of all the callback arguments, including the error.
```js
const request = require('request');
const pify = require('pify');
pify(request, {multiArgs: true})('https://sindresorhus.com').then(result => {
const [httpResponse, body] = result;
});
```
##### include
Type: `string[]` `RegExp[]`
Methods in a module to promisify. Remaining methods will be left untouched.
##### exclude
Type: `string[]` `RegExp[]`<br>
Default: `[/.+(Sync|Stream)$/]`
Methods in a module **not** to promisify. Methods with names ending with `'Sync'` are excluded by default.
##### excludeMain
Type: `boolean`<br>
Default: `false`
If given module is a function itself, it will be promisified. Turn this option on if you want to promisify only methods of the module.
```js
const pify = require('pify');
function fn() {
return true;
}
fn.method = (data, callback) => {
setImmediate(() => {
callback(null, data);
});
};
// Promisify methods but not `fn()`
const promiseFn = pify(fn, {excludeMain: true});
if (promiseFn()) {
promiseFn.method('hi').then(data => {
console.log(data);
});
}
```
##### errorFirst
Type: `boolean`<br>
Default: `true`
Whether the callback has an error as the first argument. You'll want to set this to `false` if you're dealing with an API that doesn't have an error as the first argument, like `fs.exists()`, some browser APIs, Chrome Extension APIs, etc.
##### promiseModule
Type: `Function`
Custom promise module to use instead of the native one.
Check out [`pinkie-promise`](https://github.com/floatdrop/pinkie-promise) if you need a tiny promise polyfill.
## Related
- [p-event](https://github.com/sindresorhus/p-event) - Promisify an event by waiting for it to be emitted
- [p-map](https://github.com/sindresorhus/p-map) - Map over promises concurrently
- [More…](https://github.com/sindresorhus/promise-fun)
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)
@@ -0,0 +1,47 @@
'use strict';
const path = require('path');
const loadJsonFile = require('load-json-file');
const pathType = require('path-type');
module.exports = (fp, opts) => {
if (typeof fp !== 'string') {
opts = fp;
fp = '.';
}
opts = opts || {};
return pathType.dir(fp)
.then(isDir => {
if (isDir) {
fp = path.join(fp, 'package.json');
}
return loadJsonFile(fp);
})
.then(x => {
if (opts.normalize !== false) {
require('normalize-package-data')(x);
}
return x;
});
};
module.exports.sync = (fp, opts) => {
if (typeof fp !== 'string') {
opts = fp;
fp = '.';
}
opts = opts || {};
fp = pathType.dirSync(fp) ? path.join(fp, 'package.json') : fp;
const x = loadJsonFile.sync(fp);
if (opts.normalize !== false) {
require('normalize-package-data')(x);
}
return x;
};
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,77 @@
{
"_from": "read-pkg@^2.0.0",
"_id": "read-pkg@2.0.0",
"_inBundle": false,
"_integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
"_location": "/alfred-mvns/alfred-notifier/read-pkg",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "read-pkg@^2.0.0",
"name": "read-pkg",
"escapedName": "read-pkg",
"rawSpec": "^2.0.0",
"saveSpec": null,
"fetchSpec": "^2.0.0"
},
"_requiredBy": [
"/alfred-mvns/alfred-notifier"
],
"_resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
"_shasum": "8ef1c0623c6a6db0dc6713c4bfac46332b2368f8",
"_spec": "read-pkg@^2.0.0",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/alfred-notifier",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/read-pkg/issues"
},
"bundleDependencies": false,
"dependencies": {
"load-json-file": "^2.0.0",
"normalize-package-data": "^2.3.2",
"path-type": "^2.0.0"
},
"deprecated": false,
"description": "Read a package.json file",
"devDependencies": {
"ava": "*",
"xo": "*"
},
"engines": {
"node": ">=4"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/read-pkg#readme",
"keywords": [
"json",
"read",
"parse",
"file",
"fs",
"graceful",
"load",
"pkg",
"package",
"normalize"
],
"license": "MIT",
"name": "read-pkg",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/read-pkg.git"
},
"scripts": {
"test": "xo && ava"
},
"version": "2.0.0",
"xo": {
"esnext": true
}
}
@@ -0,0 +1,79 @@
# read-pkg [![Build Status](https://travis-ci.org/sindresorhus/read-pkg.svg?branch=master)](https://travis-ci.org/sindresorhus/read-pkg)
> Read a package.json file
## Why
- [Gracefully handles filesystem issues](https://github.com/isaacs/node-graceful-fs)
- [Strips UTF-8 BOM](https://github.com/sindresorhus/strip-bom)
- [Throws more helpful JSON errors](https://github.com/sindresorhus/parse-json)
- [Normalizes the data](https://github.com/npm/normalize-package-data#what-normalization-currently-entails)
## Install
```
$ npm install --save read-pkg
```
## Usage
```js
const readPkg = require('read-pkg');
readPkg().then(pkg => {
console.log(pkg);
//=> {name: 'read-pkg', ...}
});
readPkg(__dirname).then(pkg => {
console.log(pkg);
//=> {name: 'read-pkg', ...}
});
readPkg(path.join('unicorn', 'package.json')).then(pkg => {
console.log(pkg);
//=> {name: 'read-pkg', ...}
});
```
## API
### readPkg([path], [options])
Returns a `Promise` for the parsed JSON.
### readPkg.sync([path], [options])
Returns the parsed JSON.
#### path
Type: `string`<br>
Default: `.`
Path to a `package.json` file or its directory.
#### options
##### normalize
Type: `boolean`<br>
Default: `true`
[Normalize](https://github.com/npm/normalize-package-data#what-normalization-currently-entails) the package data.
## Related
- [read-pkg-up](https://github.com/sindresorhus/read-pkg-up) - Read the closest package.json file
- [write-pkg](https://github.com/sindresorhus/write-pkg) - Write a `package.json` file
- [load-json-file](https://github.com/sindresorhus/load-json-file) - Read and parse a JSON file
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)
@@ -0,0 +1,14 @@
'use strict';
module.exports = x => {
if (typeof x !== 'string') {
throw new TypeError('Expected a string, got ' + typeof x);
}
// Catches EFBBBF (UTF-8 BOM) because the buffer-to-string
// conversion translates it to FEFF (UTF-16 BOM)
if (x.charCodeAt(0) === 0xFEFF) {
return x.slice(1);
}
return x;
};
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,72 @@
{
"_from": "strip-bom@^3.0.0",
"_id": "strip-bom@3.0.0",
"_inBundle": false,
"_integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
"_location": "/alfred-mvns/alfred-notifier/strip-bom",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "strip-bom@^3.0.0",
"name": "strip-bom",
"escapedName": "strip-bom",
"rawSpec": "^3.0.0",
"saveSpec": null,
"fetchSpec": "^3.0.0"
},
"_requiredBy": [
"/alfred-mvns/alfred-notifier/load-json-file"
],
"_resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
"_shasum": "2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3",
"_spec": "strip-bom@^3.0.0",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/alfred-notifier/node_modules/load-json-file",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/strip-bom/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Strip UTF-8 byte order mark (BOM) from a string",
"devDependencies": {
"ava": "*",
"xo": "*"
},
"engines": {
"node": ">=4"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/strip-bom#readme",
"keywords": [
"strip",
"bom",
"byte",
"order",
"mark",
"unicode",
"utf8",
"utf-8",
"remove",
"delete",
"trim",
"text",
"string"
],
"license": "MIT",
"name": "strip-bom",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/strip-bom.git"
},
"scripts": {
"test": "xo && ava"
},
"version": "3.0.0"
}
@@ -0,0 +1,36 @@
# strip-bom [![Build Status](https://travis-ci.org/sindresorhus/strip-bom.svg?branch=master)](https://travis-ci.org/sindresorhus/strip-bom)
> Strip UTF-8 [byte order mark](http://en.wikipedia.org/wiki/Byte_order_mark#UTF-8) (BOM) from a string
From Wikipedia:
> The Unicode Standard permits the BOM in UTF-8, but does not require nor recommend its use. Byte order has no meaning in UTF-8.
## Install
```
$ npm install --save strip-bom
```
## Usage
```js
const stripBom = require('strip-bom');
stripBom('\uFEFFunicorn');
//=> 'unicorn'
```
## Related
- [strip-bom-cli](https://github.com/sindresorhus/strip-bom-cli) - CLI for this module
- [strip-bom-buf](https://github.com/sindresorhus/strip-bom-buf) - Buffer version of this module
- [strip-bom-stream](https://github.com/sindresorhus/strip-bom-stream) - Stream version of this module
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)
@@ -0,0 +1,100 @@
{
"_from": "alfred-notifier@^0.2.0",
"_id": "alfred-notifier@0.2.3",
"_inBundle": false,
"_integrity": "sha512-RB03gRcGKPxiby+1zijbUQslRNfX1uhFCtsudmGd/gaVnTShByAfAKIL+uKNU6VngXjpqCQmeAyUIxdWbsZaAw==",
"_location": "/alfred-mvns/alfred-notifier",
"_phantomChildren": {
"cross-spawn": "5.1.0",
"dot-prop": "4.2.0",
"env-paths": "1.0.0",
"get-stream": "3.0.0",
"graceful-fs": "4.1.11",
"is-stream": "1.1.0",
"mkdirp": "0.5.1",
"normalize-package-data": "2.4.0",
"npm-run-path": "2.0.2",
"p-finally": "1.0.0",
"parse-json": "2.2.0",
"pkg-up": "1.0.0",
"signal-exit": "3.0.2",
"strip-eof": "1.0.0"
},
"_requested": {
"type": "range",
"registry": true,
"raw": "alfred-notifier@^0.2.0",
"name": "alfred-notifier",
"escapedName": "alfred-notifier",
"rawSpec": "^0.2.0",
"saveSpec": null,
"fetchSpec": "^0.2.0"
},
"_requiredBy": [
"/alfred-mvns/alfy"
],
"_resolved": "https://registry.npmjs.org/alfred-notifier/-/alfred-notifier-0.2.3.tgz",
"_shasum": "678816641fff03b0fe0a03f14630a778c057b399",
"_spec": "alfred-notifier@^0.2.0",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/alfy",
"author": {
"name": "Sam Verschueren",
"email": "sam.verschueren@gmail.com",
"url": "github.com/SamVerschueren"
},
"bugs": {
"url": "https://github.com/SamVerschueren/alfred-notifier/issues"
},
"bundleDependencies": false,
"dependencies": {
"cache-conf": "^0.5.0",
"execa": "^0.8.0",
"latest-version": "^3.1.0",
"pify": "^3.0.0",
"plist": "^2.0.1",
"read-pkg": "^2.0.0",
"semver": "^5.3.0"
},
"deprecated": false,
"description": "Update notifications for your Alfred workflow",
"devDependencies": {
"xo": "*"
},
"engines": {
"node": ">=4"
},
"files": [
"index.js",
"check.js",
"lib"
],
"homepage": "https://github.com/SamVerschueren/alfred-notifier#readme",
"keywords": [
"alfred",
"alfy",
"workflow",
"update",
"updater",
"notify",
"notifier",
"module",
"version"
],
"license": "MIT",
"maintainers": [
{
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
}
],
"name": "alfred-notifier",
"repository": {
"type": "git",
"url": "git+https://github.com/SamVerschueren/alfred-notifier.git"
},
"scripts": {
"test": "xo"
},
"version": "0.2.3"
}
@@ -0,0 +1,50 @@
# alfred-notifier [![Build Status](https://travis-ci.org/SamVerschueren/alfred-notifier.svg?branch=master)](https://travis-ci.org/SamVerschueren/alfred-notifier)
> Update notifications for your [Alfred](https://www.alfredapp.com/) workflow
<img src="screenshot.png">
## Install
```
$ npm install --save alfred-notifier
```
## Usage
### Simple example
```js
const alfredNotifier = require('alfred-notifier');
alfredNotifier();
```
### Comprehensive example
```js
const alfy = require('alfy');
const alfredNotifier = require('alfred-notifier');
// Checks for available update and updates the `info.plist`
alfredNotifier();
alfy.output([
{title: '🦄'},
{title: '🌈'}
]);
```
## API
### alfredNotifier()
Checks if there is an available update. If an update is available, it will add a message as subtext of your workflow.
## License
MIT © [Sam Verschueren](https://github.com/SamVerschueren)
@@ -0,0 +1,11 @@
#!/usr/bin/env node
'use strict';
const execa = require('execa');
const npmRunPath = require('npm-run-path');
const env = npmRunPath.env({cwd: __dirname});
execa('alfred-unlink', {env}).catch(err => {
console.error(err);
process.exit(1);
});
@@ -0,0 +1,164 @@
'use strict';
/* eslint-disable dot-notation */
const os = require('os');
const Conf = require('conf');
const got = require('got');
const hookStd = require('hook-std');
const loudRejection = require('loud-rejection');
const cleanStack = require('clean-stack');
const dotProp = require('dot-prop');
const CacheConf = require('cache-conf');
const updateNotification = require('./lib/update-notification');
const alfy = module.exports;
updateNotification();
const getIcon = name => `/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/${name}.icns`;
const getEnv = key => process.env[`alfred_${key}`];
alfy.meta = {
name: getEnv('workflow_name'),
version: getEnv('workflow_version'),
uid: getEnv('workflow_uid'),
bundleId: getEnv('workflow_bundleid')
};
alfy.alfred = {
version: getEnv('version'),
theme: getEnv('theme'),
themeBackground: getEnv('theme_background'),
themeSelectionBackground: getEnv('theme_selection_background'),
themeSubtext: Number(getEnv('theme_subtext')),
data: getEnv('workflow_data'),
cache: getEnv('workflow_cache'),
preferences: getEnv('preferences'),
preferencesLocalHash: getEnv('preferences_localhash')
};
alfy.input = process.argv[2];
alfy.output = arr => {
console.log(JSON.stringify({items: arr}, null, '\t'));
};
alfy.matches = (input, list, item) => {
input = input.toLowerCase().normalize();
return list.filter(x => {
if (typeof item === 'string') {
x = dotProp.get(x, item);
}
if (typeof x === 'string') {
x = x.toLowerCase();
}
if (typeof item === 'function') {
return item(x, input);
}
return x.includes(input);
});
};
alfy.inputMatches = (list, item) => alfy.matches(alfy.input, list, item);
alfy.log = str => {
if (alfy.debug) {
console.log(str);
}
};
alfy.error = err => {
const stack = cleanStack(err.stack || err);
const copy = `
\`\`\`
${stack}
\`\`\`
-
${alfy.meta.name} ${alfy.meta.version}
Alfred ${alfy.alfred.version}
${process.platform} ${process.arch} ${os.release()}
`.trim();
alfy.output([{
title: err.stack ? `${err.name}: ${err.message}` : err,
subtitle: 'Press ⌘L to see the full error and ⌘C to copy it.',
valid: false,
text: {
copy,
largetype: stack
},
icon: {
path: exports.icon.error
}
}]);
};
alfy.config = new Conf({
cwd: alfy.alfred.data
});
alfy.cache = new CacheConf({
configName: 'cache',
cwd: alfy.alfred.cache,
version: alfy.meta.version
});
alfy.fetch = (url, opts) => {
opts = Object.assign({
json: true
}, opts);
if (typeof url !== 'string') {
return Promise.reject(new TypeError(`Expected \`url\` to be a \`string\`, got \`${typeof url}\``));
}
if (opts.transform && typeof opts.transform !== 'function') {
return Promise.reject(new TypeError(`Expected \`transform\` to be a \`function\`, got \`${typeof opts.transform}\``));
}
const rawKey = url + JSON.stringify(opts);
const key = rawKey.replace(/\./g, '\\.');
const cachedResponse = alfy.cache.store[rawKey] && alfy.cache.store[rawKey].data;
if (cachedResponse && !alfy.cache.isExpired(key)) {
return Promise.resolve(cachedResponse);
}
return got(url, opts)
.then(res => opts.transform ? opts.transform(res.body) : res.body)
.then(data => {
if (opts.maxAge) {
alfy.cache.set(key, data, {maxAge: opts.maxAge});
}
return data;
})
.catch(err => {
if (cachedResponse) {
return cachedResponse;
}
throw err;
});
};
alfy.debug = getEnv('debug') === '1';
alfy.icon = {
get: getIcon,
info: getIcon('ToolbarInfo'),
warning: getIcon('AlertCautionIcon'),
error: getIcon('AlertStopIcon'),
alert: getIcon('Actions'),
like: getIcon('ToolbarFavoritesIcon'),
delete: getIcon('ToolbarDeleteIcon')
};
loudRejection(alfy.error);
process.on('uncaughtException', alfy.error);
hookStd.stderr(alfy.error);
@@ -0,0 +1,11 @@
#!/usr/bin/env node
'use strict';
const execa = require('execa');
const npmRunPath = require('npm-run-path');
const env = npmRunPath.env({cwd: __dirname});
execa('alfred-link', {env}).catch(err => {
console.error(err);
process.exit(1);
});
@@ -0,0 +1,13 @@
'use strict';
const readPkgUp = require('read-pkg-up');
const alfredNotifier = require('alfred-notifier');
module.exports = () => {
readPkgUp().then(result => {
const alfy = result.pkg.alfy || {};
if (alfy.updateNotification !== false) {
alfredNotifier();
}
});
};
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,102 @@
{
"_from": "alfy@^0.6.0",
"_id": "alfy@0.6.0",
"_inBundle": false,
"_integrity": "sha1-PB3fA+RLPPmkh3r0vOt6zZaDHXE=",
"_location": "/alfred-mvns/alfy",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "alfy@^0.6.0",
"name": "alfy",
"escapedName": "alfy",
"rawSpec": "^0.6.0",
"saveSpec": null,
"fetchSpec": "^0.6.0"
},
"_requiredBy": [
"/alfred-mvns"
],
"_resolved": "https://registry.npmjs.org/alfy/-/alfy-0.6.0.tgz",
"_shasum": "3c1ddf03e44b3cf9a4877af4bceb7acd96831d71",
"_spec": "alfy@^0.6.0",
"_where": "/usr/local/lib/node_modules/alfred-mvns",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bin": {
"run-node": "run-node.sh",
"alfy-init": "init.js",
"alfy-cleanup": "cleanup.js"
},
"bugs": {
"url": "https://github.com/sindresorhus/alfy/issues"
},
"bundleDependencies": false,
"dependencies": {
"alfred-link": "^0.2.0",
"alfred-notifier": "^0.2.0",
"cache-conf": "^0.3.0",
"clean-stack": "^1.0.0",
"conf": "^0.11.0",
"dot-prop": "^4.0.0",
"execa": "^0.5.0",
"got": "^6.3.0",
"hook-std": "^0.2.0",
"loud-rejection": "^1.6.0",
"npm-run-path": "^2.0.2",
"read-pkg-up": "^1.0.1"
},
"deprecated": false,
"description": "Create Alfred workflows with ease",
"devDependencies": {
"ava": "*",
"delay": "^1.3.1",
"nock": "^8.0.0",
"tempfile": "^1.1.1",
"xo": "*"
},
"engines": {
"node": ">=4"
},
"files": [
"index.js",
"init.js",
"cleanup.js",
"run-node.sh",
"lib"
],
"homepage": "https://github.com/sindresorhus/alfy#readme",
"keywords": [
"alfred",
"app",
"workflow",
"plugin",
"helper",
"util",
"utility",
"macos",
"mac",
"osx"
],
"license": "MIT",
"maintainers": [
{
"name": "Sam Verschueren",
"email": "sam.verschueren@gmail.com",
"url": "github.com/SamVerschueren"
}
],
"name": "alfy",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/alfy.git"
},
"scripts": {
"test": "xo && ava"
},
"version": "0.6.0"
}
@@ -0,0 +1,523 @@
# ![Alfy](https://cdn.rawgit.com/sindresorhus/alfy/4b50f0323dd99eafdd34523dc8de0680be04e049/media/header.svg)
> Create [Alfred workflows](https://www.alfredapp.com/workflows/) with ease
[![Build Status](https://travis-ci.org/sindresorhus/alfy.svg?branch=master)](https://travis-ci.org/sindresorhus/alfy)
## Highlights
- Easy input↔output.
- Config and [cache](#caching) handling built-in.
- Fetching remote files with optional caching.
- Publish your workflow to npm.
- Automatic [update notifications](#update-notifications).
- Easily [testable workflows](#testing).
- [Finds the `node` binary.](run-node.sh)
- Presents uncaught exceptions and unhandled Promise rejections to the user.<br>
*No need to manually `.catch()` top-level promises.*
## Prerequisites
You need [Node.js 4+](https://nodejs.org) and [Alfred 3](https://www.alfredapp.com) with the paid [Powerpack](https://www.alfredapp.com/powerpack/) upgrade.
## Install
```
$ npm install --save alfy
```
## Usage
Create a new Alfred workflow and add a Script Filter with the following script:
```sh
./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](https://github.com/SamVerschueren/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:
```js
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);
});
```
<img src="media/screenshot.png" width="694">
###### More
Some example usage in the wild: [`alfred-npms`](https://github.com/sindresorhus/alfred-npms), [`alfred-emoj`](https://github.com/sindresorhus/alfred-emoj), [`alfred-ng2`](https://github.com/SamVerschueren/alfred-ng2).
## Update notifications
Alfy uses [alfred-notifier](https://github.com/SamVerschueren/alfred-notifier) in the background to show a notification when an update for your workflow is available.
<img src="media/screenshot-update.png" width="694">
## Caching
Alfy offers the possibility of caching data, either with the [fetch](#fetchurl-options) or directly through the [cache](#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.
## Publish to npm
By adding `alfy-init` as `postinstall` and `alfy-cleanup` as `preuninstall` script, you can publish your package to [npm](https://npmjs.org) instead of to [Packal](http://www.packal.org). This way, your packages are only one simple `npm install` command away.
```json
{
"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](https://github.com/samverschueren/alfred-link#infoplist) 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](https://github.com/SamVerschueren/alfred-updater) workflow to do that for you.
## Testing
Workflows can easily be tested with [alfy-test](https://github.com/SamVerschueren/alfy-test). Here is a small example.
```js
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](https://www.alfredapp.com/help/workflows/inputs/script-filter/json/).
Example:
```js
alfy.output([{
title: 'Unicorn'
}, {
title: 'Rainbow'
}]);
```
<img src="media/screenshot-output.png" width="694">
#### matches(input, list, [item])
Returns an `Array` of items in `list` that case-insensitively contains `input`.
```js
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:
```js
const list = [{
title: 'foo'
}, {
title: 'unicorn'
}];
alfy.matches('Unicorn', list, 'title');
//=> [{title: 'unicorn'}]
```
Or [nested property](https://github.com/sindresorhus/dot-prop):
```js
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:
```js
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.
<img src="media/screenshot-error.png" width="694">
#### 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](https://github.com/sindresorhus/got#options).
###### json
Type: `boolean`<br>
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.
```js
alfy.fetch('https://api.foo.com', {
transform: body => {
body.foo = 'bar';
return body;
}
})
```
You can also return a Promise.
```js
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](https://github.com/sindresorhus/conf#instance) with the correct config path set.
Example:
```js
alfy.config.set('unicorn', '🦄');
alfy.config.get('unicorn');
//=> '🦄'
```
#### cache
Type: `Object`
Persist cache data.
Exports a modified [`conf` instance](https://github.com/sindresorhus/conf#instance) with the correct cache path set.
Example:
```js
alfy.cache.set('unicorn', '🦄');
alfy.cache.get('unicorn');
//=> '🦄'
```
##### maxAge
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:
```js
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
```
#### debug
Type: `boolean`
Whether the user currently has the [workflow debugger](https://www.alfredapp.com/help/workflows/advanced/debugger/) open.
#### icon
Type: `Object`<br>
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:
```js
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'
```
#### meta
Type: `Object`
Example:
```js
{
name: 'Emoj',
version: '0.2.5',
uid: 'user.workflow.B0AC54EC-601C-479A-9428-01F9FD732959',
bundleId: 'com.sindresorhus.emoj'
}
```
#### alfred
Type: `Object`
Alfred metadata.
##### version
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.
##### theme
Example: `'alfred.theme.yosemite'`
Current theme used.
##### themeBackground
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.
##### themeSelectionBackground
Example: `'rgba(255,255,255,0.98)'`
The color of the selected result.
##### themeSubtext
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.
##### data
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.
##### cache
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.
##### preferences
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.
##### preferencesLocalHash
Example: `'adbd4f66bc3ae8493832af61a41ee609b20d8705'`
Non-synced local preferences are stored within `Alfred.alfredpreferences` under `…/preferences/local/${preferencesLocalHash}/`.
## Users
*Alfred workflows using Alfy*
- [alfred-emoj](https://github.com/sindresorhus/alfred-emoj) - Find relevant emoji from text
- [alfred-npms](https://github.com/sindresorhus/alfred-npms) - Search for npm packages with npms.io
- [alfred-ng2](https://github.com/SamVerschueren/alfred-ng2) - Search for Angular 2 API references
- [alfred-react-native](https://github.com/ekonstantinidis/alfred-react-native) - Access the React Native documentation
- [alfred-hl](https://github.com/importre/alfred-hl) - Syntax highlight code in the clipboard
- [alfred-workflow-docs-elastic](https://github.com/spinscale/alfred-workflow-elastic-docs) - Search the Elastic.co documentation
- [alfredinary](https://github.com/urre/alfredinary) - Capture screenshots and upload to Cloudinary
## Related
- [alfred-simple](https://github.com/sindresorhus/alfred-simple) - Simple theme for Alfred *(Used in the screenshots)*
- [alfred-updater](https://github.com/SamVerschueren/alfred-updater) - Workflow updater
- [alfred-notifier](https://github.com/SamVerschueren/alfred-notifier) - Update notifications for your workflow
- [generator-alfred](https://github.com/samverschueren/generator-alfred) - Scaffold out an Alfred workflow
## Created by
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Sam Verschueren](https://github.com/SamVerschueren)
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)
@@ -0,0 +1,49 @@
#!/bin/bash
if [[ -z "$alfred_workflow_cache" ]]; then
echo "This script must be called from Alfred, \$alfred_workflow_cache is missing. Make sure a Bundle ID is set."
exit 1
fi
if [[ ! -d "$alfred_workflow_cache" ]]; then
mkdir -p "$alfred_workflow_cache"
fi
PATH_CACHE="$alfred_workflow_cache"/node_path
get_user_path() {
eval $(/usr/libexec/path_helper -s)
echo "$($SHELL -i -l -c 'echo -e "\n"PATH=\"$PATH:\$PATH\""\n"' 2>/dev/null | grep "^PATH=")" > "$PATH_CACHE"
}
set_path() {
if [[ -f "$PATH_CACHE" ]]; then
. "$PATH_CACHE"
else
get_user_path
. "$PATH_CACHE"
fi
export PATH
}
has_node() {
command -v node >/dev/null 2>&1
}
# check if we have node, otherwise inherit path from user shell
if ! has_node; then
set_path
# retry by deleting old path cache
if ! has_node; then
rm "$PATH_CACHE"
set_path
fi
fi
if has_node; then
node "$@"
else
echo $'{"items":[{"title": "Couldn\'t find the `node` binary", "subtitle": "Symlink it to `/usr/local/bin`"}]}'
fi
@@ -0,0 +1,4 @@
'use strict';
module.exports = function () {
return /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]/g;
};
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,109 @@
{
"_from": "ansi-regex@^2.0.0",
"_id": "ansi-regex@2.1.1",
"_inBundle": false,
"_integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"_location": "/alfred-mvns/ansi-regex",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "ansi-regex@^2.0.0",
"name": "ansi-regex",
"escapedName": "ansi-regex",
"rawSpec": "^2.0.0",
"saveSpec": null,
"fetchSpec": "^2.0.0"
},
"_requiredBy": [
"/alfred-mvns/has-ansi",
"/alfred-mvns/strip-ansi"
],
"_resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"_shasum": "c3b33ab5ee360d86e0e628f0468ae7ef27d654df",
"_spec": "ansi-regex@^2.0.0",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/has-ansi",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/chalk/ansi-regex/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Regular expression for matching ANSI escape codes",
"devDependencies": {
"ava": "0.17.0",
"xo": "0.16.0"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js"
],
"homepage": "https://github.com/chalk/ansi-regex#readme",
"keywords": [
"ansi",
"styles",
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"string",
"tty",
"escape",
"formatting",
"rgb",
"256",
"shell",
"xterm",
"command-line",
"text",
"regex",
"regexp",
"re",
"match",
"test",
"find",
"pattern"
],
"license": "MIT",
"maintainers": [
{
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
{
"name": "Joshua Appelman",
"email": "jappelman@xebia.com",
"url": "jbnicolai.com"
},
{
"name": "JD Ballard",
"email": "i.am.qix@gmail.com",
"url": "github.com/qix-"
}
],
"name": "ansi-regex",
"repository": {
"type": "git",
"url": "git+https://github.com/chalk/ansi-regex.git"
},
"scripts": {
"test": "xo && ava --verbose",
"view-supported": "node fixtures/view-codes.js"
},
"version": "2.1.1",
"xo": {
"rules": {
"guard-for-in": 0,
"no-loop-func": 0
}
}
}
@@ -0,0 +1,39 @@
# ansi-regex [![Build Status](https://travis-ci.org/chalk/ansi-regex.svg?branch=master)](https://travis-ci.org/chalk/ansi-regex)
> Regular expression for matching [ANSI escape codes](http://en.wikipedia.org/wiki/ANSI_escape_code)
## Install
```
$ npm install --save ansi-regex
```
## Usage
```js
const ansiRegex = require('ansi-regex');
ansiRegex().test('\u001b[4mcake\u001b[0m');
//=> true
ansiRegex().test('cake');
//=> false
'\u001b[4mcake\u001b[0m'.match(ansiRegex());
//=> ['\u001b[4m', '\u001b[0m']
```
## FAQ
### Why do you test for codes not in the ECMA 48 standard?
Some of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. If I recall correctly, we test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them.
On the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of "interrupts" that can mean different things on certain brands of processors, most of which have been phased out.
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,65 @@
'use strict';
function assembleStyles () {
var styles = {
modifiers: {
reset: [0, 0],
bold: [1, 22], // 21 isn't widely supported and 22 does the same thing
dim: [2, 22],
italic: [3, 23],
underline: [4, 24],
inverse: [7, 27],
hidden: [8, 28],
strikethrough: [9, 29]
},
colors: {
black: [30, 39],
red: [31, 39],
green: [32, 39],
yellow: [33, 39],
blue: [34, 39],
magenta: [35, 39],
cyan: [36, 39],
white: [37, 39],
gray: [90, 39]
},
bgColors: {
bgBlack: [40, 49],
bgRed: [41, 49],
bgGreen: [42, 49],
bgYellow: [43, 49],
bgBlue: [44, 49],
bgMagenta: [45, 49],
bgCyan: [46, 49],
bgWhite: [47, 49]
}
};
// fix humans
styles.colors.grey = styles.colors.gray;
Object.keys(styles).forEach(function (groupName) {
var group = styles[groupName];
Object.keys(group).forEach(function (styleName) {
var style = group[styleName];
styles[styleName] = group[styleName] = {
open: '\u001b[' + style[0] + 'm',
close: '\u001b[' + style[1] + 'm'
};
});
Object.defineProperty(styles, groupName, {
value: group,
enumerable: false
});
});
return styles;
}
Object.defineProperty(module, 'exports', {
enumerable: true,
get: assembleStyles
});
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,90 @@
{
"_from": "ansi-styles@^2.2.1",
"_id": "ansi-styles@2.2.1",
"_inBundle": false,
"_integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
"_location": "/alfred-mvns/ansi-styles",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "ansi-styles@^2.2.1",
"name": "ansi-styles",
"escapedName": "ansi-styles",
"rawSpec": "^2.2.1",
"saveSpec": null,
"fetchSpec": "^2.2.1"
},
"_requiredBy": [
"/alfred-mvns/chalk"
],
"_resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"_shasum": "b432dd3358b634cf75e1e4664368240533c1ddbe",
"_spec": "ansi-styles@^2.2.1",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/chalk",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/chalk/ansi-styles/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "ANSI escape codes for styling strings in the terminal",
"devDependencies": {
"mocha": "*"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js"
],
"homepage": "https://github.com/chalk/ansi-styles#readme",
"keywords": [
"ansi",
"styles",
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"string",
"tty",
"escape",
"formatting",
"rgb",
"256",
"shell",
"xterm",
"log",
"logging",
"command-line",
"text"
],
"license": "MIT",
"maintainers": [
{
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
{
"name": "Joshua Appelman",
"email": "jappelman@xebia.com",
"url": "jbnicolai.com"
}
],
"name": "ansi-styles",
"repository": {
"type": "git",
"url": "git+https://github.com/chalk/ansi-styles.git"
},
"scripts": {
"test": "mocha"
},
"version": "2.2.1"
}
@@ -0,0 +1,86 @@
# ansi-styles [![Build Status](https://travis-ci.org/chalk/ansi-styles.svg?branch=master)](https://travis-ci.org/chalk/ansi-styles)
> [ANSI escape codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) for styling strings in the terminal
You probably want the higher-level [chalk](https://github.com/chalk/chalk) module for styling your strings.
![](screenshot.png)
## Install
```
$ npm install --save ansi-styles
```
## Usage
```js
var ansi = require('ansi-styles');
console.log(ansi.green.open + 'Hello world!' + ansi.green.close);
```
## API
Each style has an `open` and `close` property.
## Styles
### Modifiers
- `reset`
- `bold`
- `dim`
- `italic` *(not widely supported)*
- `underline`
- `inverse`
- `hidden`
- `strikethrough` *(not widely supported)*
### Colors
- `black`
- `red`
- `green`
- `yellow`
- `blue`
- `magenta`
- `cyan`
- `white`
- `gray`
### Background colors
- `bgBlack`
- `bgRed`
- `bgGreen`
- `bgYellow`
- `bgBlue`
- `bgMagenta`
- `bgCyan`
- `bgWhite`
## Advanced usage
By default you get a map of styles, but the styles are also available as groups. They are non-enumerable so they don't show up unless you access them explicitly. This makes it easier to expose only a subset in a higher-level module.
- `ansi.modifiers`
- `ansi.colors`
- `ansi.bgColors`
###### Example
```js
console.log(ansi.colors.green.open);
```
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,25 @@
'use strict';
module.exports = function (arr, predicate, ctx) {
if (typeof Array.prototype.findIndex === 'function') {
return arr.findIndex(predicate, ctx);
}
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
var list = Object(arr);
var len = list.length;
if (len === 0) {
return -1;
}
for (var i = 0; i < len; i++) {
if (predicate.call(ctx, list[i], i, list)) {
return i;
}
}
return -1;
};
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,67 @@
{
"_from": "array-find-index@^1.0.1",
"_id": "array-find-index@1.0.2",
"_inBundle": false,
"_integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
"_location": "/alfred-mvns/array-find-index",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "array-find-index@^1.0.1",
"name": "array-find-index",
"escapedName": "array-find-index",
"rawSpec": "^1.0.1",
"saveSpec": null,
"fetchSpec": "^1.0.1"
},
"_requiredBy": [
"/alfred-mvns/currently-unhandled"
],
"_resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
"_shasum": "df010aa1287e164bbda6f9723b0a96a1ec4187a1",
"_spec": "array-find-index@^1.0.1",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/currently-unhandled",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/array-find-index/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "ES2015 `Array#findIndex()` ponyfill",
"devDependencies": {
"ava": "*",
"xo": "*"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/array-find-index#readme",
"keywords": [
"es2015",
"ponyfill",
"polyfill",
"shim",
"find",
"index",
"findindex",
"array"
],
"license": "MIT",
"name": "array-find-index",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/array-find-index.git"
},
"scripts": {
"test": "xo && ava"
},
"version": "1.0.2"
}
@@ -0,0 +1,30 @@
# array-find-index [![Build Status](https://travis-ci.org/sindresorhus/array-find-index.svg?branch=master)](https://travis-ci.org/sindresorhus/array-find-index)
> ES2015 [`Array#findIndex()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex) [ponyfill](https://ponyfill.com)
## Install
```
$ npm install --save array-find-index
```
## Usage
```js
const arrayFindIndex = require('array-find-index');
arrayFindIndex(['rainbow', 'unicorn', 'pony'], x => x === 'unicorn');
//=> 1
```
## API
Same as `Array#findIndex()`, but with the input array as the first argument.
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)
@@ -0,0 +1,6 @@
'use strict';
var arrayUniq = require('array-uniq');
module.exports = function () {
return arrayUniq([].concat.apply([], arguments));
};
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,72 @@
{
"_from": "array-union@^1.0.1",
"_id": "array-union@1.0.2",
"_inBundle": false,
"_integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
"_location": "/alfred-mvns/array-union",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "array-union@^1.0.1",
"name": "array-union",
"escapedName": "array-union",
"rawSpec": "^1.0.1",
"saveSpec": null,
"fetchSpec": "^1.0.1"
},
"_requiredBy": [
"/alfred-mvns/globby"
],
"_resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
"_shasum": "9a34410e4f4e3da23dea375be5be70f24778ec39",
"_spec": "array-union@^1.0.1",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/globby",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/array-union/issues"
},
"bundleDependencies": false,
"dependencies": {
"array-uniq": "^1.0.1"
},
"deprecated": false,
"description": "Create an array of unique values, in order, from the input arrays",
"devDependencies": {
"ava": "*",
"xo": "*"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/array-union#readme",
"keywords": [
"array",
"arr",
"set",
"uniq",
"unique",
"duplicate",
"remove",
"union",
"combine",
"merge"
],
"license": "MIT",
"name": "array-union",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/array-union.git"
},
"scripts": {
"test": "xo && ava"
},
"version": "1.0.2"
}
@@ -0,0 +1,28 @@
# array-union [![Build Status](https://travis-ci.org/sindresorhus/array-union.svg?branch=master)](https://travis-ci.org/sindresorhus/array-union)
> Create an array of unique values, in order, from the input arrays
## Install
```
$ npm install --save array-union
```
## Usage
```js
const arrayUnion = require('array-union');
arrayUnion([1, 1, 2, 3], [2, 3]);
//=> [1, 2, 3]
arrayUnion(['foo', 'foo', 'bar'], ['foo']);
//=> ['foo', 'bar']
```
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)
@@ -0,0 +1,62 @@
'use strict';
// there's 3 implementations written in increasing order of efficiency
// 1 - no Set type is defined
function uniqNoSet(arr) {
var ret = [];
for (var i = 0; i < arr.length; i++) {
if (ret.indexOf(arr[i]) === -1) {
ret.push(arr[i]);
}
}
return ret;
}
// 2 - a simple Set type is defined
function uniqSet(arr) {
var seen = new Set();
return arr.filter(function (el) {
if (!seen.has(el)) {
seen.add(el);
return true;
}
return false;
});
}
// 3 - a standard Set type is defined and it has a forEach method
function uniqSetWithForEach(arr) {
var ret = [];
(new Set(arr)).forEach(function (el) {
ret.push(el);
});
return ret;
}
// V8 currently has a broken implementation
// https://github.com/joyent/node/issues/8449
function doesForEachActuallyWork() {
var ret = false;
(new Set([true])).forEach(function (el) {
ret = el;
});
return ret === true;
}
if ('Set' in global) {
if (typeof Set.prototype.forEach === 'function' && doesForEachActuallyWork()) {
module.exports = uniqSetWithForEach;
} else {
module.exports = uniqSet;
}
} else {
module.exports = uniqNoSet;
}
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,69 @@
{
"_from": "array-uniq@^1.0.1",
"_id": "array-uniq@1.0.3",
"_inBundle": false,
"_integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
"_location": "/alfred-mvns/array-uniq",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "array-uniq@^1.0.1",
"name": "array-uniq",
"escapedName": "array-uniq",
"rawSpec": "^1.0.1",
"saveSpec": null,
"fetchSpec": "^1.0.1"
},
"_requiredBy": [
"/alfred-mvns/array-union"
],
"_resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
"_shasum": "af6ac877a25cc7f74e058894753858dfdb24fdb6",
"_spec": "array-uniq@^1.0.1",
"_where": "/usr/local/lib/node_modules/alfred-mvns/node_modules/array-union",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/array-uniq/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Create an array without duplicates",
"devDependencies": {
"ava": "*",
"es6-set": "^0.1.0",
"require-uncached": "^1.0.2",
"xo": "*"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/array-uniq#readme",
"keywords": [
"array",
"arr",
"set",
"uniq",
"unique",
"es6",
"duplicate",
"remove"
],
"license": "MIT",
"name": "array-uniq",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/array-uniq.git"
},
"scripts": {
"test": "xo && ava"
},
"version": "1.0.3"
}

Some files were not shown because too many files have changed in this diff Show More