Issues (23)

src/boilerplate.js (2 issues)

1
import fs from 'fs';
2
import path from 'path';
3
import process from 'process';
4
import { all, promisify, reject } from 'bluebird';
5
import {
6
    T,
7
    append,
8
    cond,
9
    dropWhile,
10
    equals,
11
    flatten,
12
    join,
13
    juxt,
14
    last,
15
    map,
16
    merge,
17
    pick,
18
    prop,
19
    replace,
20
    split,
21
    startsWith
22
} from 'ramda';
23
import semver from 'semver';
24
import superagent from 'superagent';
25
import inquirer from 'inquirer';
26
import { emitSuccess } from './input';
27
28
const request = superagent.agent();
29
const createFolder = promisify(fs.mkdir);
30
const createFile = promisify(fs.writeFile);
31
32
/**
33
 * Formats a formatted String
34
 *
35
 * @param {String} source
36
 * @return {String}
37
 */
38
const format = replace(/\n {8}/g, '\n')
39
    & dropWhile(equals('\n'))
40
    & append('\n')
41
    & join('');
42
43
/**
44
 * Returns the default name for the project according to the OS
45
 *
46
 * @param {String} directory
47
 * @return {String}
48
 */
49
const getDefaultName = cond([
50
    [~startsWith('win32', process.platform), split('\\')],
51
    [T, split('/')]
52
]) & last;
53
54
/**
55
 * Generate the answers from the stdin.
56
 *
57
 * @return {Promise}
58
 */
59
function askQuestions() {
60
    return request.get('https://app.rung.com.br/api/categories')
61
        .then(prop('body') & map(({ name, alias: value }) => ({ name, value })))
0 ignored issues
show
The variable value seems to be never declared. If this is a global, consider adding a /** global: value */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
The parameter alias is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
62
        .catch(~[{ name: 'Miscellaneous', value: 'miscellaneous' }])
63
        .then(categories => [
64
            { name: 'name', message: 'Project name', default: getDefaultName(process.cwd()) },
65
            { name: 'version', message: 'Version', default: '1.0.0', validate: semver.valid & Boolean },
66
            { name: 'title', message: 'Title', default: 'Untitled' },
67
            { name: 'description', message: 'Description' },
68
            { name: 'category', type: 'list', message: 'Category', default: 'miscellaneous', choices: categories },
69
            { name: 'license', message: 'license', default: 'MIT' }
70
        ])
71
        .then(inquirer.createPromptModule());
72
}
73
74
/**
75
 * Creates the folder for the boilerplate based on package name. If the folder
76
 * already exists, throw an error
77
 * Queria estar morta
78
 *
79
 * @param {Object} answers
80
 * @return {Promise}
81
 */
82
function createBoilerplateFolder(answers) {
83
    return createFolder(answers.name)
84
        .tap(createFolder(`${answers.name}/info`))
85
        .catch(~reject(new Error(`Unable to create folder ${answers.name}`)))
86
        .return(answers);
87
}
88
89
/**
90
 * Returns an object in the format { filename :: String, content :: String }
91
 * containing meta-informations about the file
92
 *
93
 * @param {Object} answers
94
 * @return {Object}
95
 */
96
function getPackageMetaFile(answers) {
97
    const packageFields = ['name', 'version', 'license', 'category'];
98
    const packageObject = merge(pick(packageFields, answers),
99
        { dependencies: { 'rung-cli': '1.0.0' } });
100
101
    return {
102
        filename: path.join(answers.name, 'package.json'),
103
        content: JSON.stringify(packageObject, null, 2)
104
    };
105
}
106
107
/**
108
 * Content about README.md file
109
 *
110
 * @param {Object} answers
111
 * @return {Object}
112
 */
113
function getReadMeMetaFile(answers) {
114
    const content = format(`
115
        # Rung ─ ${answers.title}
116
117
        # Development
118
119
        - Use \`yarn\` to install the dependencies
120
        - Use \`rung run\` to start the CLI wizard
121
    `);
122
123
    return { filename: path.join(answers.name, 'README.md'), content };
124
}
125
126
/**
127
 * Content about info files
128
 *
129
 * @param {Object} answers
130
 * @return {Object}
131
 */
132
function getInfoFiles(answers) {
133
    const locales = ['en', 'es', 'pt_BR'];
134
    return locales
135
        | map(locale => ({ filename: path.join(answers.name, `info/${locale}.md`), content: '' }));
136
}
137
138
/**
139
 * Content about index.js file
140
 *
141
 * @param {Object} answers
142
 * @return {Object}
143
 */
144
function getIndexFile(answers) {
145
    const content = format(`
146
        import { create } from 'rung-sdk';
147
        import { String as Text } from 'rung-cli/dist/types';
148
149
        function render(name) {
150
            return <b>{ _('Hello {{name}}', { name }) }</b>;
151
        }
152
153
        function main(context) {
154
            const { name } = context.params;
155
            return {
156
                alerts: [{
157
                    title: _('Welcome'),
158
                    content: render(name),
159
                    resources: []
160
                }]
161
            };
162
        }
163
164
        const params = {
165
            name: {
166
                description: _('What is your name?'),
167
                type: Text
168
            }
169
        };
170
171
        export default create(main, {
172
            params,
173
            primaryKey: true,
174
            title: _(${JSON.stringify(answers.title)}),
175
            description: _(${JSON.stringify(answers.description)}),
176
            preview: render('Trixie')
177
        });
178
    `);
179
180
    return { filename: path.join(answers.name, 'index.js'), content };
181
}
182
183
/**
184
 * Creates a boilerplate project
185
 *
186
 * @return {Promise}
187
 */
188
export default function boilerplate() {
189
    return askQuestions()
190
        .then(createBoilerplateFolder)
191
        .then(juxt([getPackageMetaFile, getReadMeMetaFile, getIndexFile, getInfoFiles]))
192
        .then(flatten)
193
        .then(map(({ filename, content }) => createFile(filename, content)) & all)
194
        .then(~emitSuccess('project generated'));
195
}
196