@deot/dev-cli 1.0.1 → 1.0.2
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/README.md +1 -0
- package/config/.eslintrc.cjs +2 -2
- package/config/api-extractor.json +2 -1
- package/config/commit-lint.js +1 -1
- package/config/jest.config.js +3 -3
- package/dist/index.js +765 -130
- package/package.json +25 -24
- package/LICENSE +0 -21
package/README.md
CHANGED
package/config/.eslintrc.cjs
CHANGED
package/config/commit-lint.js
CHANGED
|
@@ -3,7 +3,7 @@ import fs from 'fs';
|
|
|
3
3
|
const commitRE = /^(revert: )?(fix|feat|docs|style|perf|test|types|build|chore|refactor|workflow|ci|wip|release|breaking change)(\(.+\))?: .{1,50}/;
|
|
4
4
|
const mergeRE = /Merge branch /;
|
|
5
5
|
|
|
6
|
-
const gitParams = process.env.HUSKY_GIT_PARAMS;
|
|
6
|
+
const gitParams = process.env.HUSKY_GIT_PARAMS || process.argv.pop(); // 兼容husky@v4和husky@v8
|
|
7
7
|
const commitMsg = fs.readFileSync(gitParams, 'utf-8').trim();
|
|
8
8
|
|
|
9
9
|
if (!commitRE.test(commitMsg) && !mergeRE.test(commitMsg)) {
|
package/config/jest.config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const options = JSON.parse(decodeURIComponent(process.env.TEST_OPTIONS || '{}'));
|
|
2
|
-
const {
|
|
2
|
+
const { packageFolderName } = options;
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
5
|
preset: 'ts-jest',
|
|
@@ -28,13 +28,13 @@ export default {
|
|
|
28
28
|
'/node_modules/'
|
|
29
29
|
],
|
|
30
30
|
testMatch: [
|
|
31
|
-
`<rootDir>/packages/${
|
|
31
|
+
`<rootDir>/packages/${packageFolderName || '**'}/__tests__/**.(spec|test).[jt]s?(x)`
|
|
32
32
|
],
|
|
33
33
|
|
|
34
34
|
collectCoverage: true,
|
|
35
35
|
coverageDirectory: 'coverage',
|
|
36
36
|
collectCoverageFrom: [
|
|
37
|
-
`packages/${
|
|
37
|
+
`packages/${packageFolderName || '*'}/src/**/*.ts`
|
|
38
38
|
],
|
|
39
39
|
coverageThreshold: {
|
|
40
40
|
global: {
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { program } from 'commander';
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import
|
|
4
|
-
import path, { resolve } from 'node:path';
|
|
3
|
+
import chalk from 'chalk';
|
|
5
4
|
import ora from 'ora';
|
|
5
|
+
import { Utils, Shell, Logger } from '@deot/dev-shared';
|
|
6
|
+
import * as path from 'node:path';
|
|
7
|
+
import { resolve } from 'node:path';
|
|
6
8
|
import fs from 'fs-extra';
|
|
7
9
|
import inquirer from 'inquirer';
|
|
8
10
|
import autocomplete from 'inquirer-autocomplete-prompt';
|
|
@@ -12,38 +14,141 @@ import commonjs from '@rollup/plugin-commonjs';
|
|
|
12
14
|
import replace from '@rollup/plugin-replace';
|
|
13
15
|
import { rollup } from 'rollup';
|
|
14
16
|
import { Extractor, ExtractorConfig } from '@microsoft/api-extractor';
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
const run$4 = () => Utils.autoCatch(async () => {
|
|
18
|
-
const command = 'lerna link --force-local';
|
|
19
|
-
if (process.env.NODE_ENV === 'UNIT')
|
|
20
|
-
return Shell.spawn(`echo ${command}`);
|
|
21
|
-
await Shell.spawn(command);
|
|
22
|
-
});
|
|
17
|
+
import parser from 'conventional-commits-parser';
|
|
18
|
+
import semver from 'semver';
|
|
23
19
|
|
|
24
|
-
const require$$1 = createRequire(import.meta.url);
|
|
25
20
|
const cwd = process.cwd();
|
|
21
|
+
const require$$2 = createRequire(cwd);
|
|
26
22
|
class Shared {
|
|
23
|
+
static config;
|
|
24
|
+
static getNormalizePackage = (dataMap) => {
|
|
25
|
+
Object.keys(dataMap).forEach(packageName => {
|
|
26
|
+
const relations = dataMap[packageName];
|
|
27
|
+
relations.forEach((packageName$) => {
|
|
28
|
+
if (dataMap[packageName$].includes(packageName)) {
|
|
29
|
+
throw new Error(`${packageName} ${packageName$} deps loop`);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
const needUseMap = Object.keys(dataMap).reduce((pre, key) => (pre[key] = 0, pre), {});
|
|
34
|
+
const queue = [];
|
|
35
|
+
for (let key in dataMap) {
|
|
36
|
+
const dependencies = dataMap[key];
|
|
37
|
+
dependencies.forEach((dependency) => {
|
|
38
|
+
needUseMap[dependency] += 1;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
for (let key in needUseMap) {
|
|
42
|
+
if (needUseMap[key] === 0) {
|
|
43
|
+
queue.push(key);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const result = [];
|
|
47
|
+
while (queue.length > 0) {
|
|
48
|
+
const node = queue.shift();
|
|
49
|
+
if (!node)
|
|
50
|
+
return [];
|
|
51
|
+
result.push(node);
|
|
52
|
+
const dependencies = dataMap[node];
|
|
53
|
+
for (let i = 0; i < dependencies.length; i++) {
|
|
54
|
+
const dependency = dependencies[i];
|
|
55
|
+
needUseMap[dependency] -= 1;
|
|
56
|
+
if (needUseMap[dependency] === 0) {
|
|
57
|
+
queue.push(dependency);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return result.reverse();
|
|
62
|
+
};
|
|
63
|
+
static getPackageName = (packageFolderName$) => {
|
|
64
|
+
const { packageFolderName, packageName } = Shared.impl();
|
|
65
|
+
if (!packageFolderName$ || packageFolderName$ === packageFolderName) {
|
|
66
|
+
return `${packageName}`;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
return `${packageName}-${packageFolderName$.replace(new RegExp(`${packageName}-?`), '')}`;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
static getPackageFolderName = (packageName$) => {
|
|
73
|
+
const { packageFolderName, packageName } = Shared.impl();
|
|
74
|
+
if (packageName$ === packageName)
|
|
75
|
+
return packageFolderName;
|
|
76
|
+
return packageName$?.replace(new RegExp(`${packageName}-?`), '');
|
|
77
|
+
};
|
|
27
78
|
static impl() {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
79
|
+
if (Shared.config)
|
|
80
|
+
return Shared.config;
|
|
81
|
+
const rootPackageOptions = require$$2(`${cwd}/package.json`);
|
|
82
|
+
const packageFolderName = 'index';
|
|
83
|
+
const packageDir = path.resolve(cwd, './packages');
|
|
84
|
+
const packageOptions = require$$2(`${cwd}/packages/${packageFolderName}/package.json`);
|
|
85
|
+
const packageName = packageOptions.name;
|
|
86
|
+
const packageVersion = packageOptions.version;
|
|
87
|
+
const packageFolderNames = fs
|
|
88
|
+
.readdirSync(packageDir)
|
|
89
|
+
.reduce((pre, file) => {
|
|
90
|
+
const fullpath = path.resolve(packageDir, file);
|
|
91
|
+
const stat = fs.statSync(fullpath);
|
|
92
|
+
if (!(/(^_|tpl)/.test(file))
|
|
93
|
+
&& stat.isDirectory()) {
|
|
94
|
+
pre.push(file);
|
|
95
|
+
}
|
|
96
|
+
return pre;
|
|
97
|
+
}, []);
|
|
98
|
+
const packageOptionsMap = packageFolderNames.reduce((pre, packageFolderDir) => {
|
|
99
|
+
pre[packageFolderDir] = require$$2(`${cwd}/packages/${packageFolderDir}/package.json`);
|
|
100
|
+
return pre;
|
|
101
|
+
}, {});
|
|
102
|
+
const packageRelation = packageFolderNames.reduce((pre, packageFolderDir) => {
|
|
103
|
+
let packagesOptions = packageOptionsMap[packageFolderDir];
|
|
104
|
+
let deps = {
|
|
105
|
+
...(packagesOptions.dependencies || {}),
|
|
106
|
+
...(packagesOptions.devDependencies || {}),
|
|
107
|
+
};
|
|
108
|
+
pre[packagesOptions.name] = Object.keys(deps).filter(i => new RegExp(`${packageName}`).test(i));
|
|
109
|
+
return pre;
|
|
110
|
+
}, {});
|
|
111
|
+
const normalizePackageNames = Shared.getNormalizePackage(packageRelation);
|
|
112
|
+
const normalizePackageFolderNames = normalizePackageNames
|
|
113
|
+
.map(i => i.replace(new RegExp(`${packageName}-?`), '') || packageFolderName);
|
|
114
|
+
const config = {
|
|
115
|
+
homepage: (rootPackageOptions.homepage || packageOptions.homepage).replace(/(#.+)/, ''),
|
|
116
|
+
packageFolderName,
|
|
117
|
+
packageDir,
|
|
118
|
+
packageOptions,
|
|
119
|
+
packageName,
|
|
120
|
+
packageVersion,
|
|
121
|
+
packageFolderNames,
|
|
122
|
+
packageOptionsMap,
|
|
123
|
+
packageRelation,
|
|
124
|
+
normalizePackageNames,
|
|
125
|
+
normalizePackageFolderNames
|
|
31
126
|
};
|
|
127
|
+
Shared.config = config;
|
|
128
|
+
return config;
|
|
32
129
|
}
|
|
33
130
|
}
|
|
34
131
|
|
|
35
|
-
const
|
|
132
|
+
const run$5 = (options) => Utils.autoCatch(async () => {
|
|
133
|
+
if (typeof options.dryRun === 'undefined') {
|
|
134
|
+
options.dryRun = process.env.NODE_ENV === 'UNIT';
|
|
135
|
+
}
|
|
136
|
+
const command = 'npx pnpm link ./packages/';
|
|
137
|
+
if (options.dryRun)
|
|
138
|
+
return Shell.spawn(`echo ${command}`);
|
|
139
|
+
const { packageFolderNames } = Shared.impl();
|
|
140
|
+
const spinner = ora(`Links ...\n`);
|
|
141
|
+
spinner.start();
|
|
142
|
+
await Promise.all(packageFolderNames.map(i => {
|
|
143
|
+
return Shell.spawn(`${command}${i}`);
|
|
144
|
+
}));
|
|
145
|
+
spinner.stop();
|
|
146
|
+
Logger.log(`${chalk.green('Links Success')}`);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const { prompt: prompt$2, registerPrompt: registerPrompt$1, Separator } = inquirer;
|
|
36
150
|
const getOptions$1 = async () => {
|
|
37
|
-
const {
|
|
38
|
-
const packages$ = [];
|
|
39
|
-
fs.readdirSync(directory).forEach((file) => {
|
|
40
|
-
const fullpath = resolve(directory, file);
|
|
41
|
-
const stat = fs.statSync(fullpath);
|
|
42
|
-
if (!(/(^_|tpl)/.test(file))
|
|
43
|
-
&& stat.isDirectory()) {
|
|
44
|
-
packages$.push(file);
|
|
45
|
-
}
|
|
46
|
-
});
|
|
151
|
+
const { packageFolderNames } = Shared.impl();
|
|
47
152
|
const question = [
|
|
48
153
|
{
|
|
49
154
|
type: 'list',
|
|
@@ -60,14 +165,14 @@ const getOptions$1 = async () => {
|
|
|
60
165
|
type: 'autocomplete',
|
|
61
166
|
message: 'Select Package To Install:',
|
|
62
167
|
when: (answers) => answers.mode === 'dependent',
|
|
63
|
-
name: '
|
|
168
|
+
name: 'packageFolderName',
|
|
64
169
|
default: 'index',
|
|
65
170
|
source: (_, input) => {
|
|
66
171
|
input = input || '';
|
|
67
172
|
return new Promise(($resolve => {
|
|
68
173
|
let filter = input
|
|
69
|
-
?
|
|
70
|
-
:
|
|
174
|
+
? packageFolderNames.filter(item => item.includes(input))
|
|
175
|
+
: packageFolderNames;
|
|
71
176
|
$resolve(filter);
|
|
72
177
|
}));
|
|
73
178
|
}
|
|
@@ -86,26 +191,19 @@ const getOptions$1 = async () => {
|
|
|
86
191
|
}
|
|
87
192
|
},
|
|
88
193
|
{
|
|
89
|
-
type: '
|
|
194
|
+
type: 'list',
|
|
90
195
|
name: 'args',
|
|
91
196
|
when: (answers) => answers.mode === 'dependent',
|
|
92
|
-
message: 'Select
|
|
197
|
+
message: 'Select Install Mode:',
|
|
93
198
|
choices: [
|
|
94
|
-
'
|
|
95
|
-
'
|
|
96
|
-
'
|
|
97
|
-
|
|
98
|
-
],
|
|
99
|
-
validate(answer) {
|
|
100
|
-
if (answer.length < 1) {
|
|
101
|
-
return '至少选择一个模块, 使用Space键选中';
|
|
102
|
-
}
|
|
103
|
-
return true;
|
|
104
|
-
}
|
|
199
|
+
'-S',
|
|
200
|
+
'-D',
|
|
201
|
+
'-O'
|
|
202
|
+
]
|
|
105
203
|
},
|
|
106
204
|
{
|
|
107
205
|
type: 'input',
|
|
108
|
-
name: '
|
|
206
|
+
name: 'packageFolderName',
|
|
109
207
|
message: 'Input Package Name',
|
|
110
208
|
default: '',
|
|
111
209
|
when: (answers) => answers.mode === 'package',
|
|
@@ -113,7 +211,7 @@ const getOptions$1 = async () => {
|
|
|
113
211
|
if (!answer) {
|
|
114
212
|
return '请输入需要添加的包名';
|
|
115
213
|
}
|
|
116
|
-
if (
|
|
214
|
+
if (packageFolderNames.includes(answer) || answer === 'dev') {
|
|
117
215
|
return '包名已存在';
|
|
118
216
|
}
|
|
119
217
|
return true;
|
|
@@ -121,41 +219,38 @@ const getOptions$1 = async () => {
|
|
|
121
219
|
}
|
|
122
220
|
];
|
|
123
221
|
registerPrompt$1('autocomplete', autocomplete);
|
|
124
|
-
let result = await prompt$
|
|
222
|
+
let result = await prompt$2(question);
|
|
125
223
|
if (result.mode == 'dependent') {
|
|
126
|
-
|
|
127
|
-
result.$packageName = `${packageName}`;
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
result.$packageName = `${packageName}-${result.packageName}`;
|
|
131
|
-
}
|
|
224
|
+
result.packageName = Shared.getPackageName(result.packageFolderName);
|
|
132
225
|
}
|
|
133
226
|
if (result.mode == 'package') {
|
|
134
|
-
result
|
|
227
|
+
result.packageName = Shared.getPackageName(result.packageFolderName);
|
|
135
228
|
}
|
|
229
|
+
result.args = [result.args];
|
|
136
230
|
return result;
|
|
137
231
|
};
|
|
138
232
|
|
|
139
|
-
const run$
|
|
140
|
-
|
|
141
|
-
|
|
233
|
+
const run$4 = (options) => Utils.autoCatch(async () => {
|
|
234
|
+
if (typeof options.dryRun === 'undefined') {
|
|
235
|
+
options.dryRun = process.env.NODE_ENV === 'UNIT';
|
|
236
|
+
}
|
|
237
|
+
const { mode, dependentName, args, packageFolderName, packageName } = await getOptions$1();
|
|
238
|
+
const { packageDir } = Shared.impl();
|
|
142
239
|
let command = mode === 'dependent'
|
|
143
|
-
? `
|
|
144
|
-
: `
|
|
145
|
-
if (
|
|
240
|
+
? `npx pnpm add --filter ${packageName} ${dependentName} ${args.join(' ')}`
|
|
241
|
+
: `npx pnpm link ./packages/${packageFolderName}`;
|
|
242
|
+
if (options.dryRun)
|
|
146
243
|
return Shell.spawn(`echo "${command}"`);
|
|
147
|
-
const spinner = ora(command).start();
|
|
244
|
+
const spinner = ora(`${command}\n`).start();
|
|
148
245
|
await Shell.spawn(command);
|
|
149
246
|
spinner.stop();
|
|
150
247
|
if (mode === 'package') {
|
|
151
|
-
let dir = resolve(
|
|
152
|
-
fs.
|
|
153
|
-
fs.
|
|
154
|
-
fs.
|
|
155
|
-
fs.outputFileSync(`${dir}/${
|
|
156
|
-
|
|
157
|
-
fs.outputFileSync(`${dir}/${packageName}/package.json`, JSON.stringify({
|
|
158
|
-
name: $packageName,
|
|
248
|
+
let dir = resolve(packageDir);
|
|
249
|
+
fs.outputFileSync(`${dir}/${packageFolderName}/README.md`, '// TODO');
|
|
250
|
+
fs.outputFileSync(`${dir}/${packageFolderName}/src/index.ts`, '// TODO');
|
|
251
|
+
fs.outputFileSync(`${dir}/${packageFolderName}/__tests__/index.spec.ts`, '// TODO');
|
|
252
|
+
fs.outputFileSync(`${dir}/${packageFolderName}/package.json`, JSON.stringify({
|
|
253
|
+
name: packageName,
|
|
159
254
|
version: '1.0.0',
|
|
160
255
|
main: 'dist/index.js',
|
|
161
256
|
types: "dist/index.d.ts",
|
|
@@ -168,36 +263,29 @@ const run$3 = () => Utils.autoCatch(async () => {
|
|
|
168
263
|
access: 'public'
|
|
169
264
|
},
|
|
170
265
|
dependencies: {}
|
|
171
|
-
}, null,
|
|
172
|
-
fs.outputFileSync(`${dir}/${
|
|
266
|
+
}, null, 2));
|
|
267
|
+
fs.outputFileSync(`${dir}/${packageFolderName}/api-extractor.json`, JSON.stringify({
|
|
173
268
|
extends: "../../api-extractor.json",
|
|
174
|
-
mainEntryPointFilePath: `./dist/packages/${
|
|
269
|
+
mainEntryPointFilePath: `./dist/packages/${packageFolderName}/src/index.d.ts`,
|
|
175
270
|
dtsRollup: {
|
|
176
271
|
publicTrimmedFilePath: "./dist/index.d.ts"
|
|
177
272
|
}
|
|
178
|
-
}, null,
|
|
273
|
+
}, null, 2));
|
|
179
274
|
}
|
|
275
|
+
await Shell.spawn(command);
|
|
180
276
|
});
|
|
181
277
|
|
|
182
278
|
const ALL_PACKAGE = 'All Packages';
|
|
183
|
-
const { prompt, registerPrompt } = inquirer;
|
|
279
|
+
const { prompt: prompt$1, registerPrompt } = inquirer;
|
|
184
280
|
const getOptions = async () => {
|
|
185
281
|
const isDev = process.env.NODE_ENV === 'development';
|
|
186
|
-
const {
|
|
187
|
-
const packages$ = [ALL_PACKAGE];
|
|
188
|
-
fs.readdirSync(directory).forEach((file) => {
|
|
189
|
-
const fullpath = resolve(directory, file);
|
|
190
|
-
const stat = fs.statSync(fullpath);
|
|
191
|
-
if (!(/(^_|tpl)/.test(file))
|
|
192
|
-
&& stat.isDirectory()) {
|
|
193
|
-
packages$.push(file);
|
|
194
|
-
}
|
|
195
|
-
});
|
|
282
|
+
const { packageFolderNames } = Shared.impl();
|
|
283
|
+
const packages$ = [ALL_PACKAGE, ...packageFolderNames];
|
|
196
284
|
const question = [
|
|
197
285
|
{
|
|
198
286
|
type: 'autocomplete',
|
|
199
287
|
message: `Select Package To ${isDev ? 'Develop' : 'Test'}:`,
|
|
200
|
-
name: '
|
|
288
|
+
name: 'packageFolderName',
|
|
201
289
|
default: 'cli',
|
|
202
290
|
source: (_, input) => {
|
|
203
291
|
input = input || '';
|
|
@@ -215,30 +303,41 @@ const getOptions = async () => {
|
|
|
215
303
|
name: 'watch',
|
|
216
304
|
when: () => !isDev,
|
|
217
305
|
default: (answers) => {
|
|
218
|
-
return answers.
|
|
306
|
+
return answers.packageFolderName !== ALL_PACKAGE;
|
|
219
307
|
}
|
|
220
308
|
}
|
|
221
309
|
];
|
|
222
310
|
registerPrompt('autocomplete', autocomplete);
|
|
223
|
-
let result = await prompt(question);
|
|
224
|
-
result.
|
|
311
|
+
let result = await prompt$1(question);
|
|
312
|
+
result.packageFolderName = result.packageFolderName == ALL_PACKAGE
|
|
225
313
|
? undefined
|
|
226
|
-
: result.
|
|
314
|
+
: result.packageFolderName;
|
|
227
315
|
result.watch = result.watch || isDev;
|
|
228
316
|
return result;
|
|
229
317
|
};
|
|
230
318
|
|
|
231
|
-
const run$
|
|
232
|
-
if (
|
|
233
|
-
options =
|
|
319
|
+
const run$3 = (options) => Utils.autoCatch(async () => {
|
|
320
|
+
if (typeof options.dryRun === 'undefined') {
|
|
321
|
+
options.dryRun = process.env.NODE_ENV === 'UNIT';
|
|
322
|
+
}
|
|
323
|
+
if (!options.packageName) {
|
|
324
|
+
const promptOptions = await getOptions();
|
|
325
|
+
options = {
|
|
326
|
+
...options,
|
|
327
|
+
...promptOptions
|
|
328
|
+
};
|
|
234
329
|
}
|
|
235
|
-
const { packageName, watch } = options;
|
|
330
|
+
const { packageName, watch, dryRun } = options;
|
|
331
|
+
options.packageFolderName = Shared.getPackageFolderName(options.packageName) || options.packageFolderName;
|
|
332
|
+
if (!options.packageFolderName)
|
|
333
|
+
delete options.packageFolderName;
|
|
334
|
+
delete options.packageName;
|
|
236
335
|
const command = `cross-env NODE_ENV=${process.env.NODE_ENV || 'TEST'} TEST_OPTIONS=${encodeURIComponent(JSON.stringify(options))} jest `
|
|
237
336
|
+ ([
|
|
238
337
|
'--passWithNoTests',
|
|
239
338
|
`${watch ? '--watchAll' : ''}`
|
|
240
339
|
].join(' '));
|
|
241
|
-
if (
|
|
340
|
+
if (dryRun)
|
|
242
341
|
return Shell.spawn(`echo ${command}`);
|
|
243
342
|
await Shell.spawn(command);
|
|
244
343
|
if (!watch)
|
|
@@ -252,27 +351,46 @@ const run$2 = (options) => Utils.autoCatch(async () => {
|
|
|
252
351
|
else {
|
|
253
352
|
Logger.error(e);
|
|
254
353
|
}
|
|
354
|
+
process.exit(1);
|
|
255
355
|
}
|
|
256
356
|
});
|
|
257
357
|
|
|
258
|
-
const run$
|
|
259
|
-
if (
|
|
358
|
+
const run$2 = (options) => Utils.autoCatch(async () => {
|
|
359
|
+
if (typeof options.dryRun === 'undefined') {
|
|
360
|
+
options.dryRun = process.env.NODE_ENV === 'UNIT';
|
|
361
|
+
}
|
|
362
|
+
if (options.dryRun)
|
|
260
363
|
return Shell.spawn(`echo development`);
|
|
261
364
|
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
|
262
|
-
await run$
|
|
365
|
+
await run$3(options);
|
|
263
366
|
});
|
|
264
367
|
|
|
265
|
-
const require
|
|
368
|
+
const require$$1 = createRequire(import.meta.url);
|
|
266
369
|
class Builder {
|
|
267
370
|
packageDir;
|
|
268
371
|
packageName;
|
|
269
372
|
packageOptions;
|
|
270
373
|
config;
|
|
271
374
|
constructor(config) {
|
|
272
|
-
const {
|
|
273
|
-
|
|
375
|
+
const { packageDir, packageName } = Shared.impl();
|
|
376
|
+
if (typeof config === 'string') {
|
|
377
|
+
let packageFolderName = config;
|
|
378
|
+
let packageDir$ = path.resolve(packageDir, packageFolderName);
|
|
379
|
+
config = {
|
|
380
|
+
dir: packageDir$,
|
|
381
|
+
name: packageFolderName,
|
|
382
|
+
input: packageDir$ + '/src/index.ts',
|
|
383
|
+
output: {
|
|
384
|
+
file: packageDir$ + '/dist/index.js',
|
|
385
|
+
format: 'es',
|
|
386
|
+
exports: 'named',
|
|
387
|
+
sourcemap: false
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
this.packageDir = path.resolve(packageDir, `./${config.name}`);
|
|
274
392
|
this.packageName = config.name === 'index' ? packageName : `${packageName}-${config.name}`;
|
|
275
|
-
this.packageOptions = require
|
|
393
|
+
this.packageOptions = require$$1(`${this.packageDir}/package.json`);
|
|
276
394
|
this.config = config;
|
|
277
395
|
}
|
|
278
396
|
async process() {
|
|
@@ -320,7 +438,7 @@ class Builder {
|
|
|
320
438
|
commonjs({ extensions: ['.js', '.ts'] }),
|
|
321
439
|
nodeResolve(),
|
|
322
440
|
replace({
|
|
323
|
-
'1.0.
|
|
441
|
+
'1.0.1': `'${packageOptions.version}'`,
|
|
324
442
|
false: 'false',
|
|
325
443
|
true: true
|
|
326
444
|
})
|
|
@@ -344,35 +462,529 @@ class Builder {
|
|
|
344
462
|
await fs.remove(`${packageDir}/dist/packages`);
|
|
345
463
|
}
|
|
346
464
|
}
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
465
|
+
const builder = (options) => {
|
|
466
|
+
return new Builder(options);
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
const run$1 = (options) => Utils.autoCatch(async () => {
|
|
470
|
+
if (typeof options.dryRun === 'undefined') {
|
|
471
|
+
options.dryRun = process.env.NODE_ENV === 'UNIT';
|
|
472
|
+
}
|
|
473
|
+
const { normalizePackageFolderNames } = Shared.impl();
|
|
474
|
+
let packageFolderName = Shared.getPackageFolderName(options.packageName || '**');
|
|
475
|
+
let inputs = [];
|
|
476
|
+
if (packageFolderName === '**') {
|
|
477
|
+
inputs = normalizePackageFolderNames;
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
inputs = [packageFolderName];
|
|
481
|
+
}
|
|
482
|
+
if (options.dryRun)
|
|
483
|
+
return Shell.spawn(`echo ${inputs.join(' ')}`);
|
|
484
|
+
await inputs
|
|
485
|
+
.reduce((preProcess, packageFolderName$) => {
|
|
486
|
+
preProcess = preProcess.then(() => builder(packageFolderName$).process());
|
|
487
|
+
return preProcess;
|
|
488
|
+
}, Promise.resolve());
|
|
489
|
+
}, {
|
|
490
|
+
onError: (e) => {
|
|
491
|
+
if (typeof e === 'number' && e === 1) {
|
|
492
|
+
Logger.error('编译未通过');
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
Logger.error(e);
|
|
496
|
+
}
|
|
497
|
+
process.exit(1);
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
const require$ = createRequire(import.meta.url);
|
|
502
|
+
const { prompt } = inquirer;
|
|
503
|
+
const HASH = '-hash-';
|
|
504
|
+
const SUFFIX = '🐒💨🙊';
|
|
505
|
+
const parserOptions = {
|
|
506
|
+
noteKeywords: ['BREAKING CHANGE', 'Breaking Change']
|
|
507
|
+
};
|
|
508
|
+
const reBreaking = new RegExp(`(${parserOptions.noteKeywords.join(')|(')})`);
|
|
509
|
+
class Releaser {
|
|
510
|
+
packageDir;
|
|
511
|
+
packageName;
|
|
512
|
+
packageFolderName;
|
|
513
|
+
packageOptions;
|
|
514
|
+
packageRelation;
|
|
515
|
+
config;
|
|
516
|
+
changeLog;
|
|
517
|
+
version;
|
|
518
|
+
commits;
|
|
519
|
+
commandOptions;
|
|
520
|
+
constructor(config, commandOptions) {
|
|
521
|
+
const { packageDir, packageRelation } = Shared.impl();
|
|
522
|
+
if (typeof config === 'string') {
|
|
523
|
+
let packageFolderName = config;
|
|
524
|
+
let packageDir$ = path.resolve(packageDir, packageFolderName);
|
|
525
|
+
config = {
|
|
526
|
+
dir: packageDir$,
|
|
527
|
+
name: packageFolderName
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
this.packageDir = config.dir;
|
|
531
|
+
this.packageName = Shared.getPackageName(config.name);
|
|
532
|
+
this.packageFolderName = config.name;
|
|
533
|
+
this.packageOptions = require$(`${this.packageDir}/package.json`);
|
|
534
|
+
this.packageRelation = packageRelation[this.packageName];
|
|
535
|
+
this.config = config;
|
|
536
|
+
this.commits = [];
|
|
537
|
+
this.changeLog = '';
|
|
538
|
+
this.version = '';
|
|
539
|
+
this.commandOptions = commandOptions;
|
|
540
|
+
}
|
|
541
|
+
async parseCommits() {
|
|
542
|
+
const { packageFolderName, packageName, commandOptions } = this;
|
|
543
|
+
let params = ['tag', '--list', `'${packageName}@*'`, '--sort', '-v:refname'];
|
|
544
|
+
const { stdout: tags } = await Shell.exec('git', params);
|
|
545
|
+
const [latestTag] = tags.split('\n');
|
|
546
|
+
Logger.log(chalk.yellow(`Last Release Tag`) + `: ${latestTag || '<none>'}`);
|
|
547
|
+
params = ['--no-pager', 'log', `${latestTag}..HEAD`, `--format=%B%n${HASH}%n%H${SUFFIX}`];
|
|
548
|
+
const rePlugin = new RegExp(`^[\\w\\!]+\\(([\\w,-]+)?${packageFolderName}([\\w,-]+)?\\)`, 'i');
|
|
549
|
+
let { stdout } = await Shell.exec('git', params);
|
|
550
|
+
if (!stdout) {
|
|
551
|
+
if (latestTag)
|
|
552
|
+
params.splice(2, 1, `${latestTag}`);
|
|
553
|
+
else
|
|
554
|
+
params.splice(2, 1, 'HEAD');
|
|
555
|
+
({
|
|
556
|
+
stdout
|
|
557
|
+
} = await Shell.exec('git', params));
|
|
558
|
+
}
|
|
559
|
+
const commits = stdout
|
|
560
|
+
.split(SUFFIX)
|
|
561
|
+
.filter((commit) => {
|
|
562
|
+
const chunk = commit.trim();
|
|
563
|
+
return chunk && rePlugin.test(chunk);
|
|
564
|
+
})
|
|
565
|
+
.map((commit) => {
|
|
566
|
+
const node = parser.sync(commit);
|
|
567
|
+
const body = (node.body || node.footer);
|
|
568
|
+
if (!node.type)
|
|
569
|
+
node.type = parser.sync(node.header?.replace(/\(.+\)!?:/, ':') || '').type;
|
|
570
|
+
if (!node.hash)
|
|
571
|
+
node.hash = commit.split(HASH).pop()?.trim();
|
|
572
|
+
node.breaking = reBreaking.test(body) || /!:/.test(node.header);
|
|
573
|
+
node.effect = false;
|
|
574
|
+
node.custom = false;
|
|
575
|
+
return node;
|
|
576
|
+
});
|
|
577
|
+
if (!commits.length) {
|
|
578
|
+
Logger.log(chalk.red(`No Commits Found.`));
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
Logger.log(chalk.yellow(`Found `) + chalk.bold(`${commits.length}`) + ` Commits`);
|
|
582
|
+
}
|
|
583
|
+
const { skipUpdatePackage } = commandOptions;
|
|
584
|
+
if (commits.length && skipUpdatePackage) {
|
|
585
|
+
let skip = false;
|
|
586
|
+
if (typeof skipUpdatePackage === 'boolean' && skipUpdatePackage) {
|
|
587
|
+
let result = await prompt([
|
|
588
|
+
{
|
|
589
|
+
type: 'confirm',
|
|
590
|
+
name: 'skip',
|
|
591
|
+
message: `Skip Update(${this.packageName}@${this.packageOptions.version}):`,
|
|
592
|
+
default: true
|
|
367
593
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
}
|
|
594
|
+
]);
|
|
595
|
+
skip = result.skip;
|
|
596
|
+
}
|
|
597
|
+
else if (typeof skipUpdatePackage === 'string'
|
|
598
|
+
&& (skipUpdatePackage === '**'
|
|
599
|
+
|| skipUpdatePackage.split(',').includes(this.packageName))) {
|
|
600
|
+
skip = true;
|
|
601
|
+
}
|
|
602
|
+
if (skip) {
|
|
603
|
+
Logger.log(chalk.red(`Skipping Update\n`));
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
await this.updateVersion();
|
|
608
|
+
await this.updateCommits(commits);
|
|
609
|
+
const { forceUpdatePackage } = commandOptions;
|
|
610
|
+
if (!commits.length && forceUpdatePackage) {
|
|
611
|
+
let force = false;
|
|
612
|
+
if (typeof forceUpdatePackage === 'boolean' && forceUpdatePackage) {
|
|
613
|
+
let result = await prompt([
|
|
614
|
+
{
|
|
615
|
+
type: 'confirm',
|
|
616
|
+
name: 'force',
|
|
617
|
+
message: `Force Update(${this.packageName}@${this.packageOptions.version}):`,
|
|
618
|
+
default: true
|
|
619
|
+
}
|
|
620
|
+
]);
|
|
621
|
+
force = result.force;
|
|
622
|
+
}
|
|
623
|
+
else if (typeof forceUpdatePackage === 'string'
|
|
624
|
+
&& (forceUpdatePackage === '**'
|
|
625
|
+
|| forceUpdatePackage.split(',').includes(this.packageName))) {
|
|
626
|
+
force = true;
|
|
627
|
+
}
|
|
628
|
+
if (force) {
|
|
629
|
+
const oldVersion = this.packageOptions.version;
|
|
630
|
+
const versionChanged = `\`${oldVersion}\` -> \`${this.version}\``;
|
|
631
|
+
this.commits = [
|
|
632
|
+
{
|
|
633
|
+
type: 'chore',
|
|
634
|
+
header: `chore(${this.packageFolderName}): force-publish ${versionChanged}`,
|
|
635
|
+
hash: '',
|
|
636
|
+
effect: false,
|
|
637
|
+
breaking: false,
|
|
638
|
+
custom: true
|
|
639
|
+
}
|
|
640
|
+
];
|
|
641
|
+
this.changeLog = `### Force Update Package\n\n- ${versionChanged}`.trim();
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
rebuildChangeLog(commits) {
|
|
646
|
+
const { packageDir } = this;
|
|
647
|
+
const { homepage } = Shared.impl();
|
|
648
|
+
const logPath = path.resolve(packageDir, './CHANGELOG.md');
|
|
649
|
+
const logFile = fs.existsSync(logPath) ? fs.readFileSync(logPath, 'utf-8') : '';
|
|
650
|
+
const notes = {
|
|
651
|
+
breaking: [],
|
|
652
|
+
features: [],
|
|
653
|
+
fixes: [],
|
|
654
|
+
updates: []
|
|
655
|
+
};
|
|
656
|
+
const closeRegxp = /\(?(closes? )\(?#((\d+))\)/ig;
|
|
657
|
+
const pullRegxp = /(?<!closes? )\((#(\d+))\)/ig;
|
|
658
|
+
for (const commit of commits) {
|
|
659
|
+
const { effect, breaking, hash, header, type } = commit;
|
|
660
|
+
const ref = !hash || pullRegxp.test(header)
|
|
661
|
+
? ''
|
|
662
|
+
: ` ([${hash?.substring(0, 7)}](${homepage}/commit/${hash}))`;
|
|
663
|
+
let message = header?.trim();
|
|
664
|
+
if (!effect) {
|
|
665
|
+
message = message.replace(/\(.+\)!?:/, ':');
|
|
666
|
+
}
|
|
667
|
+
message = message
|
|
668
|
+
.replace(pullRegxp, `[$1](${homepage}/pull/$2)`)
|
|
669
|
+
.replace(closeRegxp, `[$1$2](${homepage}/issues/$2)`) + ref;
|
|
670
|
+
if (breaking) {
|
|
671
|
+
notes.breaking.push(message);
|
|
672
|
+
}
|
|
673
|
+
else if (type === 'fix') {
|
|
674
|
+
notes.fixes.push(message);
|
|
675
|
+
}
|
|
676
|
+
else if (type === 'feat') {
|
|
677
|
+
notes.features.push(message);
|
|
678
|
+
}
|
|
679
|
+
else {
|
|
680
|
+
notes.updates.push(message);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
const parts = [
|
|
684
|
+
notes.breaking.length ? `### Breaking Changes\n\n- ${notes.breaking.join('\n- ')}`.trim() : '',
|
|
685
|
+
notes.fixes.length ? `### Bugfixes\n\n- ${notes.fixes.join('\n- ')}`.trim() : '',
|
|
686
|
+
notes.features.length ? `### Features\n\n- ${notes.features.join('\n- ')}`.trim() : '',
|
|
687
|
+
notes.updates.length ? `### Updates\n\n- ${notes.updates.join('\n- ')}`.trim() : ''
|
|
688
|
+
].filter(Boolean);
|
|
689
|
+
const newLog = parts.join('\n\n');
|
|
690
|
+
return !parts.length || logFile.includes(newLog)
|
|
691
|
+
? ''
|
|
692
|
+
: newLog;
|
|
693
|
+
}
|
|
694
|
+
async updateVersion() {
|
|
695
|
+
const { packageOptions, commits, commandOptions } = this;
|
|
696
|
+
const { version } = packageOptions;
|
|
697
|
+
let newVersion = '';
|
|
698
|
+
if (commandOptions.customVersion) {
|
|
699
|
+
newVersion = commandOptions.customVersion;
|
|
700
|
+
if (!(/\d+.\d+.\d+/.test(newVersion)) || version === newVersion) {
|
|
701
|
+
let result = await prompt([
|
|
702
|
+
{
|
|
703
|
+
type: 'input',
|
|
704
|
+
name: 'version',
|
|
705
|
+
message: `Custom Update Version(${this.packageName}@${version}):`,
|
|
706
|
+
default: '',
|
|
707
|
+
validate: (answer) => {
|
|
708
|
+
if (!(/\d+.\d+.\d+/.test(answer))) {
|
|
709
|
+
return 'Version Should Be Like x.x.x';
|
|
710
|
+
}
|
|
711
|
+
if (answer === version) {
|
|
712
|
+
return 'Version Should Be Diff Than Before';
|
|
713
|
+
}
|
|
714
|
+
return true;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
]);
|
|
718
|
+
newVersion = result.version;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
else {
|
|
722
|
+
const intersection = [
|
|
723
|
+
commandOptions.major && 'major',
|
|
724
|
+
commandOptions.minor && 'minor',
|
|
725
|
+
commandOptions.patch && 'patch'
|
|
726
|
+
].filter(i => !!i);
|
|
727
|
+
if (intersection.length) {
|
|
728
|
+
newVersion = semver.inc(version, intersection[0]) || '';
|
|
729
|
+
}
|
|
730
|
+
else {
|
|
731
|
+
const types = new Set(commits.map(({ type }) => type));
|
|
732
|
+
const breaking = commits.some((commit) => !!commit.breaking);
|
|
733
|
+
const level = breaking
|
|
734
|
+
? 'major'
|
|
735
|
+
: types.has('feat')
|
|
736
|
+
? 'minor'
|
|
737
|
+
: 'patch';
|
|
738
|
+
newVersion = semver.inc(version, level) || '';
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
this.version = newVersion;
|
|
742
|
+
}
|
|
743
|
+
isChanged() {
|
|
744
|
+
return !!this.commits.length;
|
|
745
|
+
}
|
|
746
|
+
async updateCommits(commits, source) {
|
|
747
|
+
if (!commits.length)
|
|
748
|
+
return;
|
|
749
|
+
const { packageName } = this;
|
|
750
|
+
const olds = this.commits.map(i => JSON.stringify(i));
|
|
751
|
+
const newCommits = commits
|
|
752
|
+
.filter(i => {
|
|
753
|
+
return !olds.includes(JSON.stringify(i));
|
|
754
|
+
})
|
|
755
|
+
.map(j => {
|
|
756
|
+
return {
|
|
757
|
+
...j,
|
|
758
|
+
effect: !!source
|
|
759
|
+
};
|
|
760
|
+
});
|
|
761
|
+
if (newCommits.length && this.commits.length) {
|
|
762
|
+
this.commits = this.commits.filter(i => !i.custom);
|
|
763
|
+
}
|
|
764
|
+
const commits$ = this.commits.concat(newCommits);
|
|
765
|
+
if (source) {
|
|
766
|
+
Logger.log(chalk.magenta(`MERGE COMMITS: `)
|
|
767
|
+
+ chalk.bold(`${commits.length}`) + ` Commits. `
|
|
768
|
+
+ 'merge ' + chalk.yellow(source) + ' into ' + chalk.green(packageName));
|
|
769
|
+
}
|
|
770
|
+
else {
|
|
771
|
+
Logger.log(``);
|
|
772
|
+
}
|
|
773
|
+
const changeLog = this.rebuildChangeLog(commits$);
|
|
774
|
+
if (changeLog) {
|
|
775
|
+
this.commits = commits$;
|
|
776
|
+
this.changeLog = changeLog;
|
|
777
|
+
}
|
|
778
|
+
else if (commits.length) {
|
|
779
|
+
Logger.log(chalk.red(`${commits.length} Commits Already Exists.`));
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
async updatePackageOptions(relationVerisons = {}) {
|
|
783
|
+
if (!this.isChanged())
|
|
784
|
+
return;
|
|
785
|
+
const { packageDir, packageOptions, commandOptions } = this;
|
|
786
|
+
const { dependencies, devDependencies } = packageOptions;
|
|
787
|
+
const newVersion = this.version;
|
|
788
|
+
Logger.log(chalk.yellow(`New Version: `) + `${newVersion}`);
|
|
789
|
+
packageOptions.version = newVersion;
|
|
790
|
+
if (Object.keys(this.packageRelation).length) {
|
|
791
|
+
for (let packageName$ in relationVerisons) {
|
|
792
|
+
let newVersion$ = relationVerisons[packageName$];
|
|
793
|
+
if (dependencies?.[packageName$]) {
|
|
794
|
+
dependencies[packageName$] = newVersion$;
|
|
795
|
+
}
|
|
796
|
+
if (devDependencies?.[packageName$]) {
|
|
797
|
+
devDependencies[packageName$] = newVersion$;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
if (commandOptions.dryRun) {
|
|
802
|
+
Logger.log(chalk.yellow(`Skipping package.json Update`));
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
Logger.log(chalk.yellow(`Updating `) + 'package.json');
|
|
806
|
+
fs.outputFileSync(`${packageDir}/package.json`, JSON.stringify(packageOptions, null, 2));
|
|
807
|
+
}
|
|
808
|
+
async updateChangelog() {
|
|
809
|
+
if (!this.isChanged())
|
|
810
|
+
return;
|
|
811
|
+
const { packageName, packageDir, packageOptions, commandOptions } = this;
|
|
812
|
+
const title = `# ${packageName} ChangeLog`;
|
|
813
|
+
const [date] = new Date().toISOString().split('T');
|
|
814
|
+
const logPath = path.resolve(packageDir, './CHANGELOG.md');
|
|
815
|
+
const logFile = fs.existsSync(logPath) ? fs.readFileSync(logPath, 'utf-8') : '';
|
|
816
|
+
const oldNotes = logFile.startsWith(title) ? logFile.slice(title.length).trim() : logFile;
|
|
817
|
+
const parts = [
|
|
818
|
+
`## v${packageOptions.version}`,
|
|
819
|
+
`_${date}_`,
|
|
820
|
+
this.changeLog
|
|
821
|
+
].filter(Boolean);
|
|
822
|
+
const newLog = parts.join('\n\n');
|
|
823
|
+
if (commandOptions.dryRun) {
|
|
824
|
+
Logger.log(chalk.yellow(`New ChangeLog:`) + `\n${newLog}`);
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
Logger.log(chalk.yellow(`Updating `) + `CHANGELOG.md`);
|
|
828
|
+
let content = [title, newLog, oldNotes].filter(Boolean).join('\n\n');
|
|
829
|
+
if (!content.endsWith('\n'))
|
|
830
|
+
content += '\n';
|
|
831
|
+
fs.writeFileSync(logPath, content, 'utf-8');
|
|
832
|
+
}
|
|
833
|
+
async test() {
|
|
834
|
+
if (!this.isChanged())
|
|
835
|
+
return;
|
|
836
|
+
const { commandOptions } = this;
|
|
837
|
+
if (commandOptions.dryRun) {
|
|
838
|
+
Logger.log(chalk.yellow('Skipping Test'));
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
else {
|
|
842
|
+
Logger.log(chalk.yellow('Test...'));
|
|
843
|
+
}
|
|
844
|
+
await Shell.exec(`npm run test -- --package-name ${this.packageName}`);
|
|
845
|
+
}
|
|
846
|
+
async build() {
|
|
847
|
+
if (!this.isChanged())
|
|
848
|
+
return;
|
|
849
|
+
const { commandOptions } = this;
|
|
850
|
+
if (commandOptions.dryRun) {
|
|
851
|
+
Logger.log(chalk.yellow('Skipping Build'));
|
|
852
|
+
return;
|
|
371
853
|
}
|
|
372
854
|
else {
|
|
373
|
-
|
|
855
|
+
Logger.log(chalk.yellow('Build...'));
|
|
374
856
|
}
|
|
857
|
+
await Shell.exec(`npm run build -- --package-name ${this.packageName}`);
|
|
858
|
+
}
|
|
859
|
+
async publish() {
|
|
860
|
+
if (!this.isChanged())
|
|
861
|
+
return;
|
|
862
|
+
const { commandOptions, packageDir } = this;
|
|
863
|
+
if (commandOptions.dryRun || !commandOptions.publish) {
|
|
864
|
+
Logger.log(chalk.yellow(`Skipping Publish`));
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
Logger.log(chalk.cyan(`\n Publishing to NPM`));
|
|
868
|
+
await Shell.spawn('npm', ['publish', '--no-git-checks', '--access', 'public'], {
|
|
869
|
+
cwd: packageDir
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
async tag() {
|
|
873
|
+
if (!this.isChanged())
|
|
874
|
+
return;
|
|
875
|
+
const { commandOptions, packageDir } = this;
|
|
876
|
+
const { packageName, packageOptions } = this;
|
|
877
|
+
if (commandOptions.dryRun || !commandOptions.tag) {
|
|
878
|
+
Logger.log(chalk.yellow(`Skipping Git Tag`));
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
const tagName = `${packageName}@${packageOptions.version}`;
|
|
882
|
+
Logger.log(chalk.blue(`\n Tagging`) + chalk.grey(`${tagName}`));
|
|
883
|
+
await Shell.spawn('git', ['tag', tagName], {
|
|
884
|
+
cwd: packageDir
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
async process() {
|
|
888
|
+
const { packageName, packageDir, packageFolderName } = this;
|
|
889
|
+
if (!packageDir || !fs.pathExists(packageDir)) {
|
|
890
|
+
throw new RangeError(`Could not find directory for package: ${packageFolderName}`);
|
|
891
|
+
}
|
|
892
|
+
Logger.log(chalk.cyan(`Releasing ${packageName}`) + ' from ' + chalk.grey(`packages/${packageFolderName}`));
|
|
893
|
+
await this.parseCommits();
|
|
894
|
+
return this;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
const releaser = (options, commandOptions) => {
|
|
898
|
+
return new Releaser(options, commandOptions);
|
|
899
|
+
};
|
|
900
|
+
|
|
901
|
+
const run = (options) => Utils.autoCatch(async () => {
|
|
902
|
+
if (options.dryRun) {
|
|
903
|
+
Logger.log(chalk.magenta(`DRY RUN: `)
|
|
904
|
+
+ 'No files will be modified.');
|
|
905
|
+
}
|
|
906
|
+
const { normalizePackageFolderNames } = Shared.impl();
|
|
907
|
+
const instances = {};
|
|
908
|
+
await normalizePackageFolderNames
|
|
909
|
+
.reduce((preProcess, packageFolderName) => {
|
|
910
|
+
preProcess = preProcess
|
|
911
|
+
.then(() => releaser(packageFolderName, options).process())
|
|
912
|
+
.then((instance) => {
|
|
913
|
+
instances[packageFolderName] = instance;
|
|
914
|
+
});
|
|
915
|
+
return preProcess;
|
|
375
916
|
}, Promise.resolve());
|
|
917
|
+
Logger.log(chalk.blue(`---------------------\n`));
|
|
918
|
+
let message = `chore(release): publish\n\n`;
|
|
919
|
+
let relationVerisons = {};
|
|
920
|
+
await normalizePackageFolderNames.reduce((preProcess, packageFolderName) => {
|
|
921
|
+
const instance = instances[packageFolderName];
|
|
922
|
+
instance.packageRelation.forEach(i => {
|
|
923
|
+
let packageFolderName$ = Shared.getPackageFolderName(i);
|
|
924
|
+
let instance$ = instances[packageFolderName$];
|
|
925
|
+
if (instance$.commits.length > 0) {
|
|
926
|
+
instance.updateCommits(instance$.commits, instance$.packageName);
|
|
927
|
+
}
|
|
928
|
+
});
|
|
929
|
+
if (instance.commits.length) {
|
|
930
|
+
preProcess = preProcess
|
|
931
|
+
.then(() => Logger.log(chalk.magenta(`CHANGED: `) + instance.packageName))
|
|
932
|
+
.then(() => instance.test())
|
|
933
|
+
.then(() => instance.build())
|
|
934
|
+
.then(() => instance.updatePackageOptions(relationVerisons))
|
|
935
|
+
.then(() => instance.updateChangelog())
|
|
936
|
+
.then(() => {
|
|
937
|
+
message += `- ${instance.packageName}@${instance.packageOptions.version}\n`;
|
|
938
|
+
relationVerisons[instance.packageName] = `^${instance.packageOptions.version}`;
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
return preProcess;
|
|
942
|
+
}, Promise.resolve());
|
|
943
|
+
Logger.log(chalk.blue(`\n---------------------\n`));
|
|
944
|
+
const isChanged = Object.keys(relationVerisons).length;
|
|
945
|
+
if (!isChanged) {
|
|
946
|
+
Logger.log(chalk.magenta(`COMMIT: `) + 'Nothing Chanaged Found.');
|
|
947
|
+
}
|
|
948
|
+
else if (options.dryRun || !options.commit) {
|
|
949
|
+
Logger.log(chalk.magenta(`COMMIT: `) + chalk.yellow(`Skipping Git Commit`) + `\n${message}`);
|
|
950
|
+
}
|
|
951
|
+
else {
|
|
952
|
+
Logger.log(chalk.magenta(`COMMIT: `) + `CHANGELOG.md, package.json`);
|
|
953
|
+
await Shell.spawn('git', ['add', process.cwd()]);
|
|
954
|
+
await Shell.spawn('git', ['commit', '--m', `'${message}'`]);
|
|
955
|
+
}
|
|
956
|
+
await normalizePackageFolderNames
|
|
957
|
+
.reduce((preProcess, packageFolderName) => {
|
|
958
|
+
const instance = instances[packageFolderName];
|
|
959
|
+
preProcess = preProcess
|
|
960
|
+
.then(() => instance.publish())
|
|
961
|
+
.then(() => instance.tag());
|
|
962
|
+
return preProcess;
|
|
963
|
+
}, Promise.resolve());
|
|
964
|
+
Logger.log(chalk.blue(`\n---------------------\n`));
|
|
965
|
+
if (options.dryRun || !options.push) {
|
|
966
|
+
Logger.log(chalk.magenta(`FINISH: `) + 'Skipping Git Push');
|
|
967
|
+
}
|
|
968
|
+
else if (!isChanged) {
|
|
969
|
+
Logger.log(chalk.magenta(`FINISH: `) + 'Nothing Chanaged.');
|
|
970
|
+
}
|
|
971
|
+
else {
|
|
972
|
+
await Shell.spawn('git', ['push']);
|
|
973
|
+
}
|
|
974
|
+
if (options.dryRun) {
|
|
975
|
+
Logger.log(chalk.green('NO DRY RUN WAY: ')
|
|
976
|
+
+ chalk.grey(`npm run release -- --no-dry-run\n`));
|
|
977
|
+
}
|
|
978
|
+
}, {
|
|
979
|
+
onError: (e) => {
|
|
980
|
+
if (typeof e === 'number' && e === 1) {
|
|
981
|
+
Logger.error('发布失败');
|
|
982
|
+
}
|
|
983
|
+
else {
|
|
984
|
+
Logger.error(e);
|
|
985
|
+
}
|
|
986
|
+
process.exit(1);
|
|
987
|
+
}
|
|
376
988
|
});
|
|
377
989
|
|
|
378
990
|
const require = createRequire(import.meta.url);
|
|
@@ -383,29 +995,52 @@ program
|
|
|
383
995
|
program
|
|
384
996
|
.command('link')
|
|
385
997
|
.alias('d')
|
|
386
|
-
.description('
|
|
387
|
-
.
|
|
998
|
+
.description('pnpm link')
|
|
999
|
+
.option('--dry-run [boolean]', 'Dry Run')
|
|
1000
|
+
.action(run$5);
|
|
388
1001
|
program
|
|
389
1002
|
.command('add')
|
|
390
1003
|
.alias('a')
|
|
391
|
-
.description('
|
|
392
|
-
.
|
|
1004
|
+
.description('add dep or create package')
|
|
1005
|
+
.option('--dry-run [boolean]', 'Dry Run')
|
|
1006
|
+
.action(run$4);
|
|
393
1007
|
program
|
|
394
1008
|
.command('dev')
|
|
395
1009
|
.alias('d')
|
|
396
1010
|
.description('dev')
|
|
397
|
-
.
|
|
1011
|
+
.option('--dry-run [boolean]', 'Dry Run')
|
|
1012
|
+
.action(run$2);
|
|
398
1013
|
program
|
|
399
1014
|
.command('build')
|
|
400
1015
|
.alias('b')
|
|
401
1016
|
.description('build')
|
|
1017
|
+
.option('-p, --package-name <string>', 'select packageName')
|
|
1018
|
+
.option('--dry-run [boolean]', 'Dry Run')
|
|
1019
|
+
.action(run$1);
|
|
1020
|
+
program
|
|
1021
|
+
.command('release')
|
|
1022
|
+
.alias('r')
|
|
1023
|
+
.description('release')
|
|
1024
|
+
.option('--no-dry-run [boolean]', 'No Dry Run')
|
|
1025
|
+
.option('--no-tag [boolean]', 'No Tag')
|
|
1026
|
+
.option('--no-publish [boolean]', 'No Publish')
|
|
1027
|
+
.option('--no-commit [boolean]', 'No Commit')
|
|
1028
|
+
.option('--no-push [boolean]', 'No Push')
|
|
1029
|
+
.option('--force-update-package [string]', 'Force Update Package')
|
|
1030
|
+
.option('--skip-update-package [string]', 'Skip Update Package')
|
|
1031
|
+
.option('--custom-version [string]', 'Dry Run')
|
|
1032
|
+
.option('--patch [boolean]', 'Patch')
|
|
1033
|
+
.option('--major [boolean]', 'Major')
|
|
1034
|
+
.option('--minor [boolean]', 'Minor')
|
|
402
1035
|
.action(run);
|
|
403
1036
|
program
|
|
404
1037
|
.command('test')
|
|
405
1038
|
.alias('t')
|
|
406
1039
|
.description('unit-test')
|
|
407
|
-
.option('-p, --
|
|
408
|
-
.
|
|
1040
|
+
.option('-p, --package-name <string>', 'Select PackageName')
|
|
1041
|
+
.option('-w, --watch [boolean]', 'Watch Test')
|
|
1042
|
+
.option('--dry-run [boolean]', 'Dry Run')
|
|
1043
|
+
.action(run$3);
|
|
409
1044
|
program.parse(process.argv);
|
|
410
1045
|
if (!program.args.length) {
|
|
411
1046
|
program.help();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deot/dev-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -13,46 +13,47 @@
|
|
|
13
13
|
"access": "public"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@babel/core": "^7.21.
|
|
17
|
-
"@babel/
|
|
18
|
-
"@
|
|
16
|
+
"@babel/core": "^7.21.4",
|
|
17
|
+
"@babel/eslint-plugin": "^7.19.1",
|
|
18
|
+
"@babel/preset-env": "^7.21.4",
|
|
19
|
+
"@deot/dev-shared": "^1.0.2",
|
|
19
20
|
"@microsoft/api-extractor": "^7.34.4",
|
|
20
|
-
"@rollup/plugin-commonjs": "^24.0
|
|
21
|
-
"@rollup/plugin-node-resolve": "^15.0.
|
|
21
|
+
"@rollup/plugin-commonjs": "^24.1.0",
|
|
22
|
+
"@rollup/plugin-node-resolve": "^15.0.2",
|
|
22
23
|
"@rollup/plugin-replace": "^5.0.2",
|
|
23
|
-
"@rollup/plugin-typescript": "11.
|
|
24
|
-
"@types/jest": "^29.
|
|
25
|
-
"@types/node": "^18.11
|
|
24
|
+
"@rollup/plugin-typescript": "11.1.0",
|
|
25
|
+
"@types/jest": "^29.5.0",
|
|
26
|
+
"@types/node": "^18.15.11",
|
|
26
27
|
"@typescript-eslint/eslint-plugin": "^5.44.0",
|
|
27
28
|
"@typescript-eslint/parser": "^5.44.0",
|
|
28
|
-
"
|
|
29
|
+
"chalk": "^5.2.0",
|
|
30
|
+
"commander": "^10.0.1",
|
|
29
31
|
"cross-env": "^7.0.3",
|
|
30
|
-
"eslint": "^8.
|
|
32
|
+
"eslint": "^8.38.0",
|
|
31
33
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
32
|
-
"eslint-plugin-babel": "^5.3.1",
|
|
33
34
|
"eslint-plugin-import": "^2.27.5",
|
|
34
|
-
"eslint-plugin-jsdoc": "^
|
|
35
|
+
"eslint-plugin-jsdoc": "^43.0.0",
|
|
35
36
|
"eslint-plugin-markdown": "^3.0.0",
|
|
36
37
|
"eslint-watch": "^8.0.0",
|
|
37
|
-
"fs-extra": "^
|
|
38
|
-
"husky": "^
|
|
38
|
+
"fs-extra": "^11.1.1",
|
|
39
|
+
"husky": "^8.0.3",
|
|
39
40
|
"inquirer": "^9.1.5",
|
|
40
41
|
"inquirer-autocomplete-prompt": "^3.0.0",
|
|
41
42
|
"jest": "^29.5.0",
|
|
42
43
|
"jest-environment-jsdom": "^29.5.0",
|
|
43
|
-
"
|
|
44
|
-
"lint-staged": "^11.1.2",
|
|
44
|
+
"lint-staged": "^13.2.1",
|
|
45
45
|
"ora": "^6.1.2",
|
|
46
|
-
"rollup": "^3.
|
|
47
|
-
"
|
|
48
|
-
"
|
|
46
|
+
"rollup": "^3.20.5",
|
|
47
|
+
"semver": "^7.3.8",
|
|
48
|
+
"ts-jest": "^29.1.0",
|
|
49
|
+
"typescript": "^5.0.4",
|
|
49
50
|
"upath": "^2.0.1"
|
|
50
51
|
},
|
|
51
52
|
"devDependencies": {
|
|
52
|
-
"@deot/dev-test": "^1.0.
|
|
53
|
+
"@deot/dev-test": "^1.0.2",
|
|
54
|
+
"conventional-commits-parser": "^3.2.4"
|
|
53
55
|
},
|
|
54
56
|
"bin": {
|
|
55
57
|
"ddc": "bin/cli.js"
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
}
|
|
58
|
+
}
|
|
59
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2023 deot
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|