@peiyanlu/cli-utils 0.0.2 → 0.0.3

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.
@@ -1,6 +1,7 @@
1
1
  let node_child_process = require("node:child_process");
2
2
  let node_fs = require("node:fs");
3
3
  let node_fs_promises = require("node:fs/promises");
4
+ let node_os = require("node:os");
4
5
  let node_path = require("node:path");
5
6
  let node_util = require("node:util");
6
7
 
@@ -125,16 +126,20 @@ const isTestFile = (name) => {
125
126
  /^vitest([-.])(.*)\.m?(ts|js)$/
126
127
  ].some((reg) => reg.test(name));
127
128
  };
129
+ /** 解析 Github 链接获取 owner 和 repo */
128
130
  const parseGitHubRepo = (url) => {
129
131
  const match = url.trim().match(/github(?:\.com)?[:/](.+?)\/(.+?)(?:[#/?].+?)?(?:\.git)?$/);
130
132
  return match ? match.slice(1, 3) : [];
131
133
  };
134
+ /** 基于 EOL 的可多换行函数 */
135
+ const eol = (n = 1) => node_os.EOL.repeat(n);
132
136
 
133
137
  //#endregion
134
138
  //#region src/shell.ts
135
139
  const dim = (text) => (0, node_util.styleText)(["dim"], text);
136
140
  const red = (text) => (0, node_util.styleText)(["red"], text);
137
141
  const yellow = (text) => (0, node_util.styleText)(["yellow"], text);
142
+ const underline = (text) => (0, node_util.styleText)(["underline"], text);
138
143
  const spawnAsync = (cmd, args, options) => {
139
144
  return new Promise((resolve$1) => {
140
145
  const { trim, error, dryRun, ...others } = options ?? {};
@@ -185,12 +190,50 @@ const execAsync = (cmd, options) => {
185
190
  });
186
191
  });
187
192
  };
188
- const runGit = async (args, trim = true) => {
189
- return spawnAsync("git", args, { trim });
193
+ const runGit = async (args, options = { trim: true }) => {
194
+ return spawnAsync("git", args, options);
190
195
  };
191
- const runNpm = (args) => {
192
- return execAsync(["npm", ...args].join(" "));
196
+ const runNpm = (args, options = { trim: true }) => {
197
+ return execAsync(["npm", ...args].join(" "), options);
193
198
  };
199
+ const fixArgs = (args) => args.trim() ? args.trim().split(" ") : [];
200
+ const checkVersion = async (cmd) => {
201
+ return execAsync(`${cmd} --version`);
202
+ };
203
+
204
+ //#endregion
205
+ //#region src/joinUrl.ts
206
+ function joinUrl(input) {
207
+ const temps = Array.isArray(input) ? input : [...arguments];
208
+ if (temps.length === 0) return "";
209
+ const result = [];
210
+ const parts = [...temps];
211
+ /** 协议正则 */
212
+ const PROTOCOL_RE = /^[^/:]+:\/*$/;
213
+ const FILE_PROTOCOL_RE = /^file:\/\/\//;
214
+ if (PROTOCOL_RE.test(parts[0]) && parts.length > 1) {
215
+ parts[1] = parts[0] + parts[1];
216
+ parts.shift();
217
+ }
218
+ if (FILE_PROTOCOL_RE.test(parts[0])) parts[0] = parts[0].replace(/^([^/:]+):\/*/, "$1:///");
219
+ else parts[0] = parts[0].replace(/^([^/:]+):\/*/, "$1://");
220
+ parts.forEach((part, index) => {
221
+ if (!part) return;
222
+ let segment = part;
223
+ if (index > 0) segment = segment.replace(/^\/+/, "");
224
+ if (index < parts.length - 1) segment = segment.replace(/\/+$/, "");
225
+ else segment = segment.replace(/\/+$/, "/");
226
+ result.push(segment);
227
+ });
228
+ let url = result.join("/");
229
+ url = url.replace(/\/(\?|&|#[^!])/g, "$1");
230
+ const [base, ...queryParts] = url.split("?");
231
+ url = base + (queryParts.length ? "?" + queryParts.join("&") : "");
232
+ return url;
233
+ }
234
+
235
+ //#endregion
236
+ //#region src/git.ts
194
237
  const isGitRepo = async (dir) => {
195
238
  return !!await runGit([
196
239
  "-C",
@@ -217,6 +260,9 @@ const getGitRemoteUrl = async (remoteName = "origin") => {
217
260
  `remote.${remoteName}.url`
218
261
  ]));
219
262
  };
263
+
264
+ //#endregion
265
+ //#region src/npm.ts
220
266
  const pkgVersion = (pkg) => {
221
267
  return runNpm([
222
268
  "view",
@@ -224,9 +270,6 @@ const pkgVersion = (pkg) => {
224
270
  "version"
225
271
  ]);
226
272
  };
227
- const checkVersion = async (cmd) => {
228
- return execAsync(`${cmd} --version`);
229
- };
230
273
 
231
274
  //#endregion
232
275
  exports.ConfirmResult = ConfirmResult;
@@ -239,13 +282,16 @@ exports.dim = dim;
239
282
  exports.editFile = editFile;
240
283
  exports.editJsonFile = editJsonFile;
241
284
  exports.emptyDir = emptyDir;
285
+ exports.eol = eol;
242
286
  exports.execAsync = execAsync;
287
+ exports.fixArgs = fixArgs;
243
288
  exports.getGitConfig = getGitConfig;
244
289
  exports.getGitRemoteUrl = getGitRemoteUrl;
245
290
  exports.isEmpty = isEmpty;
246
291
  exports.isGitRepo = isGitRepo;
247
292
  exports.isTestFile = isTestFile;
248
293
  exports.isValidPackageName = isValidPackageName;
294
+ exports.joinUrl = joinUrl;
249
295
  exports.parseGitHubRepo = parseGitHubRepo;
250
296
  exports.pkgFromUserAgent = pkgFromUserAgent;
251
297
  exports.pkgVersion = pkgVersion;
@@ -258,4 +304,5 @@ exports.runNpm = runNpm;
258
304
  exports.spawnAsync = spawnAsync;
259
305
  exports.toValidPackageName = toValidPackageName;
260
306
  exports.toValidProjectName = toValidProjectName;
307
+ exports.underline = underline;
261
308
  exports.yellow = yellow;
@@ -62,20 +62,33 @@ declare const pkgFromUserAgent: (userAgent: string | undefined) => PkgInfo | und
62
62
  declare const runCliForTest: (path: string, args: string[], options?: SpawnSyncOptionsWithStringEncoding) => child_process0.SpawnSyncReturns<string>;
63
63
  /** 判断测试文件(夹) */
64
64
  declare const isTestFile: (name: string) => boolean;
65
+ /** 解析 Github 链接获取 owner 和 repo */
65
66
  declare const parseGitHubRepo: (url: string) => string[];
67
+ /** 基于 EOL 的可多换行函数 */
68
+ declare const eol: (n?: number) => string;
66
69
  //#endregion
67
70
  //#region src/shell.d.ts
68
71
  declare const dim: (text: string) => string;
69
72
  declare const red: (text: string) => string;
70
73
  declare const yellow: (text: string) => string;
74
+ declare const underline: (text: string) => string;
71
75
  declare const spawnAsync: <T = SpawnOptions>(cmd: string, args: string[], options?: SpawnAsyncOptions<T>) => Promise<string | undefined>;
72
76
  declare const execAsync: <T = ExecOptions>(cmd: string, options?: ExecAsyncOptions<T>) => Promise<string | undefined>;
73
- declare const runGit: (args: string[], trim?: boolean) => Promise<string | undefined>;
74
- declare const runNpm: (args: string[]) => Promise<string | undefined>;
77
+ declare const runGit: (args: string[], options?: SpawnAsyncOptions) => Promise<string | undefined>;
78
+ declare const runNpm: (args: string[], options?: ExecAsyncOptions) => Promise<string | undefined>;
79
+ declare const fixArgs: (args: string) => string[];
80
+ declare const checkVersion: (cmd: string) => Promise<string | undefined>;
81
+ //#endregion
82
+ //#region src/joinUrl.d.ts
83
+ declare function joinUrl(...args: string[]): string;
84
+ declare function joinUrl(input: readonly string[]): string;
85
+ //#endregion
86
+ //#region src/git.d.ts
75
87
  declare const isGitRepo: (dir?: string) => Promise<boolean>;
76
88
  declare const getGitConfig: (key: string, global?: boolean) => Promise<string | undefined>;
77
89
  declare const getGitRemoteUrl: (remoteName?: string) => Promise<string | undefined>;
90
+ //#endregion
91
+ //#region src/npm.d.ts
78
92
  declare const pkgVersion: (pkg: string) => Promise<string | undefined>;
79
- declare const checkVersion: (cmd: string) => Promise<string | undefined>;
80
93
  //#endregion
81
- export { CliOptions, ConfirmResult, CopyOptions, ExecAsyncOptions, ExecResultOptions, HttpLibrary, PkgInfo, PkgManager, SpawnAsyncOptions, YesOrNo, checkVersion, copyDirAsync, dim, editFile, editJsonFile, emptyDir, execAsync, getGitConfig, getGitRemoteUrl, isEmpty, isGitRepo, isTestFile, isValidPackageName, parseGitHubRepo, pkgFromUserAgent, pkgVersion, readJsonFile, readSubDirs, red, runCliForTest, runGit, runNpm, spawnAsync, toValidPackageName, toValidProjectName, yellow };
94
+ export { CliOptions, ConfirmResult, CopyOptions, ExecAsyncOptions, ExecResultOptions, HttpLibrary, PkgInfo, PkgManager, SpawnAsyncOptions, YesOrNo, checkVersion, copyDirAsync, dim, editFile, editJsonFile, emptyDir, eol, execAsync, fixArgs, getGitConfig, getGitRemoteUrl, isEmpty, isGitRepo, isTestFile, isValidPackageName, joinUrl, parseGitHubRepo, pkgFromUserAgent, pkgVersion, readJsonFile, readSubDirs, red, runCliForTest, runGit, runNpm, spawnAsync, toValidPackageName, toValidProjectName, underline, yellow };
@@ -62,20 +62,33 @@ declare const pkgFromUserAgent: (userAgent: string | undefined) => PkgInfo | und
62
62
  declare const runCliForTest: (path: string, args: string[], options?: SpawnSyncOptionsWithStringEncoding) => child_process0.SpawnSyncReturns<string>;
63
63
  /** 判断测试文件(夹) */
64
64
  declare const isTestFile: (name: string) => boolean;
65
+ /** 解析 Github 链接获取 owner 和 repo */
65
66
  declare const parseGitHubRepo: (url: string) => string[];
67
+ /** 基于 EOL 的可多换行函数 */
68
+ declare const eol: (n?: number) => string;
66
69
  //#endregion
67
70
  //#region src/shell.d.ts
68
71
  declare const dim: (text: string) => string;
69
72
  declare const red: (text: string) => string;
70
73
  declare const yellow: (text: string) => string;
74
+ declare const underline: (text: string) => string;
71
75
  declare const spawnAsync: <T = SpawnOptions>(cmd: string, args: string[], options?: SpawnAsyncOptions<T>) => Promise<string | undefined>;
72
76
  declare const execAsync: <T = ExecOptions>(cmd: string, options?: ExecAsyncOptions<T>) => Promise<string | undefined>;
73
- declare const runGit: (args: string[], trim?: boolean) => Promise<string | undefined>;
74
- declare const runNpm: (args: string[]) => Promise<string | undefined>;
77
+ declare const runGit: (args: string[], options?: SpawnAsyncOptions) => Promise<string | undefined>;
78
+ declare const runNpm: (args: string[], options?: ExecAsyncOptions) => Promise<string | undefined>;
79
+ declare const fixArgs: (args: string) => string[];
80
+ declare const checkVersion: (cmd: string) => Promise<string | undefined>;
81
+ //#endregion
82
+ //#region src/joinUrl.d.ts
83
+ declare function joinUrl(...args: string[]): string;
84
+ declare function joinUrl(input: readonly string[]): string;
85
+ //#endregion
86
+ //#region src/git.d.ts
75
87
  declare const isGitRepo: (dir?: string) => Promise<boolean>;
76
88
  declare const getGitConfig: (key: string, global?: boolean) => Promise<string | undefined>;
77
89
  declare const getGitRemoteUrl: (remoteName?: string) => Promise<string | undefined>;
90
+ //#endregion
91
+ //#region src/npm.d.ts
78
92
  declare const pkgVersion: (pkg: string) => Promise<string | undefined>;
79
- declare const checkVersion: (cmd: string) => Promise<string | undefined>;
80
93
  //#endregion
81
- export { CliOptions, ConfirmResult, CopyOptions, ExecAsyncOptions, ExecResultOptions, HttpLibrary, PkgInfo, PkgManager, SpawnAsyncOptions, YesOrNo, checkVersion, copyDirAsync, dim, editFile, editJsonFile, emptyDir, execAsync, getGitConfig, getGitRemoteUrl, isEmpty, isGitRepo, isTestFile, isValidPackageName, parseGitHubRepo, pkgFromUserAgent, pkgVersion, readJsonFile, readSubDirs, red, runCliForTest, runGit, runNpm, spawnAsync, toValidPackageName, toValidProjectName, yellow };
94
+ export { CliOptions, ConfirmResult, CopyOptions, ExecAsyncOptions, ExecResultOptions, HttpLibrary, PkgInfo, PkgManager, SpawnAsyncOptions, YesOrNo, checkVersion, copyDirAsync, dim, editFile, editJsonFile, emptyDir, eol, execAsync, fixArgs, getGitConfig, getGitRemoteUrl, isEmpty, isGitRepo, isTestFile, isValidPackageName, joinUrl, parseGitHubRepo, pkgFromUserAgent, pkgVersion, readJsonFile, readSubDirs, red, runCliForTest, runGit, runNpm, spawnAsync, toValidPackageName, toValidProjectName, underline, yellow };
@@ -1,6 +1,7 @@
1
1
  import { exec, 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
+ import { EOL } from "node:os";
4
5
  import { join, resolve } from "node:path";
5
6
  import { styleText } from "node:util";
6
7
 
@@ -125,16 +126,20 @@ const isTestFile = (name) => {
125
126
  /^vitest([-.])(.*)\.m?(ts|js)$/
126
127
  ].some((reg) => reg.test(name));
127
128
  };
129
+ /** 解析 Github 链接获取 owner 和 repo */
128
130
  const parseGitHubRepo = (url) => {
129
131
  const match = url.trim().match(/github(?:\.com)?[:/](.+?)\/(.+?)(?:[#/?].+?)?(?:\.git)?$/);
130
132
  return match ? match.slice(1, 3) : [];
131
133
  };
134
+ /** 基于 EOL 的可多换行函数 */
135
+ const eol = (n = 1) => EOL.repeat(n);
132
136
 
133
137
  //#endregion
134
138
  //#region src/shell.ts
135
139
  const dim = (text) => styleText(["dim"], text);
136
140
  const red = (text) => styleText(["red"], text);
137
141
  const yellow = (text) => styleText(["yellow"], text);
142
+ const underline = (text) => styleText(["underline"], text);
138
143
  const spawnAsync = (cmd, args, options) => {
139
144
  return new Promise((resolve$1) => {
140
145
  const { trim, error, dryRun, ...others } = options ?? {};
@@ -185,12 +190,50 @@ const execAsync = (cmd, options) => {
185
190
  });
186
191
  });
187
192
  };
188
- const runGit = async (args, trim = true) => {
189
- return spawnAsync("git", args, { trim });
193
+ const runGit = async (args, options = { trim: true }) => {
194
+ return spawnAsync("git", args, options);
190
195
  };
191
- const runNpm = (args) => {
192
- return execAsync(["npm", ...args].join(" "));
196
+ const runNpm = (args, options = { trim: true }) => {
197
+ return execAsync(["npm", ...args].join(" "), options);
193
198
  };
199
+ const fixArgs = (args) => args.trim() ? args.trim().split(" ") : [];
200
+ const checkVersion = async (cmd) => {
201
+ return execAsync(`${cmd} --version`);
202
+ };
203
+
204
+ //#endregion
205
+ //#region src/joinUrl.ts
206
+ function joinUrl(input) {
207
+ const temps = Array.isArray(input) ? input : [...arguments];
208
+ if (temps.length === 0) return "";
209
+ const result = [];
210
+ const parts = [...temps];
211
+ /** 协议正则 */
212
+ const PROTOCOL_RE = /^[^/:]+:\/*$/;
213
+ const FILE_PROTOCOL_RE = /^file:\/\/\//;
214
+ if (PROTOCOL_RE.test(parts[0]) && parts.length > 1) {
215
+ parts[1] = parts[0] + parts[1];
216
+ parts.shift();
217
+ }
218
+ if (FILE_PROTOCOL_RE.test(parts[0])) parts[0] = parts[0].replace(/^([^/:]+):\/*/, "$1:///");
219
+ else parts[0] = parts[0].replace(/^([^/:]+):\/*/, "$1://");
220
+ parts.forEach((part, index) => {
221
+ if (!part) return;
222
+ let segment = part;
223
+ if (index > 0) segment = segment.replace(/^\/+/, "");
224
+ if (index < parts.length - 1) segment = segment.replace(/\/+$/, "");
225
+ else segment = segment.replace(/\/+$/, "/");
226
+ result.push(segment);
227
+ });
228
+ let url = result.join("/");
229
+ url = url.replace(/\/(\?|&|#[^!])/g, "$1");
230
+ const [base, ...queryParts] = url.split("?");
231
+ url = base + (queryParts.length ? "?" + queryParts.join("&") : "");
232
+ return url;
233
+ }
234
+
235
+ //#endregion
236
+ //#region src/git.ts
194
237
  const isGitRepo = async (dir) => {
195
238
  return !!await runGit([
196
239
  "-C",
@@ -217,6 +260,9 @@ const getGitRemoteUrl = async (remoteName = "origin") => {
217
260
  `remote.${remoteName}.url`
218
261
  ]));
219
262
  };
263
+
264
+ //#endregion
265
+ //#region src/npm.ts
220
266
  const pkgVersion = (pkg) => {
221
267
  return runNpm([
222
268
  "view",
@@ -224,9 +270,6 @@ const pkgVersion = (pkg) => {
224
270
  "version"
225
271
  ]);
226
272
  };
227
- const checkVersion = async (cmd) => {
228
- return execAsync(`${cmd} --version`);
229
- };
230
273
 
231
274
  //#endregion
232
- export { ConfirmResult, HttpLibrary, PkgManager, YesOrNo, checkVersion, copyDirAsync, dim, editFile, editJsonFile, emptyDir, execAsync, getGitConfig, getGitRemoteUrl, isEmpty, isGitRepo, isTestFile, isValidPackageName, parseGitHubRepo, pkgFromUserAgent, pkgVersion, readJsonFile, readSubDirs, red, runCliForTest, runGit, runNpm, spawnAsync, toValidPackageName, toValidProjectName, yellow };
275
+ export { ConfirmResult, HttpLibrary, PkgManager, YesOrNo, checkVersion, copyDirAsync, dim, editFile, editJsonFile, emptyDir, eol, execAsync, fixArgs, getGitConfig, getGitRemoteUrl, isEmpty, isGitRepo, isTestFile, isValidPackageName, joinUrl, parseGitHubRepo, pkgFromUserAgent, pkgVersion, readJsonFile, readSubDirs, red, runCliForTest, runGit, runNpm, spawnAsync, toValidPackageName, toValidProjectName, underline, yellow };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peiyanlu/cli-utils",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Shared utils for building interactive Node.js CLI applications.",
5
5
  "license": "MIT",
6
6
  "type": "module",