quan-cli 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ {
2
+ "semi": true,
3
+ "singleQuote": true,
4
+ "tabWidth": 2,
5
+ "printWidth": 120
6
+ }
package/README.md ADDED
File without changes
package/bin/index.js ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ // const path = require('path');
3
+ // const execa = require('execa');
4
+ // const modulePath = path.resolve(__dirname, '../lib/index.ts');
5
+ // try {
6
+ // execa.commandSync('ts-node ' + modulePath, {
7
+ // stdio: 'inherit',
8
+ // });
9
+ // } catch (e) {
10
+ // process.exit(1);
11
+ // }
12
+
13
+ require('../lib/index.js');
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./initAction"), exports);
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.InitAction = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ //@ts-ignore
10
+ const userhome_1 = __importDefault(require("userhome"));
11
+ const inquirer_1 = __importDefault(require("inquirer"));
12
+ const fs_extra_1 = __importDefault(require("fs-extra"));
13
+ const axios_1 = __importDefault(require("axios"));
14
+ //@ts-ignore
15
+ const npminstall_1 = __importDefault(require("npminstall"));
16
+ const utils_1 = require("../utils");
17
+ const config_1 = require("../config");
18
+ class InitAction {
19
+ constructor(option) {
20
+ this.cwdPath = process.cwd();
21
+ this.homePath = (0, userhome_1.default)();
22
+ this.basePath = option.packagePath || this.cwdPath;
23
+ this.force = option.force || false;
24
+ this.origin = option.origin || utils_1.NpmUtil.getNpmRegistry(true);
25
+ this.initAction();
26
+ }
27
+ //初始化
28
+ async initAction() {
29
+ utils_1.log.debug('homePath', this.homePath);
30
+ utils_1.log.debug('工作路径', this.cwdPath);
31
+ utils_1.log.debug('要创建的目录', this.basePath);
32
+ //路径不存在
33
+ this.checkPath();
34
+ this.checkForce();
35
+ await this.checkPrompt();
36
+ await this.getTemplate();
37
+ await this.selectTemplate();
38
+ await this.getTemplateVersion();
39
+ await this.install();
40
+ }
41
+ //检查路径是否可用
42
+ checkPath() {
43
+ if (!fs_1.default.existsSync(this.basePath)) {
44
+ utils_1.log.error('error', '路径不存在,请重试!');
45
+ process.exit(1);
46
+ }
47
+ }
48
+ //force清空目录
49
+ checkForce() {
50
+ const isEmpty = utils_1.FileUtil.isEmptyDir(this.basePath);
51
+ if (!isEmpty && this.force) {
52
+ fs_extra_1.default.emptyDirSync(this.basePath);
53
+ }
54
+ }
55
+ //checkPrompt 清空目录
56
+ async checkPrompt() {
57
+ const isEmpty = utils_1.FileUtil.isEmptyDir(this.basePath);
58
+ if (!isEmpty) {
59
+ const isDelDir = await this.getDelPrompt();
60
+ if (!isDelDir) {
61
+ process.exit(1);
62
+ }
63
+ else {
64
+ fs_extra_1.default.emptyDirSync(this.basePath);
65
+ }
66
+ }
67
+ }
68
+ async getDelPrompt() {
69
+ const { isDelDir } = await inquirer_1.default.prompt([
70
+ {
71
+ type: 'confirm',
72
+ name: 'isDelDir',
73
+ message: `是否清空${this.basePath}。注意(文件无法恢复,请谨慎操作)`,
74
+ },
75
+ ]);
76
+ return isDelDir;
77
+ }
78
+ async getTemplateVersion() {
79
+ return await utils_1.NpmUtil.getLatestVersion(this.template.store, this.origin);
80
+ }
81
+ async install() {
82
+ const version = await this.getTemplateVersion();
83
+ utils_1.log.debug(`执行安装:${this.template.store},版本:${version}`);
84
+ utils_1.log.debug(path_1.default.resolve(this.homePath, config_1.paths.ROOT_PATH, config_1.paths.TARGET_PATH));
85
+ const loadingStart = (0, utils_1.loading)('正在下载模板...');
86
+ await (0, utils_1.sleep)(1500);
87
+ await (0, npminstall_1.default)({
88
+ root: path_1.default.resolve(this.homePath, config_1.paths.ROOT_PATH, config_1.paths.TARGET_PATH),
89
+ registry: this.origin,
90
+ pkgs: [{ name: this.template.store, version: version }],
91
+ });
92
+ this.copy(this.template.store, version);
93
+ loadingStart.stop(true);
94
+ utils_1.log.info('info', '模板下载完成');
95
+ }
96
+ //執行copy
97
+ copy(name, version) {
98
+ const packageName = utils_1.NpmUtil.getPackageDirName(name, version);
99
+ const originPath = path_1.default.resolve(this.homePath, config_1.paths.ROOT_PATH, config_1.paths.TARGET_PATH, 'node_modules', packageName, 'template');
100
+ const targetPath = this.basePath;
101
+ fs_extra_1.default.copySync(originPath, targetPath);
102
+ process.exit(1);
103
+ }
104
+ async selectTemplate() {
105
+ const { template } = await inquirer_1.default.prompt([
106
+ {
107
+ type: 'list',
108
+ name: 'template',
109
+ message: '请选择要下载的模板',
110
+ choices: this.templates.map((item) => item.name),
111
+ },
112
+ ]);
113
+ this.template = this.templates.filter((item) => item.name === template)[0];
114
+ }
115
+ async getTemplate() {
116
+ const { data: { data }, } = await (0, axios_1.default)({
117
+ method: 'get',
118
+ url: 'http://101.42.154.196/quan-cli/getAllTemplate',
119
+ });
120
+ this.templates = data;
121
+ }
122
+ }
123
+ exports.InitAction = InitAction;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./package"), exports);
18
+ __exportStar(require("./path"), exports);
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pack = void 0;
4
+ const utils_1 = require("../utils");
5
+ const packJson = require('../../package');
6
+ utils_1.log.debug('package', JSON.stringify(packJson));
7
+ exports.pack = packJson;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.paths = void 0;
4
+ var paths;
5
+ (function (paths) {
6
+ paths["ROOT_PATH"] = ".quan-cli";
7
+ paths["TARGET_PATH"] = "dependencies";
8
+ })(paths = exports.paths || (exports.paths = {}));
package/lib/index.js ADDED
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const commander_1 = require("commander");
7
+ const semver_1 = __importDefault(require("semver"));
8
+ const minimist_1 = __importDefault(require("minimist"));
9
+ const utils_1 = require("./utils");
10
+ const config_1 = require("./config");
11
+ const actions_1 = require("./actions");
12
+ class Cli {
13
+ constructor() {
14
+ this.program = commander_1.program;
15
+ this.init();
16
+ }
17
+ async init() {
18
+ this.checkEnv();
19
+ await this.checkCli();
20
+ this.registerCommand();
21
+ }
22
+ checkEnv() {
23
+ const args = (0, minimist_1.default)(process.argv.slice(2));
24
+ if (args.debug || args.d) {
25
+ (0, utils_1.setLogLevel)('debug');
26
+ }
27
+ }
28
+ async checkCli() {
29
+ const currentVersion = config_1.pack.version;
30
+ let lastVersion;
31
+ try {
32
+ lastVersion = await utils_1.NpmUtil.getLatestVersion('cyq-cli-template-vue3');
33
+ }
34
+ catch (e) {
35
+ lastVersion = '0.0.0';
36
+ }
37
+ if (!semver_1.default.lt(currentVersion, lastVersion)) {
38
+ utils_1.log.info('tip', `quan-cli最新版本${lastVersion} 当前版本${currentVersion}`);
39
+ utils_1.log.info('tip', `使用npm install quan-cli 更新`);
40
+ }
41
+ utils_1.log.debug('quan-cli当前版本', currentVersion);
42
+ utils_1.log.debug('quan-cli最新版本', lastVersion);
43
+ }
44
+ registerCommand() {
45
+ this.program.name(config_1.pack.name).version(config_1.pack.version).description(`quan-cli version:${config_1.pack.version}`);
46
+ this.program.option('-d, --debug', '开启debug模式(打印信息)');
47
+ this.program
48
+ .command('init [type]')
49
+ .description('quan-cli 初始化项目')
50
+ .option('-p, --packagePath <packagePath>', '指定init包的路径')
51
+ .option('-f, --force', '覆盖当前项目')
52
+ .option('-o, --origin <origin>', '指定初始化使用的npm源')
53
+ .action((str, option) => {
54
+ utils_1.log.debug('输入参数', option);
55
+ new actions_1.InitAction(option);
56
+ });
57
+ this.program.parse();
58
+ }
59
+ }
60
+ new Cli();
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FileUtil = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ class FileUtil {
9
+ }
10
+ exports.FileUtil = FileUtil;
11
+ FileUtil.isEmptyDir = (path) => {
12
+ let fileList = fs_1.default.readdirSync(path);
13
+ fileList = fileList.filter((file) => ['node_modules', 'src', 'tsconfig.json', 'package.json', '.git', '.DS_Store'].includes(file));
14
+ if (fileList && fileList.length > 0) {
15
+ return false;
16
+ }
17
+ else {
18
+ return true;
19
+ }
20
+ };
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./file"), exports);
18
+ __exportStar(require("./log"), exports);
19
+ __exportStar(require("./npm"), exports);
20
+ __exportStar(require("./loading"), exports);
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sleep = exports.loading = void 0;
4
+ const cli_spinner_1 = require("cli-spinner");
5
+ const loading = (msg, spinnerString = '|/-\\') => {
6
+ const spinner = new cli_spinner_1.Spinner(`${msg}.. %s`);
7
+ spinner.setSpinnerString(spinnerString);
8
+ spinner.start();
9
+ return spinner;
10
+ };
11
+ exports.loading = loading;
12
+ const sleep = async (time = 0) => {
13
+ await new Promise((resolve) => {
14
+ let timer = setTimeout(() => {
15
+ resolve(undefined);
16
+ clearTimeout(timer);
17
+ }, time);
18
+ });
19
+ };
20
+ exports.sleep = sleep;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.setLogLevel = exports.log = void 0;
7
+ const npmlog_1 = __importDefault(require("npmlog"));
8
+ exports.log = npmlog_1.default;
9
+ npmlog_1.default.level = process.env.LOG_LEVEL || 'info';
10
+ npmlog_1.default.heading = 'quan-cli';
11
+ npmlog_1.default.addLevel('success', 2000, { fg: 'green', bold: true });
12
+ npmlog_1.default.addLevel('debug', 1000, { fg: 'blue', bg: 'black' });
13
+ const setLogLevel = (level) => {
14
+ npmlog_1.default.level = level;
15
+ npmlog_1.default.debug(npmlog_1.default.level + '模式开启');
16
+ };
17
+ exports.setLogLevel = setLogLevel;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.NpmUtil = void 0;
7
+ const log_1 = require("./log");
8
+ const axios_1 = __importDefault(require("axios"));
9
+ class NpmUtil {
10
+ // 获取 registry 信息
11
+ static getNpmRegistry(isOriginal = false) {
12
+ return isOriginal ? 'https://registry.npmjs.org' : 'https://registry.npm.taobao.org';
13
+ }
14
+ //获取npm最新版本号
15
+ static async getLatestVersion(packageName, origin = NpmUtil.getNpmRegistry(true)) {
16
+ log_1.log.debug('链接' + origin + '/' + packageName);
17
+ const { data } = await (0, axios_1.default)({
18
+ method: 'get',
19
+ url: origin + '/' + packageName,
20
+ });
21
+ const version = data['dist-tags'].latest;
22
+ return version;
23
+ }
24
+ //获取npm包在文件中的名字
25
+ static getPackageDirName(packageName, version) {
26
+ return '_' + packageName + '@' + version + '@' + packageName;
27
+ }
28
+ }
29
+ exports.NpmUtil = NpmUtil;
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "quan-cli",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "quan-cli": "./bin/index.js"
8
+ },
9
+ "scripts": {
10
+ "dev": "ts-node-dev --respawn --transpile-only src/index.ts ",
11
+ "build": "tsc --build",
12
+ "prettier": "prettier --write ."
13
+ },
14
+ "keywords": [],
15
+ "author": "",
16
+ "license": "ISC",
17
+ "type": "commonjs",
18
+ "devDependencies": {
19
+ "@types/axios": "^0.14.0",
20
+ "@types/cli-spinner": "^0.2.1",
21
+ "@types/commander": "^2.12.2",
22
+ "@types/execa": "^2.0.0",
23
+ "@types/fs-extra": "^9.0.13",
24
+ "@types/inquirer": "^8.2.1",
25
+ "@types/minimist": "^1.2.2",
26
+ "@types/node": "^18.6.3",
27
+ "@types/npmlog": "^4.1.4",
28
+ "@types/semver": "^7.3.10",
29
+ "npmlog": "^6.0.2",
30
+ "prettier": "^2.7.1",
31
+ "ts-loader": "^9.3.1",
32
+ "ts-node": "^10.9.1",
33
+ "ts-node-dev": "^2.0.0",
34
+ "webpack": "^5.74.0",
35
+ "webpack-cli": "^4.10.0"
36
+ },
37
+ "dependencies": {
38
+ "axios": "^0.27.2",
39
+ "cli-spinner": "^0.2.10",
40
+ "commander": "^9.4.0",
41
+ "execa": "^5.1.1",
42
+ "fs-extra": "^10.1.0",
43
+ "inquirer": "^8.2.4",
44
+ "minimist": "^1.2.6",
45
+ "npminstall": "^5.8.1",
46
+ "semver": "^7.3.7",
47
+ "ts-node": "^10.9.1",
48
+ "typescript": "^4.7.4",
49
+ "userhome": "^1.0.0"
50
+ }
51
+ }
@@ -0,0 +1 @@
1
+ export * from './initAction';
@@ -0,0 +1,143 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ //@ts-ignore
4
+ import userhome from 'userhome';
5
+ import inquirer from 'inquirer';
6
+ import fse from 'fs-extra';
7
+ import axios from 'axios';
8
+ //@ts-ignore
9
+ import npminstall from 'npminstall';
10
+ import { log, FileUtil, NpmUtil, loading, sleep } from '../utils';
11
+ import { paths } from '../config';
12
+
13
+ export interface initCommand {
14
+ packagePath?: string;
15
+ force?: boolean;
16
+ origin?: string;
17
+ }
18
+
19
+ export interface template {
20
+ id: number;
21
+ name: string;
22
+ store: string;
23
+ }
24
+
25
+ export class InitAction {
26
+ cwdPath: string = process.cwd();
27
+ basePath!: string;
28
+ force: boolean;
29
+ templates!: template[];
30
+ template!: template;
31
+ origin!: string;
32
+ homePath: string = userhome();
33
+ constructor(option: initCommand) {
34
+ this.basePath = option.packagePath || this.cwdPath;
35
+ this.force = option.force || false;
36
+ this.origin = option.origin || NpmUtil.getNpmRegistry(true);
37
+ this.initAction();
38
+ }
39
+ //初始化
40
+ async initAction() {
41
+ log.debug('homePath', this.homePath);
42
+ log.debug('工作路径', this.cwdPath);
43
+ log.debug('要创建的目录', this.basePath);
44
+ //路径不存在
45
+ this.checkPath();
46
+ this.checkForce();
47
+ await this.checkPrompt();
48
+ await this.getTemplate();
49
+ await this.selectTemplate();
50
+ await this.getTemplateVersion();
51
+ await this.install();
52
+ }
53
+ //检查路径是否可用
54
+ checkPath() {
55
+ if (!fs.existsSync(this.basePath)) {
56
+ log.error('error', '路径不存在,请重试!');
57
+ process.exit(1);
58
+ }
59
+ }
60
+ //force清空目录
61
+ checkForce() {
62
+ const isEmpty = FileUtil.isEmptyDir(this.basePath);
63
+ if (!isEmpty && this.force) {
64
+ fse.emptyDirSync(this.basePath);
65
+ }
66
+ }
67
+ //checkPrompt 清空目录
68
+ async checkPrompt() {
69
+ const isEmpty = FileUtil.isEmptyDir(this.basePath);
70
+ if (!isEmpty) {
71
+ const isDelDir = await this.getDelPrompt();
72
+ if (!isDelDir) {
73
+ process.exit(1);
74
+ } else {
75
+ fse.emptyDirSync(this.basePath);
76
+ }
77
+ }
78
+ }
79
+ async getDelPrompt() {
80
+ const { isDelDir } = await inquirer.prompt([
81
+ {
82
+ type: 'confirm',
83
+ name: 'isDelDir',
84
+ message: `是否清空${this.basePath}。注意(文件无法恢复,请谨慎操作)`,
85
+ },
86
+ ]);
87
+ return isDelDir;
88
+ }
89
+ async getTemplateVersion() {
90
+ return await NpmUtil.getLatestVersion(this.template.store, this.origin);
91
+ }
92
+ async install() {
93
+ const version = await this.getTemplateVersion();
94
+ log.debug(`执行安装:${this.template.store},版本:${version}`);
95
+ log.debug(path.resolve(this.homePath, paths.ROOT_PATH, paths.TARGET_PATH));
96
+ const loadingStart = loading('正在下载模板...');
97
+ await sleep(1500);
98
+ await npminstall({
99
+ root: path.resolve(this.homePath, paths.ROOT_PATH, paths.TARGET_PATH),
100
+ registry: this.origin,
101
+ pkgs: [{ name: this.template.store, version: version }],
102
+ });
103
+ this.copy(this.template.store, version);
104
+ loadingStart.stop(true);
105
+ log.info('info', '模板下载完成');
106
+ }
107
+ //執行copy
108
+ copy(name: string, version: string) {
109
+ const packageName = NpmUtil.getPackageDirName(name, version);
110
+ const originPath = path.resolve(
111
+ this.homePath,
112
+ paths.ROOT_PATH,
113
+ paths.TARGET_PATH,
114
+ 'node_modules',
115
+ packageName,
116
+ 'template'
117
+ );
118
+ const targetPath = this.basePath;
119
+ fse.copySync(originPath, targetPath);
120
+ process.exit(1);
121
+ }
122
+ async selectTemplate() {
123
+ const { template } = await inquirer.prompt([
124
+ {
125
+ type: 'list',
126
+ name: 'template',
127
+ message: '请选择要下载的模板',
128
+ choices: this.templates.map((item) => item.name),
129
+ },
130
+ ]);
131
+ this.template = this.templates.filter((item) => item.name === template)[0];
132
+ }
133
+ async getTemplate() {
134
+
135
+ const {
136
+ data: { data },
137
+ } = await axios({
138
+ method: 'get',
139
+ url: 'http://101.42.154.196/quan-cli/getAllTemplate',
140
+ });
141
+ this.templates = data;
142
+ }
143
+ }
@@ -0,0 +1,2 @@
1
+ export * from './package';
2
+ export * from './path';
@@ -0,0 +1,12 @@
1
+ import { log } from '../utils';
2
+ const packJson = require('../../package');
3
+
4
+ log.debug('package', JSON.stringify(packJson));
5
+
6
+ export interface Package {
7
+ name: string;
8
+ version: string;
9
+ author: string;
10
+ }
11
+
12
+ export const pack = packJson as Package;
@@ -0,0 +1,4 @@
1
+ export enum paths {
2
+ ROOT_PATH = '.quan-cli',
3
+ TARGET_PATH = 'dependencies',
4
+ }
package/src/index.ts ADDED
@@ -0,0 +1,56 @@
1
+ import { program, Command } from 'commander';
2
+ import semver from 'semver';
3
+ import minimist from 'minimist';
4
+ import { log, setLogLevel, NpmUtil } from './utils';
5
+ import { pack } from './config';
6
+ import { initCommand, InitAction } from './actions';
7
+
8
+ class Cli {
9
+ program: Command = program;
10
+ constructor() {
11
+ this.init();
12
+ }
13
+ async init() {
14
+ this.checkEnv();
15
+ await this.checkCli();
16
+ this.registerCommand();
17
+ }
18
+ checkEnv() {
19
+ const args = minimist(process.argv.slice(2));
20
+ if (args.debug || args.d) {
21
+ setLogLevel('debug');
22
+ }
23
+ }
24
+ async checkCli() {
25
+ const currentVersion = pack.version;
26
+ let lastVersion;
27
+ try {
28
+ lastVersion = await NpmUtil.getLatestVersion('cyq-cli-template-vue3');
29
+ } catch (e) {
30
+ lastVersion = '0.0.0';
31
+ }
32
+ if (!semver.lt(currentVersion, lastVersion)) {
33
+ log.info('tip', `quan-cli最新版本${lastVersion} 当前版本${currentVersion}`);
34
+ log.info('tip', `使用npm install quan-cli 更新`);
35
+ }
36
+ log.debug('quan-cli当前版本', currentVersion);
37
+ log.debug('quan-cli最新版本', lastVersion);
38
+ }
39
+ registerCommand() {
40
+ this.program.name(pack.name).version(pack.version).description(`quan-cli version:${pack.version}`);
41
+ this.program.option('-d, --debug', '开启debug模式(打印信息)');
42
+ this.program
43
+ .command('init [type]')
44
+ .description('quan-cli 初始化项目')
45
+ .option('-p, --packagePath <packagePath>', '指定init包的路径')
46
+ .option('-f, --force', '覆盖当前项目')
47
+ .option('-o, --origin <origin>', '指定初始化使用的npm源')
48
+ .action((str: string, option: initCommand) => {
49
+ log.debug('输入参数', option);
50
+ new InitAction(option);
51
+ });
52
+ this.program.parse();
53
+ }
54
+ }
55
+
56
+ new Cli();
@@ -0,0 +1,12 @@
1
+ import fs from 'fs';
2
+ export class FileUtil {
3
+ static isEmptyDir = (path: string) => {
4
+ let fileList = fs.readdirSync(path);
5
+ fileList = fileList.filter((file) => ['node_modules', 'src', 'tsconfig.json', 'package.json', '.git', '.DS_Store'].includes(file));
6
+ if (fileList && fileList.length > 0) {
7
+ return false;
8
+ } else {
9
+ return true;
10
+ }
11
+ };
12
+ }
@@ -0,0 +1,4 @@
1
+ export * from './file';
2
+ export * from './log';
3
+ export * from './npm';
4
+ export * from './loading';
@@ -0,0 +1,17 @@
1
+ import { Spinner } from 'cli-spinner';
2
+
3
+ export const loading = (msg: string, spinnerString: string = '|/-\\') => {
4
+ const spinner = new Spinner(`${msg}.. %s`);
5
+ spinner.setSpinnerString(spinnerString);
6
+ spinner.start();
7
+ return spinner;
8
+ };
9
+
10
+ export const sleep = async (time: number = 0) => {
11
+ await new Promise((resolve) => {
12
+ let timer = setTimeout(() => {
13
+ resolve(undefined);
14
+ clearTimeout(timer);
15
+ }, time);
16
+ });
17
+ };
@@ -0,0 +1,16 @@
1
+ import log from 'npmlog';
2
+
3
+ export type customLogLevels = log.LogLevels | 'success' | 'debug';
4
+
5
+ log.level = process.env.LOG_LEVEL || 'info';
6
+ log.heading = 'quan-cli';
7
+
8
+ log.addLevel('success', 2000, { fg: 'green', bold: true });
9
+ log.addLevel('debug', 1000, { fg: 'blue', bg: 'black' });
10
+
11
+ const setLogLevel = (level: customLogLevels) => {
12
+ log.level = level;
13
+ log.debug(log.level + '模式开启');
14
+ };
15
+
16
+ export { log, setLogLevel };
@@ -0,0 +1,23 @@
1
+ import { log } from './log';
2
+ import axios from 'axios';
3
+ export class NpmUtil {
4
+ // 获取 registry 信息
5
+ static getNpmRegistry(isOriginal = false): string {
6
+ return isOriginal ? 'https://registry.npmjs.org' : 'https://registry.npm.taobao.org';
7
+ }
8
+ //获取npm最新版本号
9
+ static async getLatestVersion(packageName: string, origin: string = NpmUtil.getNpmRegistry(true)) {
10
+ log.debug('链接' + origin + '/' + packageName);
11
+ const { data } = await axios({
12
+ method: 'get',
13
+ url: origin + '/' + packageName,
14
+ });
15
+
16
+ const version = data['dist-tags'].latest;
17
+ return version;
18
+ }
19
+ //获取npm包在文件中的名字
20
+ static getPackageDirName(packageName: string, version: string): string {
21
+ return '_' + packageName + '@' + version + '@' + packageName;
22
+ }
23
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,105 @@
1
+ {
2
+ "compilerOptions": {
3
+ /* Visit https://aka.ms/tsconfig to read more about this file */
4
+
5
+ /* Projects */
6
+ // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
7
+ // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8
+ // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
9
+ // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
10
+ // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11
+ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12
+
13
+ /* Language and Environment */
14
+ "target": "es2018" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
15
+ // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16
+ // "jsx": "preserve", /* Specify what JSX code is generated. */
17
+ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
18
+ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19
+ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
20
+ // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21
+ // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
22
+ // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
23
+ // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24
+ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25
+ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26
+
27
+ /* Modules */
28
+ "module": "commonjs" /* Specify what module code is generated. */,
29
+ // "rootDir": "./", /* Specify the root folder within your source files. */
30
+ // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
31
+ "baseUrl": "./" /* Specify the base directory to resolve non-relative module names. */,
32
+ "paths": {} /* Specify a set of entries that re-map imports to additional lookup locations. */,
33
+ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
34
+ // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
35
+ // "types": [], /* Specify type package names to be included without being referenced in a source file. */
36
+ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
37
+ // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
38
+ // "resolveJsonModule": true, /* Enable importing .json files. */
39
+ // "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
40
+
41
+ /* JavaScript Support */
42
+ // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
43
+ // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
44
+ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
45
+
46
+ /* Emit */
47
+ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
48
+ // "declarationMap": true, /* Create sourcemaps for d.ts files. */
49
+ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
50
+ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
51
+ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
52
+ "outDir": "./lib" /* Specify an output folder for all emitted files. */,
53
+ // "removeComments": true, /* Disable emitting comments. */
54
+ // "noEmit": true, /* Disable emitting files from a compilation. */
55
+ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
56
+ // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
57
+ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
58
+ // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
59
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
60
+ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
61
+ // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
62
+ // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
63
+ // "newLine": "crlf", /* Set the newline character for emitting files. */
64
+ // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
65
+ // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
66
+ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
67
+ // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
68
+ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
69
+ // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
70
+
71
+ /* Interop Constraints */
72
+ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
73
+ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
74
+ "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
75
+ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
76
+ "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
77
+
78
+ /* Type Checking */
79
+ "strict": true /* Enable all strict type-checking options. */,
80
+ "noImplicitAny": true /* Enable error reporting for expressions and declarations with an implied 'any' type. */,
81
+ // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
82
+ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
83
+ // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
84
+ // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
85
+ // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
86
+ // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
87
+ // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
88
+ // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
89
+ // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
90
+ // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
91
+ // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
92
+ // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
93
+ // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
94
+ // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
95
+ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
96
+ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
97
+ // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
98
+
99
+ /* Completeness */
100
+ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
101
+ "skipLibCheck": true /* Skip type checking all .d.ts files. */
102
+ },
103
+ "include": ["./src/**/*"],
104
+ "exclude": ["node_modules"]
105
+ }