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