@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 +21 -0
- package/README.md +33 -0
- package/dist/cjs/index.cjs +163 -0
- package/dist/cjs/index.d.cts +67 -0
- package/dist/esm/index.d.mts +67 -0
- package/dist/esm/index.mjs +143 -0
- package/package.json +62 -0
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
|
+
}
|