Issues (23)

src/boilerplate.js (1 issue)

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...
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