@peiyanlu/cli-utils 0.0.3 → 0.0.4
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/dist/cjs/index.cjs +66 -30
- package/dist/cjs/index.d.cts +31 -11
- package/dist/esm/index.d.mts +31 -11
- package/dist/esm/index.mjs +58 -21
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -135,26 +135,28 @@ const parseGitHubRepo = (url) => {
|
|
|
135
135
|
const eol = (n = 1) => node_os.EOL.repeat(n);
|
|
136
136
|
|
|
137
137
|
//#endregion
|
|
138
|
-
//#region src/
|
|
138
|
+
//#region src/styleText.ts
|
|
139
139
|
const dim = (text) => (0, node_util.styleText)(["dim"], text);
|
|
140
140
|
const red = (text) => (0, node_util.styleText)(["red"], text);
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
|
|
142
|
+
//#endregion
|
|
143
|
+
//#region src/shell.ts
|
|
144
|
+
/** 异步执行 `spawn` 获取字符串类型的结果 */
|
|
143
145
|
const spawnAsync = (cmd, args, options) => {
|
|
144
|
-
return new Promise((resolve$
|
|
146
|
+
return new Promise((resolve$2) => {
|
|
145
147
|
const { trim, error, dryRun, ...others } = options ?? {};
|
|
146
|
-
const fullCmd = [cmd, ...args]
|
|
148
|
+
const fullCmd = stringifyArgs([cmd, ...args]);
|
|
147
149
|
if (dryRun) {
|
|
148
150
|
console.log(`${dim("[dry-run]")} ${fullCmd}`);
|
|
149
|
-
return resolve$
|
|
151
|
+
return resolve$2(void 0);
|
|
150
152
|
}
|
|
151
153
|
const child = (0, node_child_process.spawn)(cmd, args, { ...others });
|
|
152
154
|
let stdout = "";
|
|
153
|
-
child.stdout
|
|
155
|
+
child.stdout.setEncoding("utf-8");
|
|
154
156
|
child.stdout?.on("data", (data) => stdout += trim ? data.trim() : data);
|
|
155
157
|
let stderr = "";
|
|
156
|
-
child.stderr
|
|
157
|
-
child.stderr
|
|
158
|
+
child.stderr.setEncoding("utf-8");
|
|
159
|
+
child.stderr.on("data", (data) => stderr += trim ? data.trim() : data);
|
|
158
160
|
child.on("close", (code) => {
|
|
159
161
|
if (stderr) {
|
|
160
162
|
const err = `${red("spawnAsync")} ${dim(fullCmd)} ${stderr}`;
|
|
@@ -165,38 +167,69 @@ const spawnAsync = (cmd, args, options) => {
|
|
|
165
167
|
case "throw": throw new Error(err);
|
|
166
168
|
}
|
|
167
169
|
}
|
|
168
|
-
resolve$
|
|
170
|
+
resolve$2(0 === code ? stdout : void 0);
|
|
169
171
|
});
|
|
170
172
|
});
|
|
171
173
|
};
|
|
172
|
-
|
|
173
|
-
|
|
174
|
+
/** 异步执行 `exec` 获取字符串类型的结果 */
|
|
175
|
+
const execAsync = (cmd, argsOrOptions, maybeOptions) => {
|
|
176
|
+
return new Promise((resolve$2) => {
|
|
177
|
+
let command;
|
|
178
|
+
let options;
|
|
179
|
+
if (Array.isArray(argsOrOptions)) {
|
|
180
|
+
command = stringifyArgs([cmd, ...argsOrOptions]);
|
|
181
|
+
options = maybeOptions;
|
|
182
|
+
} else {
|
|
183
|
+
command = cmd;
|
|
184
|
+
options = argsOrOptions;
|
|
185
|
+
}
|
|
174
186
|
const { trim, dryRun, error, ...others } = options ?? {};
|
|
175
187
|
if (dryRun) {
|
|
176
|
-
console.log(`${dim("[dry-run]")} ${
|
|
177
|
-
return resolve$
|
|
188
|
+
console.log(`${dim("[dry-run]")} ${command}`);
|
|
189
|
+
return resolve$2(void 0);
|
|
178
190
|
}
|
|
179
|
-
(0, node_child_process.exec)(
|
|
180
|
-
if (
|
|
181
|
-
const
|
|
191
|
+
(0, node_child_process.exec)(command, { ...others }, (stderr, stdout) => {
|
|
192
|
+
if (stderr) {
|
|
193
|
+
const err = `${red("execAsync")} ${dim(command)} ${stderr.message}`;
|
|
182
194
|
switch (error) {
|
|
183
195
|
case "log":
|
|
184
|
-
console.error(
|
|
196
|
+
console.error(err);
|
|
185
197
|
break;
|
|
186
|
-
case "throw": throw new Error(
|
|
198
|
+
case "throw": throw new Error(err);
|
|
187
199
|
}
|
|
188
200
|
}
|
|
189
|
-
resolve$
|
|
201
|
+
resolve$2(stderr ? void 0 : trim ? stdout.trim() : stdout);
|
|
190
202
|
});
|
|
191
203
|
});
|
|
192
204
|
};
|
|
205
|
+
/** 基于 {@link spawnAsync} 实现 */
|
|
193
206
|
const runGit = async (args, options = { trim: true }) => {
|
|
194
207
|
return spawnAsync("git", args, options);
|
|
195
208
|
};
|
|
209
|
+
/** 基于 {@link execAsync} 实现 */
|
|
196
210
|
const runNpm = (args, options = { trim: true }) => {
|
|
197
|
-
return execAsync(
|
|
211
|
+
return execAsync("npm", args, options);
|
|
212
|
+
};
|
|
213
|
+
/** 基于 {@link spawnSync} 实现 */
|
|
214
|
+
const runGitSync = (args, options) => {
|
|
215
|
+
const { stdout } = (0, node_child_process.spawnSync)("git", args, {
|
|
216
|
+
encoding: "utf-8",
|
|
217
|
+
...options
|
|
218
|
+
});
|
|
219
|
+
return stdout.toString().trim();
|
|
220
|
+
};
|
|
221
|
+
/** 基于 {@link execSync} 实现 */
|
|
222
|
+
const runNpmSync = (args, options) => {
|
|
223
|
+
return (0, node_child_process.execSync)(stringifyArgs(["npm", ...args]), {
|
|
224
|
+
encoding: "utf-8",
|
|
225
|
+
...options
|
|
226
|
+
}).toString().trim();
|
|
198
227
|
};
|
|
199
|
-
|
|
228
|
+
/** 将字符串以空格分割为数组 */
|
|
229
|
+
const parseArgs = (args) => args.trim() ? args.trim().split(" ") : [];
|
|
230
|
+
/** 将数组以空格拼接为字符串 */
|
|
231
|
+
const stringifyArgs = (args) => args.length ? args.join(" ") : "";
|
|
232
|
+
/** 支持所有支持 `--version` 命令的脚本查看版本 */
|
|
200
233
|
const checkVersion = async (cmd) => {
|
|
201
234
|
return execAsync(`${cmd} --version`);
|
|
202
235
|
};
|
|
@@ -234,14 +267,16 @@ function joinUrl(input) {
|
|
|
234
267
|
|
|
235
268
|
//#endregion
|
|
236
269
|
//#region src/git.ts
|
|
270
|
+
/** 判断指定目录是否是 git 仓库 */
|
|
237
271
|
const isGitRepo = async (dir) => {
|
|
238
|
-
return
|
|
272
|
+
return "true" === await runGit([
|
|
239
273
|
"-C",
|
|
240
|
-
|
|
274
|
+
(0, node_path.resolve)(process.cwd(), dir || "."),
|
|
241
275
|
"rev-parse",
|
|
242
276
|
"--is-inside-work-tree"
|
|
243
277
|
]);
|
|
244
278
|
};
|
|
279
|
+
/** 获取指定的 git 配置 */
|
|
245
280
|
const getGitConfig = (key, global = true) => {
|
|
246
281
|
return runGit([
|
|
247
282
|
"config",
|
|
@@ -249,6 +284,7 @@ const getGitConfig = (key, global = true) => {
|
|
|
249
284
|
key
|
|
250
285
|
]);
|
|
251
286
|
};
|
|
287
|
+
/** 获取 git 远程地址 */
|
|
252
288
|
const getGitRemoteUrl = async (remoteName = "origin") => {
|
|
253
289
|
return runGit([
|
|
254
290
|
"remote",
|
|
@@ -263,6 +299,7 @@ const getGitRemoteUrl = async (remoteName = "origin") => {
|
|
|
263
299
|
|
|
264
300
|
//#endregion
|
|
265
301
|
//#region src/npm.ts
|
|
302
|
+
/** 获取指定包的版本 */
|
|
266
303
|
const pkgVersion = (pkg) => {
|
|
267
304
|
return runNpm([
|
|
268
305
|
"view",
|
|
@@ -278,13 +315,11 @@ exports.PkgManager = PkgManager;
|
|
|
278
315
|
exports.YesOrNo = YesOrNo;
|
|
279
316
|
exports.checkVersion = checkVersion;
|
|
280
317
|
exports.copyDirAsync = copyDirAsync;
|
|
281
|
-
exports.dim = dim;
|
|
282
318
|
exports.editFile = editFile;
|
|
283
319
|
exports.editJsonFile = editJsonFile;
|
|
284
320
|
exports.emptyDir = emptyDir;
|
|
285
321
|
exports.eol = eol;
|
|
286
322
|
exports.execAsync = execAsync;
|
|
287
|
-
exports.fixArgs = fixArgs;
|
|
288
323
|
exports.getGitConfig = getGitConfig;
|
|
289
324
|
exports.getGitRemoteUrl = getGitRemoteUrl;
|
|
290
325
|
exports.isEmpty = isEmpty;
|
|
@@ -292,17 +327,18 @@ exports.isGitRepo = isGitRepo;
|
|
|
292
327
|
exports.isTestFile = isTestFile;
|
|
293
328
|
exports.isValidPackageName = isValidPackageName;
|
|
294
329
|
exports.joinUrl = joinUrl;
|
|
330
|
+
exports.parseArgs = parseArgs;
|
|
295
331
|
exports.parseGitHubRepo = parseGitHubRepo;
|
|
296
332
|
exports.pkgFromUserAgent = pkgFromUserAgent;
|
|
297
333
|
exports.pkgVersion = pkgVersion;
|
|
298
334
|
exports.readJsonFile = readJsonFile;
|
|
299
335
|
exports.readSubDirs = readSubDirs;
|
|
300
|
-
exports.red = red;
|
|
301
336
|
exports.runCliForTest = runCliForTest;
|
|
302
337
|
exports.runGit = runGit;
|
|
338
|
+
exports.runGitSync = runGitSync;
|
|
303
339
|
exports.runNpm = runNpm;
|
|
340
|
+
exports.runNpmSync = runNpmSync;
|
|
304
341
|
exports.spawnAsync = spawnAsync;
|
|
342
|
+
exports.stringifyArgs = stringifyArgs;
|
|
305
343
|
exports.toValidPackageName = toValidPackageName;
|
|
306
|
-
exports.toValidProjectName = toValidProjectName;
|
|
307
|
-
exports.underline = underline;
|
|
308
|
-
exports.yellow = yellow;
|
|
344
|
+
exports.toValidProjectName = toValidProjectName;
|
package/dist/cjs/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { ExecOptionsWithStringEncoding, SpawnOptionsWithoutStdio } from "node:child_process";
|
|
1
2
|
import * as child_process0 from "child_process";
|
|
2
|
-
import {
|
|
3
|
+
import { ExecSyncOptionsWithStringEncoding, SpawnSyncOptionsWithStringEncoding } from "child_process";
|
|
3
4
|
|
|
4
5
|
//#region src/enums.d.ts
|
|
5
6
|
declare enum PkgManager {
|
|
@@ -38,12 +39,15 @@ interface PkgInfo {
|
|
|
38
39
|
version: string;
|
|
39
40
|
}
|
|
40
41
|
interface ExecResultOptions {
|
|
42
|
+
/** 去掉结果的首尾空格 */
|
|
41
43
|
trim?: boolean;
|
|
44
|
+
/** 仅打印命令,不实际执行命令 */
|
|
42
45
|
dryRun?: boolean;
|
|
46
|
+
/** log: 打印错误信息,返回 undefined; throw: 抛出错误; ignore: 返回 undefined */
|
|
43
47
|
error?: 'log' | 'throw' | 'ignore';
|
|
44
48
|
}
|
|
45
|
-
type SpawnAsyncOptions
|
|
46
|
-
type ExecAsyncOptions
|
|
49
|
+
type SpawnAsyncOptions = SpawnOptionsWithoutStdio & ExecResultOptions;
|
|
50
|
+
type ExecAsyncOptions = ExecOptionsWithStringEncoding & ExecResultOptions;
|
|
47
51
|
//#endregion
|
|
48
52
|
//#region src/utils.d.ts
|
|
49
53
|
declare const isValidPackageName: (packageName: string) => boolean;
|
|
@@ -68,15 +72,27 @@ declare const parseGitHubRepo: (url: string) => string[];
|
|
|
68
72
|
declare const eol: (n?: number) => string;
|
|
69
73
|
//#endregion
|
|
70
74
|
//#region src/shell.d.ts
|
|
71
|
-
|
|
72
|
-
declare const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
/** 异步执行 `spawn` 获取字符串类型的结果 */
|
|
76
|
+
declare const spawnAsync: (cmd: string, args: string[], options?: SpawnAsyncOptions) => Promise<string | undefined>;
|
|
77
|
+
type ExecAsync = {
|
|
78
|
+
(cmd: string, options?: ExecAsyncOptions): Promise<string | undefined>;
|
|
79
|
+
(cmd: string, args: string[], options?: ExecAsyncOptions): Promise<string | undefined>;
|
|
80
|
+
};
|
|
81
|
+
/** 异步执行 `exec` 获取字符串类型的结果 */
|
|
82
|
+
declare const execAsync: ExecAsync;
|
|
83
|
+
/** 基于 {@link spawnAsync} 实现 */
|
|
77
84
|
declare const runGit: (args: string[], options?: SpawnAsyncOptions) => Promise<string | undefined>;
|
|
85
|
+
/** 基于 {@link execAsync} 实现 */
|
|
78
86
|
declare const runNpm: (args: string[], options?: ExecAsyncOptions) => Promise<string | undefined>;
|
|
79
|
-
|
|
87
|
+
/** 基于 {@link spawnSync} 实现 */
|
|
88
|
+
declare const runGitSync: (args: string[], options?: SpawnSyncOptionsWithStringEncoding) => string;
|
|
89
|
+
/** 基于 {@link execSync} 实现 */
|
|
90
|
+
declare const runNpmSync: (args: string[], options?: ExecSyncOptionsWithStringEncoding) => string;
|
|
91
|
+
/** 将字符串以空格分割为数组 */
|
|
92
|
+
declare const parseArgs: (args: string) => string[];
|
|
93
|
+
/** 将数组以空格拼接为字符串 */
|
|
94
|
+
declare const stringifyArgs: (args: string[]) => string;
|
|
95
|
+
/** 支持所有支持 `--version` 命令的脚本查看版本 */
|
|
80
96
|
declare const checkVersion: (cmd: string) => Promise<string | undefined>;
|
|
81
97
|
//#endregion
|
|
82
98
|
//#region src/joinUrl.d.ts
|
|
@@ -84,11 +100,15 @@ declare function joinUrl(...args: string[]): string;
|
|
|
84
100
|
declare function joinUrl(input: readonly string[]): string;
|
|
85
101
|
//#endregion
|
|
86
102
|
//#region src/git.d.ts
|
|
103
|
+
/** 判断指定目录是否是 git 仓库 */
|
|
87
104
|
declare const isGitRepo: (dir?: string) => Promise<boolean>;
|
|
105
|
+
/** 获取指定的 git 配置 */
|
|
88
106
|
declare const getGitConfig: (key: string, global?: boolean) => Promise<string | undefined>;
|
|
107
|
+
/** 获取 git 远程地址 */
|
|
89
108
|
declare const getGitRemoteUrl: (remoteName?: string) => Promise<string | undefined>;
|
|
90
109
|
//#endregion
|
|
91
110
|
//#region src/npm.d.ts
|
|
111
|
+
/** 获取指定包的版本 */
|
|
92
112
|
declare const pkgVersion: (pkg: string) => Promise<string | undefined>;
|
|
93
113
|
//#endregion
|
|
94
|
-
export { CliOptions, ConfirmResult, CopyOptions, ExecAsyncOptions, ExecResultOptions, HttpLibrary, PkgInfo, PkgManager, SpawnAsyncOptions, YesOrNo, checkVersion, copyDirAsync,
|
|
114
|
+
export { CliOptions, ConfirmResult, CopyOptions, ExecAsyncOptions, ExecResultOptions, HttpLibrary, PkgInfo, PkgManager, SpawnAsyncOptions, YesOrNo, checkVersion, copyDirAsync, editFile, editJsonFile, emptyDir, eol, execAsync, getGitConfig, getGitRemoteUrl, isEmpty, isGitRepo, isTestFile, isValidPackageName, joinUrl, parseArgs, parseGitHubRepo, pkgFromUserAgent, pkgVersion, readJsonFile, readSubDirs, runCliForTest, runGit, runGitSync, runNpm, runNpmSync, spawnAsync, stringifyArgs, toValidPackageName, toValidProjectName };
|
package/dist/esm/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { ExecOptionsWithStringEncoding, SpawnOptionsWithoutStdio } from "node:child_process";
|
|
1
2
|
import * as child_process0 from "child_process";
|
|
2
|
-
import {
|
|
3
|
+
import { ExecSyncOptionsWithStringEncoding, SpawnSyncOptionsWithStringEncoding } from "child_process";
|
|
3
4
|
|
|
4
5
|
//#region src/enums.d.ts
|
|
5
6
|
declare enum PkgManager {
|
|
@@ -38,12 +39,15 @@ interface PkgInfo {
|
|
|
38
39
|
version: string;
|
|
39
40
|
}
|
|
40
41
|
interface ExecResultOptions {
|
|
42
|
+
/** 去掉结果的首尾空格 */
|
|
41
43
|
trim?: boolean;
|
|
44
|
+
/** 仅打印命令,不实际执行命令 */
|
|
42
45
|
dryRun?: boolean;
|
|
46
|
+
/** log: 打印错误信息,返回 undefined; throw: 抛出错误; ignore: 返回 undefined */
|
|
43
47
|
error?: 'log' | 'throw' | 'ignore';
|
|
44
48
|
}
|
|
45
|
-
type SpawnAsyncOptions
|
|
46
|
-
type ExecAsyncOptions
|
|
49
|
+
type SpawnAsyncOptions = SpawnOptionsWithoutStdio & ExecResultOptions;
|
|
50
|
+
type ExecAsyncOptions = ExecOptionsWithStringEncoding & ExecResultOptions;
|
|
47
51
|
//#endregion
|
|
48
52
|
//#region src/utils.d.ts
|
|
49
53
|
declare const isValidPackageName: (packageName: string) => boolean;
|
|
@@ -68,15 +72,27 @@ declare const parseGitHubRepo: (url: string) => string[];
|
|
|
68
72
|
declare const eol: (n?: number) => string;
|
|
69
73
|
//#endregion
|
|
70
74
|
//#region src/shell.d.ts
|
|
71
|
-
|
|
72
|
-
declare const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
/** 异步执行 `spawn` 获取字符串类型的结果 */
|
|
76
|
+
declare const spawnAsync: (cmd: string, args: string[], options?: SpawnAsyncOptions) => Promise<string | undefined>;
|
|
77
|
+
type ExecAsync = {
|
|
78
|
+
(cmd: string, options?: ExecAsyncOptions): Promise<string | undefined>;
|
|
79
|
+
(cmd: string, args: string[], options?: ExecAsyncOptions): Promise<string | undefined>;
|
|
80
|
+
};
|
|
81
|
+
/** 异步执行 `exec` 获取字符串类型的结果 */
|
|
82
|
+
declare const execAsync: ExecAsync;
|
|
83
|
+
/** 基于 {@link spawnAsync} 实现 */
|
|
77
84
|
declare const runGit: (args: string[], options?: SpawnAsyncOptions) => Promise<string | undefined>;
|
|
85
|
+
/** 基于 {@link execAsync} 实现 */
|
|
78
86
|
declare const runNpm: (args: string[], options?: ExecAsyncOptions) => Promise<string | undefined>;
|
|
79
|
-
|
|
87
|
+
/** 基于 {@link spawnSync} 实现 */
|
|
88
|
+
declare const runGitSync: (args: string[], options?: SpawnSyncOptionsWithStringEncoding) => string;
|
|
89
|
+
/** 基于 {@link execSync} 实现 */
|
|
90
|
+
declare const runNpmSync: (args: string[], options?: ExecSyncOptionsWithStringEncoding) => string;
|
|
91
|
+
/** 将字符串以空格分割为数组 */
|
|
92
|
+
declare const parseArgs: (args: string) => string[];
|
|
93
|
+
/** 将数组以空格拼接为字符串 */
|
|
94
|
+
declare const stringifyArgs: (args: string[]) => string;
|
|
95
|
+
/** 支持所有支持 `--version` 命令的脚本查看版本 */
|
|
80
96
|
declare const checkVersion: (cmd: string) => Promise<string | undefined>;
|
|
81
97
|
//#endregion
|
|
82
98
|
//#region src/joinUrl.d.ts
|
|
@@ -84,11 +100,15 @@ declare function joinUrl(...args: string[]): string;
|
|
|
84
100
|
declare function joinUrl(input: readonly string[]): string;
|
|
85
101
|
//#endregion
|
|
86
102
|
//#region src/git.d.ts
|
|
103
|
+
/** 判断指定目录是否是 git 仓库 */
|
|
87
104
|
declare const isGitRepo: (dir?: string) => Promise<boolean>;
|
|
105
|
+
/** 获取指定的 git 配置 */
|
|
88
106
|
declare const getGitConfig: (key: string, global?: boolean) => Promise<string | undefined>;
|
|
107
|
+
/** 获取 git 远程地址 */
|
|
89
108
|
declare const getGitRemoteUrl: (remoteName?: string) => Promise<string | undefined>;
|
|
90
109
|
//#endregion
|
|
91
110
|
//#region src/npm.d.ts
|
|
111
|
+
/** 获取指定包的版本 */
|
|
92
112
|
declare const pkgVersion: (pkg: string) => Promise<string | undefined>;
|
|
93
113
|
//#endregion
|
|
94
|
-
export { CliOptions, ConfirmResult, CopyOptions, ExecAsyncOptions, ExecResultOptions, HttpLibrary, PkgInfo, PkgManager, SpawnAsyncOptions, YesOrNo, checkVersion, copyDirAsync,
|
|
114
|
+
export { CliOptions, ConfirmResult, CopyOptions, ExecAsyncOptions, ExecResultOptions, HttpLibrary, PkgInfo, PkgManager, SpawnAsyncOptions, YesOrNo, checkVersion, copyDirAsync, editFile, editJsonFile, emptyDir, eol, execAsync, getGitConfig, getGitRemoteUrl, isEmpty, isGitRepo, isTestFile, isValidPackageName, joinUrl, parseArgs, parseGitHubRepo, pkgFromUserAgent, pkgVersion, readJsonFile, readSubDirs, runCliForTest, runGit, runGitSync, runNpm, runNpmSync, spawnAsync, stringifyArgs, toValidPackageName, toValidProjectName };
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { exec, spawn, spawnSync } from "node:child_process";
|
|
1
|
+
import { exec, execSync, spawn, spawnSync } from "node:child_process";
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { copyFile, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
4
4
|
import { EOL } from "node:os";
|
|
@@ -135,26 +135,28 @@ const parseGitHubRepo = (url) => {
|
|
|
135
135
|
const eol = (n = 1) => EOL.repeat(n);
|
|
136
136
|
|
|
137
137
|
//#endregion
|
|
138
|
-
//#region src/
|
|
138
|
+
//#region src/styleText.ts
|
|
139
139
|
const dim = (text) => styleText(["dim"], text);
|
|
140
140
|
const red = (text) => styleText(["red"], text);
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
|
|
142
|
+
//#endregion
|
|
143
|
+
//#region src/shell.ts
|
|
144
|
+
/** 异步执行 `spawn` 获取字符串类型的结果 */
|
|
143
145
|
const spawnAsync = (cmd, args, options) => {
|
|
144
146
|
return new Promise((resolve$1) => {
|
|
145
147
|
const { trim, error, dryRun, ...others } = options ?? {};
|
|
146
|
-
const fullCmd = [cmd, ...args]
|
|
148
|
+
const fullCmd = stringifyArgs([cmd, ...args]);
|
|
147
149
|
if (dryRun) {
|
|
148
150
|
console.log(`${dim("[dry-run]")} ${fullCmd}`);
|
|
149
151
|
return resolve$1(void 0);
|
|
150
152
|
}
|
|
151
153
|
const child = spawn(cmd, args, { ...others });
|
|
152
154
|
let stdout = "";
|
|
153
|
-
child.stdout
|
|
155
|
+
child.stdout.setEncoding("utf-8");
|
|
154
156
|
child.stdout?.on("data", (data) => stdout += trim ? data.trim() : data);
|
|
155
157
|
let stderr = "";
|
|
156
|
-
child.stderr
|
|
157
|
-
child.stderr
|
|
158
|
+
child.stderr.setEncoding("utf-8");
|
|
159
|
+
child.stderr.on("data", (data) => stderr += trim ? data.trim() : data);
|
|
158
160
|
child.on("close", (code) => {
|
|
159
161
|
if (stderr) {
|
|
160
162
|
const err = `${red("spawnAsync")} ${dim(fullCmd)} ${stderr}`;
|
|
@@ -169,34 +171,65 @@ const spawnAsync = (cmd, args, options) => {
|
|
|
169
171
|
});
|
|
170
172
|
});
|
|
171
173
|
};
|
|
172
|
-
|
|
174
|
+
/** 异步执行 `exec` 获取字符串类型的结果 */
|
|
175
|
+
const execAsync = (cmd, argsOrOptions, maybeOptions) => {
|
|
173
176
|
return new Promise((resolve$1) => {
|
|
177
|
+
let command;
|
|
178
|
+
let options;
|
|
179
|
+
if (Array.isArray(argsOrOptions)) {
|
|
180
|
+
command = stringifyArgs([cmd, ...argsOrOptions]);
|
|
181
|
+
options = maybeOptions;
|
|
182
|
+
} else {
|
|
183
|
+
command = cmd;
|
|
184
|
+
options = argsOrOptions;
|
|
185
|
+
}
|
|
174
186
|
const { trim, dryRun, error, ...others } = options ?? {};
|
|
175
187
|
if (dryRun) {
|
|
176
|
-
console.log(`${dim("[dry-run]")} ${
|
|
188
|
+
console.log(`${dim("[dry-run]")} ${command}`);
|
|
177
189
|
return resolve$1(void 0);
|
|
178
190
|
}
|
|
179
|
-
exec(
|
|
180
|
-
if (
|
|
181
|
-
const
|
|
191
|
+
exec(command, { ...others }, (stderr, stdout) => {
|
|
192
|
+
if (stderr) {
|
|
193
|
+
const err = `${red("execAsync")} ${dim(command)} ${stderr.message}`;
|
|
182
194
|
switch (error) {
|
|
183
195
|
case "log":
|
|
184
|
-
console.error(
|
|
196
|
+
console.error(err);
|
|
185
197
|
break;
|
|
186
|
-
case "throw": throw new Error(
|
|
198
|
+
case "throw": throw new Error(err);
|
|
187
199
|
}
|
|
188
200
|
}
|
|
189
|
-
resolve$1(
|
|
201
|
+
resolve$1(stderr ? void 0 : trim ? stdout.trim() : stdout);
|
|
190
202
|
});
|
|
191
203
|
});
|
|
192
204
|
};
|
|
205
|
+
/** 基于 {@link spawnAsync} 实现 */
|
|
193
206
|
const runGit = async (args, options = { trim: true }) => {
|
|
194
207
|
return spawnAsync("git", args, options);
|
|
195
208
|
};
|
|
209
|
+
/** 基于 {@link execAsync} 实现 */
|
|
196
210
|
const runNpm = (args, options = { trim: true }) => {
|
|
197
|
-
return execAsync(
|
|
211
|
+
return execAsync("npm", args, options);
|
|
212
|
+
};
|
|
213
|
+
/** 基于 {@link spawnSync} 实现 */
|
|
214
|
+
const runGitSync = (args, options) => {
|
|
215
|
+
const { stdout } = spawnSync("git", args, {
|
|
216
|
+
encoding: "utf-8",
|
|
217
|
+
...options
|
|
218
|
+
});
|
|
219
|
+
return stdout.toString().trim();
|
|
220
|
+
};
|
|
221
|
+
/** 基于 {@link execSync} 实现 */
|
|
222
|
+
const runNpmSync = (args, options) => {
|
|
223
|
+
return execSync(stringifyArgs(["npm", ...args]), {
|
|
224
|
+
encoding: "utf-8",
|
|
225
|
+
...options
|
|
226
|
+
}).toString().trim();
|
|
198
227
|
};
|
|
199
|
-
|
|
228
|
+
/** 将字符串以空格分割为数组 */
|
|
229
|
+
const parseArgs = (args) => args.trim() ? args.trim().split(" ") : [];
|
|
230
|
+
/** 将数组以空格拼接为字符串 */
|
|
231
|
+
const stringifyArgs = (args) => args.length ? args.join(" ") : "";
|
|
232
|
+
/** 支持所有支持 `--version` 命令的脚本查看版本 */
|
|
200
233
|
const checkVersion = async (cmd) => {
|
|
201
234
|
return execAsync(`${cmd} --version`);
|
|
202
235
|
};
|
|
@@ -234,14 +267,16 @@ function joinUrl(input) {
|
|
|
234
267
|
|
|
235
268
|
//#endregion
|
|
236
269
|
//#region src/git.ts
|
|
270
|
+
/** 判断指定目录是否是 git 仓库 */
|
|
237
271
|
const isGitRepo = async (dir) => {
|
|
238
|
-
return
|
|
272
|
+
return "true" === await runGit([
|
|
239
273
|
"-C",
|
|
240
|
-
|
|
274
|
+
resolve(process.cwd(), dir || "."),
|
|
241
275
|
"rev-parse",
|
|
242
276
|
"--is-inside-work-tree"
|
|
243
277
|
]);
|
|
244
278
|
};
|
|
279
|
+
/** 获取指定的 git 配置 */
|
|
245
280
|
const getGitConfig = (key, global = true) => {
|
|
246
281
|
return runGit([
|
|
247
282
|
"config",
|
|
@@ -249,6 +284,7 @@ const getGitConfig = (key, global = true) => {
|
|
|
249
284
|
key
|
|
250
285
|
]);
|
|
251
286
|
};
|
|
287
|
+
/** 获取 git 远程地址 */
|
|
252
288
|
const getGitRemoteUrl = async (remoteName = "origin") => {
|
|
253
289
|
return runGit([
|
|
254
290
|
"remote",
|
|
@@ -263,6 +299,7 @@ const getGitRemoteUrl = async (remoteName = "origin") => {
|
|
|
263
299
|
|
|
264
300
|
//#endregion
|
|
265
301
|
//#region src/npm.ts
|
|
302
|
+
/** 获取指定包的版本 */
|
|
266
303
|
const pkgVersion = (pkg) => {
|
|
267
304
|
return runNpm([
|
|
268
305
|
"view",
|
|
@@ -272,4 +309,4 @@ const pkgVersion = (pkg) => {
|
|
|
272
309
|
};
|
|
273
310
|
|
|
274
311
|
//#endregion
|
|
275
|
-
export { ConfirmResult, HttpLibrary, PkgManager, YesOrNo, checkVersion, copyDirAsync,
|
|
312
|
+
export { ConfirmResult, HttpLibrary, PkgManager, YesOrNo, checkVersion, copyDirAsync, editFile, editJsonFile, emptyDir, eol, execAsync, getGitConfig, getGitRemoteUrl, isEmpty, isGitRepo, isTestFile, isValidPackageName, joinUrl, parseArgs, parseGitHubRepo, pkgFromUserAgent, pkgVersion, readJsonFile, readSubDirs, runCliForTest, runGit, runGitSync, runNpm, runNpmSync, spawnAsync, stringifyArgs, toValidPackageName, toValidProjectName };
|