重构生成脚本
							parent
							
								
									9953ad30e9
								
							
						
					
					
						commit
						6ad6f94472
					
				
							
								
								
									
										41
									
								
								Readme.md
								
								
								
								
							
							
						
						
									
										41
									
								
								Readme.md
								
								
								
								
							|  | @ -4,48 +4,11 @@ | |||
|  / _` | '_ ` _ \|___ \ _____ / __| | | | ||||
| | (_| | | | | | |___) |_____| (__| | | | ||||
|  \__, |_| |_| |_|____/       \___|_|_| | ||||
|  |___/                        一键安装、管理Five.js框架的脚本工具                       | ||||
|  |___/                        一键安装 Five.js 框架的脚本工具                       | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| ## 安装 | ||||
| ```bash | ||||
| npm i -g @gm5/cli | ||||
| npm create five | ||||
| ``` | ||||
| 
 | ||||
| ## 用法 | ||||
| > 用法: `five-cli [command] args...` | ||||
| 
 | ||||
| + Commands: | ||||
|   * init             -    初始化框架 | ||||
|   * start [prod|dev] -    运行当前的应用(可指定运行环境) | ||||
|   * stop             -    停止当前应用 | ||||
|   * st|status        -    查看当前应用状态 | ||||
|   * r|restart        -    重启当前应用 | ||||
|   * del|delete       -    删除当前应用 | ||||
|   * -h               -    查看帮助文档 | ||||
|   * -v               -    查看工具的版本 | ||||
| 
 | ||||
| 
 | ||||
| ## 更新日志 | ||||
| 
 | ||||
| ### v1.0.0 | ||||
| * 脚本重构,支持windows | ||||
| * 支持最新框架 | ||||
| 
 | ||||
| 
 | ||||
| ### v0.4.1 | ||||
| * 优化项目构建 | ||||
| * 支持指令简写 | ||||
| * 优化启动逻辑 | ||||
| 
 | ||||
| 
 | ||||
| ### v0.2.0 | ||||
| * 从 v0.2版开始, 将只支持 linux/macos, 且框架自动为最新的3.x。 | ||||
| * [优化] 优化five-cli start [dev|prod] 指令 | ||||
| 
 | ||||
| 
 | ||||
| ### v0.1.2 | ||||
| * 下载地址改用github | ||||
| * 兼容windows | ||||
| * 优化操作提示 | ||||
							
								
								
									
										214
									
								
								index.js
								
								
								
								
							
							
						
						
									
										214
									
								
								index.js
								
								
								
								
							|  | @ -1,109 +1,151 @@ | |||
| #!/usr/bin/env node
 | ||||
| 
 | ||||
| #!/usr/bin/node
 | ||||
| /** | ||||
|  * 脚手架 | ||||
|  * | ||||
|  * @author yutent<yutent.io@gmail.com> | ||||
|  * @date 2020/09/28 11:35:16 | ||||
|  * @date 2022/10/10 15:17:36 | ||||
|  */ | ||||
| 
 | ||||
| const fs = require('iofs') | ||||
| const chalk = require('chalk') | ||||
| const path = require('path') | ||||
| import { red, cyan, blue, grey } from 'kolorist' | ||||
| import prompts from 'prompts' | ||||
| import fs from 'iofs' | ||||
| import { resolve, join, dirname } from 'path' | ||||
| 
 | ||||
| var pm2 | ||||
| var pkg = require('./package.json') | ||||
| var { do_init } = require('./lib/init') | ||||
| var { start, stop, restart, remove, status } = require('./lib/pm2') | ||||
| import { | ||||
|   writePackageJson, | ||||
|   writeGitIgnore, | ||||
|   writePrettierrc, | ||||
|   writePm2File | ||||
| } from './lib/demo-config.js' | ||||
| import { writeMainJs, writeAppJs, writeModelJs } from './lib/demo-js.js' | ||||
| 
 | ||||
| var { arch, platform, version } = process | ||||
| var os = { linux: 'Linux', darwin: 'MacOS', win: 'Windows' } | ||||
| var cwd = process.cwd() | ||||
| var args = process.argv.slice(2) | ||||
| var action = args.shift() | ||||
| const CURRENT_DIR = process.cwd() | ||||
| const root = dirname(import.meta.url.slice(process.platform === 'win32' ? 10 : 7)) | ||||
| const { version } = JSON.parse(fs.cat(join(root, './package.json'))) | ||||
| 
 | ||||
| try { | ||||
|   pm2 = require('pm2/package.json') | ||||
| } catch (error) { | ||||
|   print('#'.repeat(64)) | ||||
|   console.log(chalk.red('脚手架使用pm2作为守护进程, 请先安装pm2')) | ||||
|   console.log(chalk.green('npm i -g pm2')) | ||||
|   print('#'.repeat(64)) | ||||
|   process.exit() | ||||
| } | ||||
| const DEFAULT_NAME = 'gm5-app' | ||||
| 
 | ||||
| function print(...args) { | ||||
|   args[0] = args[0].padEnd(20, ' ') | ||||
|   if (args.length > 1) { | ||||
|     args.splice(1, 0, '   -   ') | ||||
| let args = process.argv.slice(2) | ||||
| let targetDir = '' | ||||
| 
 | ||||
| function isEmpty(dir) { | ||||
|   let list = fs.ls(dir) | ||||
|   if (list && list.length) { | ||||
|     return false | ||||
|   } | ||||
|   console.log.apply(null, args) | ||||
|   return true | ||||
| } | ||||
| 
 | ||||
| function logo() { | ||||
|   return chalk.green.bold(`                 ____  
 | ||||
|   __ _ _ __ ___ | ___|  | ||||
|  / _\` | '_ \` _ \\|___ \\  | ||||
| | (_| | | | | | |___) | | ||||
|  \\__, |_| |_| |_|____/  | ||||
|  |___/`)
 | ||||
| function sleep(num = 1) { | ||||
|   return new Promise(resolve => setTimeout(resolve, num * 1000)) | ||||
| } | ||||
| 
 | ||||
| function print_help() { | ||||
|   print('='.repeat(64)) | ||||
|   print(`${logo()}                     v${pkg.version},    作者: 宇天`) | ||||
|   print('-'.repeat(64)) | ||||
|   print('node版本:  ' + version) | ||||
|   print('pm2 版本:  v' + pm2.version) | ||||
|   print(`当前系统:  ${os[platform]}(${arch})`) | ||||
|   print('当前路径:  ' + chalk.red.underline(cwd)) | ||||
|   print('='.repeat(64)) | ||||
|   print('用法: five-cli [command] args...') | ||||
|   print('Commands:') | ||||
|   print('  init', '初始化框架') | ||||
|   print('  start [prod|dev]', '运行当前的应用(可指定运行环境)') | ||||
|   print('  stop', '停止当前应用') | ||||
|   print('  st|status', '查看当前应用状态') | ||||
|   print('  r|restart', '重启当前应用') | ||||
|   print('  del|delete', '删除当前应用') | ||||
|   print('  -h', '查看帮助文档') | ||||
|   print('  -v', '查看工具的版本') | ||||
| function printHelp() { | ||||
|   console.log('Usage: create-five {command} [arguments]') | ||||
|   console.log('  ', 'create-five init', '一个快速创建Five.js项目的小工具') | ||||
|   console.log('  ', 'create-five -h[--help]', '打印帮助信息') | ||||
|   console.log() | ||||
|   process.exit() | ||||
| } | ||||
| 
 | ||||
| switch (action) { | ||||
|   case 'init': | ||||
|     do_init(cwd) | ||||
|     break | ||||
| !(async function () { | ||||
|   switch (args[0]) { | ||||
|     case '-v': | ||||
|     case '--version': | ||||
|       console.log('v' + version) | ||||
|       break | ||||
| 
 | ||||
|   case 'start': | ||||
|     start(cwd, args[0]) | ||||
|     break | ||||
|     case '-h': | ||||
|     case '--help': | ||||
|       printHelp() | ||||
|       break | ||||
| 
 | ||||
|   case 'stop': | ||||
|     stop(cwd) | ||||
|     break | ||||
|     default: | ||||
|       let res = await prompts([ | ||||
|         { | ||||
|           name: 'projectName', | ||||
|           type: 'text', | ||||
|           message: '项目名称(也是目录名, 只能为英文、数字、-、.):', | ||||
|           initial: DEFAULT_NAME, | ||||
|           validate: val => /^[a-zA-Z\d\-\.]+$/.test(val), | ||||
|           onState: ({ value }) => (targetDir = join(CURRENT_DIR, value)) | ||||
|         }, | ||||
|         { | ||||
|           name: 'shouldOverwrite', | ||||
|           type: _ => (isEmpty(targetDir) ? null : 'toggle'), | ||||
|           message: _ => `目录 ${cyan(targetDir)} 非空, 是否${red('删除')}目录下所有的文件?`, | ||||
|           initial: false, | ||||
|           active: '是', | ||||
|           inactive: '否' | ||||
|         }, | ||||
|         { | ||||
|           name: 'confirmCheck', | ||||
|           type: shouldOverwrite => { | ||||
|             if (shouldOverwrite === false) { | ||||
|               console.log(red('✖') + ' 操作取消~~') | ||||
|               process.exit(1) | ||||
|             } | ||||
|             return null | ||||
|           } | ||||
|         } | ||||
|       ]) | ||||
| 
 | ||||
|   case 'st': | ||||
|   case 'status': | ||||
|     status(cwd) | ||||
|     break | ||||
|       console.log() | ||||
| 
 | ||||
|   case 'r': | ||||
|   case 'restart': | ||||
|     restart(cwd) | ||||
|     break | ||||
|       if (res.projectName === '.') { | ||||
|         res.projectName = DEFAULT_NAME | ||||
|       } | ||||
| 
 | ||||
|   case 'del': | ||||
|   case 'delete': | ||||
|     remove(cwd) | ||||
|     break | ||||
|       console.log('指定的项目名为: %s', cyan(res.projectName)) | ||||
|       console.log('项目目录为: %s', cyan(targetDir)) | ||||
| 
 | ||||
|   case '-v': | ||||
|     print(pkg.version) | ||||
|     process.exit() | ||||
|     break | ||||
|       if (res.shouldOverwrite) { | ||||
|         console.log(red('目录非空, 1s 后将清空目录~~')) | ||||
|         await sleep(1) | ||||
|         let list = fs.ls(targetDir) | ||||
|         list.forEach(it => fs.rm(it, true)) | ||||
|       } else { | ||||
|         console.log(red('程序将在 1s 后初始化项目~~')) | ||||
|         await sleep(1) | ||||
|       } | ||||
| 
 | ||||
|   default: | ||||
|     print_help() | ||||
|     break | ||||
| } | ||||
|       console.log(cyan('\n初始化项目...')) | ||||
| 
 | ||||
|       fs.mkdir(join(targetDir, 'apps')) | ||||
|       fs.mkdir(join(targetDir, 'models')) | ||||
|       fs.mkdir(join(targetDir, 'config')) | ||||
|       fs.mkdir(join(targetDir, 'data')) | ||||
|       fs.mkdir(join(targetDir, 'public')) | ||||
|       fs.mkdir(join(targetDir, 'views')) | ||||
| 
 | ||||
|       console.log('[c---------]', '10%') | ||||
| 
 | ||||
|       writePackageJson(join(targetDir, 'package.json'), res.projectName) | ||||
|       writeGitIgnore(join(targetDir, '.gitignore')) | ||||
|       writePrettierrc(join(targetDir, '.prettierrc.yaml')) | ||||
|       writePm2File(join(targetDir, 'app.dev.yaml'), { | ||||
|         name: res.projectName, | ||||
|         env: 'development', | ||||
|         cluster: false | ||||
|       }) | ||||
|       writePm2File(join(targetDir, 'app.yaml'), { | ||||
|         name: res.projectName, | ||||
|         cluster: false | ||||
|       }) | ||||
| 
 | ||||
|       console.log('[ooc-------]', '30%') | ||||
| 
 | ||||
|       console.log('[oooooc----]', '60%') | ||||
| 
 | ||||
|       writeMainJs(join(targetDir, 'app.js')) | ||||
|       writeAppJs(join(targetDir, 'apps/index.js')) | ||||
|       writeModelJs(join(targetDir, 'models/index.js')) | ||||
| 
 | ||||
|       console.log('[oooooooooo]', '100%') | ||||
|       console.log(cyan('初始化完成, 可依次执行以下命令启动项目: ')) | ||||
|       console.log(blue('npm i')) | ||||
|       console.log(blue('pm2 start app.dev.yaml'), grey('# 开发模式')) | ||||
|       console.log(blue('pm2 start app.yaml'), grey('# 生产模式')) | ||||
| 
 | ||||
|       break | ||||
|   } | ||||
| })() | ||||
|  |  | |||
|  | @ -0,0 +1,92 @@ | |||
| /** | ||||
|  * {} | ||||
|  * @author yutent<yutent.io@gmail.com> | ||||
|  * @date 2022/10/10 16:49:07 | ||||
|  */ | ||||
| 
 | ||||
| import fs from 'iofs' | ||||
| 
 | ||||
| export function writePackageJson(file, name) { | ||||
|   fs.echo( | ||||
|     JSON.stringify( | ||||
|       { | ||||
|         name: name || 'gm5-app', | ||||
|         type: 'module', | ||||
|         main: 'app.js', | ||||
|         dependencies: { | ||||
|           '@gm5/core': '^1.1.4' | ||||
|         } | ||||
|       }, | ||||
|       null, | ||||
|       2 | ||||
|     ), | ||||
|     file | ||||
|   ) | ||||
| } | ||||
| 
 | ||||
| export function writeGitIgnore(file) { | ||||
|   fs.echo( | ||||
|     ` | ||||
| *.sublime-project | ||||
| *.sublime-workspace | ||||
| 
 | ||||
| node_modules | ||||
| package-lock.json | ||||
| data/logs | ||||
| public/upload/ | ||||
| 
 | ||||
| ._* | ||||
| .idea | ||||
| .vscode | ||||
| .Spotlight-V100 | ||||
| .Trashes | ||||
| .DS_Store | ||||
| .AppleDouble | ||||
| .LSOverride | ||||
| 
 | ||||
| `,
 | ||||
|     file | ||||
|   ) | ||||
| } | ||||
| 
 | ||||
| export function writePrettierrc(file) { | ||||
|   fs.echo( | ||||
|     ` | ||||
| jsxBracketSameLine: true | ||||
| jsxSingleQuote: true | ||||
| semi: false | ||||
| singleQuote: true | ||||
| printWidth: 100 | ||||
| useTabs: false | ||||
| tabWidth: 2 | ||||
| trailingComma: none | ||||
| bracketSpacing: true | ||||
| arrowParens: avoid | ||||
| `,
 | ||||
|     file | ||||
|   ) | ||||
| } | ||||
| 
 | ||||
| export function writePm2File(file, { env = 'production', name = 'gm5-app', cluster = true }) { | ||||
|   fs.echo( | ||||
|     ` | ||||
| script: node --experimental-json-modules ./app.js | ||||
| cwd: ./ | ||||
| watch: true | ||||
| name: ${name} | ||||
| ignore_watch: [data, public, package.json, package-lock.json, node_modules, .git, .gitignore, app.yaml] | ||||
| exec_mode: ${cluster ? 'cluster' : 'fork'} | ||||
| ${cluster ? 'instances: max' : ''} | ||||
| error_file: ./data/logs/error.log | ||||
| out_file: ./data/logs/out.log | ||||
| merge_logs: true | ||||
| min_uptime: 60s | ||||
| max_restarts: 1 | ||||
| max_memory_restart: 300M | ||||
| env: | ||||
|   NODE_ENV: ${env} | ||||
|    | ||||
|   `,
 | ||||
|     file | ||||
|   ) | ||||
| } | ||||
|  | @ -0,0 +1,107 @@ | |||
| /** | ||||
|  * {} | ||||
|  * @author yutent<yutent.io@gmail.com> | ||||
|  * @date 2022/10/10 17:00:29 | ||||
|  */ | ||||
| 
 | ||||
| import fs from 'iofs' | ||||
| 
 | ||||
| export function writeMainJs(file) { | ||||
|   fs.echo( | ||||
|     ` | ||||
| import Five from '@gm5/core' | ||||
| 
 | ||||
| const app = new Five() | ||||
| 
 | ||||
| // app.set({ 
 | ||||
| //   // 可开启session支持
 | ||||
| //   session: { enabled: true, type: 'redis' } 
 | ||||
| //
 | ||||
| //   // 可开启模板引擎的支持
 | ||||
| //   views: { enabled: true, dir: './views' }
 | ||||
| // })
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| // 预加载应用, 这一步是必须的, 且需要在listen方法前调用
 | ||||
| app.preload('./apps/') | ||||
| 
 | ||||
| // 中间件示例
 | ||||
| // 这里的回调, 如果不用箭头函数的话, this指向app
 | ||||
| // app.use((req, res, next) => {
 | ||||
| //   if (req.method !== 'GET') {
 | ||||
| //     return res.error('', 401)
 | ||||
| //   }
 | ||||
| //   // 这一步很重要, 如果没有执行 next(), 则程序就会在这个回调里终止
 | ||||
| //   // 不会再往后执行其他的了
 | ||||
| //   next()
 | ||||
| // })
 | ||||
| 
 | ||||
| // 安装拓展包, 可以应用中通过 this.context.$$mysql 调用到, 
 | ||||
| // 在中间件, 或后面的其他拓展包中, 可以直接 this.$$mysql 调用 
 | ||||
| // app.install({
 | ||||
| //   name: 'mysql', 
 | ||||
| //   install: function() {
 | ||||
| //     return new Mysqli(conf)
 | ||||
| //   }
 | ||||
| // })
 | ||||
| 
 | ||||
| app.listen(3000) | ||||
|      | ||||
| `,
 | ||||
|     file | ||||
|   ) | ||||
| } | ||||
| 
 | ||||
| export function writeModelJs(file) { | ||||
|   fs.echo( | ||||
|     ` | ||||
| 
 | ||||
| // 数据模型|存储交互
 | ||||
| export default class Index { | ||||
|    | ||||
|   constructor(conn){ | ||||
|     // this.db = conn.emit(false, 'test')
 | ||||
|   } | ||||
| 
 | ||||
|   list(){ | ||||
|     // return this.db.table('user').withFields(['id', 'name']).getAll()
 | ||||
|   } | ||||
| } | ||||
|      | ||||
|      | ||||
| `,
 | ||||
|     file | ||||
|   ) | ||||
| } | ||||
| 
 | ||||
| export function writeAppJs(file) { | ||||
|   fs.echo( | ||||
|     ` | ||||
| 
 | ||||
| import Controller from '@gm5/controller' | ||||
| 
 | ||||
| // import Model from '../models/index.js'
 | ||||
| 
 | ||||
| // 所有的应用, 都要继承Controller
 | ||||
| // 以获取跟框架交互的能力
 | ||||
| export default class Index extends Controller  { | ||||
|    | ||||
|   // 这个main方法是可选的, 如果有定义, 会自动先调用
 | ||||
|   // 可以在这里做任何需要预处理的事, 支持async/await
 | ||||
|   // 若返回 false, 则可以终止程序往下执行
 | ||||
|   // 这个特性, 可用于权限验证等操作
 | ||||
|   __main__() { | ||||
|     // this.model = new Model(this.context.$$mysql)
 | ||||
|   } | ||||
| 
 | ||||
|   async indexAction(){ | ||||
|     this.response.end('It works!') | ||||
|   } | ||||
| } | ||||
|    | ||||
|      | ||||
| `,
 | ||||
|     file | ||||
|   ) | ||||
| } | ||||
							
								
								
									
										164
									
								
								lib/init.js
								
								
								
								
							
							
						
						
									
										164
									
								
								lib/init.js
								
								
								
								
							|  | @ -1,164 +0,0 @@ | |||
| /** | ||||
|  * 初始化项目 | ||||
|  * @author yutent<yutent.io@gmail.com> | ||||
|  * @date 2020/09/28 15:45:46 | ||||
|  */ | ||||
| 
 | ||||
| const fs = require('iofs') | ||||
| const path = require('path') | ||||
| const chalk = require('chalk') | ||||
| 
 | ||||
| const { exec, read } = require('./tools') | ||||
| const { start } = require('./pm2') | ||||
| 
 | ||||
| function encode(obj) { | ||||
|   return JSON.stringify(obj, null, 2) | ||||
| } | ||||
| 
 | ||||
| exports.do_init = async function(dir) { | ||||
|   var files = fs.ls(dir) | ||||
|   if (files && files.length) { | ||||
|     console.log(chalk.red('当前目录非空, 初始化失败...')) | ||||
|     process.exit() | ||||
|   } | ||||
| 
 | ||||
|   console.log(chalk.green('初始化目录...')) | ||||
|   fs.mkdir(path.join(dir, 'apps')) | ||||
|   fs.mkdir(path.join(dir, 'models')) | ||||
|   fs.mkdir(path.join(dir, 'config')) | ||||
|   fs.mkdir(path.join(dir, 'data')) | ||||
|   fs.mkdir(path.join(dir, 'public')) | ||||
|   fs.mkdir(path.join(dir, 'views')) | ||||
| 
 | ||||
|   fs.echo( | ||||
|     encode({ | ||||
|       name: 'fivejs-instance', | ||||
|       type: 'module', | ||||
|       main: 'app.js' | ||||
|     }), | ||||
|     path.join(dir, 'package.json') | ||||
|   ) | ||||
| 
 | ||||
|   // git忽略配置
 | ||||
|   fs.echo( | ||||
|     ` | ||||
| .Spotlight-V100 | ||||
| .Trashes | ||||
| .DS_Store | ||||
| .AppleDouble | ||||
| .LSOverride | ||||
| ._* | ||||
| .idea | ||||
| .vscode | ||||
| 
 | ||||
| node_modules/ | ||||
| data/logs | ||||
| public/upload/ | ||||
| package-lock.json | ||||
| app.yaml | ||||
| `,
 | ||||
|     path.join(dir, '.gitignore') | ||||
|   ) | ||||
| 
 | ||||
|   // 应用控制器
 | ||||
|   fs.echo( | ||||
|     ` | ||||
| 
 | ||||
| import Controller from '@gm5/controller' | ||||
| 
 | ||||
| // import Model from '../models/index.js'
 | ||||
| 
 | ||||
| // 所有的应用, 都要继承Controller
 | ||||
| // 以获取跟框架交互的能力
 | ||||
| export default class Index extends Controller  { | ||||
|    | ||||
| 
 | ||||
|   // 这个main方法是可选的, 如果有定义, 会自动先调用
 | ||||
|   // 可以在这里做任何需要预处理的事, 支持async/await
 | ||||
|   __main__(){ | ||||
|     // this.model = new Model(this.ctx.ins('mysql'))
 | ||||
|   } | ||||
| 
 | ||||
|   async indexAction(){ | ||||
|     this.response.end('It works!') | ||||
|   } | ||||
| } | ||||
|   `,
 | ||||
|     path.join(dir, 'apps/index.js') | ||||
|   ) | ||||
| 
 | ||||
|   // 数据模型
 | ||||
|   fs.echo( | ||||
|     ` | ||||
| // 数据模型|存储交互
 | ||||
| export default class Index { | ||||
|    | ||||
|   constructor(conn){ | ||||
|     // this.db = conn.emit(false, 'test')
 | ||||
|   } | ||||
| 
 | ||||
|   list(){ | ||||
|     // return this.db.table('user').withFields(['id', 'name']).getAll()
 | ||||
|   } | ||||
| } | ||||
|   `,
 | ||||
|     path.join(dir, 'models/index.js') | ||||
|   ) | ||||
| 
 | ||||
|   // 入口js
 | ||||
|   fs.echo( | ||||
|     ` | ||||
| import Five from '@gm5/core' | ||||
| 
 | ||||
| const app = new Five() | ||||
| 
 | ||||
| // 可开启session支持
 | ||||
| // app.set({ session: { enabled: true, type: 'redis' } })
 | ||||
| 
 | ||||
| // 可开启模板引擎的支持
 | ||||
| // app.set({ views: { enabled: true, dir: './views' } })
 | ||||
| 
 | ||||
| // 预加载应用, 这一步是必须的, 且需要在listen方法前调用
 | ||||
| app.preload('./apps/') | ||||
| 
 | ||||
| // 中间件示例
 | ||||
| // app.use((req, res, next) => {
 | ||||
| //   if (req.method !== 'GET') {
 | ||||
| //     res.error('', 401)
 | ||||
| //   }
 | ||||
| //   next()
 | ||||
| // })
 | ||||
| 
 | ||||
| // 安装拓展包, 可以应用中通过 this.context.$$log调用到, 
 | ||||
| // 在中间件, 或后面的其他拓展包中, 可以直接 this.$$log 调用 
 | ||||
| // app.install({
 | ||||
| //   name: 'log', 
 | ||||
| //   install: function() {
 | ||||
| //     return new Logs('run_time.log', './data/logs/')
 | ||||
| //   }
 | ||||
| // })
 | ||||
| 
 | ||||
| app.listen(3000) | ||||
| 
 | ||||
| 
 | ||||
|   `,
 | ||||
|     path.join(dir, 'app.js') | ||||
|   ) | ||||
| 
 | ||||
|   console.log(chalk.green('目录初始化完成!')) | ||||
| 
 | ||||
|   var confirm = await read('是否立即安装依赖? y/n: ') | ||||
|   if (confirm === 'y') { | ||||
|     console.log(chalk.green('依赖安装中...')) | ||||
|     exec('npm i @gm5/core') | ||||
|     console.log(chalk.blue('依赖安装完成 ^_^')) | ||||
|   } | ||||
| 
 | ||||
|   confirm = await read('是否立即运行? y/n: ') | ||||
| 
 | ||||
|   if (confirm === 'y') { | ||||
|     start(dir) | ||||
|   } else { | ||||
|     process.exit() | ||||
|   } | ||||
| } | ||||
							
								
								
									
										168
									
								
								lib/pm2.js
								
								
								
								
							
							
						
						
									
										168
									
								
								lib/pm2.js
								
								
								
								
							|  | @ -1,168 +0,0 @@ | |||
| /** | ||||
|  * 进程管理 | ||||
|  * @author yutent<yutent.io@gmail.com> | ||||
|  * @date 2020/09/28 15:45:46 | ||||
|  */ | ||||
| 
 | ||||
| const fs = require('iofs') | ||||
| const path = require('path') | ||||
| const os = require('os') | ||||
| const chalk = require('chalk') | ||||
| 
 | ||||
| const { exec, read } = require('./tools') | ||||
| 
 | ||||
| var cpus = os.cpus() | ||||
| 
 | ||||
| exports.start = async function(dir, env) { | ||||
|   var confFile = path.join(dir, 'app.yaml') | ||||
|   var run_env = process.env.NODE_ENV || 'development' | ||||
|   var name, cluster, instances | ||||
| 
 | ||||
|   if (env === 'prod') { | ||||
|     run_env = 'production' | ||||
|   } | ||||
| 
 | ||||
|   if (fs.exists(confFile)) { | ||||
|     console.log( | ||||
|       chalk.yellow('应用可能已经启动, 请确认是否在列表中, 以免重复启动!') | ||||
|     ) | ||||
|     exec('pm2 ls') | ||||
|     var act = await read( | ||||
|       '请确认操作, 如已在列表中, 请回车或按Ctrl + C取消, 输入任意内容将会重新启动: ' | ||||
|     ) | ||||
|     if (act) { | ||||
|       var data = fs.cat(confFile).toString() | ||||
|       data = data.replace(/NODE_ENV: [a-z]+/, `NODE_ENV: ${run_env}`) | ||||
|       fs.echo(data, confFile) | ||||
|       exec('pm2 start app.yaml') | ||||
|       console.log(chalk.blue('应用启动成功!!!')) | ||||
|     } | ||||
|     process.exit() | ||||
|   } | ||||
| 
 | ||||
|   console.log('首次运行,请根据提示完成配置') | ||||
| 
 | ||||
|   // ---------------
 | ||||
|   name = await read('(请输入应用唯一名称, 不能含中文): ') | ||||
|   if (name === '') { | ||||
|     console.log(chalk.yellow('没有输入, 自动使用随机名称')) | ||||
|     name = 'five-demo-' + ~~(Math.random() * 99) | ||||
|   } | ||||
|   console.log(`当前应用名称为: ${name}`) | ||||
| 
 | ||||
|   // ---------------
 | ||||
|   cluster = await read('(是否开启集群模式, 生产环境建议开启, y/n): ') | ||||
|   if (cluster === '') { | ||||
|     console.log(chalk.yellow('没有输入, 默认不开启集群模式')) | ||||
|     cluster = 'fork' | ||||
|   } else { | ||||
|     if (cluster === 'y') { | ||||
|       cluster = 'cluster' | ||||
|     } else { | ||||
|       cluster = 'fork' | ||||
|     } | ||||
|   } | ||||
|   console.log(`当前运行模式为: ${cluster}`) | ||||
| 
 | ||||
|   // ---------------
 | ||||
|   if (cluster === 'cluster') { | ||||
|     instances = await read(`(请设置开启的线程数: 0-${cpus}, 0为自动): `) | ||||
|     instances = +instances | ||||
| 
 | ||||
|     if (instances === 0) { | ||||
|       instances = 'max' | ||||
|     } else { | ||||
|       if (instances > cpus) { | ||||
|         instances = cpus | ||||
|       } else if (instances < 0) { | ||||
|         instances = 1 | ||||
|       } | ||||
|     } | ||||
|     instances = `instances: ${instances}` | ||||
|   } else { | ||||
|     instances = '' | ||||
|   } | ||||
| 
 | ||||
|   fs.echo( | ||||
|     ` | ||||
| script: node --experimental-json-modules ./app.js | ||||
| cwd: ./ | ||||
| watch: true | ||||
| name: ${name} | ||||
| ignore_watch: [data, public, package.json, package-lock.json, node_modules, .git, .gitignore, app.yaml] | ||||
| exec_mode: ${cluster} | ||||
| ${instances} | ||||
| error_file: ./data/logs/error.log | ||||
| out_file: ./data/logs/out.log | ||||
| merge_logs: true | ||||
| min_uptime: 60s | ||||
| max_restarts: 1 | ||||
| max_memory_restart: 300M | ||||
| env: | ||||
|   NODE_ENV: ${run_env} | ||||
|    | ||||
|   `,
 | ||||
|     confFile | ||||
|   ) | ||||
| 
 | ||||
|   console.log(chalk.blue('配置完成, 启动中...')) | ||||
|   exec('pm2 start app.yaml') | ||||
|   console.log(chalk.blue('应用成功启动, 打开浏览器体验一下吧.')) | ||||
|   process.exit() | ||||
| } | ||||
| 
 | ||||
| exports.stop = async function(dir) { | ||||
|   var confFile = path.join(dir, 'app.yaml') | ||||
|   if (fs.exists(confFile)) { | ||||
|     var confirm = await read('(你确定要停止应用吗? y/n): ') | ||||
|     if (confirm === 'y') { | ||||
|       exec('pm2 stop app.yaml') | ||||
|       console.log(chalk.blue('应用已经停止.')) | ||||
|     } | ||||
|   } else { | ||||
|     console.log(chalk.yellow('应用尚未配置启动...')) | ||||
|   } | ||||
|   process.exit() | ||||
| } | ||||
| 
 | ||||
| exports.restart = async function(dir) { | ||||
|   var confFile = path.join(dir, 'app.yaml') | ||||
|   if (fs.exists(confFile)) { | ||||
|     var confirm = await read('(你确定要重启应用吗? y/n): ') | ||||
|     if (confirm === 'y') { | ||||
|       exec('pm2 restart app.yaml') | ||||
|       console.log(chalk.blue('应用已经重启.')) | ||||
|     } | ||||
|   } else { | ||||
|     console.log(chalk.yellow('应用尚未配置启动...')) | ||||
|   } | ||||
|   process.exit() | ||||
| } | ||||
| 
 | ||||
| exports.remove = async function(dir) { | ||||
|   var confFile = path.join(dir, 'app.yaml') | ||||
|   if (fs.exists(confFile)) { | ||||
|     console.log(chalk.yellow('你确定要删除应用吗? ')) | ||||
|     console.log( | ||||
|       chalk.yellow('(该操作只是从守护进程列表中移除当前应用,不会删除任何文件)') | ||||
|     ) | ||||
|     var confirm = await read('(请确认操作 y/n): ') | ||||
|     if (confirm === 'y') { | ||||
|       exec('pm2 delete app.yaml') | ||||
|       console.log(chalk.blue('应用已经删除.')) | ||||
|     } | ||||
|   } else { | ||||
|     console.log(chalk.yellow('应用尚未配置启动...')) | ||||
|   } | ||||
|   process.exit() | ||||
| } | ||||
| 
 | ||||
| exports.status = async function(dir) { | ||||
|   var confFile = path.join(dir, 'app.yaml') | ||||
|   if (fs.exists(confFile)) { | ||||
|     exec('pm2 status app.yaml') | ||||
|   } else { | ||||
|     console.log(chalk.yellow('应用尚未配置启动...')) | ||||
|   } | ||||
|   process.exit() | ||||
| } | ||||
							
								
								
									
										22
									
								
								lib/tools.js
								
								
								
								
							
							
						
						
									
										22
									
								
								lib/tools.js
								
								
								
								
							|  | @ -1,22 +0,0 @@ | |||
| const child = require('child_process') | ||||
| const readline = require('readline') | ||||
| 
 | ||||
| exports.exec = function(cmd) { | ||||
|   return child.execSync(cmd, { | ||||
|     stdio: [process.stdin, process.stdout, process.stdout] | ||||
|   }) | ||||
| } | ||||
| 
 | ||||
| var rl = readline.createInterface({ | ||||
|   input: process.stdin, | ||||
|   output: process.stdout | ||||
| }) | ||||
| 
 | ||||
| exports.read = function(msg) { | ||||
|   return new Promise(r => { | ||||
|     rl.question(msg, _ => { | ||||
|       r(_.trim()) | ||||
|       rl.pause() | ||||
|     }) | ||||
|   }) | ||||
| } | ||||
							
								
								
									
										12
									
								
								package.json
								
								
								
								
							
							
						
						
									
										12
									
								
								package.json
								
								
								
								
							|  | @ -1,14 +1,16 @@ | |||
| { | ||||
|   "name": "@gm5/cli", | ||||
|   "description": "Five.js框架控制台工具", | ||||
|   "name": "create-five", | ||||
|   "description": "一个快速创建Five.js项目的小工具", | ||||
|   "type": "module", | ||||
|   "version": "1.0.0", | ||||
|   "author": "yutent <yutent.io@gmail.com>", | ||||
|   "bin": { | ||||
|     "five-cli": "index.js" | ||||
|     "create-five": "index.js" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "chalk": "^4.0.0", | ||||
|     "iofs": "^1.5.0" | ||||
|     "iofs": "^1.5.0", | ||||
|     "prompts": "^2.4.2", | ||||
|     "kolorist": "^1.6.0" | ||||
|   }, | ||||
|   "repository": { | ||||
|     "type": "git", | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue