1 | import fs from 'fs'; |
||
2 | import path from 'path'; |
||
3 | import Promise, { all, promisify } from 'bluebird'; |
||
4 | import agent from 'superagent'; |
||
5 | import promisifyAgent from 'superagent-promise'; |
||
6 | import R, { |
||
7 | fromPairs, |
||
8 | is, |
||
9 | take, |
||
10 | test |
||
11 | } from 'ramda'; |
||
12 | import { compileES6 } from './compiler'; |
||
13 | import { runInBrowser } from './vm'; |
||
14 | |||
15 | const readFile = promisify(fs.readFile); |
||
16 | const directory = promisify(fs.readdir); |
||
17 | |||
18 | const lib = { |
||
19 | request: promisifyAgent(agent, Promise), |
||
20 | ramda: R |
||
21 | }; |
||
22 | |||
23 | /** |
||
24 | * Converts a string to a native JS closure |
||
25 | * |
||
26 | * @param {String} code |
||
27 | * @return {*} |
||
28 | */ |
||
29 | export const stringToClosure = compileES6 & runInBrowser({ module: {}, exports: {} }); |
||
30 | |||
31 | /** |
||
32 | * Adapts the user provided closure to Inquirer style. If the user provides |
||
33 | * a 2+ arguments closure, it has a done callback; otherwise expect to be a |
||
34 | * promise. If a promise is not provided, it is an error |
||
35 | * |
||
36 | * @param {String} name |
||
37 | * @param {String} source |
||
38 | * @return {(Object, String) -> Promise} |
||
39 | */ |
||
40 | export function compileClosure(name, source) { |
||
41 | const functor = stringToClosure(source); |
||
42 | if (!is(Function, functor)) { |
||
43 | throw new TypeError(`autocomplete/${name}.js must export a function`); |
||
44 | } |
||
45 | |||
46 | return (params, input) => new Promise(resolve => { |
||
47 | const context = { params, input: input || '', lib }; |
||
48 | if (functor.length < 2) { |
||
49 | return resolve(functor(context)); |
||
50 | } |
||
51 | |||
52 | functor(context, resolve); |
||
0 ignored issues
–
show
Best Practice
introduced
by
![]() |
|||
53 | }); |
||
54 | } |
||
55 | |||
56 | /** |
||
57 | * Reads all the autocomplete sources and returns an object containing the |
||
58 | * name of the parameter as key and the source as value |
||
59 | * |
||
60 | * @return {Promise} |
||
61 | */ |
||
62 | export default ~directory('./autocomplete/') |
||
63 | .catch({ code: 'ENOENT' }, ~[]) |
||
64 | .filter(test(/^.*\.js$/)) |
||
65 | .map(file => all([ |
||
66 | take(file.length - 3, file), |
||
67 | readFile(path.join('autocomplete', file), 'utf-8')])) |
||
68 | .then(fromPairs); |
||
69 |