1 | import inquirer = require('inquirer');
|
2 | import * as path from 'path';
|
3 | import * as jsonfile from 'jsonfile';
|
4 | import * as _ from 'lodash';
|
5 | import * as async from 'async';
|
6 | import * as fs from 'fs';
|
7 | import * as shelljs from 'shelljs';
|
8 | import * as ejs from 'ejs';
|
9 | import {default as chalk} from 'chalk';
|
10 | let simpleGit = require('simple-git/promise');
|
11 |
|
12 | export class ExtLB {
|
13 | logo: string = chalk.green(` (
|
14 | ) )\\ ) (
|
15 | ( ) ( /((()/( ( )\\
|
16 | )\\ ( /( )\\())/(_)))((_)
|
17 | ((_) )\\())(_))/(_)) ((_)_
|
18 | | __|((_)\\ | |_ | | | _ )
|
19 | | _| \\ \\ / | _|| |__ | _ \\
|
20 | |___|/_\\_\\ \\__||____||___/ `);
|
21 | versions: string[] = ['v1'];
|
22 | authentication: object[] = [{name: 'User', value: 'users'},{name: 'Accounts', value: 'accounts'}];
|
23 | platforms: object[] = [{name:'desktop', checked: true}, {name:'phone'}];
|
24 | features: object[] = [
|
25 | new inquirer.Separator('ExtLoop Features'), {
|
26 | name: 'Browserify',
|
27 | value: 'browserify',
|
28 | checked: true
|
29 | }, {
|
30 | name: 'Socket.IO',
|
31 | value: 'socketio',
|
32 | checked: true
|
33 | }, {
|
34 | name: 'Authentication',
|
35 | value: 'auth',
|
36 | checked: true
|
37 | }, {
|
38 | name: 'Queues',
|
39 | value: 'queues'
|
40 | }, new inquirer.Separator('ExtLoop Perspectives'), {
|
41 | name: 'Admin',
|
42 | value: 'perspective-admin',
|
43 | checked: true
|
44 | }, {
|
45 | name: 'Auth',
|
46 | value: 'perspective-auth',
|
47 | checked: true
|
48 | }, {
|
49 | name: 'Error',
|
50 | value: 'perspective-error',
|
51 | checked: true
|
52 | }, {
|
53 | name: 'Main',
|
54 | value: 'perspective-main',
|
55 | checked: true
|
56 | }
|
57 | ];
|
58 | models: object[] = [
|
59 | {name: 'Model', value: 'Model'},
|
60 | {name: 'PersistedModel', value: 'PersistedModel'},
|
61 | {name: 'ACL', value: 'ACL'},
|
62 | {name: 'AccessToken', value: 'AccessToken'},
|
63 | {name: 'Application', value: 'Application'},
|
64 | {name: 'Change', value: 'Change'},
|
65 | {name: 'Checkpoint', value: 'Checkpoint'},
|
66 | {name: 'Email', value: 'Email'},
|
67 | {name: 'KeyValueModel', value: 'KeyValueModel'},
|
68 | {name: 'Role', value: 'Role'},
|
69 | {name: 'RoleMapping', value: 'RoleMapping'},
|
70 | {name: 'Scope', value: 'Scope'},
|
71 | {name: 'User', value: 'User'},
|
72 | {name: '(custom)', value: 'custom'}
|
73 | ];
|
74 | constructor() {
|
75 | }
|
76 | static checkAvailable(dir: string): boolean {
|
77 | return !shelljs.test('-e', path.join(dir, 'package.json'));
|
78 | }
|
79 | createApp(options: { name: string, camelName: string, snakeName: string, capitalName: string, description: string, version: string, authType: string, platforms: [string], features: [string]}) {
|
80 | console.log('Creating Application', options);
|
81 | if (ExtLB.checkAvailable(process.cwd())) {
|
82 | process.stdout.write(chalk.keyword('limegreen')('Retrieving application template '));
|
83 | simpleGit().clone('https://gitlab.com/ExtLB/app-template.git', '.').then(() => {
|
84 | process.stdout.write(chalk.keyword('limegreen')(' done!\n'));
|
85 | shelljs.rm('-fr', '.git');
|
86 | if (!_.includes(options.platforms, 'desktop')) {
|
87 | shelljs.rm('-fr', ['config/client/desktop.json', 'resources/moderndesktop', 'app/desktop']);
|
88 | }
|
89 | if (!_.includes(options.platforms, 'phone')) {
|
90 | shelljs.rm('-fr', ['config/client/phone.json', 'resources/modernphone', 'app/phone']);
|
91 | }
|
92 | let modifications: any = {};
|
93 | _.filter(shelljs.ls(`${__dirname}${path.sep}app${path.sep}*.ts`), (file) => {
|
94 | return !_.endsWith(file, '.d.ts');
|
95 | }).map((file) => {
|
96 | return file.substr(0, file.length - 3);
|
97 | }).forEach((changer) => {
|
98 | modifications[changer] = require(`${changer}`).default;
|
99 | });
|
100 | let modifiers: any = {};
|
101 | _.each(modifications, (files) => {
|
102 | _.each(files, (changes, file) => {
|
103 | if (_.isUndefined(modifiers[file])) {
|
104 | modifiers[file] = [];
|
105 | }
|
106 | modifiers[file].push(changes);
|
107 | });
|
108 | });
|
109 | process.stdout.write(chalk.keyword('limegreen')(`Modifying ${_.keys(modifiers).length} files `));
|
110 | let files = _.keys(modifiers);
|
111 | _.each(files, (file) => {
|
112 | let content: any = null;
|
113 | if (_.endsWith(file, '.json')) {
|
114 | content = jsonfile.readFileSync(file);
|
115 | } else {
|
116 | content = fs.readFileSync(file, {encoding: 'utf8'});
|
117 | }
|
118 | modifiers[file].forEach((modifier: (options: object, content: any) => object) => {
|
119 | content = modifier(options, content);
|
120 | });
|
121 | process.stdout.write('.');
|
122 | if (_.isNull(content)) {
|
123 | shelljs.rm(file);
|
124 | } else {
|
125 | if (_.endsWith(file, '.json')) {
|
126 | jsonfile.writeFileSync(file, content, {spaces: 2});
|
127 | } else {
|
128 | fs.writeFileSync(file, content, {encoding: 'utf8'});
|
129 | }
|
130 | }
|
131 | });
|
132 | process.stdout.write(chalk.keyword('limegreen')(' done!\n'));
|
133 | console.log(chalk.keyword('limegreen')('Installing/Building Modules (npm install)'));
|
134 | shelljs.exec('npm install', {silent:false}, () => {
|
135 | console.log(chalk.keyword('limegreen')('Modules Installed!'));
|
136 | if (
|
137 | _.includes(options.features, 'perspective-admin') ||
|
138 | _.includes(options.features, 'perspective-auth') ||
|
139 | _.includes(options.features, 'perspective-error') ||
|
140 | _.includes(options.features, 'perspective-main') ||
|
141 | _.includes(options.features, 'auth')
|
142 | ) {
|
143 | let perspectives = _.filter(options.features, (feature) => {
|
144 | return _.startsWith(feature, 'perspective-');
|
145 | }).map((feature) => {
|
146 | return `@extlb/${feature}`;
|
147 | });
|
148 | let installs: async.Dictionary<async.AsyncFunction<{},{}>> = {};
|
149 |
|
150 | if (perspectives.length !== 0) {
|
151 | installs.perspectives = (cb: (err?: {}, result?: {}) => void) => {
|
152 | process.stdout.write(chalk.keyword('limegreen')(`Installing ${perspectives.length} Perspectives `));
|
153 | shelljs.exec(`npm install ${perspectives.join(' ')} -S`, {silent:true}, (err) => {
|
154 | if (err) {
|
155 | console.error(err);
|
156 | cb(err);
|
157 | } else {
|
158 | process.stdout.write(chalk.keyword('limegreen')(' done!\n'));
|
159 | cb();
|
160 | }
|
161 | });
|
162 | };
|
163 | }
|
164 | if (_.includes(options.features, 'auth')) {
|
165 | if (options.authType === 'users') {
|
166 | installs.authentication = (cb: (err?: {}, result?: {}) => void) => {
|
167 | process.stdout.write(chalk.keyword('limegreen')('Installing Authentication Module '));
|
168 | shelljs.exec('npm install @extlb/auth -S', {silent: true}, (err) => {
|
169 | if (err) {
|
170 | console.error(err);
|
171 | cb(err);
|
172 | } else {
|
173 | process.stdout.write(chalk.keyword('limegreen')(' done!\n'));
|
174 | cb();
|
175 | }
|
176 | });
|
177 | };
|
178 | } else if (options.authType === 'accounts') {
|
179 | installs.authentication = (cb: (err?: {}, result?: {}) => void) => {
|
180 | process.stdout.write(chalk.keyword('limegreen')('Installing Accounts Module '));
|
181 | shelljs.exec('npm install @extlb/module-admin-accounts -S', {silent: true}, (err) => {
|
182 | if (err) {
|
183 | console.error(err);
|
184 | cb(err);
|
185 | } else {
|
186 | process.stdout.write(chalk.keyword('limegreen')(' done!\n'));
|
187 | cb();
|
188 | }
|
189 | });
|
190 | };
|
191 | }
|
192 | }
|
193 | installs.grunt = (cb: (err?: {}, result?: {}) => void) => {
|
194 | process.stdout.write(chalk.keyword('limegreen')('Building application '));
|
195 | shelljs.exec('grunt "Build Testing Desktop"', {silent:true}, (err) => {
|
196 | if (err) {
|
197 | console.error(err);
|
198 | cb(err);
|
199 | } else {
|
200 | process.stdout.write(chalk.keyword('limegreen')(' done!\n'));
|
201 | cb();
|
202 | }
|
203 | });
|
204 | };
|
205 | async.series(installs, (err) => {
|
206 | if (err) {
|
207 | console.log(err);
|
208 | } else {
|
209 | console.log(chalk.keyword('limegreen')('Install Completed!'));
|
210 | }
|
211 | });
|
212 | }
|
213 | });
|
214 | }).catch((err: any) => {
|
215 | console.error(err);
|
216 | });
|
217 | } else {
|
218 | console.log(chalk.red('package.json already exists!\n'));
|
219 | }
|
220 |
|
221 | }
|
222 | createModule(options: { name: string, camelName: string, snakeName: string, capitalName: string, server: boolean, client: boolean}) {
|
223 | console.log('Creating Module', options);
|
224 | if (ExtLB.checkAvailable(process.cwd())) {
|
225 | process.stdout.write(chalk.keyword('limegreen')('Retrieving module template '));
|
226 | simpleGit().clone('https://gitlab.com/ExtLB/module-template.git', '.').then(() => {
|
227 | process.stdout.write(chalk.keyword('limegreen')(' done!\n'));
|
228 | shelljs.rm('-fr', '.git');
|
229 | let modifications: any = {};
|
230 | _.filter(shelljs.ls(`${__dirname}${path.sep}module${path.sep}*.ts`), (file) => {
|
231 | return !_.endsWith(file, '.d.ts');
|
232 | }).map((file) => {
|
233 | return file.substr(0, file.length - 3);
|
234 | }).forEach((changer) => {
|
235 | modifications[changer] = require(`${changer}`).default;
|
236 | });
|
237 | let modifiers: any = {};
|
238 | _.each(modifications, (files) => {
|
239 | _.each(files, (changes, file) => {
|
240 | if (_.isUndefined(modifiers[file])) {
|
241 | modifiers[file] = [];
|
242 | }
|
243 | modifiers[file].push(changes);
|
244 | });
|
245 | });
|
246 | process.stdout.write(chalk.keyword('limegreen')(`Modifying ${_.keys(modifiers).length} files `));
|
247 | let files = _.keys(modifiers);
|
248 | _.each(files, (file) => {
|
249 | let content: any = null;
|
250 | if (_.endsWith(file, '.json')) {
|
251 | content = jsonfile.readFileSync(file);
|
252 | } else {
|
253 | content = fs.readFileSync(file, {encoding: 'utf8'});
|
254 | }
|
255 | modifiers[file].forEach((modifier: (options: object, content: any) => object) => {
|
256 | content = modifier(options, content);
|
257 | });
|
258 | process.stdout.write('.');
|
259 | if (_.isNull(content)) {
|
260 | shelljs.rm(file);
|
261 | } else {
|
262 | if (_.endsWith(file, '.json')) {
|
263 | jsonfile.writeFileSync(file, content, {spaces: 2});
|
264 | } else {
|
265 | fs.writeFileSync(file, content, {encoding: 'utf8'});
|
266 | }
|
267 | }
|
268 | });
|
269 | process.stdout.write(chalk.keyword('limegreen')(' done!\n'));
|
270 | process.stdout.write(chalk.keyword('limegreen')('Relocating 2 paths '));
|
271 | shelljs.mv(`app${path.sep}desktop${path.sep}src${path.sep}view${path.sep}template`, `app${path.sep}desktop${path.sep}src${path.sep}view${path.sep}${options.name}`);
|
272 | process.stdout.write('.');
|
273 | shelljs.mv(`locales${path.sep}en-US${path.sep}mod-template.json`, `locales${path.sep}en-US${path.sep}mod-${options.name}.json`);
|
274 | process.stdout.write('.');
|
275 | process.stdout.write(chalk.keyword('limegreen')(' done!\n'));
|
276 | console.log(chalk.keyword('limegreen')('Installing/Building Modules (npm install)'));
|
277 | shelljs.exec('npm install', {silent:false}, () => {
|
278 | console.log(chalk.keyword('limegreen')('Modules Installed!'));
|
279 | });
|
280 | }).catch((err: any) => {
|
281 | console.error(err);
|
282 | });
|
283 | } else {
|
284 | console.log(chalk.red('package.json already exists!\n'));
|
285 | }
|
286 | }
|
287 | createPerspective(options: { name: string, camelName: string, snakeName: string, capitalName: string, server: boolean, client: boolean}) {
|
288 | console.log('Creating Perspective', options);
|
289 | if (ExtLB.checkAvailable(process.cwd())) {
|
290 | process.stdout.write(chalk.keyword('limegreen')('Retrieving perspective template '));
|
291 | simpleGit().clone('https://gitlab.com/ExtLB/perspective-template.git', '.').then(() => {
|
292 | process.stdout.write(chalk.keyword('limegreen')(' done!\n'));
|
293 | shelljs.rm('-fr', '.git');
|
294 | let modifications: any = {};
|
295 | _.filter(shelljs.ls(`${__dirname}${path.sep}perspective${path.sep}*.ts`), (file) => {
|
296 | return !_.endsWith(file, '.d.ts');
|
297 | }).map((file) => {
|
298 | return file.substr(0, file.length - 3);
|
299 | }).forEach((changer) => {
|
300 | modifications[changer] = require(`${changer}`).default;
|
301 | });
|
302 | let modifiers: any = {};
|
303 | _.each(modifications, (files) => {
|
304 | _.each(files, (changes, file) => {
|
305 | if (_.isUndefined(modifiers[file])) {
|
306 | modifiers[file] = [];
|
307 | }
|
308 | modifiers[file].push(changes);
|
309 | });
|
310 | });
|
311 | process.stdout.write(chalk.keyword('limegreen')(`Modifying ${_.keys(modifiers).length} files `));
|
312 | let files = _.keys(modifiers);
|
313 | _.each(files, (file) => {
|
314 | let content: any = null;
|
315 | if (_.endsWith(file, '.json')) {
|
316 | content = jsonfile.readFileSync(file);
|
317 | } else {
|
318 | content = fs.readFileSync(file, {encoding: 'utf8'});
|
319 | }
|
320 | modifiers[file].forEach((modifier: (options: object, content: any) => object) => {
|
321 | content = modifier(options, content);
|
322 | });
|
323 | process.stdout.write('.');
|
324 | if (_.isNull(content)) {
|
325 | shelljs.rm(file);
|
326 | } else {
|
327 | if (_.endsWith(file, '.json')) {
|
328 | jsonfile.writeFileSync(file, content, {spaces: 2});
|
329 | } else {
|
330 | fs.writeFileSync(file, content, {encoding: 'utf8'});
|
331 | }
|
332 | }
|
333 | });
|
334 | process.stdout.write(chalk.keyword('limegreen')(' done!\n'));
|
335 | process.stdout.write(chalk.keyword('limegreen')('Relocating 7 paths '));
|
336 | shelljs.mv(`app${path.sep}desktop${path.sep}src${path.sep}model${path.sep}perspective${path.sep}template`, `app${path.sep}desktop${path.sep}src${path.sep}model${path.sep}perspective${path.sep}${options.name}`);
|
337 | process.stdout.write('.');
|
338 | shelljs.mv(`app${path.sep}desktop${path.sep}src${path.sep}view${path.sep}perspective${path.sep}template`, `app${path.sep}desktop${path.sep}src${path.sep}view${path.sep}perspective${path.sep}${options.name}`);
|
339 | process.stdout.write('.');
|
340 | shelljs.mv(`locales${path.sep}en-US${path.sep}per-template.json`, `locales${path.sep}en-US${path.sep}per-${options.name}.json`);
|
341 | process.stdout.write('.');
|
342 | shelljs.mv(`server${path.sep}models${path.sep}template-navigation.js`, `server${path.sep}models${path.sep}${options.name}-navigation.js`);
|
343 | process.stdout.write('.');
|
344 | shelljs.mv(`server${path.sep}models${path.sep}template-navigation.json`, `server${path.sep}models${path.sep}${options.name}-navigation.json`);
|
345 | process.stdout.write('.');
|
346 | shelljs.mv(`server${path.sep}models${path.sep}template-notification.ts`, `server${path.sep}models${path.sep}${options.name}-notification.ts`);
|
347 | process.stdout.write('.');
|
348 | shelljs.mv(`server${path.sep}models${path.sep}template-notification.json`, `server${path.sep}models${path.sep}${options.name}-notification.json`);
|
349 | process.stdout.write(chalk.keyword('limegreen')(' done!\n'));
|
350 | console.log(chalk.keyword('limegreen')('Installing/Building Modules (npm install)'));
|
351 | shelljs.exec('npm install', {silent:false}, () => {
|
352 | console.log(chalk.keyword('limegreen')('Modules Installed!'));
|
353 | });
|
354 | }).catch((err: any) => {
|
355 | console.error(err);
|
356 | });
|
357 | } else {
|
358 | console.log(chalk.red('package.json already exists!\n'));
|
359 | }
|
360 | }
|
361 | createModel(options: { name: string, camelName: string, snakeName: string, capitalName: string, pluralName: string, dataSource: string, baseClass: string, public: boolean, type: string}) {
|
362 | console.log('Creating Model', options);
|
363 | if (!ExtLB.checkAvailable(process.cwd())) {
|
364 | let modelDir = `${process.cwd()}${path.sep}${options.type}${path.sep}models${path.sep}`;
|
365 | if (!shelljs.test('-d', modelDir)) {
|
366 | shelljs.mkdir('-p', modelDir);
|
367 | }
|
368 | let modelConfigFile = `${modelDir}${options.snakeName}.json`;
|
369 | let modelConfig = jsonfile.readFileSync(`${__dirname}${path.sep}model${path.sep}config.json`);
|
370 | modelConfig.name = options.name;
|
371 | modelConfig.plural = options.pluralName;
|
372 | modelConfig.base = options.baseClass;
|
373 | jsonfile.writeFileSync(modelConfigFile, modelConfig, {spaces: 2});
|
374 | let modelCodeFile = `${modelDir}${options.snakeName}.ts`;
|
375 | let modelCode = fs.readFileSync(`${__dirname}${path.sep}model${path.sep}code.ejs`, {encoding: 'utf8'});
|
376 | modelCode = ejs.render(modelCode, {options: options});
|
377 | fs.writeFileSync(modelCodeFile, modelCode);
|
378 | if (shelljs.test('-e', `${process.cwd()}${path.sep}config${path.sep}server${path.sep}model-config.json`)) {
|
379 | let modelsFile = `${process.cwd()}${path.sep}config${path.sep}server${path.sep}model-config.json`;
|
380 | let modelsContent = jsonfile.readFileSync(modelsFile);
|
381 | modelsContent[options.name] = {dataSource: options.dataSource, public: options.public};
|
382 | jsonfile.writeFileSync(modelsFile, modelsContent, {spaces: 2});
|
383 | } else if (shelljs.test('-e', `${process.cwd()}${path.sep}server${path.sep}model-config.json`)) {
|
384 | let modelsFile = `${process.cwd()}${path.sep}server${path.sep}model-config.json`;
|
385 | let models = jsonfile.readFileSync(modelsFile);
|
386 | if (!_.isObject(models)) {
|
387 | models.models = {};
|
388 | }
|
389 | models.models[options.name] = {dataSource: options.dataSource, public: options.public};
|
390 | jsonfile.writeFileSync(modelsFile, models, {spaces: 2});
|
391 | } else {
|
392 | console.log(chalk.red('model-config.json missing'));
|
393 | }
|
394 | } else {
|
395 | console.log(chalk.red('package.json missing!\n'));
|
396 | }
|
397 | }
|
398 | createView(options: { name: string, camelName: string, snakeName: string, capitalName: string}) {
|
399 | console.log('Creating View', options);
|
400 | }
|
401 | }
|
402 | let extLoop = new ExtLB();
|
403 | export default extLoop;
|