重构生成脚本
parent
9953ad30e9
commit
6ad6f94472
41
Readme.md
41
Readme.md
|
@ -4,48 +4,11 @@
|
||||||
/ _` | '_ ` _ \|___ \ _____ / __| | |
|
/ _` | '_ ` _ \|___ \ _____ / __| | |
|
||||||
| (_| | | | | | |___) |_____| (__| | |
|
| (_| | | | | | |___) |_____| (__| | |
|
||||||
\__, |_| |_| |_|____/ \___|_|_|
|
\__, |_| |_| |_|____/ \___|_|_|
|
||||||
|___/ 一键安装、管理Five.js框架的脚本工具
|
|___/ 一键安装 Five.js 框架的脚本工具
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
```bash
|
```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
|
|
||||||
* 优化操作提示
|
|
228
index.js
228
index.js
|
@ -1,109 +1,151 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/node
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 脚手架
|
*
|
||||||
* @author yutent<yutent.io@gmail.com>
|
* @author yutent<yutent.io@gmail.com>
|
||||||
* @date 2020/09/28 11:35:16
|
* @date 2022/10/10 15:17:36
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('iofs')
|
import { red, cyan, blue, grey } from 'kolorist'
|
||||||
const chalk = require('chalk')
|
import prompts from 'prompts'
|
||||||
const path = require('path')
|
import fs from 'iofs'
|
||||||
|
import { resolve, join, dirname } from 'path'
|
||||||
|
|
||||||
var pm2
|
import {
|
||||||
var pkg = require('./package.json')
|
writePackageJson,
|
||||||
var { do_init } = require('./lib/init')
|
writeGitIgnore,
|
||||||
var { start, stop, restart, remove, status } = require('./lib/pm2')
|
writePrettierrc,
|
||||||
|
writePm2File
|
||||||
|
} from './lib/demo-config.js'
|
||||||
|
import { writeMainJs, writeAppJs, writeModelJs } from './lib/demo-js.js'
|
||||||
|
|
||||||
var { arch, platform, version } = process
|
const CURRENT_DIR = process.cwd()
|
||||||
var os = { linux: 'Linux', darwin: 'MacOS', win: 'Windows' }
|
const root = dirname(import.meta.url.slice(process.platform === 'win32' ? 10 : 7))
|
||||||
var cwd = process.cwd()
|
const { version } = JSON.parse(fs.cat(join(root, './package.json')))
|
||||||
var args = process.argv.slice(2)
|
|
||||||
var action = args.shift()
|
|
||||||
|
|
||||||
try {
|
const DEFAULT_NAME = 'gm5-app'
|
||||||
pm2 = require('pm2/package.json')
|
|
||||||
} catch (error) {
|
let args = process.argv.slice(2)
|
||||||
print('#'.repeat(64))
|
let targetDir = ''
|
||||||
console.log(chalk.red('脚手架使用pm2作为守护进程, 请先安装pm2'))
|
|
||||||
console.log(chalk.green('npm i -g pm2'))
|
function isEmpty(dir) {
|
||||||
print('#'.repeat(64))
|
let list = fs.ls(dir)
|
||||||
|
if (list && list.length) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
function sleep(num = 1) {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, num * 1000))
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
process.exit()
|
||||||
}
|
}
|
||||||
|
|
||||||
function print(...args) {
|
!(async function () {
|
||||||
args[0] = args[0].padEnd(20, ' ')
|
switch (args[0]) {
|
||||||
if (args.length > 1) {
|
|
||||||
args.splice(1, 0, ' - ')
|
|
||||||
}
|
|
||||||
console.log.apply(null, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
function logo() {
|
|
||||||
return chalk.green.bold(` ____
|
|
||||||
__ _ _ __ ___ | ___|
|
|
||||||
/ _\` | '_ \` _ \\|___ \\
|
|
||||||
| (_| | | | | | |___) |
|
|
||||||
\\__, |_| |_| |_|____/
|
|
||||||
|___/`)
|
|
||||||
}
|
|
||||||
|
|
||||||
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', '查看工具的版本')
|
|
||||||
process.exit()
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (action) {
|
|
||||||
case 'init':
|
|
||||||
do_init(cwd)
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'start':
|
|
||||||
start(cwd, args[0])
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'stop':
|
|
||||||
stop(cwd)
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'st':
|
|
||||||
case 'status':
|
|
||||||
status(cwd)
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'r':
|
|
||||||
case 'restart':
|
|
||||||
restart(cwd)
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'del':
|
|
||||||
case 'delete':
|
|
||||||
remove(cwd)
|
|
||||||
break
|
|
||||||
|
|
||||||
case '-v':
|
case '-v':
|
||||||
print(pkg.version)
|
case '--version':
|
||||||
process.exit()
|
console.log('v' + version)
|
||||||
|
break
|
||||||
|
|
||||||
|
case '-h':
|
||||||
|
case '--help':
|
||||||
|
printHelp()
|
||||||
break
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print_help()
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
console.log()
|
||||||
|
|
||||||
|
if (res.projectName === '.') {
|
||||||
|
res.projectName = DEFAULT_NAME
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('指定的项目名为: %s', cyan(res.projectName))
|
||||||
|
console.log('项目目录为: %s', cyan(targetDir))
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
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",
|
"name": "create-five",
|
||||||
"description": "Five.js框架控制台工具",
|
"description": "一个快速创建Five.js项目的小工具",
|
||||||
|
"type": "module",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "yutent <yutent.io@gmail.com>",
|
"author": "yutent <yutent.io@gmail.com>",
|
||||||
"bin": {
|
"bin": {
|
||||||
"five-cli": "index.js"
|
"create-five": "index.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chalk": "^4.0.0",
|
"iofs": "^1.5.0",
|
||||||
"iofs": "^1.5.0"
|
"prompts": "^2.4.2",
|
||||||
|
"kolorist": "^1.6.0"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
Loading…
Reference in New Issue