Commit 8d5f2f61 authored by chenzexi's avatar chenzexi

‘end’

parents
node_modules
package-lock.json
\ No newline at end of file
const cloneGit = (config)=>{
const { inquirer, action, ...props } = config
props.log({ message: `**创建:根目录${action.param.proName}`, color: 'green' })
props.fs.mkdirSync(`${props.process.cwd()}\\${action.param.proName}`)
props.log({ message: '**开始:拉取模板', color: "green" })
props.exec(`git clone ${action.param.gitLinke} ${props.process.cwd()}\\${action.param.proName}`, (err) => {
// console.log(err)
if (!err) {
props.log({ message: '**拉取git模板成功', color: "green" })
} else {
console.log(err)
props.log({ message: '**拉取git模板失败,请检查git地址', color: 'red' })
}
})
}
module.exports = cloneGit
\ No newline at end of file
const collectProjectStrut = (config) => {
try {
const { collectId, inquirer, action, ...props } = config
const { dir, proName } = action.param
const projectStrut = [{ name: proName, type: "dir", path: `\\${proName}` }]
const dirList = props.fs.readdirSync(dir, {})
props.log({ message: `开始:收集路径${proName}项目结构`, color: "green" })
const readProjectStrut = (baseDir, files) => {
files.forEach(file => {
const realPath = `${baseDir}\\${file}`
const path = `\\${proName}${realPath.replace(dir, "")}`
const stat = props.fs.statSync(realPath)
props.log({ message: `收集:${realPath}`, color: "green" })
if (stat.isDirectory()) {
const childrenFiles = props.fs.readdirSync(realPath, {})
projectStrut.push({
name: file,
type: "dir",
path: path,
})
readProjectStrut(realPath, childrenFiles)
return
}
if (stat.isFile()) {
const childrenFileContent = props.fs.readFileSync(realPath)
projectStrut.push({
name: file,
type: "file",
path: path,
content: childrenFileContent.toString()
})
}
});
}
readProjectStrut(dir, dirList)
// console.log('fdsafdsa', JSON.stringify(projectStrut, null, 2))
props.fs.writeFileSync(props.path.resolve(__dirname, `../store/collect-${collectId}.json`), JSON.stringify(projectStrut, null, 2))
} catch (err) {
console.log('err', err)
}
}
const collectProject = (config) => {
const { inquirer, action, ...props } = config
inquirer
.prompt([
{
type: 'input', name: "name", message: "请输入收集的预设名称", validate: function (input) {
// Declare function as asynchronous, and save the done callback
const done = this.async();
if (!input) {
done('预设名不能为空');
return
}
if (input.length > 20) {
done('预设名不能超出20个字符');
return
}
done(null, true);
}
},
{ type: 'list', name: "type", message: "请选择收集的预设类型", choices: ['PC', 'Small'] },
{
type: 'input', name: "desc", message: "请输入收集的预设描述", validate: function (input) {
// Declare function as asynchronous, and save the done callback
const done = this.async();
if (!input) {
done('预设描述不能为空');
return
}
if (input.length > 100) {
done('预设描述不能超出100个字符');
return
}
done(null, true);
}
},
// { type: 'list', name: "storeType", message: "请选择收集的存储位置", choices: ['存储到指定git上', '存储到本地'] },
])
.then((answers) => {
// console.log('fdsfdsa', answers)
// if (answers.storeType == '存储到本地') {
// const collectId = props.uuid4()
// const list = props.store.getStore()
// list.push({
// name: answers.name,
// type: answers.type,
// desc: answers.desc,
// collectId: `collect-${collectId}`
// })
// collectProjectStrut({ collectId, ...config })
// props.store.saveStore(list, (err) => {
// if (err) {
// props.log({
// message: "保存收集预设失败",
// color: "red"
// })
// } else {
// props.log({
// message: "保存收集预设成功",
// color: "green"
// })
// }
// })
// }
const collectId = props.uuid4()
const list = props.store.getStore()
list.push({
name: answers.name,
type: answers.type,
desc: answers.desc,
collectId: `collect-${collectId}`
})
collectProjectStrut({ collectId, ...config })
props.store.saveStore(list, (err) => {
if (err) {
props.log({
message: "保存收集预设失败",
color: "red"
})
} else {
props.log({
message: "保存收集预设成功",
color: "green"
})
}
})
})
.catch((error) => {
if (error.isTtyError) {
// Prompt couldn't be rendered in the current environment
} else {
// Something else went wrong
}
});
}
module.exports = collectProject
\ No newline at end of file
const savePreinstall = (config) => {
return new Promise((resolve, reject) => {
const { isSavePreinstall, gitLinke, inquirer, action, ...props } = config
if (isSavePreinstall) {
const storeList = props.store.getStore()
const newStoreItem = { gitLinke }
inquirer.prompt([
{
type: 'input', name: "name", message: "请输入预设名称", validate: function (input) {
// Declare function as asynchronous, and save the done callback
const done = this.async();
if (!input) {
done('预设名不能为空');
return
}
if (input.length > 20) {
done('预设名不能超出20个字符');
return
}
done(null, true);
}
},
{ type: 'list', name: "type", message: "请选择预设类型", choices: ['PC', 'Small'] },
{
type: 'input', name: "desc", message: "请输入预设描述", validate: function (input) {
// Declare function as asynchronous, and save the done callback
const done = this.async();
if (!input) {
done('预设描述不能为空');
return
}
if (input.length > 100) {
done('预设描述不能超出100个字符');
return
}
done(null, true);
}
},
]).then(answers => {
Object.assign(newStoreItem, answers)
storeList.push(newStoreItem)
props.store.saveStore(storeList, () => {
resolve()
})
}).catch(err => {
resolve()
})
}
})
}
const createGit = (config) => {
const { inquirer, action, ...props } = config
inquirer.prompt([
{
type: 'input',
name: "gitLinke",
message: "拉取的git地址(http)",
validate: function (input) {
// Declare function as asynchronous, and save the done callback
const done = this.async();
if (!input) {
done('git地址不能为空');
return
}
done(null, true);
}
},
{
type: 'confirm',
name: 'isSavePreinstall',
message: "是否保持为预设",
default: "N"
}
]).then((answers) => {
savePreinstall({ isSavePreinstall: answers.isSavePreinstall, gitLinke: answers.gitLinke, ...config }).then(() => {
props.actions([
{
type: "cloneGit",
param: {
gitLinke: answers.gitLinke,
...action.param
}
}
], props)
})
}).catch(err => {
})
}
module.exports = createGit
\ No newline at end of file
const createMode = (config) => {
const { inquirer, action, ...props } = config
inquirer.prompt([
{
type: 'list',
name: 'createMode',
message: "请选择项目模板的创建模式?",
default: 0,
choices: ['创建PC端模板', '创建小程序模板', '从git上拉取模板', '选择预设中模板']
}
])
.then((answers) => {
// console.log('选择的结果', answers)
if (answers.createMode == '创建PC端模板') {
props.actions([{
type: 'createPC',
param:action.param
}], props)
}
if (answers.createMode == '创建小程序模板') {
props.actions([{
type: 'createSmallProgram',
param:action.param
}], props)
}
if (answers.createMode == '从git上拉取模板') {
props.actions([{
type: 'createGit',
param:action.param
}], props)
}
if(answers.createMode == '选择预设中模板'){
props.actions([{
type: 'createTemplate',
param:action.param
}], props)
}
})
.catch((error) => {
if (error.isTtyError) {
// Prompt couldn't be rendered in the current environment
} else {
// Something else went wrong
}
});
}
module.exports = createMode
\ No newline at end of file
const createPC = (config) => {
const { inquirer, action, ...props } = config
const defaultPCTemplate = require(`../store/${action.param.collectId || 'collect-default'}.json`)
props.log({
message: '开始:构建PC端模板',
color: "green"
})
defaultPCTemplate.forEach(item => {
const path = `${props.process.cwd()}${item.path.replace('collect-project', action.param.proName)}`
props.log({
message: `创建:${path}`,
color: "green"
})
if (item.type == 'dir') {
props.fs.mkdirSync(`${path}`)
return
}
if (item.type == 'file') {
props.fs.writeFileSync(`${path}`, item.content)
}
})
props.log({
message: '成功:构建PC端模板完成',
color: "green"
})
}
module.exports = createPC
\ No newline at end of file
const createSmallProgram = (config) => {
const { collectId,inquirer, action, ...props } = config
const defaultPCTemplate = require(`../store/${action.param.collectId || 'collect-small'}.json`)
props.log({
message: '开始:构建小程序模板',
color: "green"
})
defaultPCTemplate.forEach(item => {
const path = `${props.process.cwd()}${item.path.replace('collect-project', action.param.proName)}`
props.log({
message: `创建:${path}`,
color: "green"
})
if (item.type == 'dir') {
props.fs.mkdirSync(`${path}`)
return
}
if (item.type == 'file') {
props.fs.writeFileSync(`${path}`, item.content)
}
})
props.log({
message: '成功:构建小程序模板完成',
color: "green"
})
}
module.exports = createSmallProgram
\ No newline at end of file
const createTemplate = (config) => {
const { inquirer, action, ...props } = config
const storeList = props.store.getStore()
const preInstallList = storeList.map((item, index) => {
return `${index}_[${item.type}]${item.name}`
})
inquirer.prompt([
{
type: "list",
name: "selectPreinstall",
message: "请选择作为模板执行的预设",
default: 0,
choices: preInstallList
}
]).then(answers => {
const name = answers.selectPreinstall.split("_")
const target = storeList.find((item,index) => name[0] == index)
if (target && target.collectId && target.type == 'PC') {
props.actions([
{
type: "createPC",
param: {
collectId: target.collectId,
...action.param
}
}
], props)
return
}
if (target && target.collectId && target.type == 'Small') {
props.actions([
{
type: "createSmallProgram",
param: {
collectId: target.collectId,
...action.param
}
}
], props)
return
}
if (target && target.gitLinke) {
props.actions([
{
type: "cloneGit",
param: {
gitLinke: target.gitLinke,
...action.param
}
}
], props)
}
}).catch(err => {
})
}
module.exports = createTemplate
\ No newline at end of file
const inquirer = require('inquirer')
const actionsMap = {
createMode: require('./createMode'),
createPC: require('./createPC'),
createSmallProgram: require('./createSmallProgram'),
collectProject: require('./collectProject'),
createGit: require('./createGit'),
createTemplate: require('./createTemplate'),
cloneGit: require('./cloneGit')
}
function actions(actionArr, extra = {}) {
actionArr.forEach(action => {
if (action.type && actionsMap[action.type]) {
actionsMap[action.type]({
...extra,
action,
inquirer,
})
}
});
}
module.exports = actions
\ No newline at end of file
const collect = (props) => {
const { program, log, actions, fs } = props
program.command('collect')
.description('收集指定路径的项目结构并生成预设')
.argument('<projectDir>', '项目根目录路径')
.option('--proName,--proName <projectName>', '指定收集后的项目名称', 'collect-project')
.action((str, options) => {
if (!str) {
log({
message: "错误:项目根目录路径不能为空",
color: "red"
})
return
}
const hasDir = fs.existsSync(str)
if(!hasDir){
log({
message: `错误:项目根目录路径是无效的,请检查路径:${str}`,
color: "red"
})
return
}
const stat = fs.statSync(str)
if(!stat.isDirectory()){
log({
message: `错误:路径是无效的,必须为项目根目录文件夹路径,请检查路径:${str}`,
color: "red"
})
return
}
actions([{
type: 'collectProject',
param: {
dir: str,
proName:options?.proName
}
}], props)
})
}
module.exports = collect
\ No newline at end of file
const create = (props) => {
const { program, log, actions } = props
program.command('create')
.description('创建一个名称为<projectName>的项目')
.argument('<projectName>', '项目名称')
.action((str, options) => {
if (!str) {
log({
message: "错误:项目名称不能为空",
color: "red"
})
}
actions([{
type: 'createMode',
param:{
proName:str
}
}], props)
})
}
module.exports = create
\ No newline at end of file
const commandsMap = {
create:require("./create"),
preinstall:require('./preinstall'),
collect:require('./collect')
}
const registerCommands = (props)=>{
Object.values(commandsMap).forEach(commandFunc=>{
commandFunc(props)
})
}
module.exports = registerCommands
\ No newline at end of file
const preinstall = (props) => {
const { program, log, store } = props
program.command('preinstall')
.description('获取[preinstallName]预设的描述')
.argument('[preinstallName]', '预设名称')
.option('-l,-list', '获取所有预设列表')
.option('--t,--type <type>', '获取指定类型的预设列表')
.action((preinstallName, options) => {
let storeList = store.getStore() || []
if (!options.List && !options.type && !preinstallName) {
return
}
if(!options.List && !options.type && preinstallName){
const targetPreinstall = storeList.find(item=>item.name == preinstallName);
if(targetPreinstall){
const proinstallMap = {
name:'【预设名】',
type:'【预设类型】',
desc:'【预设描述】',
gitLinke:'【预设git地址】'
}
const proinstallLog = Object.keys(proinstallMap).reduce((pre,curr)=>{
if(targetPreinstall[curr]){
return pre+`${proinstallMap[curr]}${targetPreinstall[curr]}\n\n`
}
return pre
},'')
log({
message: `--------${targetPreinstall.name}预设信息---------\n\n${proinstallLog}--------${targetPreinstall.name}预设信息---------`,
color: 'green'
})
}else{
log({
message: `${preinstallName}预设不存在,请更换预设名`,
color: 'gray'
})
}
return
}
if (options.type) {
storeList = storeList.filter(item=>{
return item.type == options.type
})
}
storeList.forEach((storeItem, index) => {
log({
message: `|_${index+1}${log.text({
message: storeItem.type,
color:"green"
})}${storeItem.name}`,
color: 'gray'
})
});
})
}
module.exports = preinstall
\ No newline at end of file
const registerCommon = (props)=>{
const {program,log} = props
program.version('1.0.0','-v','脚手架当前版本号')
program.helpOption('-h','获取所有帮助信息')
program.addHelpCommand('help [command]','获取指定命令的帮助信息')
}
module.exports = registerCommon
\ No newline at end of file
#!/usr/bin/env node
const fs = require('fs')
const process = require('process')
const path = require('path')
const exec = require('child_process').exec
const { v4 } = require('uuid')
const { program } = require('commander');
const registerCommon = require('./common/index');
const registerCommands = require('./commands/index')
const store = require('./store/index')
const actions = require('./actions/index')
const log = require("./utils/log")
const props = {
program,
log,
store,
actions,
fs,
path,
uuid4: v4,
process,
exec
}
registerCommon(props)
registerCommands(props)
program.parse();
// console.log('fdsfasfd')
\ No newline at end of file
{
"name": "project-cli",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"bin": {
"project-cli": "./index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"chalk": "^4.1.2",
"commander": "^9.4.0",
"inquirer": "^8.0.0",
"uuid": "^9.0.0"
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
[
{
"name": "collect-project",
"type": "dir",
"path": "\\collect-project"
},
{
"name": ".editorconfig",
"type": "file",
"path": "\\collect-project\\.editorconfig",
"content": "# http://editorconfig.org\nroot = true\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.md]\ntrim_trailing_whitespace = false\n\n[Makefile]\nindent_style = tab\n"
},
{
"name": ".gitignore",
"type": "file",
"path": "\\collect-project\\.gitignore",
"content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/npm-debug.log*\n/yarn-error.log\n/yarn.lock\n/package-lock.json\n\n# production\n/dist\n\n# misc\n.DS_Store\n\n# umi\n/src/.umi\n/src/.umi-production\n/src/.umi-test\n/.env.local\n"
},
{
"name": ".prettierignore",
"type": "file",
"path": "\\collect-project\\.prettierignore",
"content": "**/*.md\n**/*.svg\n**/*.ejs\n**/*.html\npackage.json\n.umi\n.umi-production\n.umi-test\n"
},
{
"name": ".prettierrc",
"type": "file",
"path": "\\collect-project\\.prettierrc",
"content": "{\n \"singleQuote\": true,\n \"trailingComma\": \"all\",\n \"printWidth\": 80,\n \"overrides\": [\n {\n \"files\": \".prettierrc\",\n \"options\": { \"parser\": \"json\" }\n }\n ]\n}\n"
},
{
"name": ".umirc.ts",
"type": "file",
"path": "\\collect-project\\.umirc.ts",
"content": "import { defineConfig } from 'umi';\n\nexport default defineConfig({\n nodeModulesTransform: {\n type: 'none',\n },\n routes: [\n { path: '/', component: '@/pages/index' },\n ],\n fastRefresh: {},\n});\n"
},
{
"name": "mock",
"type": "dir",
"path": "\\collect-project\\mock"
},
{
"name": ".gitkeep",
"type": "file",
"path": "\\collect-project\\mock\\.gitkeep",
"content": ""
},
{
"name": "package.json",
"type": "file",
"path": "\\collect-project\\package.json",
"content": "{\n \"private\": true,\n \"scripts\": {\n \"start\": \"umi dev\",\n \"build\": \"umi build\",\n \"postinstall\": \"umi generate tmp\",\n \"prettier\": \"prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'\",\n \"test\": \"umi-test\",\n \"test:coverage\": \"umi-test --coverage\"\n },\n \"gitHooks\": {\n \"pre-commit\": \"lint-staged\"\n },\n \"lint-staged\": {\n \"*.{js,jsx,less,md,json}\": [\n \"prettier --write\"\n ],\n \"*.ts?(x)\": [\n \"prettier --parser=typescript --write\"\n ]\n },\n \"dependencies\": {\n \"@ant-design/pro-layout\": \"^6.5.0\",\n \"react\": \"17.x\",\n \"react-dom\": \"17.x\",\n \"umi\": \"^3.5.34\"\n },\n \"devDependencies\": {\n \"@types/react\": \"^17.0.0\",\n \"@types/react-dom\": \"^17.0.0\",\n \"@umijs/preset-react\": \"1.x\",\n \"@umijs/test\": \"^3.5.34\",\n \"lint-staged\": \"^10.0.7\",\n \"prettier\": \"^2.2.0\",\n \"typescript\": \"^4.1.2\",\n \"yorkie\": \"^2.0.0\"\n }\n}\n"
},
{
"name": "README.md",
"type": "file",
"path": "\\collect-project\\README.md",
"content": "# umi project\n\n## Getting Started\n\nInstall dependencies,\n\n```bash\n$ yarn\n```\n\nStart the dev server,\n\n```bash\n$ yarn start\n```\n"
},
{
"name": "src",
"type": "dir",
"path": "\\collect-project\\src"
},
{
"name": "pages",
"type": "dir",
"path": "\\collect-project\\src\\pages"
},
{
"name": "index.less",
"type": "file",
"path": "\\collect-project\\src\\pages\\index.less",
"content": ".title {\n background: rgb(121, 242, 157);\n}\n"
},
{
"name": "index.tsx",
"type": "file",
"path": "\\collect-project\\src\\pages\\index.tsx",
"content": "import styles from './index.less';\n\nexport default function IndexPage() {\n return (\n <div>\n <h1 className={styles.title}>Page index</h1>\n </div>\n );\n}\n"
},
{
"name": "tsconfig.json",
"type": "file",
"path": "\\collect-project\\tsconfig.json",
"content": "{\n \"compilerOptions\": {\n \"target\": \"esnext\",\n \"module\": \"esnext\",\n \"moduleResolution\": \"node\",\n \"resolveJsonModule\": true,\n \"importHelpers\": true,\n \"jsx\": \"react-jsx\",\n \"esModuleInterop\": true,\n \"sourceMap\": true,\n \"baseUrl\": \"./\",\n \"strict\": true,\n \"paths\": {\n \"@/*\": [\"src/*\"],\n \"@@/*\": [\"src/.umi/*\"]\n },\n \"allowSyntheticDefaultImports\": true\n },\n \"include\": [\n \"mock/**/*\",\n \"src/**/*\",\n \"config/**/*\",\n \".umirc.ts\",\n \"typings.d.ts\"\n ],\n \"exclude\": [\n \"node_modules\",\n \"lib\",\n \"es\",\n \"dist\",\n \"typings\",\n \"**/__test__\",\n \"test\",\n \"docs\",\n \"tests\"\n ]\n}\n"
},
{
"name": "typings.d.ts",
"type": "file",
"path": "\\collect-project\\typings.d.ts",
"content": "declare module '*.css';\ndeclare module '*.less';\ndeclare module '*.png';\ndeclare module '*.svg' {\n export function ReactComponent(\n props: React.SVGProps<SVGSVGElement>,\n ): React.ReactElement;\n const url: string;\n export default url;\n}\n"
}
]
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
const fs = require('fs')
const path = require("path")
const getStore = ()=>{
const storeList = require('./store.json');
if(storeList){
return storeList
}
return []
}
const saveStore = (newStore,callback)=>{
fs.writeFile(path.resolve(__dirname,'store.json'),JSON.stringify(newStore || [],null,2),(err)=>{
callback && callback(err)
})
}
module.exports = {
getStore,
saveStore
}
[
{
"name": "这是一个小程序的测试预设",
"type": "Small",
"desc": "用来测试小程序的预设",
"collectId": "collect-67ec5706-9222-4329-b9ed-dd468a89e1b9"
},
{
"name": "收集小程序的预设",
"type": "Small",
"desc": "测试收集",
"collectId": "collect-8d635ea2-e7dc-4dc5-958e-03c0c39249d5"
}
]
\ No newline at end of file
const chalk = require('chalk')
function log(config){
if(!config.message){
return
}
console.log(log.text(config))
}
log.text = (config)=>{
if(chalk[config.color]){
return chalk[config.color](config.message)
}
return ""
}
module.exports = log
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment