mythix-cli 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ {
2
+ "workbench.colorCustomizations": {
3
+ "activityBar.background": "#23320E",
4
+ "titleBar.activeBackground": "#314613",
5
+ "titleBar.activeForeground": "#F7FBF1"
6
+ }
7
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Wyatt Greenway
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # mythix-cli
2
+
3
+ Mythix CLI utility
4
+
5
+ Run CLI commands for `mythix` web-app framework.
6
+
7
+ Examples:
8
+
9
+ Create an empty `mythix` project:
10
+
11
+ ```bash
12
+ $ mythix-cli init project_name
13
+ ```
14
+
15
+ Serve your application:
16
+
17
+ ```bash
18
+ $ mythix-cli serve
19
+ ```
20
+
21
+ Drop into a REPL shell:
22
+
23
+ ```bash
24
+ $ mythix-cli shell
25
+ ```
@@ -0,0 +1,276 @@
1
+ #!/usr/bin/env node
2
+
3
+ const Path = require('path');
4
+ const FileSystem = require('fs');
5
+ const yargs = require('yargs/yargs');
6
+ const { hideBin } = require('yargs/helpers');
7
+ const SimpleYargs = require('simple-yargs');
8
+ const { spawn } = require('child_process');
9
+
10
+ const {
11
+ createHash,
12
+ randomFillSync,
13
+ } = require('crypto');
14
+
15
+ function randomBytes(length) {
16
+ var buffer = Buffer.alloc(length);
17
+ randomFillSync(buffer);
18
+
19
+ return buffer;
20
+ }
21
+
22
+ function SHA256(data) {
23
+ var hash = createHash('sha256');
24
+ hash.update(data);
25
+ return hash.digest('hex');
26
+ }
27
+
28
+ function SHA512(data) {
29
+ var hash = createHash('sha512');
30
+ hash.update(data);
31
+ return hash.digest('hex');
32
+ }
33
+
34
+ function randomHash(type = 'sha256', length = 128) {
35
+ var bytes = randomBytes(length);
36
+ var hash = createHash(type);
37
+
38
+ hash.update(bytes);
39
+
40
+ return hash.digest('hex');
41
+ }
42
+
43
+ function walkDir(rootPath, _options, _callback, _allFiles, _depth) {
44
+ var depth = _depth || 0;
45
+ var allFiles = _allFiles || [];
46
+ var callback = (typeof _options === 'function') ? _options : _callback;
47
+ var options = (typeof _options !== 'function' && _options) ? _options : {};
48
+ var filterFunc = options.filter;
49
+ var fileNames = FileSystem.readdirSync(rootPath);
50
+
51
+ for (var i = 0, il = fileNames.length; i < il; i++) {
52
+ var fileName = fileNames[i];
53
+ var fullFileName = Path.join(rootPath, fileName);
54
+ var stats = FileSystem.statSync(fullFileName);
55
+
56
+ if (typeof filterFunc === 'function' && !filterFunc(fullFileName, fileName, stats, rootPath, depth))
57
+ continue;
58
+ else if (filterFunc instanceof RegExp && !filterFunc.match(fullFileName))
59
+ continue;
60
+
61
+
62
+ if (stats.isDirectory()) {
63
+ walkDir(fullFileName, options, callback, allFiles, depth + 1);
64
+
65
+ if (typeof callback === 'function')
66
+ callback(fullFileName, fileName, rootPath, depth, stats);
67
+ } else if (stats.isFile()) {
68
+ if (typeof callback === 'function')
69
+ callback(fullFileName, fileName, rootPath, depth, stats);
70
+
71
+ allFiles.push(fullFileName);
72
+ }
73
+ }
74
+
75
+ return allFiles;
76
+ }
77
+
78
+ function spawnProcess(name, args, options) {
79
+ return new Promise((resolve, reject) => {
80
+ try {
81
+ var childProcess = spawn(
82
+ name,
83
+ args,
84
+ Object.assign({}, options || {}, {
85
+ env: Object.assign({}, process.env, (options || {}).env || {}),
86
+ stdio: 'inherit',
87
+ })
88
+ );
89
+
90
+ childProcess.on('error', (error) => {
91
+ reject(error);
92
+ });
93
+
94
+ childProcess.on('close', (code) => {
95
+ if (code !== 0) {
96
+ var error = new Error(`Process ${name} exited with non-zero code`);
97
+ return reject(error);
98
+ }
99
+
100
+ resolve(code);
101
+ });
102
+ } catch (error) {
103
+ reject(error);
104
+ }
105
+ });
106
+ }
107
+
108
+ function createTemplateEngineContext(appName) {
109
+ var context = Object.create(null);
110
+
111
+ context.APP_NAME = () => appName;
112
+ context.RANDOM_SHA256 = () => randomHash('sha256');
113
+
114
+ return context;
115
+ }
116
+
117
+ function getTemplatedFileName(fileName, context) {
118
+ return fileName.replace(/__([A-Z0-9_]+)__/g, function(m, varName) {
119
+ var func = context[varName];
120
+ if (typeof func !== 'function')
121
+ return '';
122
+
123
+ return func();
124
+ }).replace(/__/g, '');
125
+ }
126
+
127
+ function runTemplateOnFile(fullFileName, context) {
128
+ var content = FileSystem.readFileSync(fullFileName, 'utf8');
129
+
130
+ var newContent = content.replace(/<<<([A-Z0-9_]+)>>>/g, function(m, varName) {
131
+ var func = context[varName];
132
+
133
+ if (typeof func !== 'function')
134
+ return '';
135
+
136
+ return func();
137
+ });
138
+
139
+ if (newContent === content)
140
+ return;
141
+
142
+ FileSystem.writeFileSync(fullFileName, newContent, 'utf8');
143
+ }
144
+
145
+ function runTemplateEngineOnProject(projectPath, context) {
146
+ walkDir(
147
+ projectPath,
148
+ {
149
+ filter: (fullFileName, fileName, stats) => {
150
+ if (fileName === 'node_modules' && stats.isDirectory())
151
+ return false;
152
+
153
+ return true;
154
+ },
155
+ },
156
+ (_fullFileName, _fileName, rootPath, depth, stats) => {
157
+ var fullFileName = _fullFileName;
158
+ var fileName = _fileName;
159
+
160
+ var newFileName = getTemplatedFileName(fileName, context);
161
+ if (newFileName !== fileName) {
162
+ fileName = newFileName;
163
+
164
+ newFileName = Path.resolve(Path.dirname(fullFileName), newFileName);
165
+
166
+ FileSystem.renameSync(fullFileName, newFileName)
167
+
168
+ fullFileName = newFileName;
169
+ }
170
+
171
+ if (stats.isFile())
172
+ runTemplateOnFile(fullFileName, context);
173
+ }
174
+ );
175
+ }
176
+
177
+ async function initApplication(_, args) {
178
+ if (!args.dir || !('' + args.dir).match(/\S/))
179
+ args.dir = Path.resolve(process.env.PWD);
180
+ else
181
+ args.dir = Path.resolve(args.dir);
182
+
183
+ try {
184
+ var templateClonePath = Path.resolve(args.dir, args.appName);
185
+ var processArgs = [ args.template, templateClonePath ];
186
+
187
+ if (args.tag && args.tag.match(/\S/))
188
+ processArgs = [ '-b', args.tag ].concat(processArgs);
189
+
190
+ await spawnProcess('git', [ 'clone' ].concat(processArgs));
191
+
192
+ FileSystem.rmSync(Path.resolve(templateClonePath, '.git'), { recursive: true, force: true });
193
+
194
+ runTemplateEngineOnProject(templateClonePath, createTemplateEngineContext(args.appName));
195
+
196
+ await spawnProcess('npm', [ 'i' ], { env: { PWD: templateClonePath, CWD: templateClonePath }, cwd: templateClonePath });
197
+ } catch (error) {
198
+ console.error('ERROR: ', error);
199
+ }
200
+ }
201
+
202
+ function createYargsCommands(yargs, commandsObj, actionHandler) {
203
+ var commands = [];
204
+ var commandNames = Object.keys(commandsObj);
205
+
206
+ for (var i = 0, il = commandNames.length; i < il; i++) {
207
+ var commandName = commandNames[i];
208
+ var Klass = commandsObj[commandName];
209
+
210
+ commands.push(Klass.commandString);
211
+ }
212
+
213
+ return SimpleYargs.buildCommands(yargs, actionHandler, commands, {
214
+ actionHelper: function(commandName) {
215
+ var Klass = commandsObj[commandName];
216
+ return actionHandler.bind(Klass, commandName, Klass.path);
217
+ },
218
+ });
219
+ }
220
+
221
+ (async function() {
222
+ const packageJSONPath = Path.resolve(__dirname, '..', 'package.json');
223
+ const packageJSON = require(packageJSONPath);
224
+
225
+ // Windows hack
226
+ if(!process.env.PWD)
227
+ process.env.PWD = process.cwd();
228
+
229
+ var PWD = process.env.PWD;
230
+ var argv = hideBin(process.argv);
231
+ var rootCommand;
232
+
233
+ try {
234
+ if (argv[0] !== 'init') {
235
+ argv = hideBin(process.argv).concat('');
236
+ rootCommand = yargs(argv);
237
+
238
+ var mythixPath = Path.dirname(require.resolve('mythix', { paths: [ process.env.PWD, Path.resolve(process.env.PWD, 'node_modules') ] }));
239
+ var mythixCLIPAth = Path.resolve(mythixPath, 'cli');
240
+ var mythixCLI = require(mythixCLIPAth);
241
+ var config = mythixCLI.loadMythixConfig(PWD);
242
+
243
+ var Application = config.getApplicationClass(config);
244
+ if (typeof Application !== 'function')
245
+ throw new Error('Expected to find an Application class from "getApplicationClass", but none was returned.');
246
+
247
+ var application = await mythixCLI.createApplication(Application, { autoReload: false, database: false, httpServer: false });
248
+ var applicationOptions = application.getOptions();
249
+
250
+ var commands = await mythixCLI.loadCommands(applicationOptions.commandsPath);
251
+
252
+ rootCommand = createYargsCommands(rootCommand, commands, async function(command, commandPath) {
253
+ await mythixCLI.executeCommand(
254
+ config.configPath,
255
+ applicationOptions.commandsPath,
256
+ Path.dirname(require.resolve('yargs')),
257
+ Path.dirname(require.resolve('simple-yargs', '..')),
258
+ argv,
259
+ commandPath,
260
+ command,
261
+ );
262
+
263
+ await application.stop();
264
+ });
265
+ } else {
266
+ argv = hideBin(process.argv);
267
+ rootCommand = yargs(argv);
268
+ }
269
+ } catch (error) {
270
+ console.error(mythixPath, error);
271
+ }
272
+
273
+ rootCommand = SimpleYargs.buildCommands(rootCommand, initApplication, [ 'init(Create a new application with the given name) <appName:string(Specify application name)> [-d,-dir:string(Path at which to create application)] [-t,-template:string(Git URL to use to clone and create new project from)=https://github.com/th317erd/mythix-app-template.git(Default "https://github.com/th317erd/mythix-app-template.git")] [-tag:string(Specify tag or commit hash to clone template from)]' ]);
274
+
275
+ rootCommand.version(packageJSON.version).strictCommands().wrap(120).parse();
276
+ })();
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "bin": {
3
+ "mythix-cli": "./bin/mythix-cli.js"
4
+ },
5
+ "name": "mythix-cli",
6
+ "version": "1.0.2",
7
+ "description": "Mythix CLI utility",
8
+ "main": "src/index.js",
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/th317erd/mythix-cli.git"
15
+ },
16
+ "keywords": [
17
+ "mythix",
18
+ "orm",
19
+ "web-server",
20
+ "webserver",
21
+ "framework"
22
+ ],
23
+ "author": "Wyatt Greenway",
24
+ "license": "MIT",
25
+ "bugs": {
26
+ "url": "https://github.com/th317erd/mythix-cli/issues"
27
+ },
28
+ "homepage": "https://github.com/th317erd/mythix-cli#readme",
29
+ "dependencies": {
30
+ "simple-yargs": "^0.1.5",
31
+ "yargs": "^17.3.1"
32
+ }
33
+ }
package/src/index.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = {};