@pubinfo-nightly/cli 2025.11.14
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/bin/pubinfo.mjs +11 -0
- package/dist/build-TpYdEV_-.js +18 -0
- package/dist/commit-r-63XXfJ.js +103 -0
- package/dist/dev-DVlLrfjX.js +18 -0
- package/dist/generate-9OAGGbjc.js +63 -0
- package/dist/generate-MJ0AbXtK.js +33 -0
- package/dist/icon-B2EyVw8p.js +152 -0
- package/dist/index-Dp-QJh5Z.d.ts +9 -0
- package/dist/index.js +44 -0
- package/dist/monorepo-BY87UC9C.js +265 -0
- package/dist/preview-BVVgNnhp.js +16 -0
- package/dist/setup-BdawX0W3.js +93 -0
- package/dist/setup-CACbESTE.js +3 -0
- package/dist/upgrade-B-Zl5nkj.js +36 -0
- package/dist/vite-bwhDbW7x.js +39 -0
- package/package.json +42 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 PUBINFO 腾龙框架
|
|
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/bin/pubinfo.mjs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { t as runVite } from "./vite-bwhDbW7x.js";
|
|
2
|
+
import { t as setup_default } from "./setup-BdawX0W3.js";
|
|
3
|
+
import { defineCommand, runMain } from "citty";
|
|
4
|
+
|
|
5
|
+
//#region src/commands/build.ts
|
|
6
|
+
var build_default = defineCommand({
|
|
7
|
+
meta: {
|
|
8
|
+
name: "build",
|
|
9
|
+
description: "构建应用"
|
|
10
|
+
},
|
|
11
|
+
async run({ rawArgs }) {
|
|
12
|
+
await runMain(setup_default);
|
|
13
|
+
await runVite("build", rawArgs);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { build_default as default };
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
|
|
5
|
+
//#region src/commands/commit.ts
|
|
6
|
+
function isGitRepository() {
|
|
7
|
+
try {
|
|
8
|
+
return spawnSync("git", ["rev-parse", "--is-inside-work-tree"], { stdio: "ignore" }).status === 0;
|
|
9
|
+
} catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* `pubinfo-nightly commit` 子命令:
|
|
15
|
+
* 统一封装项目级提交体验,复用 `@pubinfo-nightly/commitlint` 的核心能力。
|
|
16
|
+
* 功能概述:
|
|
17
|
+
* 1. 交互式生成符合规范的提交信息(中文 + 可选 emoji)。
|
|
18
|
+
* 2. 支持 `--edit` 供 commit-msg 钩子调用,读取临时文件并执行 lint。
|
|
19
|
+
* 4. 支持 `--init` 一键初始化(cz 配置 / 模板 / git hooks)。
|
|
20
|
+
* 5. 不直接执行 `git commit`,保持透明,调用者自行决定是否提交。
|
|
21
|
+
*/
|
|
22
|
+
var commit_default = {
|
|
23
|
+
meta: {
|
|
24
|
+
name: "commit",
|
|
25
|
+
description: "交互式规范 Commit Lint 提交"
|
|
26
|
+
},
|
|
27
|
+
args: {
|
|
28
|
+
edit: {
|
|
29
|
+
type: "string",
|
|
30
|
+
description: "从 commit-msg 钩子传入的临时文件路径 (--edit $1)"
|
|
31
|
+
},
|
|
32
|
+
init: {
|
|
33
|
+
type: "boolean",
|
|
34
|
+
description: "初始化提交环境 (cz 配置 / 模板 / git hooks)"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
run: async ({ args }) => {
|
|
38
|
+
if (!isGitRepository()) console.error("[pubinfo-nightly commit] 未检测到 Git 仓库。请在已初始化的 Git 项目中运行,或执行 `git init` 后重试。");
|
|
39
|
+
else {
|
|
40
|
+
const { createCzConfig, createGitMessage, runCzConfig, runNpx, runSimpleGitHooks, runGitMessage, lintMessage, runPrompt, isCommitlintEnabled, configureGitHooksPath } = await import("@pubinfo-nightly/commitlint");
|
|
41
|
+
const commitlintEnabled = await isCommitlintEnabled();
|
|
42
|
+
if (args.init) {
|
|
43
|
+
const cwd$1 = process.cwd();
|
|
44
|
+
if (!commitlintEnabled) {
|
|
45
|
+
const removedDefault = runSimpleGitHooks("pubinfo-commit", cwd$1, false);
|
|
46
|
+
const removedCli = runSimpleGitHooks("pubinfo-nightly commit", cwd$1, false);
|
|
47
|
+
const disabledHooks = configureGitHooksPath(false, cwd$1);
|
|
48
|
+
if (removedDefault || removedCli || disabledHooks) console.log("[pubinfo-nightly commit] 检测到 pubinfo.config 中已关闭 commitlint,已停用 git hooks。");
|
|
49
|
+
else console.log("[pubinfo-nightly commit] 检测到 pubinfo.config 中已关闭 commitlint,跳过初始化。");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
configureGitHooksPath(true, cwd$1);
|
|
53
|
+
const pubinfoDir = `${cwd$1}/.pubinfo`;
|
|
54
|
+
if (!fs.existsSync(pubinfoDir)) fs.mkdirSync(pubinfoDir);
|
|
55
|
+
const gitMessageStatus = createGitMessage();
|
|
56
|
+
const czConfigStatus = createCzConfig(pubinfoDir);
|
|
57
|
+
const gitHookStatus = runGitMessage();
|
|
58
|
+
const simpleGitHooks = runSimpleGitHooks("pubinfo-nightly commit");
|
|
59
|
+
const czConfig = runCzConfig(".pubinfo/cz.config.cjs");
|
|
60
|
+
const npxStatus = runNpx();
|
|
61
|
+
console.log("[pubinfo-commit] 初始化结果:");
|
|
62
|
+
console.log(`- cz.config.cjs: ${czConfigStatus ? "已创建" : "已存在"}`);
|
|
63
|
+
console.log(`- .gitmessage: ${gitMessageStatus ? "已创建" : "已存在"}`);
|
|
64
|
+
console.log(`- Git hooks: ${gitHookStatus ? "已写入" : "已存在"}`);
|
|
65
|
+
console.log(`- package.json 配置 cz-git: ${czConfig ? "已写入" : "已存在"}`);
|
|
66
|
+
console.log(`- package.json 配置 simple-git-hooks: ${simpleGitHooks ? "已写入" : "已存在"}`);
|
|
67
|
+
console.log(`- npx simple-git-hooks 安装: ${npxStatus ? "成功" : "失败,请手动安装"}`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (args.edit) {
|
|
71
|
+
if (!commitlintEnabled) {
|
|
72
|
+
configureGitHooksPath(false, process.cwd());
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const raw = fs.readFileSync(String(args.edit), "utf8").trim();
|
|
77
|
+
if (!raw) {
|
|
78
|
+
console.error("[pubinfo-nightly commit] 空的 commit message");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
await lintMessage(raw);
|
|
82
|
+
} catch (e) {
|
|
83
|
+
console.error("[pubinfo-nightly commit] 读取 --edit 文件失败", e);
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (!commitlintEnabled) {
|
|
88
|
+
console.log("[pubinfo-nightly commit] commitlint 已关闭,交互模式不可用。");
|
|
89
|
+
configureGitHooksPath(false, process.cwd());
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const result = await runPrompt();
|
|
93
|
+
if (!result) {
|
|
94
|
+
console.error("[pubinfo-commit] 未找到 cz-git 或交互被中断");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
await lintMessage(result.raw);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
//#endregion
|
|
103
|
+
export { commit_default as default };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { t as runVite } from "./vite-bwhDbW7x.js";
|
|
2
|
+
import { t as setup_default } from "./setup-BdawX0W3.js";
|
|
3
|
+
import { defineCommand, runMain } from "citty";
|
|
4
|
+
|
|
5
|
+
//#region src/commands/dev.ts
|
|
6
|
+
var dev_default = defineCommand({
|
|
7
|
+
meta: {
|
|
8
|
+
name: "dev",
|
|
9
|
+
description: "启动应用"
|
|
10
|
+
},
|
|
11
|
+
async run({ rawArgs }) {
|
|
12
|
+
await runMain(setup_default);
|
|
13
|
+
await runVite("dev", rawArgs);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { dev_default as default };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { n as ensureValidIdentifier, r as resolvePubinfoVersionFromApps, t as ensureMonorepoAppsDir } from "./generate-MJ0AbXtK.js";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { defineCommand } from "citty";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
6
|
+
import { logger } from "@pubinfo-nightly/shared";
|
|
7
|
+
import { generate } from "create-pubinfo-nightly";
|
|
8
|
+
|
|
9
|
+
//#region src/commands/generate.ts
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
const createPubinfoPkgPath = require.resolve("create-pubinfo-nightly/package.json");
|
|
12
|
+
const createPubinfoPkg = require("create-pubinfo-nightly/package.json");
|
|
13
|
+
const monorepoAppTemplatePath = resolve(resolve(createPubinfoPkgPath, ".."), "templates/pubinfo-monorepo/apps/basic");
|
|
14
|
+
const fallbackVersion = createPubinfoPkg.version;
|
|
15
|
+
var generate_default = defineCommand({
|
|
16
|
+
meta: {
|
|
17
|
+
name: "generate",
|
|
18
|
+
description: "在 monorepo apps 目录下创建新的 pubinfo-nightly 应用"
|
|
19
|
+
},
|
|
20
|
+
args: {
|
|
21
|
+
name: {
|
|
22
|
+
type: "positional",
|
|
23
|
+
required: true,
|
|
24
|
+
description: "应用目录名称,例如 admin"
|
|
25
|
+
},
|
|
26
|
+
key: {
|
|
27
|
+
type: "string",
|
|
28
|
+
description: "应用标识,默认与目录名称一致"
|
|
29
|
+
},
|
|
30
|
+
rbac: {
|
|
31
|
+
type: "boolean",
|
|
32
|
+
default: true,
|
|
33
|
+
description: "是否包含 RBAC 模块"
|
|
34
|
+
},
|
|
35
|
+
openapi: {
|
|
36
|
+
type: "boolean",
|
|
37
|
+
default: false,
|
|
38
|
+
description: "是否启用 openapi 自动生成"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
async run({ args }) {
|
|
42
|
+
const appsDir = ensureMonorepoAppsDir(resolve("."));
|
|
43
|
+
const appName = args.name;
|
|
44
|
+
ensureValidIdentifier(appName, "应用名称");
|
|
45
|
+
const targetDir = resolve(appsDir, appName);
|
|
46
|
+
if (existsSync(targetDir)) throw new Error(`应用 ${appName} 已存在,请选择其他名称`);
|
|
47
|
+
const key = args.key ?? appName;
|
|
48
|
+
ensureValidIdentifier(key, "应用标识");
|
|
49
|
+
await generate({
|
|
50
|
+
templateName: "pubinfo-monorepo",
|
|
51
|
+
templatePath: monorepoAppTemplatePath,
|
|
52
|
+
targetDir,
|
|
53
|
+
key,
|
|
54
|
+
version: await resolvePubinfoVersionFromApps(appsDir) || fallbackVersion,
|
|
55
|
+
modules: args.rbac === false ? [] : ["rbac"],
|
|
56
|
+
openapi: Boolean(args.openapi)
|
|
57
|
+
});
|
|
58
|
+
logger.success(`应用 ${appName} 创建完成,位于 apps/${appName}`);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
//#endregion
|
|
63
|
+
export { generate_default as default };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { globby } from "globby";
|
|
5
|
+
|
|
6
|
+
//#region src/utils/generate.ts
|
|
7
|
+
const INVALID_NAME_RE = /[<>:"/\\|?*\s]/;
|
|
8
|
+
function ensureValidIdentifier(value, label) {
|
|
9
|
+
if (!value) throw new Error(`${label} 不能为空`);
|
|
10
|
+
if (INVALID_NAME_RE.test(value)) throw new Error(`${label} 不能包含空格或特殊字符 (<>:"/\\|?*)`);
|
|
11
|
+
}
|
|
12
|
+
function ensureMonorepoAppsDir(root) {
|
|
13
|
+
const appsDir = resolve(root, "apps");
|
|
14
|
+
if (!existsSync(appsDir)) throw new Error("未检测到 apps 目录,请在 pubinfo monorepo 根目录执行该命令");
|
|
15
|
+
if (!existsSync(resolve(root, "pnpm-workspace.yaml"))) throw new Error("未找到 pnpm-workspace.yaml,当前目录不是 pubinfo monorepo 工程");
|
|
16
|
+
return appsDir;
|
|
17
|
+
}
|
|
18
|
+
async function resolvePubinfoVersionFromApps(appsDir) {
|
|
19
|
+
const pkgFiles = await globby("**/package.json", {
|
|
20
|
+
cwd: appsDir,
|
|
21
|
+
absolute: true,
|
|
22
|
+
onlyFiles: true
|
|
23
|
+
});
|
|
24
|
+
for (const file of pkgFiles) {
|
|
25
|
+
const content = await readFile(file, "utf8");
|
|
26
|
+
const pkg = JSON.parse(content);
|
|
27
|
+
const version = pkg.dependencies?.pubinfo || pkg.devDependencies?.pubinfo;
|
|
28
|
+
if (version) return version;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
//#endregion
|
|
33
|
+
export { ensureValidIdentifier as n, resolvePubinfoVersionFromApps as r, ensureMonorepoAppsDir as t };
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import process from "node:process";
|
|
5
|
+
import { logger } from "@pubinfo-nightly/shared";
|
|
6
|
+
import { globby } from "globby";
|
|
7
|
+
import { load } from "cheerio";
|
|
8
|
+
|
|
9
|
+
//#region src/commands/icon.ts
|
|
10
|
+
function parseNumberLike(v) {
|
|
11
|
+
if (!v) return;
|
|
12
|
+
const num = Number.parseFloat(String(v).trim());
|
|
13
|
+
return Number.isFinite(num) ? num : void 0;
|
|
14
|
+
}
|
|
15
|
+
function toPreserveAspectRatio(aspect) {
|
|
16
|
+
if (aspect === "none") return "none";
|
|
17
|
+
return `xMidYMid ${aspect}`;
|
|
18
|
+
}
|
|
19
|
+
async function processFile(file, opts) {
|
|
20
|
+
const $ = load(await fs.readFile(file, "utf8"), { xmlMode: true });
|
|
21
|
+
const $svg = $("svg").first();
|
|
22
|
+
if ($svg.length === 0) {
|
|
23
|
+
logger.warn(`[skip] Not an <svg> root: ${file}`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const origW = parseNumberLike($svg.attr("width"));
|
|
27
|
+
const origH = parseNumberLike($svg.attr("height"));
|
|
28
|
+
const vbAttr = $svg.attr("viewBox");
|
|
29
|
+
let vbW;
|
|
30
|
+
let vbH;
|
|
31
|
+
if (vbAttr) {
|
|
32
|
+
const nums = vbAttr.split(/[\s,]+/).map((x) => Number.parseFloat(x)).filter((x) => Number.isFinite(x));
|
|
33
|
+
if (nums.length === 4) {
|
|
34
|
+
vbW = nums[2];
|
|
35
|
+
vbH = nums[3];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (!vbW || !vbH) if (origW && origH) {
|
|
39
|
+
vbW = origW;
|
|
40
|
+
vbH = origH;
|
|
41
|
+
} else {
|
|
42
|
+
vbW = 24;
|
|
43
|
+
vbH = 24;
|
|
44
|
+
logger.warn(`[warn] ${file} 无有效 viewBox/width/height,兜底为 24x24`);
|
|
45
|
+
}
|
|
46
|
+
$svg.attr("width", String(opts.size));
|
|
47
|
+
$svg.attr("height", String(opts.size));
|
|
48
|
+
$svg.attr("viewBox", `0 0 ${vbW} ${vbH}`);
|
|
49
|
+
$svg.attr("preserveAspectRatio", toPreserveAspectRatio(opts.aspect));
|
|
50
|
+
const output = $.xml($svg);
|
|
51
|
+
const targetPath = opts.inplace ? file : path.join(opts.outDir, path.relative(path.resolve(opts.baseDir), file));
|
|
52
|
+
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
53
|
+
await fs.writeFile(targetPath, output, "utf8");
|
|
54
|
+
logger.log(`[ok] ${path.relative(process.cwd(), targetPath)}`);
|
|
55
|
+
}
|
|
56
|
+
var icon_default = defineCommand({
|
|
57
|
+
meta: {
|
|
58
|
+
name: "normalize-svg",
|
|
59
|
+
description: "批量把 SVG 规范为固定 24x24(或自定义)且用原始尺寸写入 viewBox"
|
|
60
|
+
},
|
|
61
|
+
args: {
|
|
62
|
+
dir: {
|
|
63
|
+
type: "positional",
|
|
64
|
+
required: false,
|
|
65
|
+
default: ".",
|
|
66
|
+
description: "要扫描的目录(默认当前工作目录)"
|
|
67
|
+
},
|
|
68
|
+
size: {
|
|
69
|
+
type: "string",
|
|
70
|
+
default: "24",
|
|
71
|
+
description: "输出的外部宽高(px)"
|
|
72
|
+
},
|
|
73
|
+
aspect: {
|
|
74
|
+
type: "string",
|
|
75
|
+
default: "meet",
|
|
76
|
+
description: "preserveAspectRatio: meet | slice | none"
|
|
77
|
+
},
|
|
78
|
+
pattern: {
|
|
79
|
+
type: "string",
|
|
80
|
+
default: "**/*.svg",
|
|
81
|
+
description: "匹配的 glob 模式"
|
|
82
|
+
},
|
|
83
|
+
inplace: {
|
|
84
|
+
type: "boolean",
|
|
85
|
+
default: true,
|
|
86
|
+
description: "是否就地覆盖原文件"
|
|
87
|
+
},
|
|
88
|
+
outDir: {
|
|
89
|
+
type: "string",
|
|
90
|
+
description: "输出目录(未指定 --inplace 时生效)"
|
|
91
|
+
},
|
|
92
|
+
gitignore: {
|
|
93
|
+
type: "boolean",
|
|
94
|
+
default: true,
|
|
95
|
+
description: "是否遵守 .gitignore"
|
|
96
|
+
},
|
|
97
|
+
ignore: {
|
|
98
|
+
type: "string",
|
|
99
|
+
required: false,
|
|
100
|
+
description: "额外忽略(可多次传入),如 \"**/snapshots/**\""
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
run: async (ctx) => {
|
|
104
|
+
const dir = ctx.args.dir ? String(ctx.args.dir) : ".";
|
|
105
|
+
const size = Number(ctx.args.size ?? 24);
|
|
106
|
+
const aspect = String(ctx.args.aspect ?? "meet");
|
|
107
|
+
if (![
|
|
108
|
+
"meet",
|
|
109
|
+
"slice",
|
|
110
|
+
"none"
|
|
111
|
+
].includes(aspect)) throw new Error(`--aspect 仅支持 meet|slice|none,当前:${aspect}`);
|
|
112
|
+
const base = path.resolve(dir);
|
|
113
|
+
const pattern = String(ctx.args.pattern ?? "**/*.svg");
|
|
114
|
+
const inplace = Boolean(ctx.args.inplace);
|
|
115
|
+
const gitignore = Boolean(ctx.args.gitignore);
|
|
116
|
+
const raw = ctx.rawArgs || [];
|
|
117
|
+
const extraIgnores = [];
|
|
118
|
+
for (let i = 0; i < raw.length; i++) if (raw[i] === "--ignore" && raw[i + 1]) {
|
|
119
|
+
extraIgnores.push(String(raw[i + 1]));
|
|
120
|
+
i++;
|
|
121
|
+
}
|
|
122
|
+
let outDir = ctx.args.outDir ? path.resolve(String(ctx.args.outDir)) : void 0;
|
|
123
|
+
if (!inplace && !outDir) outDir = path.resolve(base, `svg-${size}`);
|
|
124
|
+
const files = await globby([path.join(base, pattern).replace(/\\/g, "/")], {
|
|
125
|
+
cwd: base,
|
|
126
|
+
gitignore,
|
|
127
|
+
absolute: true,
|
|
128
|
+
onlyFiles: true,
|
|
129
|
+
expandDirectories: false,
|
|
130
|
+
ignore: extraIgnores
|
|
131
|
+
});
|
|
132
|
+
if (!files.length) {
|
|
133
|
+
logger.warn(`No SVG matched: ${pattern} (dir: ${base})`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (!inplace && outDir) await fs.mkdir(outDir, { recursive: true });
|
|
137
|
+
for (const file of files) try {
|
|
138
|
+
await processFile(file, {
|
|
139
|
+
size,
|
|
140
|
+
aspect,
|
|
141
|
+
baseDir: base,
|
|
142
|
+
inplace,
|
|
143
|
+
outDir
|
|
144
|
+
});
|
|
145
|
+
} catch (e) {
|
|
146
|
+
logger.error(`[error] ${file}: ${e.message}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
//#endregion
|
|
152
|
+
export { icon_default as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { defineCommand, runMain as runMain$1 } from "citty";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
|
|
4
|
+
//#region package.json
|
|
5
|
+
var name = "@pubinfo-nightly/cli";
|
|
6
|
+
var version = "2.1.3";
|
|
7
|
+
var description = "CLI for Pubinfo";
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/commands/index.ts
|
|
11
|
+
const _rDefault = (r) => r.default || r;
|
|
12
|
+
const commands = {
|
|
13
|
+
dev: () => import("./dev-DVlLrfjX.js").then(_rDefault),
|
|
14
|
+
build: () => import("./build-TpYdEV_-.js").then(_rDefault),
|
|
15
|
+
preview: () => import("./preview-BVVgNnhp.js").then(_rDefault),
|
|
16
|
+
setup: () => import("./setup-CACbESTE.js").then(_rDefault),
|
|
17
|
+
commit: () => import("./commit-r-63XXfJ.js").then(_rDefault),
|
|
18
|
+
icon: () => import("./icon-B2EyVw8p.js").then(_rDefault),
|
|
19
|
+
upgrade: () => import("./upgrade-B-Zl5nkj.js").then(_rDefault),
|
|
20
|
+
generate: () => import("./generate-9OAGGbjc.js").then(_rDefault),
|
|
21
|
+
monorepo: () => import("./monorepo-BY87UC9C.js").then(_rDefault)
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/main.ts
|
|
26
|
+
const main = defineCommand({
|
|
27
|
+
meta: {
|
|
28
|
+
name,
|
|
29
|
+
version,
|
|
30
|
+
description
|
|
31
|
+
},
|
|
32
|
+
subCommands: commands
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/run.ts
|
|
37
|
+
globalThis.__pubinfo_cli__ = globalThis.__pubinfo_cli__ || {
|
|
38
|
+
startTime: Date.now(),
|
|
39
|
+
entry: fileURLToPath(new URL(import.meta.url.endsWith(".ts") ? "../bin/pubinfo.mjs" : "../../bin/pubinfo.mjs", import.meta.url))
|
|
40
|
+
};
|
|
41
|
+
const runMain = () => runMain$1(main);
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
export { main, runMain };
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { n as ensureValidIdentifier } from "./generate-MJ0AbXtK.js";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { defineCommand } from "citty";
|
|
4
|
+
import { cp, mkdir, mkdtemp, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
5
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
+
import { logger } from "@pubinfo-nightly/shared";
|
|
8
|
+
import { generate } from "create-pubinfo-nightly";
|
|
9
|
+
import { globby } from "globby";
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
|
+
|
|
12
|
+
//#region src/utils/monorepo.ts
|
|
13
|
+
const APP_DIRECTORIES = [
|
|
14
|
+
"src",
|
|
15
|
+
"public",
|
|
16
|
+
"mock",
|
|
17
|
+
"mocks",
|
|
18
|
+
"tests",
|
|
19
|
+
"test",
|
|
20
|
+
"e2e"
|
|
21
|
+
];
|
|
22
|
+
const APP_FILES = [
|
|
23
|
+
"index.html",
|
|
24
|
+
"openapi.config.ts",
|
|
25
|
+
"openapi.config.ts.hbs",
|
|
26
|
+
"pubinfo.config.ts",
|
|
27
|
+
"pubinfo.config.js",
|
|
28
|
+
"tsconfig.json",
|
|
29
|
+
"tsconfig.app.json",
|
|
30
|
+
"tsconfig.node.json",
|
|
31
|
+
"uno.config.ts",
|
|
32
|
+
"uno.config.js",
|
|
33
|
+
"vitest.config.ts",
|
|
34
|
+
"vitest.config.js",
|
|
35
|
+
"vitest.setup.ts",
|
|
36
|
+
"vite.config.ts",
|
|
37
|
+
"vite.config.js"
|
|
38
|
+
];
|
|
39
|
+
const TEMPLATE_ROOT_FILES = [
|
|
40
|
+
".browserslistrc",
|
|
41
|
+
".editorconfig",
|
|
42
|
+
".gitignore",
|
|
43
|
+
".npmrc",
|
|
44
|
+
"eslint.config.ts",
|
|
45
|
+
"stylelint.config.js",
|
|
46
|
+
"pnpm-workspace.yaml"
|
|
47
|
+
];
|
|
48
|
+
const ENV_PATTERNS = [".env", ".env.*"];
|
|
49
|
+
function hasDependency(pkg, dep) {
|
|
50
|
+
return Boolean(pkg.dependencies?.[dep] || pkg.devDependencies?.[dep]);
|
|
51
|
+
}
|
|
52
|
+
function formatTimestamp(date) {
|
|
53
|
+
const pad = (value) => value.toString().padStart(2, "0");
|
|
54
|
+
return `${[
|
|
55
|
+
date.getFullYear().toString(),
|
|
56
|
+
pad(date.getMonth() + 1),
|
|
57
|
+
pad(date.getDate())
|
|
58
|
+
].join("")}-${[
|
|
59
|
+
pad(date.getHours()),
|
|
60
|
+
pad(date.getMinutes()),
|
|
61
|
+
pad(date.getSeconds())
|
|
62
|
+
].join("")}`;
|
|
63
|
+
}
|
|
64
|
+
async function backupPath(rootDir, backupDir, target) {
|
|
65
|
+
if (!existsSync(target)) return;
|
|
66
|
+
const dest = resolve(backupDir, relative(rootDir, target));
|
|
67
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
68
|
+
await cp(target, dest, {
|
|
69
|
+
recursive: true,
|
|
70
|
+
force: true
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
async function movePath(rootDir, destinationRoot, backupDir, relativePath) {
|
|
74
|
+
const source = resolve(rootDir, relativePath);
|
|
75
|
+
if (!existsSync(source)) return false;
|
|
76
|
+
const dest = resolve(destinationRoot, relativePath);
|
|
77
|
+
if (existsSync(dest)) throw new Error(`目标路径 ${relative(rootDir, dest)} 已存在,无法覆盖`);
|
|
78
|
+
await backupPath(rootDir, backupDir, source);
|
|
79
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
80
|
+
await rename(source, dest);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
async function copyTemplateFile(templateRoot, rootDir, backupDir, relativePath) {
|
|
84
|
+
const source = resolve(templateRoot, relativePath);
|
|
85
|
+
if (!existsSync(source)) return;
|
|
86
|
+
const target = resolve(rootDir, relativePath);
|
|
87
|
+
if (existsSync(target)) await backupPath(rootDir, backupDir, target);
|
|
88
|
+
await mkdir(dirname(target), { recursive: true });
|
|
89
|
+
await cp(source, target, {
|
|
90
|
+
recursive: true,
|
|
91
|
+
force: true
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
function deriveDefaultAppName(pkgName) {
|
|
95
|
+
if (!pkgName) return "app";
|
|
96
|
+
let base = pkgName.trim();
|
|
97
|
+
if (base.startsWith("@")) {
|
|
98
|
+
const slashIndex = base.indexOf("/");
|
|
99
|
+
base = slashIndex === -1 ? base.slice(1) : base.slice(slashIndex + 1);
|
|
100
|
+
}
|
|
101
|
+
return base.replace(/\//g, "-").replace(/[^\w-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "") || "app";
|
|
102
|
+
}
|
|
103
|
+
async function extractStorageKey(rootDir) {
|
|
104
|
+
const settingsPath = resolve(rootDir, "src/settings.ts");
|
|
105
|
+
if (!existsSync(settingsPath)) return;
|
|
106
|
+
return (await readFile(settingsPath, "utf8")).match(/storagePrefix:\s*['"]([^'"\\]+)['"]/)?.[1];
|
|
107
|
+
}
|
|
108
|
+
function detectModulesFromPackage(pkg) {
|
|
109
|
+
const modules = [];
|
|
110
|
+
if (hasDependency(pkg, "@pubinfo-nightly/module-rbac")) modules.push("rbac");
|
|
111
|
+
return modules;
|
|
112
|
+
}
|
|
113
|
+
function detectOpenapiEnabled(pkg) {
|
|
114
|
+
return hasDependency(pkg, "@pubinfo/openapi") || hasDependency(pkg, "@pubinfo/preset-openapi") || Boolean(pkg.scripts?.openapi);
|
|
115
|
+
}
|
|
116
|
+
function resolvePubinfoVersionFromPackage(pkg) {
|
|
117
|
+
return pkg.dependencies?.pubinfo || pkg.devDependencies?.pubinfo;
|
|
118
|
+
}
|
|
119
|
+
function buildWorkspacePackageName(originalName) {
|
|
120
|
+
if (!originalName) return "pubinfo-monorepo";
|
|
121
|
+
if (originalName.endsWith("-workspace")) return originalName;
|
|
122
|
+
if (originalName.startsWith("@")) {
|
|
123
|
+
const [scope, name] = originalName.slice(1).split("/");
|
|
124
|
+
if (!name) return originalName;
|
|
125
|
+
return `@${scope}/${name.endsWith("-workspace") ? name : `${name}-workspace`}`;
|
|
126
|
+
}
|
|
127
|
+
return `${originalName}-workspace`;
|
|
128
|
+
}
|
|
129
|
+
function preserveFields(target, source, fields) {
|
|
130
|
+
for (const field of fields) {
|
|
131
|
+
const value = source[field];
|
|
132
|
+
if (value !== void 0) target[field] = value;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async function convertToMonorepo(options) {
|
|
136
|
+
const { rootDir, templateRoot, appName, force, rootPackageJson, rootPackageJsonContent, packageManager } = options;
|
|
137
|
+
if (existsSync(resolve(rootDir, "pnpm-workspace.yaml")) && !force) throw new Error("已检测到 pnpm-workspace.yaml,当前目录可能已经是 monorepo,如需继续请使用 --force");
|
|
138
|
+
const appsDir = resolve(rootDir, "apps");
|
|
139
|
+
await mkdir(appsDir, { recursive: true });
|
|
140
|
+
const appDir = resolve(appsDir, appName);
|
|
141
|
+
if (existsSync(appDir)) throw new Error(`应用目录 apps/${appName} 已存在,请更换名称或清理后再试`);
|
|
142
|
+
await mkdir(appDir, { recursive: true });
|
|
143
|
+
const backupDir = resolve(rootDir, ".pubinfo", "monorepo-backup", formatTimestamp(/* @__PURE__ */ new Date()));
|
|
144
|
+
await mkdir(backupDir, { recursive: true });
|
|
145
|
+
for (const dir of APP_DIRECTORIES) await movePath(rootDir, appDir, backupDir, dir);
|
|
146
|
+
for (const file of APP_FILES) await movePath(rootDir, appDir, backupDir, file);
|
|
147
|
+
const envFiles = await globby(ENV_PATTERNS, {
|
|
148
|
+
cwd: rootDir,
|
|
149
|
+
dot: true,
|
|
150
|
+
onlyFiles: true
|
|
151
|
+
});
|
|
152
|
+
for (const env of envFiles) await movePath(rootDir, appDir, backupDir, env);
|
|
153
|
+
const rootPkgPath = resolve(rootDir, "package.json");
|
|
154
|
+
const appPkgPath = resolve(appDir, "package.json");
|
|
155
|
+
await mkdir(dirname(appPkgPath), { recursive: true });
|
|
156
|
+
if (existsSync(appPkgPath)) throw new Error(`目标应用 package.json 已存在:apps/${appName}/package.json`);
|
|
157
|
+
await writeFile(appPkgPath, rootPackageJsonContent);
|
|
158
|
+
await backupPath(rootDir, backupDir, rootPkgPath);
|
|
159
|
+
const templatePkg = JSON.parse(await readFile(resolve(templateRoot, "package.json"), "utf8"));
|
|
160
|
+
templatePkg.name = buildWorkspacePackageName(rootPackageJson.name);
|
|
161
|
+
templatePkg.packageManager = packageManager || templatePkg.packageManager;
|
|
162
|
+
templatePkg.description = rootPackageJson.description || templatePkg.description || `Workspace for ${rootPackageJson.name ?? "pubinfo-nightly app"}`;
|
|
163
|
+
preserveFields(templatePkg, rootPackageJson, [
|
|
164
|
+
"license",
|
|
165
|
+
"author",
|
|
166
|
+
"repository",
|
|
167
|
+
"bugs",
|
|
168
|
+
"homepage"
|
|
169
|
+
]);
|
|
170
|
+
await writeFile(rootPkgPath, `${JSON.stringify(templatePkg, null, 2)}\n`);
|
|
171
|
+
for (const file of TEMPLATE_ROOT_FILES) await copyTemplateFile(templateRoot, rootDir, backupDir, file);
|
|
172
|
+
const lockFile = resolve(rootDir, "pnpm-lock.yaml");
|
|
173
|
+
if (existsSync(lockFile)) {
|
|
174
|
+
await backupPath(rootDir, backupDir, lockFile);
|
|
175
|
+
await rm(lockFile, { force: true });
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
appDir,
|
|
179
|
+
backupDir
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/commands/monorepo.ts
|
|
185
|
+
const require = createRequire(import.meta.url);
|
|
186
|
+
const createPubinfoPkg = (() => {
|
|
187
|
+
try {
|
|
188
|
+
const pkgPath = resolve(dirname(require.resolve("create-pubinfo-nightly")), "../package.json");
|
|
189
|
+
return { version: JSON.parse(readFileSync(pkgPath, "utf8")).version ?? "latest" };
|
|
190
|
+
} catch {
|
|
191
|
+
logger.warn("无法解析 create-pubinfo-nightly 版本,将使用最新版本");
|
|
192
|
+
return { version: "latest" };
|
|
193
|
+
}
|
|
194
|
+
})();
|
|
195
|
+
var monorepo_default = defineCommand({
|
|
196
|
+
meta: {
|
|
197
|
+
name: "monorepo",
|
|
198
|
+
description: "将现有 pubinfo-nightly 单体工程转换为 monorepo 结构"
|
|
199
|
+
},
|
|
200
|
+
args: {
|
|
201
|
+
app: {
|
|
202
|
+
type: "string",
|
|
203
|
+
description: "应用目录名称,将生成在 apps/<name>"
|
|
204
|
+
},
|
|
205
|
+
key: {
|
|
206
|
+
type: "string",
|
|
207
|
+
description: "应用 storage key,默认尝试从 src/settings.ts 推断"
|
|
208
|
+
},
|
|
209
|
+
force: {
|
|
210
|
+
type: "boolean",
|
|
211
|
+
default: false,
|
|
212
|
+
description: "强制执行,忽略已有 pnpm-workspace.yaml 等检查"
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
async run({ args }) {
|
|
216
|
+
const rootDir = resolve(".");
|
|
217
|
+
const pkgPath = resolve(rootDir, "package.json");
|
|
218
|
+
if (!existsSync(pkgPath)) throw new Error("未找到 package.json,无法识别当前工程");
|
|
219
|
+
const pkgContent = await readFile(pkgPath, "utf8");
|
|
220
|
+
const pkg = JSON.parse(pkgContent);
|
|
221
|
+
const defaultAppName = deriveDefaultAppName(pkg.name);
|
|
222
|
+
const appName = args.app ?? defaultAppName;
|
|
223
|
+
ensureValidIdentifier(appName, "应用名称");
|
|
224
|
+
const detectedKey = await extractStorageKey(rootDir);
|
|
225
|
+
const key = args.key ?? detectedKey ?? appName;
|
|
226
|
+
ensureValidIdentifier(key, "应用标识");
|
|
227
|
+
const modules = detectModulesFromPackage(pkg);
|
|
228
|
+
const openapi = detectOpenapiEnabled(pkg);
|
|
229
|
+
const detectedVersion = resolvePubinfoVersionFromPackage(pkg);
|
|
230
|
+
const resolvedVersion = detectedVersion ?? createPubinfoPkg.version;
|
|
231
|
+
if (!detectedVersion) logger.info("未在 package.json 中检测到 pubinfo-nightly 依赖,将使用 create-pubinfo-nightly 默认版本");
|
|
232
|
+
const tempDir = await mkdtemp(join(tmpdir(), "pubinfo-monorepo-"));
|
|
233
|
+
try {
|
|
234
|
+
await generate({
|
|
235
|
+
templateName: "pubinfo-monorepo",
|
|
236
|
+
targetDir: tempDir,
|
|
237
|
+
key,
|
|
238
|
+
version: resolvedVersion,
|
|
239
|
+
modules,
|
|
240
|
+
openapi,
|
|
241
|
+
dir: appName
|
|
242
|
+
});
|
|
243
|
+
const { appDir, backupDir } = await convertToMonorepo({
|
|
244
|
+
rootDir,
|
|
245
|
+
templateRoot: tempDir,
|
|
246
|
+
appName,
|
|
247
|
+
force: Boolean(args.force),
|
|
248
|
+
rootPackageJson: pkg,
|
|
249
|
+
rootPackageJsonContent: pkgContent,
|
|
250
|
+
packageManager: pkg.packageManager
|
|
251
|
+
});
|
|
252
|
+
logger.success(`monorepo 结构已准备完成,应用目录:${relative(rootDir, appDir)}`);
|
|
253
|
+
logger.info(`备份文件位于:${relative(rootDir, backupDir)}`);
|
|
254
|
+
logger.info("请运行 pnpm install 以安装新的依赖,并使用 pnpm --filter apps/<app> dev 启动开发服务器");
|
|
255
|
+
} finally {
|
|
256
|
+
await rm(tempDir, {
|
|
257
|
+
recursive: true,
|
|
258
|
+
force: true
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
//#endregion
|
|
265
|
+
export { monorepo_default as default };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { t as runVite } from "./vite-bwhDbW7x.js";
|
|
2
|
+
import { defineCommand } from "citty";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/preview.ts
|
|
5
|
+
var preview_default = defineCommand({
|
|
6
|
+
meta: {
|
|
7
|
+
name: "preview",
|
|
8
|
+
description: "预览构建的应用"
|
|
9
|
+
},
|
|
10
|
+
async run({ rawArgs }) {
|
|
11
|
+
await runVite("preview", rawArgs);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
export { preview_default as default };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { defineCommand } from "citty";
|
|
3
|
+
import { mkdir } from "node:fs/promises";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
import { existsSync, unlinkSync, writeFileSync } from "node:fs";
|
|
6
|
+
|
|
7
|
+
//#region src/utils/tsconfig.ts
|
|
8
|
+
function writeTsconfig(filePath) {
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
const resolveDeps = (name, path$1) => {
|
|
11
|
+
return join(require.resolve(name), path$1).replace(/\\/g, "/");
|
|
12
|
+
};
|
|
13
|
+
if (existsSync(filePath)) unlinkSync(filePath);
|
|
14
|
+
writeFileSync(filePath, `/* eslint-disable */
|
|
15
|
+
/* prettier-ignore */
|
|
16
|
+
// Generated by pubinfo-nightly
|
|
17
|
+
{
|
|
18
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
19
|
+
"display": "Base",
|
|
20
|
+
"compilerOptions": {
|
|
21
|
+
"target": "ESNext",
|
|
22
|
+
"jsx": "preserve",
|
|
23
|
+
"jsxImportSource": "vue",
|
|
24
|
+
"lib": [
|
|
25
|
+
"ESNext",
|
|
26
|
+
"DOM",
|
|
27
|
+
"DOM.Iterable"
|
|
28
|
+
],
|
|
29
|
+
"useDefineForClassFields": true,
|
|
30
|
+
"baseUrl": ".",
|
|
31
|
+
"module": "ESNext",
|
|
32
|
+
"moduleResolution": "Bundler",
|
|
33
|
+
"paths": {
|
|
34
|
+
"@/*": ["../src/*"],
|
|
35
|
+
"#/*": ["../types/*"],
|
|
36
|
+
|
|
37
|
+
// deps
|
|
38
|
+
"vue": ["${resolveDeps("vue", "../")}"],
|
|
39
|
+
"vue-router": ["${resolveDeps("vue-router", "../")}"],
|
|
40
|
+
"pinia": ["${resolveDeps("pinia", "../")}"],
|
|
41
|
+
"unocss": ["${resolveDeps("unocss", "../")}"],
|
|
42
|
+
},
|
|
43
|
+
"resolveJsonModule": true,
|
|
44
|
+
"types": [
|
|
45
|
+
"pubinfo-nightly/types"
|
|
46
|
+
],
|
|
47
|
+
"allowImportingTsExtensions": true,
|
|
48
|
+
"allowJs": false,
|
|
49
|
+
"strict": true,
|
|
50
|
+
"noEmit": true,
|
|
51
|
+
"sourceMap": true,
|
|
52
|
+
"esModuleInterop": true,
|
|
53
|
+
"isolatedModules": true,
|
|
54
|
+
"skipLibCheck": true
|
|
55
|
+
},
|
|
56
|
+
"include": [
|
|
57
|
+
"../src/**/*.ts",
|
|
58
|
+
"../src/**/*.tsx",
|
|
59
|
+
"../src/**/*.vue",
|
|
60
|
+
"../pubinfo.config.ts",
|
|
61
|
+
"../.pubinfo/**/*.ts",
|
|
62
|
+
"../.pubinfo/**/*.tsx",
|
|
63
|
+
"../.pubinfo/**/*.vue",
|
|
64
|
+
"../.pubinfo/**/*.d.ts",
|
|
65
|
+
"../types/**/*.d.ts",
|
|
66
|
+
"../**/*",
|
|
67
|
+
".."
|
|
68
|
+
],
|
|
69
|
+
"exclude": [
|
|
70
|
+
"dist",
|
|
71
|
+
"node_modules",
|
|
72
|
+
"assets"
|
|
73
|
+
],
|
|
74
|
+
}`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/commands/setup.ts
|
|
79
|
+
const command = defineCommand({
|
|
80
|
+
meta: {
|
|
81
|
+
name: "setup",
|
|
82
|
+
description: "初始化配置"
|
|
83
|
+
},
|
|
84
|
+
async run() {
|
|
85
|
+
const pubinfoDir = resolve(resolve("."), ".pubinfo");
|
|
86
|
+
if (!existsSync(pubinfoDir)) await mkdir(pubinfoDir, { recursive: true });
|
|
87
|
+
writeTsconfig(resolve(pubinfoDir, "tsconfig.app.json"));
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
var setup_default = command;
|
|
91
|
+
|
|
92
|
+
//#endregion
|
|
93
|
+
export { setup_default as t };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import { logger } from "@pubinfo-nightly/shared";
|
|
4
|
+
import { readPackageJSON } from "pkg-types";
|
|
5
|
+
|
|
6
|
+
//#region src/commands/upgrade.ts
|
|
7
|
+
const command = defineCommand({
|
|
8
|
+
meta: {
|
|
9
|
+
name: "upgrade",
|
|
10
|
+
description: "升级依赖版本"
|
|
11
|
+
},
|
|
12
|
+
async run() {
|
|
13
|
+
const pkg = await readPackageJSON();
|
|
14
|
+
const deps = {
|
|
15
|
+
...pkg.dependencies,
|
|
16
|
+
...pkg.devDependencies,
|
|
17
|
+
...pkg.peerDependencies
|
|
18
|
+
};
|
|
19
|
+
function isPubinfoRelated(name) {
|
|
20
|
+
return name === "pubinfo-nightly" || name.startsWith("@pubinfo/module-");
|
|
21
|
+
}
|
|
22
|
+
const pubinfoDeps = Object.keys(deps).filter(isPubinfoRelated);
|
|
23
|
+
if (!pubinfoDeps.length) {
|
|
24
|
+
logger.log("No pubinfo-related dependencies found.");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
logger.log(`Upgrading: ${pubinfoDeps.join(", ")}`);
|
|
28
|
+
const cmd = `pnpm up ${pubinfoDeps.join(" ")} --latest`;
|
|
29
|
+
logger.log(`Running: ${cmd}`);
|
|
30
|
+
execSync(cmd, { stdio: "inherit" });
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
var upgrade_default = command;
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
export { upgrade_default as default };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import { relative, resolve } from "node:path";
|
|
3
|
+
import { cwd } from "node:process";
|
|
4
|
+
import { execa } from "execa";
|
|
5
|
+
|
|
6
|
+
//#region src/utils/vite.ts
|
|
7
|
+
async function writeViteConfig(targetPath, configFile) {
|
|
8
|
+
await writeFile(targetPath, `
|
|
9
|
+
/* eslint-disable */
|
|
10
|
+
/* prettier-ignore */
|
|
11
|
+
// Generated by pubinfo-nightly
|
|
12
|
+
import pubinfoConfig from '${configFile}';
|
|
13
|
+
|
|
14
|
+
export default pubinfoConfig.vite
|
|
15
|
+
`.trim());
|
|
16
|
+
}
|
|
17
|
+
function extractConfigPath(userArgs, defaultConfig = "pubinfo.config.ts") {
|
|
18
|
+
const configIndex = userArgs.findIndex((arg) => arg === "--config");
|
|
19
|
+
if (configIndex !== -1 && userArgs[configIndex + 1]) {
|
|
20
|
+
const configPath = resolve(cwd(), userArgs[configIndex + 1]);
|
|
21
|
+
userArgs.splice(configIndex, 2);
|
|
22
|
+
return configPath;
|
|
23
|
+
}
|
|
24
|
+
return resolve(cwd(), defaultConfig);
|
|
25
|
+
}
|
|
26
|
+
async function runVite(command, userArgs) {
|
|
27
|
+
const pubinfoDir = resolve(cwd(), ".pubinfo");
|
|
28
|
+
const viteConfig = resolve(pubinfoDir, "vite.config.ts");
|
|
29
|
+
await writeViteConfig(viteConfig, relative(pubinfoDir, extractConfigPath(userArgs)).replace(/\\/g, "/"));
|
|
30
|
+
await execa("vite", [
|
|
31
|
+
command,
|
|
32
|
+
"--config",
|
|
33
|
+
viteConfig,
|
|
34
|
+
...userArgs
|
|
35
|
+
], { stdio: "inherit" });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
export { runVite as t };
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pubinfo-nightly/cli",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "2025.11.14",
|
|
5
|
+
"description": "CLI for Pubinfo",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./bin/pubinfo.mjs"
|
|
8
|
+
},
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"bin": {
|
|
11
|
+
"pubinfo": "./bin/pubinfo.mjs"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"bin",
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"@pubinfo-nightly/vite": "2025.11.14"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@pubinfo-nightly/commitlint": "2025.11.14",
|
|
25
|
+
"@pubinfo-nightly/shared": "2025.11.14",
|
|
26
|
+
"cheerio": "^1.1.2",
|
|
27
|
+
"citty": "^0.1.6",
|
|
28
|
+
"create-pubinfo-nightly": "2025.11.14",
|
|
29
|
+
"execa": "^9.6.0",
|
|
30
|
+
"globby": "^14.1.0",
|
|
31
|
+
"pkg-types": "^2.3.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@pubinfo-nightly/vite": "2025.11.14",
|
|
35
|
+
"@types/node": "^24.0.10"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"dev": "tsdown --watch",
|
|
39
|
+
"build": "tsdown",
|
|
40
|
+
"pubinfo": "node ./bin/pubinfo.mjs dev"
|
|
41
|
+
}
|
|
42
|
+
}
|