nodeJS CLI Tool With Example Make Module

TECHNIQUE

  1. commander (npm install commander –save-dev)
  2. singleton pattern
  3. fs to create and remove file

CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/usr/bin/env node

/**
* author: ANPH
* create & destroy Module
* usage: [
* 0. `piepme-express` shell script now ready with `npm link at begin`
* 1. npm install commander [--save-dev] at begin
* 2. create module: node mk-module -c(--create) <moduleName>
* 2. destroy module: node mk-module -d(--destroy) <moduleName>
* ]
* notice: be careful thinking before hitting enter, there is no way back from future
*/

const AnphTool = (() => {
let instance;
init = () => {
const fs = require('fs'),
//
TAG_RMV = '<REMOVE ME AT BEGIN FB1D2631C12FE8F7EE8951663A8A1081>',
//STAT
NOT_FOUND = 'NOT_FOUND', DENIED = 'DENIED', EXISTED = 'EXISTED',
//CONST name
CONTROLLER = 'controller', MODEL = 'model', CLIENTJS = 'clientJS', CSS = 'css', V_FOLDER = 'viewfolder', VIEW = 'view', ROUTER = 'router',
// DEFINE STRUCTURE FOLDER
_getModuleInfo = mdlName => {
return {
[CONTROLLER]: `./server/controllers/${mdlName}.js`,
[MODEL]: `./server/model/${mdlName}Model.js`,
[CLIENTJS]: `./client/js/dev/modules.${mdlName}.js`,
[CSS]: `./client/css/dev/${mdlName}.css`,
[V_FOLDER]: `./views/${mdlName}`,
[VIEW]: `./views/${mdlName}/${mdlName}_view.ejs`,
[ROUTER]: `./server/router/r${mdlName}.js`
}
},
//get message with exactly case
_getMessage = (tag, path) =>
tag === NOT_FOUND ? `FILE NOT FOUND: ${path}` :
tag === DENIED ? `ACCESS DENIED: ${path}` :
tag === EXISTED ? `OPPS! EXISTED: ${path}` : '',
//pad number < 10 left
padLeft = num => +num < 10 ? '0' + num : num,
//
toCapilalize = lower => lower.charAt(0).toUpperCase() + lower.substr(1),
//
_getCreatedDate = () => {
let date = new Date()//+ 7 in hour -> GMT +7
date = new Date(date.valueOf() + date.getTimezoneOffset() * 60000);
return `${padLeft(date.getDate())}/${padLeft(date.getMonth() + 1)}/${date.getFullYear()} ${padLeft(date.getHours() + 7)}:${padLeft(date.getMinutes())}:${padLeft(date.getSeconds())}`
},
//header comment
_getModuleDescription = (mdlName, particularName) => [CSS, VIEW].indexOf(particularName) > -1 ? TAG_RMV : `${TAG_RMV}
/*
* Author: ${require('os').userInfo().username.toLocaleUpperCase()}
* Create: ${_getCreatedDate()}
* ${mdlName.toUpperCase()} ${particularName.toUpperCase()}
*/`,
//template string of sample code
_sampleCode = mdlName => {
return {
[CONTROLLER]: `const ${toCapilalize(mdlName)}Model = require('../model/${mdlName}Model')
module.exports = class ${toCapilalize(mdlName)} extends PIEPME {
constructor() {
super()
this.affModel = new ${ toCapilalize(mdlName)}Model()
}
_${ mdlName} (req, res){ }
}`,
[MODEL]: `module.exports = class ${toCapilalize(mdlName)}Model {
constructor() { this.webServ = new Service() }
}`,
[CLIENTJS]: `'use strict';
window.onload = function () {//call method public here
//${mdlName}Plugin.getInstance().fn();
}
var ${ mdlName}Plugin = (function () {
var instance;
function init() {
function eventListener() { }
return {//what to public
}
}
return {
getInstance: function () {
if (!instance) //make sure only 1 object created
instance = init();
return instance;
}
}
})();`,
[CSS]: '',
[VIEW]: `<% - include('../layout/header', { css: ['/css/${mdlName}.css'] }); %>

<% - include('../layout/footer'); %>
<script src="/js/modules.${mdlName}.js"></script>`,
router: `const ${toCapilalize(mdlName)} = require('../controllers/voucher')
module.exports = function (app) {
this.ctrl${ toCapilalize(mdlName)} = new ${toCapilalize(mdlName)} ()
app.get('/${mdlName}', (req, res) => this.ctrl${toCapilalize(mdlName)}._${mdlName}(req, res))
}`
}
},

//
_checkTagRmv = path =>
!fs.existsSync(path) ? NOT_FOUND :
fs.readFileSync(path).toString('utf-8').split("\n")[0].trim() === TAG_RMV ? true : DENIED,
//create 1 file with required
_generateFile = (mdlName, path, keySample, fpath) => {
!!fpath && !fs.existsSync(fpath) && fs.mkdirSync(fpath)

if (!fs.existsSync(path)) {
fs.writeFileSync(path, `${_getModuleDescription(mdlName, keySample)}
${_sampleCode(mdlName)[keySample]}`);
return path;
} else return _getMessage(EXISTED, path);
},
//remove 1 file from xpath
_destroyFromPath = (xpath, folder) => {
const canRemove = _checkTagRmv(xpath);
if (+canRemove) {
fs.unlinkSync(xpath);
!!folder && fs.rmdirSync(folder)
return xpath;
} else return _getMessage(canRemove, xpath);
},
//create file follow defined structure
_makeModule = mdlName => {
const path = _getModuleInfo(mdlName);
return [
_generateFile(mdlName, path[CONTROLLER], CONTROLLER),
_generateFile(mdlName, path[MODEL], MODEL),
_generateFile(mdlName, path[CLIENTJS], CLIENTJS),
_generateFile(mdlName, path[CSS], CSS),
_generateFile(mdlName, path[ROUTER], ROUTER),
_generateFile(mdlName, path[VIEW], VIEW, path[V_FOLDER])
];
},
//remove all file
_destroyModule = mdlName => {
const path = _getModuleInfo(mdlName);
return [
_destroyFromPath(path[CONTROLLER]),
_destroyFromPath(path[MODEL]),
_destroyFromPath(path[CLIENTJS]),
_destroyFromPath(path[CSS]),
_destroyFromPath(path[ROUTER]),
_destroyFromPath(path[VIEW], path[V_FOLDER])
];
};
//public only 2 main function
return { _makeModule, _destroyModule };
}
return {
getInstance: () => {
if (!instance) instance = init();
return instance;
}
}
})();

USING

1
2
3
4
5
6
7
8
9
10
11
const anphTool = AnphTool.getInstance(),
commander = require('commander');

commander
.version('1.0.0', '-v, --version')
.option('-c, --create [value]', 'create module by name', anphTool._makeModule)
.option('-d, --destroy [value]', 'destroy module by name', anphTool._destroyModule)
.parse(process.argv);

!!create && console.log(' -- CREATED:\n\n\t%s\n\n -> successfully!', create.join('\n\t'));
!!destroy && console.log(' -- DESTROYED:\n\n\t%s\n\n -> successfully!', destroy.join('\n\t'));