jjb-cmd 1.0.10 → 1.0.12

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.
package/bin/command.js CHANGED
@@ -2,10 +2,12 @@
2
2
 
3
3
  const commander = require('commander');
4
4
  const cliScripts = require('../src/cli.pull.js');
5
+ const cliScripts2 = require('../src/cli.pull2.js');
6
+ const cliScripts3 = require('../src/cli.install/index.js');
5
7
  const MergeScripts = require('../src/cli.merge.js');
6
8
 
7
9
  commander.command('v').description('-- 查看版本').action(() => {
8
- console.log('当前版本 v1.0.0');
10
+ console.log('当前版本 v1.0.12');
9
11
  });
10
12
 
11
13
  commander.command('help').description('-- 帮助').action(() => {
@@ -13,7 +15,7 @@ commander.command('help').description('-- 帮助').action(() => {
13
15
  console.log('1.jjb-cmd v -- 查看版本。');
14
16
  console.log('2.jjb-cmd help -- 帮助。');
15
17
  console.log('3.jjb-cmd view res -- 预览资源。');
16
- console.log('4.jjb-cmd [actionName (有效值 pull)] [...args] -- 基础功能。');
18
+ console.log('4.jjb-cmd [actionName (有效值 pull | pull2)] [...args] -- 基础功能。');
17
19
  });
18
20
 
19
21
  commander.command('view res').description('-- 预览资源').action(() => {
@@ -23,13 +25,24 @@ commander.command('view res').description('-- 预览资源').action(() => {
23
25
 
24
26
  // pull 命令
25
27
  commander.command('pull -- <文件夹名称必填。>').description('-- 文件名称').action(res => {
28
+ console.log('pull命令已过时,新项目请使用pull2.');
26
29
  cliScripts(res);
27
30
  });
28
31
 
32
+ // pull 命令
33
+ commander.command('pull2 -- <文件夹名称必填。>').description('-- 文件名称').action(res => {
34
+ cliScripts2(res);
35
+ });
36
+
37
+ // install 安装
38
+ commander.command('install').description('-- 安装').action(res => {
39
+ cliScripts3(res);
40
+ });
41
+
29
42
  //多省多应用命令
30
43
  commander.command('mp -- <multi prov多省多应用启动dev>').description('-- multi prov多省多应用合并').action(res => {
31
44
  MergeScripts(res, 'mp');
32
- console.log('start test')
45
+ console.log('start test');
33
46
  });
34
47
 
35
48
  //多省单应用
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "jjb-cmd",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "jjb脚手架工具",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "node bin/command.js help",
8
- "publish": "npm publish"
7
+ "test": "node bin/command.js help"
9
8
  },
10
9
  "bin": {
11
10
  "jjb-cmd": "bin/command.js"
@@ -0,0 +1,39 @@
1
+ import dva from 'dva';
2
+ import ReactDOM from 'react-dom';
3
+ import { createBrowserHistory } from 'history';
4
+ import 'antd/dist/antd.less';
5
+
6
+ /**
7
+ * @description 注册app
8
+ * @param selector {string}
9
+ * @returns {{unmount: Function, mount: Function, bootstrap: Function}}
10
+ */
11
+ export const registerApplication = (selector = '#root') => {
12
+ const createHistory = createBrowserHistory();
13
+
14
+ const app = dva({ history: createHistory });
15
+ require('./models').automaticModels(app);
16
+
17
+ app.router(config => require('./router').AutomaticRouter({
18
+ ...config,
19
+ basename: process.env.app.basename
20
+ }));
21
+
22
+ const render = () => app.start(selector);
23
+
24
+ if (!window.__POWERED_BY_QIANKUN__) {
25
+ render();
26
+ }
27
+
28
+ return {
29
+ mount: () => render(),
30
+ unmount: props => {
31
+ const { container } = props;
32
+ const element = container
33
+ ? container.querySelector('#root')
34
+ : document.querySelector('#root');
35
+ ReactDOM.unmountComponentAtNode(element);
36
+ },
37
+ bootstrap: props => props
38
+ };
39
+ };
@@ -0,0 +1,16 @@
1
+ import dva from 'dva';
2
+ import ReactDOM from 'react-dom';
3
+ import { createBrowserHistory } from 'history';
4
+ import 'antd/dist/antd.less';
5
+
6
+ /**
7
+ * @description 注册app
8
+ * @param selector {string}
9
+ * @returns {{unmount: Function, mount: Function, bootstrap: Function}}
10
+ */
11
+ export const registerApplication = (selector = '#app-root') => {
12
+ const app = dva({ history: createBrowserHistory() });
13
+ require('./models').automaticModels(app);
14
+ app.router(config => require('./router').AutomaticRouter(config));
15
+ app.start(selector);
16
+ };
@@ -0,0 +1,124 @@
1
+ import React from 'react';
2
+ import { ConfigProvider, Result } from 'antd';
3
+ import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
4
+
5
+ /**
6
+ * @description react路由扫描器
7
+ * @param props {{app: object}}
8
+ */
9
+ function ReactRouterScanner (props) {
10
+ const paths = require.context('~/pages', true, /\.(jsx|js)$/).keys();
11
+ const symbolByEntry = 'Entry_index.js';
12
+ const symbolByContainer = 'Container_index.js';
13
+
14
+ /**
15
+ * @description 路由处理
16
+ * @param path {string}
17
+ * @return string
18
+ */
19
+ function routeHandle (path) {
20
+ return `/${path.replace(/\/index.js$/, '').split(/\//).map(a => {
21
+ a = a.replace(a[ 0 ], a[ 0 ].toLowerCase());
22
+ return a;
23
+ }).map(a => {
24
+ if (/^[a-zA-Z]+_[a-zA-Z]+$/.test(a)) {
25
+ return `:${a.split(/_/).join('')}`;
26
+ }
27
+ return a;
28
+ }).join('/')}`;
29
+ }
30
+
31
+ const routerMap = paths.map(path => {
32
+ const pure = path.replace(/^\.\//, '');
33
+ return {
34
+ path: pure === 'index.js'
35
+ ? '/'
36
+ : pure === symbolByContainer
37
+ ? '/container'
38
+ : path === symbolByEntry
39
+ ? '/entry'
40
+ : routeHandle(pure),
41
+ suffix: 'index.js',
42
+ component: require(`~/pages/${pure}`).default,
43
+ componentName: pure.replace(/\//g, '_')
44
+ };
45
+ });
46
+
47
+ const Main = routerMap.find(item => item.componentName === 'index.js');
48
+ const Entry = routerMap.find(item => item.componentName === symbolByEntry);
49
+ const Container = routerMap.find(item => item.componentName === symbolByContainer);
50
+ const ChildrenRoute = routerMap.filter(item => item.componentName.match(new RegExp('Container_')) && item.path !== '/container');
51
+ const ContainerComponent = Container
52
+ ? Container.component
53
+ : null;
54
+ return (
55
+ <Router
56
+ basename={window.__POWERED_BY_QIANKUN__
57
+ ? props.basename
58
+ : '/'}
59
+ >
60
+ <Switch>
61
+ {Main && (
62
+ <Route
63
+ exact
64
+ path={Main.path}
65
+ component={Main.component}
66
+ />
67
+ )}
68
+ {Entry && (
69
+ <Route
70
+ exact
71
+ path={Entry.path}
72
+ component={Entry.component}
73
+ />
74
+ )}
75
+ {Container && (
76
+ <Route
77
+ path={Container.path}
78
+ render={$props => (
79
+ <ContainerComponent {...$props}>
80
+ <Switch>
81
+ {ChildrenRoute.map((route, key) => (
82
+ <Route
83
+ exact
84
+ key={key}
85
+ path={route.path}
86
+ component={route.component}
87
+ />
88
+ ))}
89
+ </Switch>
90
+ </ContainerComponent>
91
+ )}
92
+ />
93
+ )}
94
+ <Route
95
+ path="*"
96
+ component={() => <Result title="非常抱歉您访问的地址暂时无法显示,请确认后再试!" />}
97
+ />
98
+ </Switch>
99
+ </Router>
100
+ );
101
+ }
102
+
103
+ /**
104
+ * @description 自动化路由组件
105
+ * @param app {object}
106
+ * @param basename {string}
107
+ * @return {JSX.Element}
108
+ */
109
+ export const AutomaticRouter = ({
110
+ app,
111
+ basename
112
+ }) => {
113
+ return (
114
+ <ConfigProvider
115
+ locale={require('antd/lib/locale/zh_CN').default}
116
+ prefixCls={require('../../../../package.json').antPrefix || 'ant'}
117
+ >
118
+ <ReactRouterScanner
119
+ app={app}
120
+ basename={basename}
121
+ />
122
+ </ConfigProvider>
123
+ );
124
+ };
@@ -0,0 +1,113 @@
1
+ import React from 'react';
2
+ import { ConfigProvider } from 'antd';
3
+ import { Route, Router, Switch } from 'dva/router';
4
+
5
+ /**
6
+ * @description react路由扫描器
7
+ * @param props {{app: object, history: any}}
8
+ */
9
+ function ReactRouterScanner (props) {
10
+ const paths = require.context('~/pages', true, /\.(jsx|js)$/).keys().filter(item => !item.match(/components/));
11
+ const symbolByEntry = 'Entry_index.js';
12
+ const symbolByContainer = 'Container_index.js';
13
+
14
+ /**
15
+ * @description 路由处理
16
+ * @param path {string}
17
+ * @return string
18
+ */
19
+ function routeHandle (path) {
20
+ return `/${path.replace(/\/index.js$/, '').split(/\//).map(a => {
21
+ a = a.replace(a[ 0 ], a[ 0 ].toLowerCase());
22
+ return a;
23
+ }).map(a => {
24
+ if (/^[a-zA-Z]+_[a-zA-Z]+$/.test(a)) {
25
+ return `:${a.split(/_/).join('')}`;
26
+ }
27
+ return a;
28
+ }).join('/')}`;
29
+ }
30
+
31
+ const routerMap = paths.map(path => {
32
+ const pure = path.replace(/^\.\//, '');
33
+ return {
34
+ path: pure === 'index.js'
35
+ ? '/'
36
+ : pure === symbolByContainer
37
+ ? '/container'
38
+ : path === symbolByEntry
39
+ ? '/entry'
40
+ : routeHandle(pure),
41
+ suffix: 'index.js',
42
+ component: require(`~/pages/${pure}`).default,
43
+ componentName: pure.replace(/\//g, '_')
44
+ };
45
+ });
46
+
47
+ const Main = routerMap.find(item => item.componentName === 'index.js');
48
+ const Entry = routerMap.find(item => item.componentName === symbolByEntry);
49
+ const Container = routerMap.find(item => item.componentName === symbolByContainer);
50
+ const ChildrenRoute = routerMap.filter(item => item.componentName.match(new RegExp('Container_')) && item.path !== '/container');
51
+ const ContainerComponent = Container
52
+ ? Container.component
53
+ : null;
54
+ return (
55
+ <Router history={props.history}>
56
+ <Switch location={history.location}>
57
+ {Main && (
58
+ <Route
59
+ exact
60
+ path={Main.path}
61
+ component={Main.component}
62
+ />
63
+ )}
64
+ {Entry && (
65
+ <Route
66
+ exact
67
+ path={Entry.path}
68
+ component={Entry.component}
69
+ />
70
+ )}
71
+ {Container && (
72
+ <Route
73
+ path={Container.path}
74
+ render={$props => (
75
+ <ContainerComponent {...$props}>
76
+ <Switch location={history.location}>
77
+ {ChildrenRoute.map((route, key) => (
78
+ <Route
79
+ exact
80
+ key={key}
81
+ path={route.path}
82
+ component={route.component}
83
+ />
84
+ ))}
85
+ </Switch>
86
+ </ContainerComponent>
87
+ )}
88
+ />
89
+ )}
90
+ </Switch>
91
+ </Router>
92
+ );
93
+ }
94
+
95
+ /**
96
+ * @description 自动化路由组件
97
+ * @param app {object}
98
+ * @param history {history}
99
+ * @return {JSX.Element}
100
+ */
101
+ export const AutomaticRouter = ({
102
+ app,
103
+ history
104
+ }) => {
105
+ return (
106
+ <ConfigProvider locale={require('antd/lib/locale/zh_CN').default}>
107
+ <ReactRouterScanner
108
+ app={app}
109
+ history={history}
110
+ />
111
+ </ConfigProvider>
112
+ );
113
+ };
@@ -0,0 +1,190 @@
1
+ const os = require('os');
2
+
3
+ exports.GIT_HOST = 'http://192.168.1.242:10985';
4
+ exports.GIT_TEMP_DIR = `jjbAssembly_${Date.now()}`;
5
+ exports.CLOUD_PROJECT = {
6
+ 'common': {
7
+ token: 'G4HJRsHr9D7Ssmixegw2',
8
+ projectId: 279
9
+ },
10
+ 'react-admin-component': {
11
+ token: 'FT3pKzxpRynFkmddJ9Bs',
12
+ projectId: 340
13
+ }
14
+ };
15
+ exports.TEMPLATE_FOLDER = `${os.tmpdir()}\\${exports.GIT_TEMP_DIR}`;
16
+ exports.CLI_DVA_ROUTER_SPA = `${__dirname}\\..\\cli.dva.router.spa.txt`;
17
+ exports.CLI_DVA_ROUTER_SAAS = `${__dirname}\\..\\cli.dva.router.saas.txt`;
18
+ exports.CLI_DVA_REGISTER_SPA = `${__dirname}\\..\\cli.dva.register.spa.txt`;
19
+ exports.CLI_DVA_REGISTER_SAAS = `${__dirname}\\..\\cli.dva.register.saas.txt`;
20
+ exports.CLI_DVA_ROUTER_PATH = '\\dva\\automatic\\router.js';
21
+ exports.CLI_DVA_REGISTER_PATH = '\\dva\\automatic\\register.js';
22
+
23
+ exports.COMMON_CONTENT_NOR_REPLACE = [
24
+ {
25
+ path: `\\tools\\index.js`,
26
+ replace: [
27
+ [
28
+ 'components',
29
+ 'jjb-react-admin-component'
30
+ ]
31
+ ]
32
+ },
33
+ {
34
+ path: `\\website\\index.js`,
35
+ replace: [
36
+ [
37
+ /const\srelation\s=\srequire\(`~\/application\/\${module.code}\/enumerate\/menu`\)\.default;/,
38
+ 'const relation = require(\'~/enumerate/menu\').default;'
39
+ ],
40
+ [
41
+ 'components',
42
+ 'jjb-react-admin-component'
43
+ ]
44
+ ]
45
+ }
46
+ ];
47
+
48
+ /**
49
+ * @description 需要替换的文本(单应用)
50
+ * @type {[{path: string, replace: string[][]}]}
51
+ */
52
+ exports.COMMON_CONTENT_SPA_REPLACE = [
53
+ {
54
+ path: `\\tools\\index.js`,
55
+ replace: [
56
+ [
57
+ 'return __planA();',
58
+ 'return process.env;'
59
+ ]
60
+ ]
61
+ }
62
+ ];
63
+
64
+ /**
65
+ * @description 需要替换的文本(微应用)
66
+ * @type {[{path: string, replace: string[][]}]}
67
+ */
68
+ exports.COMMON_CONTENT_MICRO_REPLACE = [
69
+ {
70
+ path: `\\tools\\index.js`,
71
+ replace: [
72
+ [
73
+ 'return __planA();',
74
+ 'return process.env.app;'
75
+ ]
76
+ ]
77
+ }
78
+ ];
79
+
80
+ /**
81
+ * @description react-admin-component 需要替换的文本
82
+ * @type {[{path: string, replace: string[][]},{path: string, replace: string[][]},{path: string, replace: string[][]},{path: string, replace: string[][]},{path: string, replace: string[][]},null,null,null,null]}
83
+ */
84
+ exports.COMPONENTS_CONTENT_REPLACE = [
85
+ {
86
+ path: `\\Editor\\index.js`,
87
+ replace: [
88
+ [
89
+ 'common/http',
90
+ 'jjb-common/http'
91
+ ],
92
+ [
93
+ 'common/crypto',
94
+ 'jjb-common/crypto'
95
+ ],
96
+ [
97
+ 'common/tools',
98
+ 'jjb-common/tools'
99
+ ]
100
+ ]
101
+ },
102
+ {
103
+ path: `\\RejectText\\index.js`,
104
+ replace: [
105
+ [
106
+ 'common/color',
107
+ 'jjb-common/color'
108
+ ]
109
+ ]
110
+ },
111
+ {
112
+ path: `\\RouterMenu\\index.js`,
113
+ replace: [
114
+ [
115
+ 'common/tools',
116
+ 'jjb-common/tools'
117
+ ]
118
+ ]
119
+ },
120
+ {
121
+ path: `\\FileUploader\\index.js`,
122
+ replace: [
123
+ [
124
+ 'common/http',
125
+ 'jjb-common/http'
126
+ ],
127
+ [
128
+ 'common/tools',
129
+ 'jjb-common/tools'
130
+ ]
131
+ ]
132
+ },
133
+ {
134
+ path: `\\ImageCropper\\index.js`,
135
+ replace: [
136
+ [
137
+ 'common/http',
138
+ 'jjb-common/http'
139
+ ],
140
+ [
141
+ 'common/tools',
142
+ 'jjb-common/tools'
143
+ ]
144
+ ]
145
+ },
146
+ {
147
+ path: `\\ImageUploader\\index.js`,
148
+ replace: [
149
+ [
150
+ 'common/http',
151
+ 'jjb-common/http'
152
+ ],
153
+ [
154
+ 'common/tools',
155
+ 'jjb-common/tools'
156
+ ]
157
+ ]
158
+ },
159
+ {
160
+ path: `\\PageHeaderBar\\index.js`,
161
+ replace: [
162
+ [
163
+ 'common/color',
164
+ 'jjb-common/color'
165
+ ]
166
+ ]
167
+ },
168
+ {
169
+ path: `\\RouterContainer\\index.js`,
170
+ replace: [
171
+ [
172
+ 'common/tools',
173
+ 'jjb-common/tools'
174
+ ]
175
+ ]
176
+ },
177
+ {
178
+ path: `\\RouterContainer\\components\\NavigationTab\\index.js`,
179
+ replace: [
180
+ [
181
+ 'common/website',
182
+ 'jjb-common/website'
183
+ ],
184
+ [
185
+ 'common/tools',
186
+ 'jjb-common/tools'
187
+ ]
188
+ ]
189
+ }
190
+ ];
@@ -0,0 +1,227 @@
1
+ const fs = require('fs');
2
+ const os = require('os');
3
+ const {
4
+ GIT_HOST,
5
+ GIT_TEMP_DIR,
6
+ CLOUD_PROJECT
7
+ } = require('./config');
8
+
9
+ /**
10
+ * @description 删除全部
11
+ * @param path {string} 路径
12
+ */
13
+ exports.f_rm_rf = function (path) {
14
+ if (fs.existsSync(path)) {
15
+ const list = fs.readdirSync(path);
16
+ for (let i = 0; i < list.length; i++) {
17
+ const item = list[ i ];
18
+ const vPath = `${path}/${item}`;
19
+ if (fs.statSync(vPath).isDirectory()) {
20
+ exports.f_rm_rf(vPath);
21
+ fs.rmdirSync(vPath);
22
+ } else {
23
+ fs.unlinkSync(vPath);
24
+ }
25
+ }
26
+ }
27
+ };
28
+
29
+ /**
30
+ * @typedef {object} GitResource
31
+ * @property {string} path
32
+ * @property {string} compress
33
+ * @property {string} repository
34
+ */
35
+
36
+ /**
37
+ * @description 拉取git资源
38
+ * @param installResources {Resource[]} 资源名称
39
+ * @return {GitResource[]}
40
+ */
41
+ exports.f_pull_git_repository = function (installResources = []) {
42
+ return installResources.map(item => {
43
+ const resource = CLOUD_PROJECT[ item.name ] || undefined;
44
+ const template = os.tmpdir();
45
+ return {
46
+ path: `${template}\\${GIT_TEMP_DIR}\\${item.name}.zip`,
47
+ compress: `${template}\\${GIT_TEMP_DIR}\\${item.name}_zip`,
48
+ repository: `${GIT_HOST}/api/v4/projects/${resource.projectId}/repository/archive.zip?private_token=${resource.token}&ref=master`
49
+ };
50
+ });
51
+ };
52
+
53
+ /**
54
+ * @description 扫描是否存在jjb.config.json
55
+ * @param root 路径
56
+ * @returns {boolean}
57
+ */
58
+ exports.f_scan_jjb_config_json = function (root) {
59
+ return fs.existsSync(`${root}\\jjb.config.json`);
60
+ };
61
+
62
+ /**
63
+ * @typedef {object} JJB_CONFIG_JSON
64
+ * @property {string} projectType
65
+ * @property {string} installTarget
66
+ * @property {Resource[]} installResources
67
+ */
68
+
69
+ /**
70
+ * @description 验证规则
71
+ * @param root {string} 路径
72
+ * @return {JJB_CONFIG_JSON}
73
+ */
74
+ exports.f_scan_jjb_config_json_rules = function (root) {
75
+ let jjb_config_json = {};
76
+ try {
77
+ jjb_config_json = JSON.parse(fs.readFileSync(`${root}\\jjb.config.json`).toString());
78
+ } catch (e) {
79
+ console.log('【Error】:[jjb.config.json]文件解析失败,请确认是否配置正确。');
80
+ process.exit(0);
81
+ }
82
+ if (!('projectType' in jjb_config_json)) {
83
+ console.log('【Error】:[jjb.config.json]文件配置无效,需要projectType属性。');
84
+ process.exit(0);
85
+ }
86
+ if (!('installTarget' in jjb_config_json)) {
87
+ console.log('【Error】:[jjb.config.json]文件配置无效,需要installTarget属性。');
88
+ process.exit(0);
89
+ }
90
+ if (!('installResources' in jjb_config_json)) {
91
+ console.log('【Error】:[jjb.config.json]文件配置无效,需要installResources属性。');
92
+ process.exit(0);
93
+ }
94
+ if (typeof jjb_config_json.projectType !== 'string') {
95
+ console.log('【Error】:[jjb.config.json.projectType]类型是一个string。');
96
+ process.exit(0);
97
+ }
98
+ if (![
99
+ 'multi',
100
+ 'spa',
101
+ 'uniapp',
102
+ 'micro-spa'
103
+ ].includes(jjb_config_json.projectType)) {
104
+ console.log('【Error】:[jjb.config.json.projectType]配置无效,有效值<multi | spa | micro-spa | uniapp>。');
105
+ process.exit(0);
106
+ }
107
+ if (typeof jjb_config_json.installTarget !== 'string') {
108
+ console.log('【Error】:[jjb.config.json.installTarget]类型是一个string。');
109
+ process.exit(0);
110
+ }
111
+ if (![
112
+ 'node_modules',
113
+ 'src'
114
+ ].includes(jjb_config_json.installTarget)) {
115
+ console.log('【Error】:[jjb.config.json.node_modules]配置无效,有效值<node_modules | src>。');
116
+ process.exit(0);
117
+ }
118
+ if (!Array.isArray(jjb_config_json.installResources)) {
119
+ console.log('【Error】:[jjb.config.json.installResources]类型是一个Array<string>。');
120
+ process.exit(0);
121
+ }
122
+ if (jjb_config_json.installResources.length === 0) {
123
+ console.log('【Error】:[jjb.config.json.installResources]无资源。');
124
+ process.exit(0);
125
+ }
126
+ const resources = exports.f_resolve_install_resources(jjb_config_json.installResources);
127
+ if (resources.map(item => item.name).filter(v => ![
128
+ 'common',
129
+ 'react-admin-component',
130
+ 'vue-unisass-component'
131
+ ].includes(v)).length !== 0) {
132
+ console.log('【Error】:[jjb.config.json.installResources]配置无效,有效值<common | react-admin-component | vue-unisass-component>。');
133
+ process.exit(0);
134
+ }
135
+ jjb_config_json.installResources = resources;
136
+ return jjb_config_json;
137
+ };
138
+
139
+ /**
140
+ * @description 创建package.json
141
+ * @param path {string} 路径
142
+ * @param name {string} 包名
143
+ * @param version {string} 版本
144
+ */
145
+ exports.f_create_package_json = function (path, name, version) {
146
+ fs.writeFileSync(`${path}\\package.json`, `{"name":"${name}","version":"${version}","main": "index.js"}`);
147
+ };
148
+
149
+ /**
150
+ * @typedef {object} Resource
151
+ * @property {string} name
152
+ * @property {string[]} importList
153
+ */
154
+
155
+ /**
156
+ * @description 分析resources
157
+ * @param installResources
158
+ * @return {Resource[]}
159
+ */
160
+ exports.f_resolve_install_resources = function (installResources = []) {
161
+ const resources = [];
162
+ if (Array.isArray(installResources)) {
163
+ installResources.forEach(resource => {
164
+ if (Array.isArray(resource)) {
165
+ const [ name, importList = [] ] = resource;
166
+ resources.push({
167
+ name,
168
+ importList
169
+ });
170
+ } else {
171
+ resources.push({
172
+ name: resource,
173
+ importList: []
174
+ });
175
+ }
176
+ });
177
+ }
178
+ return resources;
179
+ };
180
+
181
+ /**
182
+ * @description 更新项目package.json文件
183
+ * @param path {string} 路径
184
+ * @param name {string} 包名
185
+ * @param version {string} 版本
186
+ */
187
+ exports.f_update_project_package_json = function (path, name, version) {
188
+ const packageJSONFile = JSON.parse(fs.readFileSync(path).toString());
189
+ packageJSONFile.dependencies[ name ] = version;
190
+ fs.writeFileSync(path, JSON.stringify(packageJSONFile, null, 2));
191
+ };
192
+
193
+ /**
194
+ * @description 复制文件
195
+ * @param originSrc
196
+ * @param targetSrc
197
+ */
198
+ exports.f_file_copy = function (originSrc, targetSrc) {
199
+ fs.readdirSync(originSrc).forEach(dir => {
200
+ const oPath = `${originSrc}\\${dir}`;
201
+ const tPath = `${targetSrc}\\${dir}`;
202
+ if (fs.statSync(oPath).isDirectory()) {
203
+ fs.mkdirSync(tPath);
204
+ exports.f_file_copy(oPath, tPath);
205
+ } else {
206
+ fs.writeFileSync(tPath, fs.readFileSync(oPath).toString());
207
+ }
208
+ });
209
+ };
210
+
211
+ /**
212
+ * @description 替换文件操作
213
+ * @param source {[]} 替换源
214
+ * @param root {string} 路径
215
+ */
216
+ exports.f_content_replace = function (source = [], root) {
217
+ source.forEach(item => {
218
+ const path = root + item.path;
219
+ if (fs.existsSync(path)) {
220
+ let content = fs.readFileSync(path).toString();
221
+ item.replace.forEach(rep => {
222
+ content = content.replace(rep[ 0 ], rep[ 1 ]);
223
+ });
224
+ fs.writeFileSync(path, content);
225
+ }
226
+ });
227
+ };
@@ -0,0 +1,225 @@
1
+ const fs = require('fs');
2
+ const os = require('os');
3
+ const {
4
+ GIT_HOST,
5
+ GIT_TEMP_DIR,
6
+ CLOUD_PROJECT
7
+ } = require('./config');
8
+
9
+ /**
10
+ * @description 删除全部
11
+ * @param path {string} 路径
12
+ */
13
+ exports.f_rm_rf = function (path) {
14
+ if (fs.existsSync(path)) {
15
+ const list = fs.readdirSync(path);
16
+ for (let i = 0; i < list.length; i++) {
17
+ const item = list[ i ];
18
+ const vPath = `${path}/${item}`;
19
+ if (fs.statSync(vPath).isDirectory()) {
20
+ exports.f_rm_rf(vPath);
21
+ fs.rmdirSync(vPath);
22
+ } else {
23
+ fs.unlinkSync(vPath);
24
+ }
25
+ }
26
+ }
27
+ };
28
+
29
+ /**
30
+ * @typedef {object} GitResource
31
+ * @property {string} path
32
+ * @property {string} compress
33
+ * @property {string} repository
34
+ */
35
+
36
+ /**
37
+ * @description 拉取git资源
38
+ * @param installResources {Resource[]} 资源名称
39
+ * @return {GitResource[]}
40
+ */
41
+ exports.f_pull_git_repository = function (installResources = []) {
42
+ return installResources.map(item => {
43
+ const resource = CLOUD_PROJECT[ item.name ] || undefined;
44
+ const template = os.tmpdir();
45
+ return {
46
+ path: `${template}\\${GIT_TEMP_DIR}\\${item.name}.zip`,
47
+ compress: `${template}\\${GIT_TEMP_DIR}\\${item.name}_zip`,
48
+ repository: `${GIT_HOST}/api/v4/projects/${resource.projectId}/repository/archive.zip?private_token=${resource.token}&ref=master`
49
+ };
50
+ });
51
+ };
52
+
53
+ /**
54
+ * @description 扫描是否存在jjb.config.json
55
+ * @param root 路径
56
+ * @returns {boolean}
57
+ */
58
+ exports.f_scan_jjb_config_json = function (root) {
59
+ return fs.existsSync(`${root}\\jjb.config.json`);
60
+ };
61
+
62
+ /**
63
+ * @typedef {object} JJB_CONFIG_JSON
64
+ * @property {string} projectType
65
+ * @property {string} installTarget
66
+ * @property {Resource[]} installResources
67
+ */
68
+
69
+ /**
70
+ * @description 验证规则
71
+ * @param root {string} 路径
72
+ * @return {JJB_CONFIG_JSON}
73
+ */
74
+ exports.f_scan_jjb_config_json_rules = function (root) {
75
+ let jjb_config_json = {};
76
+ try {
77
+ jjb_config_json = JSON.parse(fs.readFileSync(`${root}\\jjb.config.json`).toString());
78
+ } catch (e) {
79
+ console.log('【Error】:[jjb.config.json]文件解析失败,请确认是否配置正确。');
80
+ process.exit(0);
81
+ }
82
+ if (!('projectType' in jjb_config_json)) {
83
+ console.log('【Error】:[jjb.config.json]文件配置无效,需要projectType属性。');
84
+ process.exit(0);
85
+ }
86
+ if (!('installTarget' in jjb_config_json)) {
87
+ console.log('【Error】:[jjb.config.json]文件配置无效,需要installTarget属性。');
88
+ process.exit(0);
89
+ }
90
+ if (!('installResources' in jjb_config_json)) {
91
+ console.log('【Error】:[jjb.config.json]文件配置无效,需要installResources属性。');
92
+ process.exit(0);
93
+ }
94
+ if (typeof jjb_config_json.projectType !== 'string') {
95
+ console.log('【Error】:[jjb.config.json.projectType]类型是一个string。');
96
+ process.exit(0);
97
+ }
98
+ if (![
99
+ 'multi',
100
+ 'spa',
101
+ 'micro-spa'
102
+ ].includes(jjb_config_json.projectType)) {
103
+ console.log('【Error】:[jjb.config.json.projectType]配置无效,有效值<multi | spa | micro-spa>。');
104
+ process.exit(0);
105
+ }
106
+ if (typeof jjb_config_json.installTarget !== 'string') {
107
+ console.log('【Error】:[jjb.config.json.installTarget]类型是一个string。');
108
+ process.exit(0);
109
+ }
110
+ if (![
111
+ 'node_modules',
112
+ 'src'
113
+ ].includes(jjb_config_json.installTarget)) {
114
+ console.log('【Error】:[jjb.config.json.node_modules]配置无效,有效值<node_modules | src>。');
115
+ process.exit(0);
116
+ }
117
+ if (!Array.isArray(jjb_config_json.installResources)) {
118
+ console.log('【Error】:[jjb.config.json.installResources]类型是一个Array<string>。');
119
+ process.exit(0);
120
+ }
121
+ if (jjb_config_json.installResources.length === 0) {
122
+ console.log('【Error】:[jjb.config.json.installResources]无资源。');
123
+ process.exit(0);
124
+ }
125
+ const resources = exports.f_resolve_install_resources(jjb_config_json.installResources);
126
+ if (resources.map(item => item.name).filter(v => ![
127
+ 'common',
128
+ 'react-admin-component'
129
+ ].includes(v)).length !== 0) {
130
+ console.log('【Error】:[jjb.config.json.installResources]配置无效,有效值<common | react-admin-component>。');
131
+ process.exit(0);
132
+ }
133
+ jjb_config_json.installResources = resources;
134
+ return jjb_config_json;
135
+ };
136
+
137
+ /**
138
+ * @description 创建package.json
139
+ * @param path {string} 路径
140
+ * @param name {string} 包名
141
+ * @param version {string} 版本
142
+ */
143
+ exports.f_create_package_json = function (path, name, version) {
144
+ fs.writeFileSync(`${path}\\package.json`, `{"name":"${name}","version":"${version}","main": "index.js"}`);
145
+ };
146
+
147
+ /**
148
+ * @typedef {object} Resource
149
+ * @property {string} name
150
+ * @property {string[]} importList
151
+ */
152
+
153
+ /**
154
+ * @description 分析resources
155
+ * @param installResources
156
+ * @return {Resource[]}
157
+ */
158
+ exports.f_resolve_install_resources = function (installResources = []) {
159
+ const resources = [];
160
+ if (Array.isArray(installResources)) {
161
+ installResources.forEach(resource => {
162
+ if (Array.isArray(resource)) {
163
+ const [ name, importList = [] ] = resource;
164
+ resources.push({
165
+ name,
166
+ importList
167
+ });
168
+ } else {
169
+ resources.push({
170
+ name: resource,
171
+ importList: []
172
+ });
173
+ }
174
+ });
175
+ }
176
+ return resources;
177
+ };
178
+
179
+ /**
180
+ * @description 更新项目package.json文件
181
+ * @param path {string} 路径
182
+ * @param name {string} 包名
183
+ * @param version {string} 版本
184
+ */
185
+ exports.f_update_project_package_json = function (path, name, version) {
186
+ const packageJSONFile = JSON.parse(fs.readFileSync(path).toString());
187
+ packageJSONFile.dependencies[ name ] = version;
188
+ fs.writeFileSync(path, JSON.stringify(packageJSONFile, null, 2));
189
+ };
190
+
191
+ /**
192
+ * @description 复制文件
193
+ * @param originSrc
194
+ * @param targetSrc
195
+ */
196
+ exports.f_file_copy = function (originSrc, targetSrc) {
197
+ fs.readdirSync(originSrc).forEach(dir => {
198
+ const oPath = `${originSrc}\\${dir}`;
199
+ const tPath = `${targetSrc}\\${dir}`;
200
+ if (fs.statSync(oPath).isDirectory()) {
201
+ fs.mkdirSync(tPath);
202
+ exports.f_file_copy(oPath, tPath);
203
+ } else {
204
+ fs.writeFileSync(tPath, fs.readFileSync(oPath).toString());
205
+ }
206
+ });
207
+ };
208
+
209
+ /**
210
+ * @description 替换文件操作
211
+ * @param source {[]} 替换源
212
+ * @param root {string} 路径
213
+ */
214
+ exports.f_content_replace = function (source = [], root) {
215
+ source.forEach(item => {
216
+ const path = root + item.path;
217
+ if (fs.existsSync(path)) {
218
+ let content = fs.readFileSync(path).toString();
219
+ item.replace.forEach(rep => {
220
+ content = content.replace(rep[ 0 ], rep[ 1 ]);
221
+ });
222
+ fs.writeFileSync(path, content);
223
+ }
224
+ });
225
+ };
package/src/cli.pull.js CHANGED
@@ -60,9 +60,11 @@ module.exports = input => {
60
60
  let commonToolsFile = fs.readFileSync(commonToolsPath).toString();
61
61
  let commonWebsiteFile = fs.readFileSync(commonWebsitePath).toString();
62
62
  commonToolsFile = commonToolsFile.replace('return __planA();', 'return process.env;');
63
- commonWebsiteFile = commonWebsiteFile.replace(/const\srelation\s=\srequire\(`\/src\/application\/\${module.code}\/enumerate\/menu`\)\.default;/, 'const relation = require(`/src/enumerate/menu`).default;');
63
+ commonWebsiteFile = commonWebsiteFile.replace(/const\srelation\s=\srequire\(`~\/application\/\${module.code}\/enumerate\/menu`\)\.default;/, "const relation = require('~/enumerate/menu').default;");
64
64
  fs.writeFileSync(commonToolsPath, commonToolsFile);
65
65
  fs.writeFileSync(commonWebsitePath, commonWebsiteFile);
66
+ fs.writeFileSync(`${srcDir}\\common\\dva\\automatic\\router.js`, fs.readFileSync(`${__dirname}\\cli.dva.router.spa.txt`).toString());
67
+ fs.writeFileSync(`${srcDir}\\common\\dva\\automatic\\register.js`, fs.readFileSync(`${__dirname}\\cli.dva.register.spa.txt`).toString());
66
68
  } else {
67
69
  fs.exists(srcDir + '\\' + 'common\\dva\\automatic\\index.js', has => {
68
70
  if (has) {
@@ -0,0 +1,377 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const os = require('os');
5
+ const path = require('path');
6
+ const utils = require('./util');
7
+ const request = require('request');
8
+ const compressing = require('compressing');
9
+
10
+ // GIT仓库
11
+ const GIT_HOST = 'http://192.168.1.242:10985';
12
+ // 临时存放目录
13
+ const GIT_TEMP_DIR = 'jjbAssembly';
14
+ // 项目列表,后期可存库
15
+ const CLOUD_PROJECT = {
16
+ 'common': {
17
+ token: 'G4HJRsHr9D7Ssmixegw2',
18
+ projectId: 279,
19
+ localName: 'common'
20
+ },
21
+ 'react-admin-component': {
22
+ token: 'FT3pKzxpRynFkmddJ9Bs',
23
+ projectId: 340,
24
+ localName: 'components'
25
+ }
26
+ };
27
+ // common 需要替换的文本(常规应用)
28
+ const COMMON_CONTENT_NOR_REPLACE = [
29
+ {
30
+ path: `\\tools\\index.js`,
31
+ replace: [
32
+ [
33
+ 'components',
34
+ 'jjb-react-admin-component'
35
+ ]
36
+ ]
37
+ },
38
+ {
39
+ path: `\\website\\index.js`,
40
+ replace: [
41
+ [
42
+ /const\srelation\s=\srequire\(`~\/application\/\${module.code}\/enumerate\/menu`\)\.default;/,
43
+ 'const relation = require(\'~/enumerate/menu\').default;'
44
+ ],
45
+ [
46
+ 'components',
47
+ 'jjb-react-admin-component'
48
+ ]
49
+ ]
50
+ }
51
+ ];
52
+ // common 需要替换的文本(单应用)
53
+ const COMMON_CONTENT_SPA_REPLACE = [
54
+ {
55
+ path: `\\tools\\index.js`,
56
+ replace: [
57
+ [
58
+ 'return __planA();',
59
+ 'return process.env;'
60
+ ]
61
+ ]
62
+ }
63
+ ];
64
+ // common 需要替换的文本(微应用)
65
+ const COMMON_CONTENT_MICRO_REPLACE = [
66
+ {
67
+ path: `\\tools\\index.js`,
68
+ replace: [
69
+ [
70
+ 'return __planA();',
71
+ 'return process.env.app;'
72
+ ]
73
+ ]
74
+ }
75
+ ];
76
+ // react-admin-component 需要替换的文本
77
+ const COMPONENTS_CONTENT_REPLACE = [
78
+ {
79
+ path: `\\Editor\\index.js`,
80
+ replace: [
81
+ [
82
+ 'common/http',
83
+ 'jjb-common/http'
84
+ ],
85
+ [
86
+ 'common/crypto',
87
+ 'jjb-common/crypto'
88
+ ],
89
+ [
90
+ 'common/tools',
91
+ 'jjb-common/tools'
92
+ ]
93
+ ]
94
+ },
95
+ {
96
+ path: `\\RejectText\\index.js`,
97
+ replace: [
98
+ [
99
+ 'common/color',
100
+ 'jjb-common/color'
101
+ ]
102
+ ]
103
+ },
104
+ {
105
+ path: `\\RouterMenu\\index.js`,
106
+ replace: [
107
+ [
108
+ 'common/tools',
109
+ 'jjb-common/tools'
110
+ ]
111
+ ]
112
+ },
113
+ {
114
+ path: `\\FileUploader\\index.js`,
115
+ replace: [
116
+ [
117
+ 'common/http',
118
+ 'jjb-common/http'
119
+ ],
120
+ [
121
+ 'common/tools',
122
+ 'jjb-common/tools'
123
+ ]
124
+ ]
125
+ },
126
+ {
127
+ path: `\\ImageCropper\\index.js`,
128
+ replace: [
129
+ [
130
+ 'common/http',
131
+ 'jjb-common/http'
132
+ ],
133
+ [
134
+ 'common/tools',
135
+ 'jjb-common/tools'
136
+ ]
137
+ ]
138
+ },
139
+ {
140
+ path: `\\ImageUploader\\index.js`,
141
+ replace: [
142
+ [
143
+ 'common/http',
144
+ 'jjb-common/http'
145
+ ],
146
+ [
147
+ 'common/tools',
148
+ 'jjb-common/tools'
149
+ ]
150
+ ]
151
+ },
152
+ {
153
+ path: `\\PageHeaderBar\\index.js`,
154
+ replace: [
155
+ [
156
+ 'common/color',
157
+ 'jjb-common/color'
158
+ ]
159
+ ]
160
+ },
161
+ {
162
+ path: `\\RouterContainer\\index.js`,
163
+ replace: [
164
+ [
165
+ 'common/tools',
166
+ 'jjb-common/tools'
167
+ ]
168
+ ]
169
+ },
170
+ {
171
+ path: `\\RouterContainer\\components\\NavigationTab\\index.js`,
172
+ replace: [
173
+ [
174
+ 'common/website',
175
+ 'jjb-common/website'
176
+ ],
177
+ [
178
+ 'common/tools',
179
+ 'jjb-common/tools'
180
+ ]
181
+ ]
182
+ }
183
+ ];
184
+
185
+ /**
186
+ * @description 生成UID
187
+ * @returns {string}
188
+ */
189
+ function uid () {
190
+ return Math.random().toString().substr(2);
191
+ }
192
+
193
+ module.exports = input => {
194
+ /* 下发项目路径 */
195
+ const root = path.resolve('./');
196
+ /* 下发包名 */
197
+ const packageName = `jjb-${input}`;
198
+ /* 下发包版本 */
199
+ const packageVerson = '1.0.0';
200
+ /* 下发项目src路径 */
201
+ const srcFolderPath = `${root}\\src`;
202
+ /* 临时文件名称 */
203
+ const templateFolderName = `template_${uid()}`;
204
+ /* 临时文件路径 */
205
+ const templateFolderPath = `${__dirname}\\${templateFolderName}`;
206
+ /* 下发安装包package.json */
207
+ const rootPackageJsonPath = `${root}\\package.json`;
208
+ /* 安装包路径 */
209
+ const rootNodeModulesPackagePath = `${root}\\node_modules\\jjb-${input}`;
210
+ try {
211
+ if (fs.existsSync(srcFolderPath)) {
212
+ const cloudObj = CLOUD_PROJECT[ input ] || undefined;
213
+ if (cloudObj) {
214
+ const tmpDir = os.tmpdir();
215
+ const zipPath = `${tmpDir}/${GIT_TEMP_DIR}/${input}.zip`;
216
+ const zipFolder = `${tmpDir}/${GIT_TEMP_DIR}/unzip/`;
217
+ utils.DeleteDirAllFile(`${tmpDir}/${GIT_TEMP_DIR}`, () => {
218
+ fs.mkdirSync(`${tmpDir}/${GIT_TEMP_DIR}`);
219
+ const stream = fs.createWriteStream(zipPath);
220
+ request(`${GIT_HOST}/api/v4/projects/${cloudObj.projectId}/repository/archive.zip?private_token=${cloudObj.token}&ref=master`)
221
+ .pipe(stream)
222
+ .on('close', () => {
223
+ fs.mkdirSync(zipFolder);
224
+ compressing.zip.uncompress(zipPath, zipFolder)
225
+ .then(() => {
226
+ setTimeout(() => {
227
+ fs.readdirSync(zipFolder).forEach(dirName => {
228
+ if (dirName.indexOf('-master-') !== -1) {
229
+ /* 删除下载的文件 */
230
+ utils.DeleteDirAllFile(`${srcFolderPath}\\${cloudObj.localName}`, () => {
231
+ /* 创建临时文件夹 */
232
+ fs.mkdirSync(templateFolderPath);
233
+ /* 拷贝解压后的文件到临时文件夹 */
234
+ utils.CopyFolder(zipFolder + dirName, templateFolderPath);
235
+ setTimeout(() => {
236
+ /* 如果输入文件名是common */
237
+ if (input === 'common') {
238
+ /* 判断是否为多应用 */
239
+ const isMutilate = fs.existsSync(`${srcFolderPath}\\application`);
240
+ if (isMutilate) {
241
+ /* 多应用模式下需要删除automatic文件夹 */
242
+ rm_rf(`${templateFolderPath}\\dva\\automatic`);
243
+ fs.rmdirSync(`${templateFolderPath}\\dva\\automatic`);
244
+ } else {
245
+ if (get_project_type(rootPackageJsonPath) === 'spa') {
246
+ /* 替换操作 */
247
+ content_replace(COMMON_CONTENT_SPA_REPLACE, templateFolderPath);
248
+ fs.writeFileSync(`${templateFolderPath}\\dva\\automatic\\router.js`, fs.readFileSync(`${__dirname}\\cli.dva.router.spa.txt`).toString());
249
+ fs.writeFileSync(`${templateFolderPath}\\dva\\automatic\\register.js`, fs.readFileSync(`${__dirname}\\cli.dva.register.spa.txt`).toString());
250
+ } else if (get_project_type(rootPackageJsonPath) === 'micro-spa') {
251
+ content_replace(COMMON_CONTENT_MICRO_REPLACE, templateFolderPath);
252
+ fs.writeFileSync(`${templateFolderPath}\\dva\\automatic\\router.js`, fs.readFileSync(`${__dirname}\\cli.dva.router.saas.txt`).toString());
253
+ fs.writeFileSync(`${templateFolderPath}\\dva\\automatic\\register.js`, fs.readFileSync(`${__dirname}\\cli.dva.register.saas.txt`).toString());
254
+ }
255
+ }
256
+ /* 替换操作 */
257
+ content_replace(COMMON_CONTENT_NOR_REPLACE, templateFolderPath);
258
+ }
259
+ /* 如果输入文件名是react-admin-component */
260
+ if (input === 'react-admin-component') {
261
+ /* 替换操作 */
262
+ content_replace(COMPONENTS_CONTENT_REPLACE, templateFolderPath);
263
+ }
264
+ rm_rf(`${templateFolderPath}\\.idea`);
265
+ if (fs.existsSync(`${templateFolderPath}\\.idea`)) {
266
+ fs.rmdirSync(`${templateFolderPath}\\.idea`);
267
+ }
268
+ if (fs.existsSync(`${templateFolderPath}\\.gitignore`)) {
269
+ fs.unlinkSync(`${templateFolderPath}\\.gitignore`);
270
+ }
271
+ /* 如果文件夹不存在 */
272
+ if (!fs.existsSync(rootNodeModulesPackagePath)) {
273
+ // 创建文件夹
274
+ fs.mkdirSync(rootNodeModulesPackagePath);
275
+ } else {
276
+ // 删除旧文件
277
+ rm_rf(rootNodeModulesPackagePath);
278
+ }
279
+ /* 复制文件到下发项目node_modules */
280
+ utils.CopyFolder(templateFolderPath, rootNodeModulesPackagePath, () => {
281
+ /* 删除所有临时文件 */
282
+ rm_rf(templateFolderPath);
283
+ /* 删除临时文件夹 */
284
+ fs.rmdirSync(templateFolderPath);
285
+ /* 创建下发包package.json */
286
+ create_package_json(rootNodeModulesPackagePath, packageName, packageVerson);
287
+ /* 下发完成更新下发项目package.json */
288
+ update_project_package_json(rootPackageJsonPath, packageName, packageVerson);
289
+ /* 完成操作 */
290
+ console.log(`【已安装】:${packageName} v${packageVerson}`);
291
+ });
292
+ }, 1000);
293
+ });
294
+ }
295
+ });
296
+ }, 2000);
297
+ });
298
+ });
299
+ });
300
+ } else {
301
+ console.error(`【Error】: 未获取到项目 ${input}`);
302
+ }
303
+ }
304
+ } catch (e) {
305
+ console.error('【Error】: 当前目录不存在src子目录,无法完成pull操作。');
306
+ }
307
+ };
308
+
309
+ /**
310
+ * @description 删除全部
311
+ * @param path
312
+ */
313
+ function rm_rf (path) {
314
+ if (fs.existsSync(path)) {
315
+ const list = fs.readdirSync(path);
316
+ for (let i = 0; i < list.length; i++) {
317
+ const item = list[ i ];
318
+ const vPath = `${path}/${item}`;
319
+ if (fs.statSync(vPath).isDirectory()) {
320
+ rm_rf(vPath);
321
+ fs.rmdirSync(vPath);
322
+ } else {
323
+ fs.unlinkSync(vPath);
324
+ }
325
+ }
326
+ }
327
+ }
328
+
329
+ /**
330
+ * @description 创建package.json
331
+ * @param path {string} 路径
332
+ * @param name {string} 包名
333
+ * @param version {string} 版本
334
+ */
335
+ function create_package_json (path, name, version) {
336
+ fs.writeFileSync(`${path}\\package.json`, `{"name":"${name}","version":"${version}","main": "index.js"}`);
337
+ }
338
+
339
+ /**
340
+ * @description 获取项目类型
341
+ * @param path {string} 路径
342
+ * @returns {string}
343
+ */
344
+ function get_project_type (path) {
345
+ const packageJSONFile = JSON.parse(fs.readFileSync(path).toString());
346
+ return packageJSONFile.projectType;
347
+ }
348
+
349
+ /**
350
+ * @description 更新项目package.json文件
351
+ * @param path {string} 路径
352
+ * @param name {string} 包名
353
+ * @param version {string} 版本
354
+ */
355
+ function update_project_package_json (path, name, version) {
356
+ const packageJSONFile = JSON.parse(fs.readFileSync(path).toString());
357
+ packageJSONFile.dependencies[ name ] = version;
358
+ fs.writeFileSync(path, JSON.stringify(packageJSONFile, null, 2));
359
+ }
360
+
361
+ /**
362
+ * @description 替换文件操作
363
+ * @param source {[]} 替换源
364
+ * @param root {string} 路径
365
+ */
366
+ function content_replace (source = [], root) {
367
+ source.forEach(item => {
368
+ const path = root + item.path;
369
+ if (fs.existsSync(path)) {
370
+ let content = fs.readFileSync(path).toString();
371
+ item.replace.forEach(rep => {
372
+ content = content.replace(rep[ 0 ], rep[ 1 ]);
373
+ });
374
+ fs.writeFileSync(path, content);
375
+ }
376
+ });
377
+ }