@peiyanlu/cli-utils 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 离殇
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.
package/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # @peiyanlu/cli-utils
2
+
3
+ My project description.
4
+
5
+ ## Project setup
6
+
7
+ ```bash
8
+ $ pnpm install
9
+ ```
10
+
11
+ ## Compile and run the project
12
+
13
+ ```bash
14
+ # development
15
+ $ pnpm run dev
16
+
17
+ # production
18
+ $ pnpm run build
19
+ ```
20
+
21
+ ## Run tests
22
+
23
+ ```bash
24
+ # unit tests
25
+ $ pnpm run test
26
+
27
+ # e2e tests
28
+ $ pnpm run test:e2e
29
+
30
+ # test coverage
31
+ $ pnpm run test:cov
32
+ ```
33
+
@@ -0,0 +1,163 @@
1
+ let node_child_process = require("node:child_process");
2
+ let node_fs = require("node:fs");
3
+ let node_fs_promises = require("node:fs/promises");
4
+ let node_path = require("node:path");
5
+
6
+ //#region src/enums.ts
7
+ let PkgManager = /* @__PURE__ */ function(PkgManager$1) {
8
+ PkgManager$1["NPM"] = "npm";
9
+ PkgManager$1["YARN"] = "yarn";
10
+ PkgManager$1["PNPM"] = "pnpm";
11
+ return PkgManager$1;
12
+ }({});
13
+ /**
14
+ * @deprecated Use `ConfirmResult` instead.
15
+ */
16
+ let YesOrNo = /* @__PURE__ */ function(YesOrNo$1) {
17
+ YesOrNo$1["Yes"] = "yes";
18
+ YesOrNo$1["No"] = "no";
19
+ YesOrNo$1["Ignore"] = "ignore";
20
+ return YesOrNo$1;
21
+ }({});
22
+ let ConfirmResult = /* @__PURE__ */ function(ConfirmResult$1) {
23
+ ConfirmResult$1["YES"] = "yes";
24
+ ConfirmResult$1["NO"] = "no";
25
+ ConfirmResult$1["IGNORE"] = "ignore";
26
+ return ConfirmResult$1;
27
+ }({});
28
+ let HttpLibrary = /* @__PURE__ */ function(HttpLibrary$1) {
29
+ HttpLibrary$1["EXPRESS"] = "express";
30
+ HttpLibrary$1["FASTIFY"] = "fastify";
31
+ HttpLibrary$1["KOA"] = "koa";
32
+ HttpLibrary$1["HONO"] = "hono";
33
+ return HttpLibrary$1;
34
+ }({});
35
+
36
+ //#endregion
37
+ //#region src/utils.ts
38
+ const execAsync = (cmd) => {
39
+ return new Promise((r) => {
40
+ (0, node_child_process.exec)(cmd, (err, stdout) => r(err ? void 0 : stdout.trim()));
41
+ });
42
+ };
43
+ const pkgVersion = (pkg) => {
44
+ return execAsync(`npm view ${pkg} version`);
45
+ };
46
+ const checkVersion = async (cmd) => {
47
+ return execAsync(`${cmd} --version`);
48
+ };
49
+ const isValidPackageName = (packageName) => {
50
+ return /^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(packageName);
51
+ };
52
+ const toValidPackageName = (packageName) => packageName.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z\d\-~]+/g, "-");
53
+ const toValidProjectName = (projectName) => projectName.trim().replace(/\/+$/g, "");
54
+ const emptyDir = async (dir, ignore = []) => {
55
+ if (!(0, node_fs.existsSync)(dir)) return false;
56
+ for (const file of await (0, node_fs_promises.readdir)(dir)) {
57
+ if (ignore.includes(file)) continue;
58
+ await (0, node_fs_promises.rm)((0, node_path.resolve)(dir, file), {
59
+ recursive: true,
60
+ force: true
61
+ });
62
+ }
63
+ return true;
64
+ };
65
+ const isEmpty = async (path, ignore = []) => {
66
+ return (await (0, node_fs_promises.readdir)(path)).filter((f) => !ignore.includes(f)).length === 0;
67
+ };
68
+ const editFile = async (file, callback) => {
69
+ if (!(0, node_fs.existsSync)(file)) return;
70
+ return (0, node_fs_promises.writeFile)(file, callback(await (0, node_fs_promises.readFile)(file, "utf-8")), "utf-8");
71
+ };
72
+ const editJsonFile = (file, callback) => {
73
+ return editFile(file, (str) => {
74
+ try {
75
+ const json = JSON.parse(str);
76
+ callback(json);
77
+ return JSON.stringify(json, null, 2);
78
+ } catch (e) {
79
+ console.error(e);
80
+ return str;
81
+ }
82
+ });
83
+ };
84
+ const isGitRepo = async (dir) => {
85
+ return !!await execAsync(`git -C "${dir ? `./${dir}` : "."}" rev-parse --is-inside-work-tree`);
86
+ };
87
+ const readSubDirs = async (source, ignore = []) => {
88
+ return (await (0, node_fs_promises.readdir)(source, { withFileTypes: true })).filter((k) => k.isDirectory() && !ignore.includes(k.name)).map((dir) => dir.name);
89
+ };
90
+ const getGitConfig = (key, global = true) => {
91
+ return execAsync(`git config ${global ? "--global" : ""} ${key}`);
92
+ };
93
+ const copyDirAsync = async (src, dest, options) => {
94
+ await (0, node_fs_promises.mkdir)(dest, { recursive: true });
95
+ const entries = await (0, node_fs_promises.readdir)(src, { withFileTypes: true });
96
+ for (const entry of entries) {
97
+ const name = entry.name;
98
+ const isDir = entry.isDirectory();
99
+ const { rename = {}, skips = [] } = options;
100
+ const relName = rename[name] ?? name;
101
+ if (skips.some((rule) => rule(name, isDir))) continue;
102
+ const from = (0, node_path.join)(src, name);
103
+ const to = (0, node_path.join)(dest, relName);
104
+ if (isDir) await copyDirAsync(from, to, options);
105
+ else await (0, node_fs_promises.copyFile)(from, to);
106
+ }
107
+ };
108
+ const readJsonFile = (file) => {
109
+ if (!(0, node_fs.existsSync)(file)) return {};
110
+ try {
111
+ return JSON.parse((0, node_fs.readFileSync)(file, "utf-8"));
112
+ } catch (e) {
113
+ return {};
114
+ }
115
+ };
116
+ /**
117
+ * 通过包管理器执行脚本时生效
118
+ *
119
+ * UserAgent: `process.env.npm_config_user_agent`
120
+ * @param {string | undefined} userAgent
121
+ * @returns {PkgInfo | undefined}
122
+ */
123
+ const pkgFromUserAgent = (userAgent) => {
124
+ if (!userAgent) return void 0;
125
+ const [name, version] = userAgent.split(" ")[0].split("/");
126
+ return {
127
+ name,
128
+ version
129
+ };
130
+ };
131
+ const runCli = (path, args, options) => {
132
+ return (0, node_child_process.spawnSync)("node", [path, ...args], {
133
+ env: {
134
+ ...process.env,
135
+ _VITE_TEST_CLI: "true"
136
+ },
137
+ encoding: "utf-8",
138
+ ...options
139
+ });
140
+ };
141
+
142
+ //#endregion
143
+ exports.ConfirmResult = ConfirmResult;
144
+ exports.HttpLibrary = HttpLibrary;
145
+ exports.PkgManager = PkgManager;
146
+ exports.YesOrNo = YesOrNo;
147
+ exports.checkVersion = checkVersion;
148
+ exports.copyDirAsync = copyDirAsync;
149
+ exports.editFile = editFile;
150
+ exports.editJsonFile = editJsonFile;
151
+ exports.emptyDir = emptyDir;
152
+ exports.execAsync = execAsync;
153
+ exports.getGitConfig = getGitConfig;
154
+ exports.isEmpty = isEmpty;
155
+ exports.isGitRepo = isGitRepo;
156
+ exports.isValidPackageName = isValidPackageName;
157
+ exports.pkgFromUserAgent = pkgFromUserAgent;
158
+ exports.pkgVersion = pkgVersion;
159
+ exports.readJsonFile = readJsonFile;
160
+ exports.readSubDirs = readSubDirs;
161
+ exports.runCli = runCli;
162
+ exports.toValidPackageName = toValidPackageName;
163
+ exports.toValidProjectName = toValidProjectName;
@@ -0,0 +1,67 @@
1
+ import * as child_process0 from "child_process";
2
+ import { SpawnSyncOptionsWithStringEncoding } from "child_process";
3
+
4
+ //#region src/enums.d.ts
5
+ declare enum PkgManager {
6
+ NPM = "npm",
7
+ YARN = "yarn",
8
+ PNPM = "pnpm",
9
+ }
10
+ /**
11
+ * @deprecated Use `ConfirmResult` instead.
12
+ */
13
+ declare enum YesOrNo {
14
+ Yes = "yes",
15
+ No = "no",
16
+ Ignore = "ignore",
17
+ }
18
+ declare enum ConfirmResult {
19
+ YES = "yes",
20
+ NO = "no",
21
+ IGNORE = "ignore",
22
+ }
23
+ declare enum HttpLibrary {
24
+ EXPRESS = "express",
25
+ FASTIFY = "fastify",
26
+ KOA = "koa",
27
+ HONO = "hono",
28
+ }
29
+ //#endregion
30
+ //#region src/types.d.ts
31
+ interface CopyOptions {
32
+ rename?: Record<string, string>;
33
+ skips?: ((name: string, isDir: boolean) => boolean)[];
34
+ }
35
+ type CliOptions<T = string | boolean> = Record<string, T>;
36
+ interface PkgInfo {
37
+ name: string;
38
+ version: string;
39
+ }
40
+ //#endregion
41
+ //#region src/utils.d.ts
42
+ declare const execAsync: (cmd: string) => Promise<string | undefined>;
43
+ declare const pkgVersion: (pkg: string) => Promise<string | undefined>;
44
+ declare const checkVersion: (cmd: string) => Promise<string | undefined>;
45
+ declare const isValidPackageName: (packageName: string) => boolean;
46
+ declare const toValidPackageName: (packageName: string) => string;
47
+ declare const toValidProjectName: (projectName: string) => string;
48
+ declare const emptyDir: (dir: string, ignore?: string[]) => Promise<boolean>;
49
+ declare const isEmpty: (path: string, ignore?: string[]) => Promise<boolean>;
50
+ declare const editFile: (file: string, callback: (content: string) => string) => Promise<void>;
51
+ declare const editJsonFile: <T extends Record<string, any>>(file: string, callback: (json: T) => void) => Promise<void>;
52
+ declare const isGitRepo: (dir?: string) => Promise<boolean>;
53
+ declare const readSubDirs: (source: string, ignore?: string[]) => Promise<string[]>;
54
+ declare const getGitConfig: (key: string, global?: boolean) => Promise<string | undefined>;
55
+ declare const copyDirAsync: (src: string, dest: string, options: CopyOptions) => Promise<void>;
56
+ declare const readJsonFile: <T extends Record<string, any>>(file: string) => T;
57
+ /**
58
+ * 通过包管理器执行脚本时生效
59
+ *
60
+ * UserAgent: `process.env.npm_config_user_agent`
61
+ * @param {string | undefined} userAgent
62
+ * @returns {PkgInfo | undefined}
63
+ */
64
+ declare const pkgFromUserAgent: (userAgent: string | undefined) => PkgInfo | undefined;
65
+ declare const runCli: (path: string, args: string[], options?: SpawnSyncOptionsWithStringEncoding) => child_process0.SpawnSyncReturns<string>;
66
+ //#endregion
67
+ export { CliOptions, ConfirmResult, CopyOptions, HttpLibrary, PkgInfo, PkgManager, YesOrNo, checkVersion, copyDirAsync, editFile, editJsonFile, emptyDir, execAsync, getGitConfig, isEmpty, isGitRepo, isValidPackageName, pkgFromUserAgent, pkgVersion, readJsonFile, readSubDirs, runCli, toValidPackageName, toValidProjectName };
@@ -0,0 +1,67 @@
1
+ import * as child_process0 from "child_process";
2
+ import { SpawnSyncOptionsWithStringEncoding } from "child_process";
3
+
4
+ //#region src/enums.d.ts
5
+ declare enum PkgManager {
6
+ NPM = "npm",
7
+ YARN = "yarn",
8
+ PNPM = "pnpm",
9
+ }
10
+ /**
11
+ * @deprecated Use `ConfirmResult` instead.
12
+ */
13
+ declare enum YesOrNo {
14
+ Yes = "yes",
15
+ No = "no",
16
+ Ignore = "ignore",
17
+ }
18
+ declare enum ConfirmResult {
19
+ YES = "yes",
20
+ NO = "no",
21
+ IGNORE = "ignore",
22
+ }
23
+ declare enum HttpLibrary {
24
+ EXPRESS = "express",
25
+ FASTIFY = "fastify",
26
+ KOA = "koa",
27
+ HONO = "hono",
28
+ }
29
+ //#endregion
30
+ //#region src/types.d.ts
31
+ interface CopyOptions {
32
+ rename?: Record<string, string>;
33
+ skips?: ((name: string, isDir: boolean) => boolean)[];
34
+ }
35
+ type CliOptions<T = string | boolean> = Record<string, T>;
36
+ interface PkgInfo {
37
+ name: string;
38
+ version: string;
39
+ }
40
+ //#endregion
41
+ //#region src/utils.d.ts
42
+ declare const execAsync: (cmd: string) => Promise<string | undefined>;
43
+ declare const pkgVersion: (pkg: string) => Promise<string | undefined>;
44
+ declare const checkVersion: (cmd: string) => Promise<string | undefined>;
45
+ declare const isValidPackageName: (packageName: string) => boolean;
46
+ declare const toValidPackageName: (packageName: string) => string;
47
+ declare const toValidProjectName: (projectName: string) => string;
48
+ declare const emptyDir: (dir: string, ignore?: string[]) => Promise<boolean>;
49
+ declare const isEmpty: (path: string, ignore?: string[]) => Promise<boolean>;
50
+ declare const editFile: (file: string, callback: (content: string) => string) => Promise<void>;
51
+ declare const editJsonFile: <T extends Record<string, any>>(file: string, callback: (json: T) => void) => Promise<void>;
52
+ declare const isGitRepo: (dir?: string) => Promise<boolean>;
53
+ declare const readSubDirs: (source: string, ignore?: string[]) => Promise<string[]>;
54
+ declare const getGitConfig: (key: string, global?: boolean) => Promise<string | undefined>;
55
+ declare const copyDirAsync: (src: string, dest: string, options: CopyOptions) => Promise<void>;
56
+ declare const readJsonFile: <T extends Record<string, any>>(file: string) => T;
57
+ /**
58
+ * 通过包管理器执行脚本时生效
59
+ *
60
+ * UserAgent: `process.env.npm_config_user_agent`
61
+ * @param {string | undefined} userAgent
62
+ * @returns {PkgInfo | undefined}
63
+ */
64
+ declare const pkgFromUserAgent: (userAgent: string | undefined) => PkgInfo | undefined;
65
+ declare const runCli: (path: string, args: string[], options?: SpawnSyncOptionsWithStringEncoding) => child_process0.SpawnSyncReturns<string>;
66
+ //#endregion
67
+ export { CliOptions, ConfirmResult, CopyOptions, HttpLibrary, PkgInfo, PkgManager, YesOrNo, checkVersion, copyDirAsync, editFile, editJsonFile, emptyDir, execAsync, getGitConfig, isEmpty, isGitRepo, isValidPackageName, pkgFromUserAgent, pkgVersion, readJsonFile, readSubDirs, runCli, toValidPackageName, toValidProjectName };
@@ -0,0 +1,143 @@
1
+ import { exec, spawnSync } from "node:child_process";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { copyFile, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
4
+ import { join, resolve } from "node:path";
5
+
6
+ //#region src/enums.ts
7
+ let PkgManager = /* @__PURE__ */ function(PkgManager$1) {
8
+ PkgManager$1["NPM"] = "npm";
9
+ PkgManager$1["YARN"] = "yarn";
10
+ PkgManager$1["PNPM"] = "pnpm";
11
+ return PkgManager$1;
12
+ }({});
13
+ /**
14
+ * @deprecated Use `ConfirmResult` instead.
15
+ */
16
+ let YesOrNo = /* @__PURE__ */ function(YesOrNo$1) {
17
+ YesOrNo$1["Yes"] = "yes";
18
+ YesOrNo$1["No"] = "no";
19
+ YesOrNo$1["Ignore"] = "ignore";
20
+ return YesOrNo$1;
21
+ }({});
22
+ let ConfirmResult = /* @__PURE__ */ function(ConfirmResult$1) {
23
+ ConfirmResult$1["YES"] = "yes";
24
+ ConfirmResult$1["NO"] = "no";
25
+ ConfirmResult$1["IGNORE"] = "ignore";
26
+ return ConfirmResult$1;
27
+ }({});
28
+ let HttpLibrary = /* @__PURE__ */ function(HttpLibrary$1) {
29
+ HttpLibrary$1["EXPRESS"] = "express";
30
+ HttpLibrary$1["FASTIFY"] = "fastify";
31
+ HttpLibrary$1["KOA"] = "koa";
32
+ HttpLibrary$1["HONO"] = "hono";
33
+ return HttpLibrary$1;
34
+ }({});
35
+
36
+ //#endregion
37
+ //#region src/utils.ts
38
+ const execAsync = (cmd) => {
39
+ return new Promise((r) => {
40
+ exec(cmd, (err, stdout) => r(err ? void 0 : stdout.trim()));
41
+ });
42
+ };
43
+ const pkgVersion = (pkg) => {
44
+ return execAsync(`npm view ${pkg} version`);
45
+ };
46
+ const checkVersion = async (cmd) => {
47
+ return execAsync(`${cmd} --version`);
48
+ };
49
+ const isValidPackageName = (packageName) => {
50
+ return /^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(packageName);
51
+ };
52
+ const toValidPackageName = (packageName) => packageName.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z\d\-~]+/g, "-");
53
+ const toValidProjectName = (projectName) => projectName.trim().replace(/\/+$/g, "");
54
+ const emptyDir = async (dir, ignore = []) => {
55
+ if (!existsSync(dir)) return false;
56
+ for (const file of await readdir(dir)) {
57
+ if (ignore.includes(file)) continue;
58
+ await rm(resolve(dir, file), {
59
+ recursive: true,
60
+ force: true
61
+ });
62
+ }
63
+ return true;
64
+ };
65
+ const isEmpty = async (path, ignore = []) => {
66
+ return (await readdir(path)).filter((f) => !ignore.includes(f)).length === 0;
67
+ };
68
+ const editFile = async (file, callback) => {
69
+ if (!existsSync(file)) return;
70
+ return writeFile(file, callback(await readFile(file, "utf-8")), "utf-8");
71
+ };
72
+ const editJsonFile = (file, callback) => {
73
+ return editFile(file, (str) => {
74
+ try {
75
+ const json = JSON.parse(str);
76
+ callback(json);
77
+ return JSON.stringify(json, null, 2);
78
+ } catch (e) {
79
+ console.error(e);
80
+ return str;
81
+ }
82
+ });
83
+ };
84
+ const isGitRepo = async (dir) => {
85
+ return !!await execAsync(`git -C "${dir ? `./${dir}` : "."}" rev-parse --is-inside-work-tree`);
86
+ };
87
+ const readSubDirs = async (source, ignore = []) => {
88
+ return (await readdir(source, { withFileTypes: true })).filter((k) => k.isDirectory() && !ignore.includes(k.name)).map((dir) => dir.name);
89
+ };
90
+ const getGitConfig = (key, global = true) => {
91
+ return execAsync(`git config ${global ? "--global" : ""} ${key}`);
92
+ };
93
+ const copyDirAsync = async (src, dest, options) => {
94
+ await mkdir(dest, { recursive: true });
95
+ const entries = await readdir(src, { withFileTypes: true });
96
+ for (const entry of entries) {
97
+ const name = entry.name;
98
+ const isDir = entry.isDirectory();
99
+ const { rename = {}, skips = [] } = options;
100
+ const relName = rename[name] ?? name;
101
+ if (skips.some((rule) => rule(name, isDir))) continue;
102
+ const from = join(src, name);
103
+ const to = join(dest, relName);
104
+ if (isDir) await copyDirAsync(from, to, options);
105
+ else await copyFile(from, to);
106
+ }
107
+ };
108
+ const readJsonFile = (file) => {
109
+ if (!existsSync(file)) return {};
110
+ try {
111
+ return JSON.parse(readFileSync(file, "utf-8"));
112
+ } catch (e) {
113
+ return {};
114
+ }
115
+ };
116
+ /**
117
+ * 通过包管理器执行脚本时生效
118
+ *
119
+ * UserAgent: `process.env.npm_config_user_agent`
120
+ * @param {string | undefined} userAgent
121
+ * @returns {PkgInfo | undefined}
122
+ */
123
+ const pkgFromUserAgent = (userAgent) => {
124
+ if (!userAgent) return void 0;
125
+ const [name, version] = userAgent.split(" ")[0].split("/");
126
+ return {
127
+ name,
128
+ version
129
+ };
130
+ };
131
+ const runCli = (path, args, options) => {
132
+ return spawnSync("node", [path, ...args], {
133
+ env: {
134
+ ...process.env,
135
+ _VITE_TEST_CLI: "true"
136
+ },
137
+ encoding: "utf-8",
138
+ ...options
139
+ });
140
+ };
141
+
142
+ //#endregion
143
+ export { ConfirmResult, HttpLibrary, PkgManager, YesOrNo, checkVersion, copyDirAsync, editFile, editJsonFile, emptyDir, execAsync, getGitConfig, isEmpty, isGitRepo, isValidPackageName, pkgFromUserAgent, pkgVersion, readJsonFile, readSubDirs, runCli, toValidPackageName, toValidProjectName };
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@peiyanlu/cli-utils",
3
+ "version": "0.0.1",
4
+ "description": "Shared utils for building interactive Node.js CLI applications.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "private": false,
8
+ "main": "./dist/cjs/index.cjs",
9
+ "types": "./dist/cjs/index.d.cts",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/esm/index.mjs",
13
+ "types": "./dist/esm/index.d.mts"
14
+ },
15
+ "./package.json": "./package.json"
16
+ },
17
+ "devDependencies": {
18
+ "@release-it/conventional-changelog": "^10.0.2",
19
+ "@types/node": "^24.10.3",
20
+ "@vitest/coverage-v8": "^4.0.15",
21
+ "release-it": "^19.0.2",
22
+ "release-it-pnpm": "^4.6.6",
23
+ "tsdown": "^0.18.1",
24
+ "typescript": "^5.9.3",
25
+ "vitest": "^4.0.15"
26
+ },
27
+ "author": {
28
+ "name": "YanluPei",
29
+ "email": "peiyanlu@vip.qq.com"
30
+ },
31
+ "engines": {
32
+ "node": ">=20"
33
+ },
34
+ "keywords": [
35
+ "typescript",
36
+ "lib"
37
+ ],
38
+ "files": [
39
+ "dist"
40
+ ],
41
+ "publishConfig": {
42
+ "access": "public",
43
+ "registry": "https://registry.npmjs.org"
44
+ },
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://github.com/peiyanlu/cli-utils.git"
48
+ },
49
+ "bugs": {
50
+ "url": "https://github.com/peiyanlu/cli-utils/issues"
51
+ },
52
+ "homepage": "https://github.com/peiyanlu/cli-utils#readme",
53
+ "scripts": {
54
+ "dev": "tsdown -w",
55
+ "build": "tsdown",
56
+ "prepublish": "tsdown",
57
+ "release": "release-it",
58
+ "test": "vitest run",
59
+ "test:e2e": "vitest run -c vitest.config.e2e.mts",
60
+ "test:cov": "vitest run --coverage"
61
+ }
62
+ }