@chatbi-v/cli 2.0.4 → 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +955 -775
- package/package.json +7 -7
- package/templates/app/package.json.hbs +3 -2
- package/templates/app/src/features/settings/PluginList.tsx.hbs +7 -1
- package/templates/plugin/package.json.hbs +3 -3
- package/templates/sandbox/.npmrc.hbs +2 -0
- package/templates/sandbox/package.json.hbs +6 -0
package/dist/index.js
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
-
}) : x)(function(x) {
|
|
6
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
-
});
|
|
9
3
|
var __esm = (fn, res) => function __init() {
|
|
10
4
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
5
|
};
|
|
@@ -17,29 +11,28 @@ var __export = (target, all) => {
|
|
|
17
11
|
// ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/esm_shims.js
|
|
18
12
|
import path from "path";
|
|
19
13
|
import { fileURLToPath } from "url";
|
|
20
|
-
var getFilename, getDirname, __dirname;
|
|
21
14
|
var init_esm_shims = __esm({
|
|
22
15
|
"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/esm_shims.js"() {
|
|
23
16
|
"use strict";
|
|
24
|
-
getFilename = () => fileURLToPath(import.meta.url);
|
|
25
|
-
getDirname = () => path.dirname(getFilename());
|
|
26
|
-
__dirname = /* @__PURE__ */ getDirname();
|
|
27
17
|
}
|
|
28
18
|
});
|
|
29
19
|
|
|
30
20
|
// src/utils.ts
|
|
31
21
|
import path2 from "path";
|
|
22
|
+
import { createRequire } from "module";
|
|
23
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
32
24
|
import fs from "fs-extra";
|
|
33
25
|
import pc from "picocolors";
|
|
34
26
|
import ora from "ora";
|
|
35
27
|
import boxen from "boxen";
|
|
36
|
-
var _require, _dirname, logger, createSpinner, printBox, findPackageRoot, getCliRoot;
|
|
28
|
+
var _require, _filename, _dirname, logger, createSpinner, printBox, findPackageRoot, getCliRoot;
|
|
37
29
|
var init_utils = __esm({
|
|
38
30
|
"src/utils.ts"() {
|
|
39
31
|
"use strict";
|
|
40
32
|
init_esm_shims();
|
|
41
|
-
_require =
|
|
42
|
-
|
|
33
|
+
_require = createRequire(import.meta.url);
|
|
34
|
+
_filename = fileURLToPath2(import.meta.url);
|
|
35
|
+
_dirname = path2.dirname(_filename);
|
|
43
36
|
logger = {
|
|
44
37
|
info: (msg) => console.log(pc.cyan(`\u2139 ${msg}`)),
|
|
45
38
|
success: (msg) => console.log(pc.green(`\u2714 ${msg}`)),
|
|
@@ -84,11 +77,7 @@ var init_utils = __esm({
|
|
|
84
77
|
if (pkgName === "@chatbi-v/cli") {
|
|
85
78
|
return path2.resolve(_dirname, "../../");
|
|
86
79
|
}
|
|
87
|
-
|
|
88
|
-
if (fs.existsSync(localPath)) {
|
|
89
|
-
return localPath;
|
|
90
|
-
}
|
|
91
|
-
throw new Error(`\u65E0\u6CD5\u627E\u5230\u5305 ${pkgName}\uFF0C\u8BF7\u786E\u4FDD\u5DF2\u901A\u8FC7 pnpm/npm \u5B89\u88C5\u3002`);
|
|
80
|
+
return null;
|
|
92
81
|
}
|
|
93
82
|
};
|
|
94
83
|
getCliRoot = async () => {
|
|
@@ -105,269 +94,299 @@ var init_utils = __esm({
|
|
|
105
94
|
checkDir = path2.dirname(checkDir);
|
|
106
95
|
}
|
|
107
96
|
if (!myCliRoot) {
|
|
108
|
-
myCliRoot = findPackageRoot("@chatbi-v/cli");
|
|
97
|
+
myCliRoot = findPackageRoot("@chatbi-v/cli") || "";
|
|
109
98
|
}
|
|
110
99
|
return myCliRoot;
|
|
111
100
|
};
|
|
112
101
|
}
|
|
113
102
|
});
|
|
114
103
|
|
|
115
|
-
// src/
|
|
116
|
-
import fs2 from "fs-extra";
|
|
104
|
+
// src/constants.ts
|
|
117
105
|
import path3 from "path";
|
|
118
106
|
import os from "os";
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
import fg from "fast-glob";
|
|
123
|
-
var Sandbox;
|
|
124
|
-
var init_sandbox = __esm({
|
|
125
|
-
"src/sandbox.ts"() {
|
|
107
|
+
var SANDBOX_CONFIG, GLOBAL_PATHS, DEPENDENCY_VERSIONS, DEFAULT_CONFIG;
|
|
108
|
+
var init_constants = __esm({
|
|
109
|
+
"src/constants.ts"() {
|
|
126
110
|
"use strict";
|
|
127
111
|
init_esm_shims();
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
112
|
+
SANDBOX_CONFIG = {
|
|
113
|
+
/** 用户主目录下的沙箱根目录名 */
|
|
114
|
+
BASE_NAME: ".chatbi-v-core",
|
|
115
|
+
/** 内部子目录结构 */
|
|
116
|
+
DIRS: {
|
|
117
|
+
VERSIONS: "versions",
|
|
118
|
+
CURRENT: "current",
|
|
119
|
+
CACHE: ".chatbi"
|
|
120
|
+
},
|
|
121
|
+
/** 关键标识文件 */
|
|
122
|
+
LOCK_FILE: ".chatbi-version"
|
|
123
|
+
};
|
|
124
|
+
GLOBAL_PATHS = {
|
|
125
|
+
/** 沙箱根路径 */
|
|
126
|
+
BASE_DIR: path3.join(os.homedir(), SANDBOX_CONFIG.BASE_NAME),
|
|
127
|
+
/** Monorepo 扫描目录 */
|
|
128
|
+
MONOREPO_ROOTS: ["apps", "plugins", "packages"]
|
|
129
|
+
};
|
|
130
|
+
DEPENDENCY_VERSIONS = {
|
|
131
|
+
// 基础框架
|
|
132
|
+
"react": "^18.3.1",
|
|
133
|
+
"react-dom": "^18.3.1",
|
|
134
|
+
"antd": "^5.20.0",
|
|
135
|
+
// 构建工具
|
|
136
|
+
"vite": "^5.0.8",
|
|
137
|
+
"typescript": "^5.3.3",
|
|
138
|
+
"tailwindcss": "^3.4.1",
|
|
139
|
+
"autoprefixer": "^10.4.17",
|
|
140
|
+
"postcss": "^8.4.35",
|
|
141
|
+
"less": "^4.2.0",
|
|
142
|
+
// 类型定义
|
|
143
|
+
"@types/react": "^18.3.1",
|
|
144
|
+
"@types/react-dom": "^18.3.1",
|
|
145
|
+
"@types/node": "^20.11.20",
|
|
146
|
+
"@vitejs/plugin-react": "^4.2.1"
|
|
147
|
+
};
|
|
148
|
+
DEFAULT_CONFIG = {
|
|
149
|
+
/** 支持的配置文件名 */
|
|
150
|
+
CONFIG_FILES: [
|
|
151
|
+
"chatbi.config.ts",
|
|
152
|
+
"chatbi.config.js",
|
|
153
|
+
"chatbi.config.json",
|
|
154
|
+
".chatbirc"
|
|
155
|
+
],
|
|
156
|
+
/** 默认 UI 主题 */
|
|
157
|
+
THEME: "standard"
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// src/sandbox/SandboxPath.ts
|
|
163
|
+
import path4 from "path";
|
|
164
|
+
import fs2 from "fs-extra";
|
|
165
|
+
var SandboxPath;
|
|
166
|
+
var init_SandboxPath = __esm({
|
|
167
|
+
"src/sandbox/SandboxPath.ts"() {
|
|
168
|
+
"use strict";
|
|
169
|
+
init_esm_shims();
|
|
170
|
+
init_constants();
|
|
171
|
+
SandboxPath = class {
|
|
144
172
|
static {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
"react",
|
|
150
|
-
"react-dom",
|
|
151
|
-
"lucide-react",
|
|
152
|
-
"framer-motion",
|
|
153
|
-
"clsx",
|
|
154
|
-
"tailwind-merge",
|
|
155
|
-
"react-router-dom",
|
|
156
|
-
"zustand",
|
|
157
|
-
"axios",
|
|
158
|
-
"less",
|
|
159
|
-
"vite"
|
|
160
|
-
];
|
|
173
|
+
/**
|
|
174
|
+
* 沙箱的基础存储目录,通常位于用户主目录下的 .chatbi-v-core
|
|
175
|
+
*/
|
|
176
|
+
this.BASE_DIR = GLOBAL_PATHS.BASE_DIR;
|
|
161
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* 获取沙箱根目录
|
|
180
|
+
* @returns 沙箱根目录的绝对路径
|
|
181
|
+
*/
|
|
162
182
|
static getRoot() {
|
|
163
183
|
return this.BASE_DIR;
|
|
164
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* 获取存储所有版本的根目录
|
|
187
|
+
* @returns versions 目录的绝对路径
|
|
188
|
+
*/
|
|
165
189
|
static getVersionRoot() {
|
|
166
|
-
return
|
|
190
|
+
return path4.join(this.BASE_DIR, SANDBOX_CONFIG.DIRS.VERSIONS);
|
|
167
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* 获取指定版本的沙箱路径
|
|
194
|
+
* @param version 版本号,或者 'current' 表示当前激活版本
|
|
195
|
+
* @returns 对应版本的绝对路径
|
|
196
|
+
*/
|
|
168
197
|
static getVersionPath(version) {
|
|
169
|
-
if (version ===
|
|
170
|
-
return
|
|
198
|
+
if (version === SANDBOX_CONFIG.DIRS.CURRENT) {
|
|
199
|
+
return path4.join(this.BASE_DIR, SANDBOX_CONFIG.DIRS.VERSIONS, SANDBOX_CONFIG.DIRS.CURRENT);
|
|
171
200
|
}
|
|
172
|
-
return
|
|
201
|
+
return path4.join(this.BASE_DIR, SANDBOX_CONFIG.DIRS.VERSIONS, version);
|
|
173
202
|
}
|
|
174
203
|
/**
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
* @param
|
|
204
|
+
* 递归向上查找工作区根目录
|
|
205
|
+
* 识别标准:包含 pnpm-workspace.yaml 或 package.json 中定义了 workspaces
|
|
206
|
+
* @param cwd 起始查找目录
|
|
207
|
+
* @returns 查找到的工作区根目录路径,若未找到则返回 cwd
|
|
178
208
|
*/
|
|
179
|
-
static async
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const pkgPath = path3.join(cwd, "package.json");
|
|
209
|
+
static async getWorkspaceRoot(cwd) {
|
|
210
|
+
let current = cwd;
|
|
211
|
+
while (current !== path4.parse(current).root) {
|
|
212
|
+
const pkgPath = path4.join(current, "package.json");
|
|
213
|
+
const pnpmWorkspacePath = path4.join(current, "pnpm-workspace.yaml");
|
|
214
|
+
if (fs2.existsSync(pnpmWorkspacePath)) return current;
|
|
186
215
|
if (fs2.existsSync(pkgPath)) {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const dirPath = path3.join(cwd, dir);
|
|
192
|
-
if (fs2.existsSync(dirPath)) {
|
|
193
|
-
const entries = await fs2.readdir(dirPath, { withFileTypes: true });
|
|
194
|
-
for (const entry of entries) {
|
|
195
|
-
if (entry.isDirectory()) {
|
|
196
|
-
const subPkgCache = path3.join(dirPath, entry.name, ".chatbi");
|
|
197
|
-
if (fs2.existsSync(subPkgCache)) {
|
|
198
|
-
await fs2.remove(subPkgCache);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
216
|
+
try {
|
|
217
|
+
const pkg = await fs2.readJson(pkgPath);
|
|
218
|
+
if (pkg.workspaces) return current;
|
|
219
|
+
} catch (e) {
|
|
204
220
|
}
|
|
205
221
|
}
|
|
222
|
+
current = path4.dirname(current);
|
|
206
223
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
224
|
+
return cwd;
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// src/sandbox/SandboxRenderer.ts
|
|
231
|
+
import fs3 from "fs-extra";
|
|
232
|
+
import path5 from "path";
|
|
233
|
+
import Handlebars from "handlebars";
|
|
234
|
+
var SandboxRenderer;
|
|
235
|
+
var init_SandboxRenderer = __esm({
|
|
236
|
+
"src/sandbox/SandboxRenderer.ts"() {
|
|
237
|
+
"use strict";
|
|
238
|
+
init_esm_shims();
|
|
239
|
+
Handlebars.registerHelper("json", (obj) => JSON.stringify(obj, null, 2));
|
|
240
|
+
Handlebars.registerHelper("eq", (a, b) => a === b);
|
|
241
|
+
SandboxRenderer = class {
|
|
242
|
+
static {
|
|
243
|
+
/**
|
|
244
|
+
* 需要转义的模板关键字列表
|
|
245
|
+
* 只有匹配这些关键字的 {{ }} 才会被 Handlebars 处理,其余(如 React 的 {{ style }})将被转义跳过
|
|
246
|
+
*/
|
|
247
|
+
this.TEMPLATE_KEYWORDS = [
|
|
248
|
+
"name",
|
|
249
|
+
"version",
|
|
250
|
+
"projectName",
|
|
251
|
+
"projectTitle",
|
|
252
|
+
"projectVersion",
|
|
253
|
+
"cliVersion",
|
|
254
|
+
"tsconfigPath",
|
|
255
|
+
"theme",
|
|
256
|
+
"isNebula",
|
|
257
|
+
"isGlass",
|
|
258
|
+
"isBusiness",
|
|
259
|
+
"isApp",
|
|
260
|
+
"isShell",
|
|
261
|
+
"pluginName",
|
|
262
|
+
"pluginPackageName",
|
|
263
|
+
"pluginVersion",
|
|
264
|
+
"pluginDisplayName",
|
|
265
|
+
"pluginDescription",
|
|
266
|
+
"pluginClassName",
|
|
267
|
+
"pluginPath",
|
|
268
|
+
"pluginFolderName",
|
|
269
|
+
"pluginType",
|
|
270
|
+
"pluginId",
|
|
271
|
+
"className",
|
|
272
|
+
"dependencies",
|
|
273
|
+
"devDependencies",
|
|
274
|
+
"json"
|
|
275
|
+
];
|
|
210
276
|
}
|
|
211
277
|
/**
|
|
212
|
-
*
|
|
278
|
+
* 递归渲染目录模板
|
|
279
|
+
* @param srcDir 模板源目录
|
|
280
|
+
* @param destDir 目标输出目录
|
|
281
|
+
* @param data 渲染模板所需的变量上下文
|
|
213
282
|
*/
|
|
214
|
-
static async
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
await fs2.ensureDir(versionPath);
|
|
226
|
-
const spinner = createSpinner(`\u6B63\u5728\u521D\u59CB\u5316\u5185\u6838\u6C99\u7BB1 ${pc2.cyan(version)}...`).start();
|
|
227
|
-
try {
|
|
228
|
-
const rootPkgJson = {
|
|
229
|
-
name: `chatbi-sandbox-${version}`,
|
|
230
|
-
private: true,
|
|
231
|
-
dependencies: {},
|
|
232
|
-
devDependencies: {
|
|
233
|
-
"tailwindcss": "^3.4.1",
|
|
234
|
-
"autoprefixer": "^10.4.17",
|
|
235
|
-
"postcss": "^8.4.35",
|
|
236
|
-
"vite": "^5.0.8",
|
|
237
|
-
"@vitejs/plugin-react": "^4.2.1",
|
|
238
|
-
"less": "^4.2.0",
|
|
239
|
-
"typescript": "^5.3.3",
|
|
240
|
-
"@types/react": "^18.3.1",
|
|
241
|
-
"@types/react-dom": "^18.3.1",
|
|
242
|
-
"@types/node": "^20.11.20"
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
for (const pkgName of _Sandbox.CORE_PACKAGES) {
|
|
246
|
-
rootPkgJson.dependencies[pkgName] = pkgName === "@chatbi-v/core" ? version : "latest";
|
|
247
|
-
}
|
|
248
|
-
for (const pkgName of _Sandbox.RUNTIME_DEPS) {
|
|
249
|
-
if (!rootPkgJson.dependencies[pkgName]) {
|
|
250
|
-
rootPkgJson.dependencies[pkgName] = "latest";
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
rootPkgJson.dependencies["react"] = "^18.3.1";
|
|
254
|
-
rootPkgJson.dependencies["react-dom"] = "^18.3.1";
|
|
255
|
-
rootPkgJson.dependencies["antd"] = "^5.20.0";
|
|
256
|
-
await fs2.writeJson(path3.join(versionPath, "package.json"), rootPkgJson, { spaces: 2 });
|
|
257
|
-
await fs2.writeFile(path3.join(versionPath, ".npmrc"), "shamefully-hoist=true\nauto-install-peers=true\n");
|
|
258
|
-
spinner.text = pc2.gray(" \u{1F50D} \u68C0\u67E5\u672C\u5730\u5F00\u53D1\u73AF\u5883...");
|
|
259
|
-
const isLocalDev = await this.tryLinkLocalPackages(versionPath);
|
|
260
|
-
const installArgs = ["install"];
|
|
261
|
-
if (isLocalDev) {
|
|
262
|
-
installArgs.push("--no-frozen-lockfile");
|
|
283
|
+
static async renderDirectory(srcDir, destDir, data) {
|
|
284
|
+
if (!fs3.existsSync(srcDir)) return;
|
|
285
|
+
const entries = await fs3.readdir(srcDir, { withFileTypes: true });
|
|
286
|
+
for (const entry of entries) {
|
|
287
|
+
const srcPath = path5.join(srcDir, entry.name);
|
|
288
|
+
const destPath = path5.join(destDir, entry.name.replace(/\.hbs$/, ""));
|
|
289
|
+
if (entry.isDirectory()) {
|
|
290
|
+
await fs3.ensureDir(destPath);
|
|
291
|
+
await this.renderDirectory(srcPath, destPath, data);
|
|
292
|
+
} else {
|
|
293
|
+
await this.renderFile(srcPath, destPath, data);
|
|
263
294
|
}
|
|
264
|
-
spinner.text = pc2.gray(` \u23F3 \u6267\u884C pnpm ${installArgs.join(" ")}...`);
|
|
265
|
-
await execa("pnpm", installArgs, { cwd: versionPath });
|
|
266
|
-
spinner.text = pc2.gray(" \u{1F3A8} \u540C\u6B65 Shell \u6A21\u677F...");
|
|
267
|
-
await this.ensureShell(version, force);
|
|
268
|
-
spinner.succeed(pc2.green(`\u5185\u6838\u6C99\u7BB1 ${version} \u521D\u59CB\u5316\u6210\u529F`));
|
|
269
|
-
} catch (e) {
|
|
270
|
-
spinner.fail(pc2.red(`\u5185\u6838\u6C99\u7BB1\u521D\u59CB\u5316\u5931\u8D25: ${e.message}`));
|
|
271
|
-
throw e;
|
|
272
295
|
}
|
|
273
|
-
return versionPath;
|
|
274
296
|
}
|
|
275
297
|
/**
|
|
276
|
-
*
|
|
298
|
+
* 渲染单个文件
|
|
277
299
|
*/
|
|
278
|
-
static async
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
return shellDestDir;
|
|
300
|
+
static async renderFile(srcPath, destPath, data) {
|
|
301
|
+
const isTemplate = srcPath.endsWith(".hbs");
|
|
302
|
+
if (!isTemplate) {
|
|
303
|
+
await fs3.copy(srcPath, destPath);
|
|
304
|
+
return;
|
|
284
305
|
}
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
await this.renderDirectory(shellTemplateDir, shellDestDir, templateData);
|
|
307
|
-
const tsConfigPaths = {
|
|
308
|
-
compilerOptions: {
|
|
309
|
-
baseUrl: ".",
|
|
310
|
-
paths: {
|
|
311
|
-
"@/*": ["./src/*"]
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
};
|
|
315
|
-
await fs2.writeJson(path3.join(shellDestDir, "tsconfig.paths.json"), tsConfigPaths, { spaces: 2 });
|
|
306
|
+
const content = await fs3.readFile(srcPath, "utf-8");
|
|
307
|
+
if (!content.includes("{{")) {
|
|
308
|
+
await fs3.outputFile(destPath, content);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
try {
|
|
312
|
+
const keywordsPattern = this.TEMPLATE_KEYWORDS.join("|");
|
|
313
|
+
const safeContent = content.replace(
|
|
314
|
+
new RegExp(`\\{\\{(?!\\{)(?!\\s*([#/]?(?:${keywordsPattern}))\\b)`, "g"),
|
|
315
|
+
"\\{{"
|
|
316
|
+
);
|
|
317
|
+
const template = Handlebars.compile(safeContent);
|
|
318
|
+
const result = template(data);
|
|
319
|
+
await fs3.outputFile(destPath, result);
|
|
320
|
+
} catch (e) {
|
|
321
|
+
let result = content;
|
|
322
|
+
for (const [key, val] of Object.entries(data)) {
|
|
323
|
+
const regex = new RegExp(`\\{\\{\\s*${key}\\s*\\}\\}`, "g");
|
|
324
|
+
result = result.replace(regex, typeof val === "object" ? JSON.stringify(val) : String(val));
|
|
325
|
+
}
|
|
326
|
+
await fs3.outputFile(destPath, result);
|
|
316
327
|
}
|
|
317
|
-
return shellDestDir;
|
|
318
328
|
}
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
// src/sandbox/SandboxContext.ts
|
|
334
|
+
import fs4 from "fs-extra";
|
|
335
|
+
import path6 from "path";
|
|
336
|
+
var SandboxContext;
|
|
337
|
+
var init_SandboxContext = __esm({
|
|
338
|
+
"src/sandbox/SandboxContext.ts"() {
|
|
339
|
+
"use strict";
|
|
340
|
+
init_esm_shims();
|
|
341
|
+
init_SandboxPath();
|
|
342
|
+
init_constants();
|
|
343
|
+
SandboxContext = class {
|
|
319
344
|
/**
|
|
320
|
-
*
|
|
345
|
+
* 注入项目虚拟上下文
|
|
346
|
+
* 包括:
|
|
347
|
+
* 1. 确定集中式 .chatbi 存放位置并处理子包软链
|
|
348
|
+
* 2. 生成适配沙箱的 tsconfig.json (配置路径别名)
|
|
349
|
+
* 3. 软链接沙箱的 node_modules 到项目 .chatbi 目录下
|
|
350
|
+
* 4. 确保 .chatbi 被加入 .gitignore
|
|
351
|
+
*
|
|
352
|
+
* @param projectRoot 当前项目根目录
|
|
353
|
+
* @param version 内核版本号
|
|
354
|
+
* @param corePackages 核心包名列表
|
|
355
|
+
* @param runtimeDeps 运行时依赖包名列表
|
|
321
356
|
*/
|
|
322
|
-
static async
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
await
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const safeContent = content.replace(/\{\{(?!\s*([#/]?(?:if|else|each|with|unless|name|version|projectName|projectTitle|projectVersion|cliVersion|tsconfigPath|theme|isNebula|isGlass|isBusiness|isApp|isShell|pluginName|pluginPackageName|pluginVersion|pluginDisplayName|pluginDescription|pluginClassName|pluginPath|pluginFolderName|pluginType|pluginId|className))\b)/g, "\\{{");
|
|
337
|
-
const template = Handlebars.compile(safeContent);
|
|
338
|
-
const result = template(data);
|
|
339
|
-
await fs2.outputFile(destPath, result);
|
|
340
|
-
} catch (e) {
|
|
341
|
-
let result = content;
|
|
342
|
-
for (const [key, val] of Object.entries(data)) {
|
|
343
|
-
const regex = new RegExp(`\\{\\{\\s*${key}\\s*\\}\\}`, "g");
|
|
344
|
-
result = result.replace(regex, String(val));
|
|
345
|
-
}
|
|
346
|
-
await fs2.outputFile(destPath, result);
|
|
357
|
+
static async inject(projectRoot, version, corePackages, runtimeDeps) {
|
|
358
|
+
const workspaceRoot = await SandboxPath.getWorkspaceRoot(projectRoot);
|
|
359
|
+
const chatbiDir = path6.join(workspaceRoot, SANDBOX_CONFIG.DIRS.CACHE);
|
|
360
|
+
await fs4.ensureDir(chatbiDir);
|
|
361
|
+
if (workspaceRoot !== projectRoot) {
|
|
362
|
+
const localChatbi = path6.join(projectRoot, SANDBOX_CONFIG.DIRS.CACHE);
|
|
363
|
+
try {
|
|
364
|
+
const stats = await fs4.lstat(localChatbi).catch(() => null);
|
|
365
|
+
if (stats) {
|
|
366
|
+
if (stats.isSymbolicLink()) {
|
|
367
|
+
const linkTarget = await fs4.readlink(localChatbi);
|
|
368
|
+
if (linkTarget !== chatbiDir) {
|
|
369
|
+
await fs4.remove(localChatbi);
|
|
370
|
+
await fs4.symlink(chatbiDir, localChatbi, "dir");
|
|
347
371
|
}
|
|
348
372
|
} else {
|
|
349
|
-
await
|
|
373
|
+
await fs4.remove(localChatbi);
|
|
374
|
+
await fs4.symlink(chatbiDir, localChatbi, "dir");
|
|
350
375
|
}
|
|
351
376
|
} else {
|
|
352
|
-
await
|
|
377
|
+
await fs4.symlink(chatbiDir, localChatbi, "dir");
|
|
353
378
|
}
|
|
379
|
+
} catch (e) {
|
|
354
380
|
}
|
|
355
381
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
* 注入项目虚拟上下文 (tsconfig, alias)
|
|
359
|
-
*/
|
|
360
|
-
static async injectContext(projectRoot, version) {
|
|
361
|
-
const chatbiDir = path3.join(projectRoot, ".chatbi");
|
|
362
|
-
await fs2.ensureDir(chatbiDir);
|
|
363
|
-
const versionPath = this.getVersionPath(version);
|
|
364
|
-
const sandboxNodeModules = path3.join(versionPath, "node_modules");
|
|
382
|
+
const versionPath = SandboxPath.getVersionPath(version);
|
|
383
|
+
const sandboxNodeModules = path6.join(versionPath, "node_modules");
|
|
365
384
|
const corePaths = {};
|
|
366
|
-
for (const pkgName of
|
|
385
|
+
for (const pkgName of corePackages) {
|
|
367
386
|
corePaths[pkgName] = [`./node_modules/${pkgName}`];
|
|
368
387
|
corePaths[`${pkgName}/*`] = [`./node_modules/${pkgName}/*`];
|
|
369
388
|
}
|
|
370
|
-
for (const pkgName of
|
|
389
|
+
for (const pkgName of runtimeDeps) {
|
|
371
390
|
corePaths[pkgName] = [`./node_modules/${pkgName}`];
|
|
372
391
|
corePaths[`${pkgName}/*`] = [`./node_modules/${pkgName}/*`];
|
|
373
392
|
if (["react", "react-dom", "node"].includes(pkgName)) {
|
|
@@ -378,152 +397,119 @@ var init_sandbox = __esm({
|
|
|
378
397
|
}
|
|
379
398
|
corePaths["@types/*"] = ["./node_modules/@types/*"];
|
|
380
399
|
corePaths["vite/client"] = ["./node_modules/vite/client.d.ts"];
|
|
381
|
-
const baseConfigPath =
|
|
382
|
-
let projectPaths = { "@/*": ["../src/*"] };
|
|
400
|
+
const baseConfigPath = path6.join(sandboxNodeModules, "@chatbi-v/tsconfig/base.json");
|
|
383
401
|
const tsConfig = {
|
|
384
402
|
extends: baseConfigPath,
|
|
385
403
|
compilerOptions: {
|
|
386
404
|
baseUrl: ".",
|
|
387
405
|
moduleResolution: "bundler",
|
|
388
406
|
skipLibCheck: true,
|
|
389
|
-
|
|
390
|
-
// This is much more robust as it works relative to the config file (.chatbi/tsconfig.json)
|
|
391
|
-
typeRoots: [
|
|
392
|
-
"./node_modules/@types"
|
|
393
|
-
],
|
|
394
|
-
// Crucial for symlinked node_modules: treat them as if they are in the project
|
|
407
|
+
typeRoots: ["./node_modules/@types"],
|
|
395
408
|
preserveSymlinks: true,
|
|
396
409
|
paths: {
|
|
397
410
|
...corePaths,
|
|
398
|
-
|
|
399
|
-
// Fallback: Try to find anything else in the virtual node_modules
|
|
411
|
+
"@/*": ["../src/*"],
|
|
400
412
|
"*": ["./node_modules/*"]
|
|
401
413
|
}
|
|
402
414
|
}
|
|
403
415
|
};
|
|
404
|
-
await
|
|
405
|
-
await
|
|
406
|
-
const virtualNodeModules =
|
|
407
|
-
if (
|
|
408
|
-
return;
|
|
409
|
-
}
|
|
410
|
-
try {
|
|
416
|
+
await fs4.writeJson(path6.join(chatbiDir, "tsconfig.json"), tsConfig, { spaces: 2 });
|
|
417
|
+
await fs4.writeJson(path6.join(chatbiDir, "tsconfig.paths.json"), { compilerOptions: tsConfig.compilerOptions }, { spaces: 2 });
|
|
418
|
+
const virtualNodeModules = path6.join(chatbiDir, "node_modules");
|
|
419
|
+
if (fs4.existsSync(sandboxNodeModules)) {
|
|
411
420
|
try {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
}
|
|
416
|
-
} catch (e) {
|
|
417
|
-
}
|
|
418
|
-
await fs2.ensureSymlink(sandboxNodeModules, virtualNodeModules, "dir");
|
|
419
|
-
const rootNodeModules = path3.join(projectRoot, "node_modules");
|
|
420
|
-
let rootNmExists = false;
|
|
421
|
-
try {
|
|
422
|
-
rootNmExists = fs2.existsSync(rootNodeModules);
|
|
421
|
+
await fs4.remove(virtualNodeModules).catch(() => {
|
|
422
|
+
});
|
|
423
|
+
await fs4.ensureSymlink(sandboxNodeModules, virtualNodeModules, "dir");
|
|
423
424
|
} catch (e) {
|
|
424
425
|
}
|
|
425
|
-
if (!rootNmExists) {
|
|
426
|
-
try {
|
|
427
|
-
await fs2.ensureSymlink(sandboxNodeModules, rootNodeModules, "dir");
|
|
428
|
-
} catch (linkErr) {
|
|
429
|
-
const appsDir = path3.join(projectRoot, "apps");
|
|
430
|
-
if (fs2.existsSync(appsDir)) {
|
|
431
|
-
const appDirs = await fg("*", { cwd: appsDir, onlyDirectories: true, absolute: true });
|
|
432
|
-
for (const appDir of appDirs) {
|
|
433
|
-
const appNm = path3.join(appDir, "node_modules");
|
|
434
|
-
if (!fs2.existsSync(appNm)) {
|
|
435
|
-
await fs2.ensureSymlink(sandboxNodeModules, appNm, "dir").catch(() => {
|
|
436
|
-
});
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
} catch (e) {
|
|
443
426
|
}
|
|
444
|
-
const gitignorePath =
|
|
445
|
-
if (
|
|
446
|
-
let content = await
|
|
447
|
-
if (!content.includes(
|
|
448
|
-
await
|
|
427
|
+
const gitignorePath = path6.join(workspaceRoot, ".gitignore");
|
|
428
|
+
if (fs4.existsSync(gitignorePath)) {
|
|
429
|
+
let content = await fs4.readFile(gitignorePath, "utf-8");
|
|
430
|
+
if (!content.includes(SANDBOX_CONFIG.DIRS.CACHE)) {
|
|
431
|
+
await fs4.appendFile(gitignorePath, `
|
|
432
|
+
# ChatBI
|
|
433
|
+
${SANDBOX_CONFIG.DIRS.CACHE}
|
|
434
|
+
`);
|
|
449
435
|
}
|
|
450
436
|
}
|
|
451
437
|
}
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
// src/sandbox/SandboxPkgManager.ts
|
|
443
|
+
import fs5 from "fs-extra";
|
|
444
|
+
import path7 from "path";
|
|
445
|
+
import pc2 from "picocolors";
|
|
446
|
+
import fg from "fast-glob";
|
|
447
|
+
var SandboxPkgManager;
|
|
448
|
+
var init_SandboxPkgManager = __esm({
|
|
449
|
+
"src/sandbox/SandboxPkgManager.ts"() {
|
|
450
|
+
"use strict";
|
|
451
|
+
init_esm_shims();
|
|
452
|
+
init_utils();
|
|
453
|
+
init_SandboxPath();
|
|
454
|
+
SandboxPkgManager = class {
|
|
452
455
|
/**
|
|
453
|
-
*
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
for (const pkg of this.CORE_PACKAGES) {
|
|
460
|
-
aliases[pkg] = path3.join(sandboxNodeModules, pkg);
|
|
461
|
-
}
|
|
462
|
-
return aliases;
|
|
463
|
-
}
|
|
464
|
-
/**
|
|
465
|
-
* 尝试将本地包 Link 到沙箱中 (模拟安装)
|
|
456
|
+
* 尝试将本地开发环境的包 Link 到沙箱中 (模拟安装)
|
|
457
|
+
* 用于 Monorepo 场景下,让沙箱直接使用最新的本地源码
|
|
458
|
+
* @param versionPath 沙箱版本的存储路径
|
|
459
|
+
* @param corePackages 核心包名列表
|
|
460
|
+
* @param runtimeDeps 运行时依赖包名列表
|
|
461
|
+
* @returns 是否成功 Link 了至少一个包
|
|
466
462
|
*/
|
|
467
|
-
static async tryLinkLocalPackages(versionPath) {
|
|
463
|
+
static async tryLinkLocalPackages(versionPath, corePackages, runtimeDeps) {
|
|
468
464
|
try {
|
|
469
465
|
const cliRoot = await getCliRoot();
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
if (fs2.existsSync(path3.join(currentDir, "pnpm-workspace.yaml"))) {
|
|
474
|
-
projectRoot = currentDir;
|
|
475
|
-
break;
|
|
476
|
-
}
|
|
477
|
-
currentDir = path3.dirname(currentDir);
|
|
466
|
+
const projectRoot = await SandboxPath.getWorkspaceRoot(cliRoot);
|
|
467
|
+
if (projectRoot === cliRoot && !fs5.existsSync(path7.join(projectRoot, "pnpm-workspace.yaml"))) {
|
|
468
|
+
return false;
|
|
478
469
|
}
|
|
479
470
|
const possiblePackagesDirs = [
|
|
480
|
-
|
|
481
|
-
//
|
|
482
|
-
|
|
471
|
+
path7.join(projectRoot, "packages"),
|
|
472
|
+
// 兼容旧版或其他可能的路径结构
|
|
473
|
+
path7.resolve(projectRoot, "../chatbi-v/packages")
|
|
483
474
|
];
|
|
484
475
|
const localPackages = {};
|
|
485
|
-
const patterns = possiblePackagesDirs.filter((dir) =>
|
|
476
|
+
const patterns = possiblePackagesDirs.filter((dir) => fs5.existsSync(dir)).map((dir) => path7.join(dir, "**/package.json"));
|
|
486
477
|
if (patterns.length > 0) {
|
|
487
478
|
const pkgJsonFiles = await fg(patterns, {
|
|
488
479
|
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"],
|
|
489
480
|
absolute: true,
|
|
490
481
|
deep: 5
|
|
491
|
-
// 允许一定的嵌套深度
|
|
492
482
|
});
|
|
493
483
|
for (const pkgJsonPath of pkgJsonFiles) {
|
|
494
484
|
try {
|
|
495
|
-
const pkgJson = await
|
|
496
|
-
if (
|
|
497
|
-
localPackages[pkgJson.name] =
|
|
485
|
+
const pkgJson = await fs5.readJson(pkgJsonPath);
|
|
486
|
+
if (corePackages.includes(pkgJson.name) || runtimeDeps.includes(pkgJson.name)) {
|
|
487
|
+
localPackages[pkgJson.name] = path7.dirname(pkgJsonPath);
|
|
498
488
|
}
|
|
499
489
|
} catch (e) {
|
|
500
490
|
}
|
|
501
491
|
}
|
|
502
492
|
}
|
|
503
|
-
if (Object.keys(localPackages).length === 0)
|
|
504
|
-
return false;
|
|
505
|
-
}
|
|
493
|
+
if (Object.keys(localPackages).length === 0) return false;
|
|
506
494
|
const linkSummary = Object.entries(localPackages).map(([name, pkgPath]) => `${pc2.cyan(name.padEnd(30))} -> ${pc2.gray(pkgPath)}`).join("\n");
|
|
507
495
|
printBox(
|
|
508
496
|
pc2.green("\u{1F517} \u5DF2\u68C0\u6D4B\u5230\u672C\u5730\u5F00\u53D1\u73AF\u5883\uFF0C\u5C06\u94FE\u63A5\u4EE5\u4E0B\u6838\u5FC3\u5305\uFF1A\n\n") + linkSummary,
|
|
509
497
|
"Monorepo Link Mode"
|
|
510
498
|
);
|
|
511
|
-
const sandboxNodeModules =
|
|
512
|
-
await
|
|
499
|
+
const sandboxNodeModules = path7.join(versionPath, "node_modules");
|
|
500
|
+
await fs5.ensureDir(sandboxNodeModules);
|
|
513
501
|
for (const [name, pkgPath] of Object.entries(localPackages)) {
|
|
514
|
-
const targetLinkPath =
|
|
515
|
-
await
|
|
502
|
+
const targetLinkPath = path7.join(sandboxNodeModules, name);
|
|
503
|
+
await fs5.ensureDir(path7.dirname(targetLinkPath));
|
|
516
504
|
try {
|
|
517
|
-
const stats = await
|
|
518
|
-
if (stats)
|
|
519
|
-
await fs2.remove(targetLinkPath);
|
|
520
|
-
}
|
|
505
|
+
const stats = await fs5.lstat(targetLinkPath).catch(() => null);
|
|
506
|
+
if (stats) await fs5.remove(targetLinkPath);
|
|
521
507
|
} catch (e) {
|
|
522
508
|
}
|
|
523
|
-
await
|
|
509
|
+
await fs5.symlink(pkgPath, targetLinkPath, "dir");
|
|
524
510
|
}
|
|
525
|
-
const sandboxPkgJsonPath =
|
|
526
|
-
const sandboxPkgJson = await
|
|
511
|
+
const sandboxPkgJsonPath = path7.join(versionPath, "package.json");
|
|
512
|
+
const sandboxPkgJson = await fs5.readJson(sandboxPkgJsonPath);
|
|
527
513
|
const sections = ["dependencies", "devDependencies"];
|
|
528
514
|
let modified = false;
|
|
529
515
|
for (const section of sections) {
|
|
@@ -536,95 +522,287 @@ var init_sandbox = __esm({
|
|
|
536
522
|
}
|
|
537
523
|
}
|
|
538
524
|
}
|
|
539
|
-
if (modified) {
|
|
540
|
-
await fs2.writeJson(sandboxPkgJsonPath, sandboxPkgJson, { spaces: 2 });
|
|
541
|
-
}
|
|
525
|
+
if (modified) await fs5.writeJson(sandboxPkgJsonPath, sandboxPkgJson, { spaces: 2 });
|
|
542
526
|
return true;
|
|
543
527
|
} catch (e) {
|
|
544
528
|
console.warn(pc2.yellow(` \u26A0\uFE0F Link \u672C\u5730\u6E90\u7801\u5931\u8D25\uFF0C\u5C06\u5C1D\u8BD5\u4ECE NPM \u5B89\u88C5: ${e.message}`));
|
|
545
529
|
return false;
|
|
546
530
|
}
|
|
547
531
|
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
// src/sandbox.ts
|
|
537
|
+
import fs6 from "fs-extra";
|
|
538
|
+
import path8 from "path";
|
|
539
|
+
import pc3 from "picocolors";
|
|
540
|
+
import fg2 from "fast-glob";
|
|
541
|
+
import { execa } from "execa";
|
|
542
|
+
var Sandbox;
|
|
543
|
+
var init_sandbox = __esm({
|
|
544
|
+
"src/sandbox.ts"() {
|
|
545
|
+
"use strict";
|
|
546
|
+
init_esm_shims();
|
|
547
|
+
init_utils();
|
|
548
|
+
init_SandboxPath();
|
|
549
|
+
init_SandboxRenderer();
|
|
550
|
+
init_SandboxContext();
|
|
551
|
+
init_SandboxPkgManager();
|
|
552
|
+
init_constants();
|
|
553
|
+
Sandbox = class {
|
|
554
|
+
static {
|
|
555
|
+
/** 核心源码包列表 */
|
|
556
|
+
this.CORE_PACKAGES = [
|
|
557
|
+
"@chatbi-v/core",
|
|
558
|
+
"@chatbi-v/mocks",
|
|
559
|
+
"@chatbi-v/tsconfig",
|
|
560
|
+
"@chatbi-v/tailwind-config",
|
|
561
|
+
"@chatbi-v/plugin-theme-manager",
|
|
562
|
+
"@chatbi-v/plugin-layout-transform",
|
|
563
|
+
"@chatbi-v/plugin-system-monitor"
|
|
564
|
+
];
|
|
565
|
+
}
|
|
566
|
+
static {
|
|
567
|
+
/** 运行时必须依赖 */
|
|
568
|
+
this.RUNTIME_DEPS = [
|
|
569
|
+
"@ant-design/x",
|
|
570
|
+
"@ant-design/icons",
|
|
571
|
+
"antd",
|
|
572
|
+
"react",
|
|
573
|
+
"react-dom",
|
|
574
|
+
"lucide-react",
|
|
575
|
+
"framer-motion",
|
|
576
|
+
"clsx",
|
|
577
|
+
"tailwind-merge",
|
|
578
|
+
"react-router-dom",
|
|
579
|
+
"zustand",
|
|
580
|
+
"axios",
|
|
581
|
+
"less",
|
|
582
|
+
"vite"
|
|
583
|
+
];
|
|
584
|
+
}
|
|
585
|
+
/** 获取沙箱根目录 */
|
|
586
|
+
static getRoot() {
|
|
587
|
+
return SandboxPath.getRoot();
|
|
588
|
+
}
|
|
589
|
+
/** 获取所有版本的根目录 */
|
|
590
|
+
static getVersionRoot() {
|
|
591
|
+
return SandboxPath.getVersionRoot();
|
|
592
|
+
}
|
|
593
|
+
/** 获取指定版本的沙箱路径 */
|
|
594
|
+
static getVersionPath(version) {
|
|
595
|
+
return SandboxPath.getVersionPath(version);
|
|
596
|
+
}
|
|
597
|
+
/** 获取项目的工作区根目录 (Monorepo 支持) */
|
|
598
|
+
static async getWorkspaceRoot(cwd) {
|
|
599
|
+
return SandboxPath.getWorkspaceRoot(cwd);
|
|
600
|
+
}
|
|
601
|
+
/** 清理指定版本的沙箱物理文件 */
|
|
602
|
+
static async cleanVersion(version) {
|
|
603
|
+
const versionPath = this.getVersionPath(version);
|
|
604
|
+
if (fs6.existsSync(versionPath)) {
|
|
605
|
+
await fs6.remove(versionPath);
|
|
560
606
|
}
|
|
561
|
-
await fs2.symlink(targetPath, currentLinkPath, "dir");
|
|
562
607
|
}
|
|
563
608
|
/**
|
|
564
|
-
*
|
|
609
|
+
* 优雅清理缓存环境
|
|
610
|
+
* @param cwd 当前项目路径
|
|
611
|
+
* @param deep 是否执行深度清理
|
|
565
612
|
*/
|
|
566
|
-
static async
|
|
567
|
-
const
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
613
|
+
static async clean(cwd, deep = false) {
|
|
614
|
+
const spinner = createSpinner("\u6B63\u5728\u6E05\u7406\u7F13\u5B58\u76EE\u5F55...").start();
|
|
615
|
+
try {
|
|
616
|
+
const workspaceRoot = await this.getWorkspaceRoot(cwd);
|
|
617
|
+
let cleanedCount = 0;
|
|
618
|
+
const cachePatterns = [
|
|
619
|
+
path8.join(workspaceRoot, `**/${SANDBOX_CONFIG.DIRS.CACHE}`)
|
|
620
|
+
];
|
|
621
|
+
const cacheDirs = await fg2(cachePatterns, {
|
|
622
|
+
onlyFiles: false,
|
|
623
|
+
// 允许匹配文件和符号链接
|
|
624
|
+
absolute: true,
|
|
625
|
+
ignore: ["**/node_modules/**"],
|
|
626
|
+
dot: true
|
|
627
|
+
// 确保能匹配到以 . 开头的目录
|
|
628
|
+
});
|
|
629
|
+
for (const dir of cacheDirs) {
|
|
630
|
+
const stats = await fs6.lstat(dir).catch(() => null);
|
|
631
|
+
if (stats) {
|
|
632
|
+
await fs6.remove(dir);
|
|
633
|
+
cleanedCount++;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
if (deep) {
|
|
637
|
+
const distPatterns = [
|
|
638
|
+
path8.join(workspaceRoot, "**/dist")
|
|
639
|
+
];
|
|
640
|
+
const distDirs = await fg2(distPatterns, {
|
|
641
|
+
onlyFiles: false,
|
|
642
|
+
absolute: true,
|
|
643
|
+
ignore: [
|
|
644
|
+
"**/node_modules/**",
|
|
645
|
+
"**/packages/cli/dist/**",
|
|
646
|
+
// 保护 CLI 自身构建产物
|
|
647
|
+
"**/.git/**"
|
|
648
|
+
]
|
|
649
|
+
});
|
|
650
|
+
for (const dir of distDirs) {
|
|
651
|
+
const stats = await fs6.lstat(dir).catch(() => null);
|
|
652
|
+
if (stats) {
|
|
653
|
+
const hasPkg = fs6.existsSync(path8.join(path8.dirname(dir), "package.json"));
|
|
654
|
+
if (hasPkg) {
|
|
655
|
+
await fs6.remove(dir);
|
|
656
|
+
cleanedCount++;
|
|
588
657
|
}
|
|
589
|
-
} catch (e) {
|
|
590
658
|
}
|
|
591
659
|
}
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
660
|
+
const globalRoot = this.getRoot();
|
|
661
|
+
if (fs6.existsSync(globalRoot)) {
|
|
662
|
+
await fs6.remove(globalRoot);
|
|
663
|
+
cleanedCount++;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
spinner.succeed(pc3.green(`\u6E05\u7406\u5B8C\u6210\uFF0C\u5171\u6E05\u7406 ${cleanedCount} \u4E2A\u9879\u76EE/\u7F13\u5B58\u76EE\u5F55`));
|
|
667
|
+
} catch (e) {
|
|
668
|
+
spinner.fail(pc3.red(`\u6E05\u7406\u5931\u8D25: ${e.message}`));
|
|
597
669
|
}
|
|
598
|
-
printBox(statusText, "ChatBI \u5185\u6838\u53EF\u89C2\u6D4B\u6027\u9762\u677F");
|
|
599
670
|
}
|
|
600
671
|
/**
|
|
601
|
-
*
|
|
672
|
+
* 准备内核沙箱环境 (安装/更新)
|
|
602
673
|
*/
|
|
603
|
-
static async
|
|
674
|
+
static async prepare(version, force = false) {
|
|
675
|
+
const versionPath = this.getVersionPath(version);
|
|
676
|
+
if (!force && fs6.existsSync(path8.join(versionPath, "node_modules/tailwindcss"))) {
|
|
677
|
+
return versionPath;
|
|
678
|
+
}
|
|
679
|
+
if (fs6.existsSync(versionPath)) {
|
|
680
|
+
await fs6.remove(path8.join(versionPath, "node_modules"));
|
|
681
|
+
}
|
|
682
|
+
await fs6.ensureDir(versionPath);
|
|
683
|
+
const spinner = createSpinner(`\u6B63\u5728\u521D\u59CB\u5316\u5185\u6838\u6C99\u7BB1 ${pc3.cyan(version)}...`).start();
|
|
604
684
|
try {
|
|
605
|
-
const
|
|
606
|
-
const
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
if (tsconfig.extends && tsconfig.extends.includes("/versions/")) {
|
|
610
|
-
const parts = tsconfig.extends.split("/");
|
|
611
|
-
const vIdx = parts.indexOf("versions");
|
|
612
|
-
if (vIdx !== -1 && parts[vIdx + 1]) {
|
|
613
|
-
return parts[vIdx + 1];
|
|
614
|
-
}
|
|
615
|
-
}
|
|
685
|
+
const cliRoot = await getCliRoot();
|
|
686
|
+
const dependencies = {};
|
|
687
|
+
for (const pkg of this.RUNTIME_DEPS) {
|
|
688
|
+
dependencies[pkg] = DEPENDENCY_VERSIONS[pkg] || "latest";
|
|
616
689
|
}
|
|
690
|
+
for (const pkg of this.CORE_PACKAGES) {
|
|
691
|
+
dependencies[pkg] = pkg === "@chatbi-v/core" ? version : "latest";
|
|
692
|
+
}
|
|
693
|
+
const templateData = {
|
|
694
|
+
version,
|
|
695
|
+
dependencies,
|
|
696
|
+
devDependencies: DEPENDENCY_VERSIONS
|
|
697
|
+
};
|
|
698
|
+
await SandboxRenderer.renderDirectory(
|
|
699
|
+
path8.join(cliRoot, "templates/sandbox"),
|
|
700
|
+
versionPath,
|
|
701
|
+
templateData
|
|
702
|
+
);
|
|
703
|
+
spinner.text = pc3.gray(" \u{1F50D} \u68C0\u67E5\u672C\u5730\u5F00\u53D1\u73AF\u5883...");
|
|
704
|
+
const isLocalDev = await SandboxPkgManager.tryLinkLocalPackages(versionPath, this.CORE_PACKAGES, this.RUNTIME_DEPS);
|
|
705
|
+
const installArgs = isLocalDev ? ["install", "--no-frozen-lockfile"] : ["install"];
|
|
706
|
+
spinner.text = pc3.gray(` \u23F3 \u6267\u884C pnpm ${installArgs.join(" ")}...`);
|
|
707
|
+
await execa("pnpm", installArgs, { cwd: versionPath });
|
|
708
|
+
spinner.text = pc3.gray(" \u{1F3A8} \u540C\u6B65 Shell \u6A21\u677F...");
|
|
709
|
+
await this.ensureShell(version, force);
|
|
710
|
+
spinner.succeed(pc3.green(`\u5185\u6838\u6C99\u7BB1 ${version} \u521D\u59CB\u5316\u6210\u529F`));
|
|
617
711
|
} catch (e) {
|
|
712
|
+
spinner.fail(pc3.red(`\u5185\u6838\u6C99\u7BB1\u521D\u59CB\u5316\u5931\u8D25: ${e.message}`));
|
|
713
|
+
throw e;
|
|
714
|
+
}
|
|
715
|
+
return versionPath;
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* 确保 Shell 模板已同步到沙箱
|
|
719
|
+
*/
|
|
720
|
+
static async ensureShell(version, force = false) {
|
|
721
|
+
const versionPath = this.getVersionPath(version);
|
|
722
|
+
const shellDestDir = path8.join(versionPath, "shell");
|
|
723
|
+
if (!force && fs6.existsSync(path8.join(shellDestDir, "tsconfig.paths.json"))) {
|
|
724
|
+
return shellDestDir;
|
|
725
|
+
}
|
|
726
|
+
const cliRoot = await getCliRoot();
|
|
727
|
+
const shellTemplateDir = path8.join(cliRoot, "templates/app");
|
|
728
|
+
if (fs6.existsSync(shellTemplateDir)) {
|
|
729
|
+
await fs6.remove(shellDestDir);
|
|
730
|
+
const templateData = {
|
|
731
|
+
name: "chatbi-shell",
|
|
732
|
+
version,
|
|
733
|
+
cliVersion: version,
|
|
734
|
+
theme: DEFAULT_CONFIG.THEME,
|
|
735
|
+
isShell: true,
|
|
736
|
+
isBusiness: true,
|
|
737
|
+
tsconfigPath: "./tsconfig.paths.json"
|
|
738
|
+
};
|
|
739
|
+
await SandboxRenderer.renderDirectory(shellTemplateDir, shellDestDir, templateData);
|
|
740
|
+
await fs6.writeJson(path8.join(shellDestDir, "tsconfig.paths.json"), {
|
|
741
|
+
compilerOptions: { baseUrl: ".", paths: { "@/*": ["./src/*"] } }
|
|
742
|
+
}, { spaces: 2 });
|
|
618
743
|
}
|
|
619
|
-
return
|
|
744
|
+
return shellDestDir;
|
|
745
|
+
}
|
|
746
|
+
/** 注入项目虚拟上下文 */
|
|
747
|
+
static async injectContext(projectRoot, version) {
|
|
748
|
+
return SandboxContext.inject(projectRoot, version, this.CORE_PACKAGES, this.RUNTIME_DEPS);
|
|
749
|
+
}
|
|
750
|
+
/** 获取核心库的 Vite Alias 配置 */
|
|
751
|
+
static getCoreAlias(version) {
|
|
752
|
+
const versionPath = this.getVersionPath(version);
|
|
753
|
+
const sandboxNodeModules = path8.join(versionPath, "node_modules");
|
|
754
|
+
return Object.fromEntries(this.CORE_PACKAGES.map((pkg) => [pkg, path8.join(sandboxNodeModules, pkg)]));
|
|
755
|
+
}
|
|
756
|
+
/** 切换内核版本 */
|
|
757
|
+
static async useVersion(version) {
|
|
758
|
+
const versionRoot = this.getVersionRoot();
|
|
759
|
+
const currentLink = path8.join(versionRoot, SANDBOX_CONFIG.DIRS.CURRENT);
|
|
760
|
+
const targetPath = this.getVersionPath(version);
|
|
761
|
+
if (!fs6.existsSync(targetPath)) throw new Error(`\u7248\u672C ${version} \u4E0D\u5B58\u5728`);
|
|
762
|
+
if (fs6.existsSync(currentLink)) await fs6.remove(currentLink);
|
|
763
|
+
await fs6.ensureSymlink(targetPath, currentLink, "dir");
|
|
764
|
+
}
|
|
765
|
+
/** 解析版本号 */
|
|
766
|
+
static async resolveVersion(version) {
|
|
767
|
+
if (!version || version === "latest" || version === "current") {
|
|
768
|
+
const currentLink = path8.join(this.getVersionRoot(), SANDBOX_CONFIG.DIRS.CURRENT);
|
|
769
|
+
if (fs6.existsSync(currentLink)) {
|
|
770
|
+
return path8.basename(await fs6.readlink(currentLink));
|
|
771
|
+
}
|
|
772
|
+
const versions = await this.listVersions();
|
|
773
|
+
return versions[0] || "1.0.0";
|
|
774
|
+
}
|
|
775
|
+
return version;
|
|
776
|
+
}
|
|
777
|
+
/** 列出所有已安装版本 */
|
|
778
|
+
static async listVersions() {
|
|
779
|
+
const versionRoot = this.getVersionRoot();
|
|
780
|
+
if (!fs6.existsSync(versionRoot)) return [];
|
|
781
|
+
const dirs = await fs6.readdir(versionRoot);
|
|
782
|
+
return dirs.filter((d) => d !== SANDBOX_CONFIG.DIRS.CURRENT && !d.startsWith(".")).sort().reverse();
|
|
783
|
+
}
|
|
784
|
+
/** 可视化展示沙箱状态 */
|
|
785
|
+
static async visualizeStatus(cwd) {
|
|
786
|
+
const workspaceRoot = await this.getWorkspaceRoot(cwd);
|
|
787
|
+
const isMonorepo = workspaceRoot !== cwd;
|
|
788
|
+
const currentVersion = await this.resolveVersion("current");
|
|
789
|
+
const versions = await this.listVersions();
|
|
790
|
+
const statusInfo = [
|
|
791
|
+
`${pc3.bold("\u9879\u76EE\u8DEF\u5F84:")} ${pc3.cyan(cwd)}`,
|
|
792
|
+
`${pc3.bold("\u67B6\u6784\u6A21\u5F0F:")} ${isMonorepo ? pc3.yellow("Monorepo") : pc3.green("Standalone")}`,
|
|
793
|
+
`${pc3.bold("\u5F53\u524D\u5185\u6838:")} ${pc3.green(currentVersion)}`,
|
|
794
|
+
`${pc3.bold("\u5DF2\u88C5\u7248\u672C:")} ${pc3.gray(versions.join(", ") || "none")}`,
|
|
795
|
+
`${pc3.bold("\u6C99\u7BB1\u6839\u76EE\u5F55:")} ${pc3.gray(this.getRoot())}`
|
|
796
|
+
].join("\n");
|
|
797
|
+
printBox(statusInfo, "ChatBI Sandbox Status");
|
|
620
798
|
}
|
|
621
799
|
};
|
|
622
800
|
}
|
|
623
801
|
});
|
|
624
802
|
|
|
625
803
|
// src/config.ts
|
|
626
|
-
import
|
|
627
|
-
import
|
|
804
|
+
import fs7 from "fs-extra";
|
|
805
|
+
import path9 from "path";
|
|
628
806
|
import { createJiti } from "jiti";
|
|
629
807
|
var ConfigManager;
|
|
630
808
|
var init_config = __esm({
|
|
@@ -632,15 +810,11 @@ var init_config = __esm({
|
|
|
632
810
|
"use strict";
|
|
633
811
|
init_esm_shims();
|
|
634
812
|
init_utils();
|
|
813
|
+
init_constants();
|
|
814
|
+
init_utils();
|
|
635
815
|
ConfigManager = class {
|
|
636
816
|
static {
|
|
637
|
-
this.CONFIG_FILES =
|
|
638
|
-
"chatbi.config.ts",
|
|
639
|
-
"chatbi.config.js",
|
|
640
|
-
"chatbi.config.json",
|
|
641
|
-
".chatbirc",
|
|
642
|
-
".chatbirc.json"
|
|
643
|
-
];
|
|
817
|
+
this.CONFIG_FILES = DEFAULT_CONFIG.CONFIG_FILES;
|
|
644
818
|
}
|
|
645
819
|
/**
|
|
646
820
|
* 加载项目配置
|
|
@@ -648,10 +822,10 @@ var init_config = __esm({
|
|
|
648
822
|
*/
|
|
649
823
|
static async loadConfig(cwd = process.cwd()) {
|
|
650
824
|
const config = {};
|
|
651
|
-
const versionFilePath =
|
|
652
|
-
if (
|
|
825
|
+
const versionFilePath = path9.join(cwd, SANDBOX_CONFIG.LOCK_FILE);
|
|
826
|
+
if (fs7.existsSync(versionFilePath)) {
|
|
653
827
|
try {
|
|
654
|
-
const version = (await
|
|
828
|
+
const version = (await fs7.readFile(versionFilePath, "utf-8")).trim();
|
|
655
829
|
if (version) {
|
|
656
830
|
config.coreVersion = version;
|
|
657
831
|
}
|
|
@@ -660,15 +834,15 @@ var init_config = __esm({
|
|
|
660
834
|
}
|
|
661
835
|
const jiti = createJiti(cwd);
|
|
662
836
|
for (const file of this.CONFIG_FILES) {
|
|
663
|
-
const configPath =
|
|
664
|
-
if (
|
|
837
|
+
const configPath = path9.join(cwd, file);
|
|
838
|
+
if (fs7.existsSync(configPath)) {
|
|
665
839
|
try {
|
|
666
840
|
let projectConfig = {};
|
|
667
841
|
if (file.endsWith(".ts") || file.endsWith(".js")) {
|
|
668
842
|
const mod = await jiti.import(configPath, { default: true });
|
|
669
843
|
projectConfig = mod.default || mod || {};
|
|
670
844
|
} else if (file.endsWith(".json") || file.startsWith(".chatbirc")) {
|
|
671
|
-
projectConfig = await
|
|
845
|
+
projectConfig = await fs7.readJson(configPath);
|
|
672
846
|
}
|
|
673
847
|
return {
|
|
674
848
|
...projectConfig,
|
|
@@ -681,17 +855,78 @@ var init_config = __esm({
|
|
|
681
855
|
}
|
|
682
856
|
return config;
|
|
683
857
|
}
|
|
858
|
+
/**
|
|
859
|
+
* 解析核心依赖的具体路径或版本号
|
|
860
|
+
* @param config 项目配置
|
|
861
|
+
* @param relativeTo 相对路径(用于 local 模式下的 file: 协议生成)
|
|
862
|
+
*/
|
|
863
|
+
static async resolveCoreDependency(config, relativeTo = ".") {
|
|
864
|
+
const { coreSource = "local", coreVersion } = config;
|
|
865
|
+
if (coreSource === "npm") {
|
|
866
|
+
if (coreVersion) return coreVersion;
|
|
867
|
+
const cliRoot = await getCliRoot();
|
|
868
|
+
const cliPkg = await fs7.readJson(path9.join(cliRoot, "package.json"));
|
|
869
|
+
return cliPkg.version;
|
|
870
|
+
}
|
|
871
|
+
const sandboxCorePath = path9.join(SANDBOX_CONFIG.DIRS.CACHE, "core");
|
|
872
|
+
const cwd = process.cwd();
|
|
873
|
+
const absoluteRelativeTo = path9.isAbsolute(relativeTo) ? relativeTo : path9.resolve(cwd, relativeTo);
|
|
874
|
+
const absoluteProjectRoot = cwd;
|
|
875
|
+
const relativePath = path9.relative(absoluteRelativeTo, path9.join(absoluteProjectRoot, sandboxCorePath));
|
|
876
|
+
return `file:${relativePath}`;
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* 加载 tsup 配置
|
|
880
|
+
* @param cwd 项目根目录
|
|
881
|
+
*/
|
|
882
|
+
static async loadTsupConfig(cwd = process.cwd()) {
|
|
883
|
+
const TSUP_CONFIG_FILES = [
|
|
884
|
+
"tsup.config.ts",
|
|
885
|
+
"tsup.config.js",
|
|
886
|
+
"tsup.config.cjs",
|
|
887
|
+
"tsup.config.mjs",
|
|
888
|
+
"tsup.config.json"
|
|
889
|
+
];
|
|
890
|
+
const jiti = createJiti(cwd);
|
|
891
|
+
for (const file of TSUP_CONFIG_FILES) {
|
|
892
|
+
const configPath = path9.join(cwd, file);
|
|
893
|
+
if (fs7.existsSync(configPath)) {
|
|
894
|
+
try {
|
|
895
|
+
if (file.endsWith(".json")) {
|
|
896
|
+
return await fs7.readJson(configPath);
|
|
897
|
+
} else {
|
|
898
|
+
const mod = await jiti.import(configPath, { default: true });
|
|
899
|
+
return mod.default || mod || {};
|
|
900
|
+
}
|
|
901
|
+
} catch (e) {
|
|
902
|
+
logger.warn(`\u52A0\u8F7D tsup \u914D\u7F6E\u6587\u4EF6 ${file} \u5931\u8D25: ${e.message}`);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
const pkgPath = path9.join(cwd, "package.json");
|
|
907
|
+
if (fs7.existsSync(pkgPath)) {
|
|
908
|
+
try {
|
|
909
|
+
const pkg = await fs7.readJson(pkgPath);
|
|
910
|
+
if (pkg.tsup) {
|
|
911
|
+
return pkg.tsup;
|
|
912
|
+
}
|
|
913
|
+
} catch (e) {
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
return {};
|
|
917
|
+
}
|
|
684
918
|
};
|
|
685
919
|
}
|
|
686
920
|
});
|
|
687
921
|
|
|
688
922
|
// src/corekit.ts
|
|
689
|
-
import
|
|
690
|
-
import
|
|
691
|
-
import
|
|
923
|
+
import { createRequire as createRequire2 } from "module";
|
|
924
|
+
import path10 from "path";
|
|
925
|
+
import fs8 from "fs-extra";
|
|
926
|
+
import pc4 from "picocolors";
|
|
692
927
|
import prompts from "prompts";
|
|
693
|
-
import
|
|
694
|
-
var CoreKit;
|
|
928
|
+
import fg3 from "fast-glob";
|
|
929
|
+
var nativeRequire, CoreKit;
|
|
695
930
|
var init_corekit = __esm({
|
|
696
931
|
"src/corekit.ts"() {
|
|
697
932
|
"use strict";
|
|
@@ -699,25 +934,26 @@ var init_corekit = __esm({
|
|
|
699
934
|
init_utils();
|
|
700
935
|
init_sandbox();
|
|
701
936
|
init_config();
|
|
937
|
+
nativeRequire = createRequire2(import.meta.url);
|
|
702
938
|
CoreKit = class {
|
|
703
939
|
/**
|
|
704
940
|
* 解析项目模式
|
|
705
941
|
*/
|
|
706
942
|
static async detectMode(cwd) {
|
|
707
|
-
const pkgPath =
|
|
708
|
-
if (!
|
|
709
|
-
const pkg = await
|
|
710
|
-
if (pkg.workspaces ||
|
|
943
|
+
const pkgPath = path10.join(cwd, "package.json");
|
|
944
|
+
if (!fs8.existsSync(pkgPath)) return "app";
|
|
945
|
+
const pkg = await fs8.readJson(pkgPath);
|
|
946
|
+
if (pkg.workspaces || fs8.existsSync(path10.join(cwd, "pnpm-workspace.yaml"))) {
|
|
711
947
|
return "monorepo";
|
|
712
948
|
}
|
|
713
949
|
if (pkg.chatbi?.type === "plugin" || pkg.plugin === true) return "plugin";
|
|
714
950
|
if (pkg.chatbi?.type === "app") return "app";
|
|
715
|
-
const pluginEntries = await
|
|
951
|
+
const pluginEntries = await fg3(["index.plugin.{ts,js}", "src/index.plugin.{ts,js}"], { cwd });
|
|
716
952
|
if (pluginEntries.length > 0) return "plugin";
|
|
717
|
-
if (
|
|
953
|
+
if (fs8.existsSync(path10.join(cwd, "index.html"))) {
|
|
718
954
|
return "app";
|
|
719
955
|
}
|
|
720
|
-
if (
|
|
956
|
+
if (fs8.existsSync(path10.join(cwd, "src/index.ts")) || fs8.existsSync(path10.join(cwd, "src/index.tsx"))) {
|
|
721
957
|
if (pkg.bin) return "lib";
|
|
722
958
|
if (pkg.peerDependencies?.react && !pkg.dependencies?.react) return "plugin";
|
|
723
959
|
return "lib";
|
|
@@ -735,18 +971,18 @@ var init_corekit = __esm({
|
|
|
735
971
|
}
|
|
736
972
|
try {
|
|
737
973
|
const cliRoot = await getCliRoot();
|
|
738
|
-
const cliVersionFile =
|
|
739
|
-
if (
|
|
740
|
-
const version = (await
|
|
974
|
+
const cliVersionFile = path10.join(cliRoot, ".chatbi-version");
|
|
975
|
+
if (fs8.existsSync(cliVersionFile)) {
|
|
976
|
+
const version = (await fs8.readFile(cliVersionFile, "utf-8")).trim();
|
|
741
977
|
if (version) return version;
|
|
742
978
|
}
|
|
743
979
|
} catch (e) {
|
|
744
980
|
}
|
|
745
|
-
const currentLinkPath =
|
|
746
|
-
if (
|
|
981
|
+
const currentLinkPath = path10.join(Sandbox.getVersionRoot(), "current");
|
|
982
|
+
if (fs8.existsSync(currentLinkPath)) {
|
|
747
983
|
try {
|
|
748
|
-
const realPath = await
|
|
749
|
-
return
|
|
984
|
+
const realPath = await fs8.realpath(currentLinkPath);
|
|
985
|
+
return path10.basename(realPath);
|
|
750
986
|
} catch (e) {
|
|
751
987
|
}
|
|
752
988
|
}
|
|
@@ -758,8 +994,8 @@ var init_corekit = __esm({
|
|
|
758
994
|
*/
|
|
759
995
|
static async listVersions() {
|
|
760
996
|
const versionsDir = Sandbox.getVersionRoot();
|
|
761
|
-
if (!
|
|
762
|
-
const dirs = await
|
|
997
|
+
if (!fs8.existsSync(versionsDir)) return [];
|
|
998
|
+
const dirs = await fg3("*", {
|
|
763
999
|
cwd: versionsDir,
|
|
764
1000
|
onlyDirectories: true,
|
|
765
1001
|
deep: 1
|
|
@@ -770,18 +1006,18 @@ var init_corekit = __esm({
|
|
|
770
1006
|
* 自动发现项目中的插件
|
|
771
1007
|
*/
|
|
772
1008
|
static async discoverPlugins(rootDir) {
|
|
773
|
-
const pluginsDir =
|
|
774
|
-
if (!
|
|
775
|
-
const pkgFiles = await
|
|
1009
|
+
const pluginsDir = path10.join(rootDir, "plugins");
|
|
1010
|
+
if (!fs8.existsSync(pluginsDir)) return [];
|
|
1011
|
+
const pkgFiles = await fg3("*/package.json", { cwd: pluginsDir, absolute: true });
|
|
776
1012
|
const plugins = [];
|
|
777
1013
|
for (const pkgPath of pkgFiles) {
|
|
778
1014
|
try {
|
|
779
|
-
const pkg = await
|
|
780
|
-
const pluginPath =
|
|
1015
|
+
const pkg = await fs8.readJson(pkgPath);
|
|
1016
|
+
const pluginPath = path10.dirname(pkgPath);
|
|
781
1017
|
plugins.push({
|
|
782
|
-
name: pkg.name ||
|
|
1018
|
+
name: pkg.name || path10.basename(pluginPath),
|
|
783
1019
|
path: pluginPath,
|
|
784
|
-
id:
|
|
1020
|
+
id: path10.basename(pluginPath)
|
|
785
1021
|
});
|
|
786
1022
|
} catch (e) {
|
|
787
1023
|
}
|
|
@@ -795,19 +1031,19 @@ var init_corekit = __esm({
|
|
|
795
1031
|
const mode = await this.detectMode(cwd);
|
|
796
1032
|
const version = await this.resolveVersion(cwd);
|
|
797
1033
|
printBox(
|
|
798
|
-
`${
|
|
1034
|
+
`${pc4.cyan(pc4.bold("\u{1F680} ChatBI Dev Server"))}
|
|
799
1035
|
|
|
800
|
-
${
|
|
801
|
-
${
|
|
802
|
-
${
|
|
1036
|
+
${pc4.gray("Mode: ")} ${pc4.yellow(mode)}
|
|
1037
|
+
${pc4.gray("Kernel: ")} ${pc4.green(version)}
|
|
1038
|
+
${pc4.gray("Root: ")} ${pc4.white(cwd)}`,
|
|
803
1039
|
"Dev Server"
|
|
804
1040
|
);
|
|
805
1041
|
const spinner = createSpinner("\u6B63\u5728\u51C6\u5907\u6C99\u7BB1\u73AF\u5883...").start();
|
|
806
1042
|
try {
|
|
807
1043
|
await Sandbox.prepare(version);
|
|
808
|
-
spinner.text =
|
|
1044
|
+
spinner.text = pc4.cyan("\u6B63\u5728\u6CE8\u5165\u865A\u62DF\u4E0A\u4E0B\u6587...");
|
|
809
1045
|
await Sandbox.injectContext(cwd, version);
|
|
810
|
-
spinner.succeed(
|
|
1046
|
+
spinner.succeed(pc4.green("\u73AF\u5883\u5C31\u7EEA"));
|
|
811
1047
|
if (mode === "plugin") {
|
|
812
1048
|
await this.startPluginDevServer(cwd, version, options.port);
|
|
813
1049
|
} else if (mode === "app") {
|
|
@@ -816,22 +1052,22 @@ ${pc3.gray("Root: ")} ${pc3.white(cwd)}`,
|
|
|
816
1052
|
await this.startMonorepoDevServer(cwd, version, options.port);
|
|
817
1053
|
}
|
|
818
1054
|
} catch (e) {
|
|
819
|
-
spinner.fail(
|
|
1055
|
+
spinner.fail(pc4.red(`\u542F\u52A8\u5931\u8D25: ${e.message}`));
|
|
820
1056
|
}
|
|
821
1057
|
}
|
|
822
1058
|
/**
|
|
823
1059
|
* 启动 Monorepo 开发服务器
|
|
824
1060
|
*/
|
|
825
1061
|
static async startMonorepoDevServer(rootDir, version, customPort) {
|
|
826
|
-
const appsDir =
|
|
827
|
-
if (!
|
|
1062
|
+
const appsDir = path10.join(rootDir, "apps");
|
|
1063
|
+
if (!fs8.existsSync(appsDir)) {
|
|
828
1064
|
logger.warn("\u5F53\u524D Monorepo \u4E0B\u672A\u627E\u5230 apps/ \u76EE\u5F55");
|
|
829
1065
|
return;
|
|
830
1066
|
}
|
|
831
|
-
const pkgFiles = await
|
|
1067
|
+
const pkgFiles = await fg3("*/package.json", { cwd: appsDir, absolute: true });
|
|
832
1068
|
const apps = pkgFiles.map((pkgPath) => ({
|
|
833
|
-
name:
|
|
834
|
-
path:
|
|
1069
|
+
name: path10.basename(path10.dirname(pkgPath)),
|
|
1070
|
+
path: path10.dirname(pkgPath)
|
|
835
1071
|
}));
|
|
836
1072
|
if (apps.length === 0) {
|
|
837
1073
|
logger.warn("\u5F53\u524D Monorepo \u4E0B\u672A\u627E\u5230\u4EFB\u4F55\u5E94\u7528 (apps/)");
|
|
@@ -858,14 +1094,14 @@ ${pc3.gray("Root: ")} ${pc3.white(cwd)}`,
|
|
|
858
1094
|
const shellPort = customPort || 5173;
|
|
859
1095
|
const sandboxRoot = Sandbox.getRoot();
|
|
860
1096
|
const versionPath = Sandbox.getVersionPath(version);
|
|
861
|
-
const sandboxNodeModules =
|
|
1097
|
+
const sandboxNodeModules = path10.join(versionPath, "node_modules");
|
|
862
1098
|
const shellDir = await Sandbox.ensureShell(version);
|
|
863
1099
|
const coreAlias = Sandbox.getCoreAlias(version);
|
|
864
|
-
const tailwindPath =
|
|
865
|
-
const autoprefixerPath =
|
|
866
|
-
let pluginEntry =
|
|
867
|
-
if (!
|
|
868
|
-
pluginEntry =
|
|
1100
|
+
const tailwindPath = path10.join(sandboxNodeModules, "tailwindcss");
|
|
1101
|
+
const autoprefixerPath = path10.join(sandboxNodeModules, "autoprefixer");
|
|
1102
|
+
let pluginEntry = path10.join(pluginDir, "src/index.tsx");
|
|
1103
|
+
if (!fs8.existsSync(pluginEntry)) {
|
|
1104
|
+
pluginEntry = path10.join(pluginDir, "src/index.ts");
|
|
869
1105
|
}
|
|
870
1106
|
const define = {
|
|
871
1107
|
"process.env.CHATBI_PLUGIN_PATH": JSON.stringify(pluginDir)
|
|
@@ -878,41 +1114,49 @@ ${pc3.gray("Root: ")} ${pc3.white(cwd)}`,
|
|
|
878
1114
|
css: {
|
|
879
1115
|
postcss: {
|
|
880
1116
|
plugins: [
|
|
881
|
-
|
|
882
|
-
presets: [
|
|
1117
|
+
nativeRequire(tailwindPath)({
|
|
1118
|
+
presets: [nativeRequire(path10.join(sandboxNodeModules, "@chatbi-v/tailwind-config"))],
|
|
883
1119
|
darkMode: "class",
|
|
884
1120
|
content: [
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
1121
|
+
path10.join(shellDir, "index.html"),
|
|
1122
|
+
path10.join(shellDir, "src/**/*.{ts,tsx}"),
|
|
1123
|
+
path10.join(pluginDir, "src/**/*.{ts,tsx}")
|
|
888
1124
|
]
|
|
889
1125
|
}),
|
|
890
|
-
|
|
1126
|
+
nativeRequire(autoprefixerPath)
|
|
891
1127
|
]
|
|
892
1128
|
}
|
|
893
1129
|
},
|
|
894
1130
|
server: {
|
|
895
1131
|
port: shellPort,
|
|
896
1132
|
host: true,
|
|
1133
|
+
watch: {
|
|
1134
|
+
// 关键:排除沙箱和软链目录,防止 Vite 挂起
|
|
1135
|
+
ignored: [
|
|
1136
|
+
"**/.chatbi/**",
|
|
1137
|
+
"**/node_modules/**",
|
|
1138
|
+
Sandbox.getRoot()
|
|
1139
|
+
]
|
|
1140
|
+
},
|
|
897
1141
|
fs: {
|
|
898
1142
|
allow: [
|
|
899
1143
|
sandboxRoot,
|
|
900
1144
|
pluginDir,
|
|
901
|
-
|
|
1145
|
+
path10.resolve(pluginDir, "../../")
|
|
902
1146
|
]
|
|
903
1147
|
}
|
|
904
1148
|
},
|
|
905
1149
|
resolve: {
|
|
906
1150
|
alias: {
|
|
907
1151
|
...coreAlias,
|
|
908
|
-
"react":
|
|
909
|
-
"react-dom":
|
|
910
|
-
"@":
|
|
1152
|
+
"react": path10.join(sandboxNodeModules, "react"),
|
|
1153
|
+
"react-dom": path10.join(sandboxNodeModules, "react-dom"),
|
|
1154
|
+
"@": path10.join(shellDir, "src"),
|
|
911
1155
|
// 关键:将虚拟模块指向用户插件
|
|
912
1156
|
"virtual:user-plugin": pluginEntry,
|
|
913
1157
|
// 防止 glob 报错,提供空的映射
|
|
914
|
-
"@chatbi-plugins":
|
|
915
|
-
"@chatbi-apps":
|
|
1158
|
+
"@chatbi-plugins": path10.join(shellDir, "empty"),
|
|
1159
|
+
"@chatbi-apps": path10.join(shellDir, "empty")
|
|
916
1160
|
}
|
|
917
1161
|
},
|
|
918
1162
|
define
|
|
@@ -920,9 +1164,9 @@ ${pc3.gray("Root: ")} ${pc3.white(cwd)}`,
|
|
|
920
1164
|
await server.listen();
|
|
921
1165
|
const localUrl = `http://localhost:${shellPort}/`;
|
|
922
1166
|
printBox(
|
|
923
|
-
`${
|
|
1167
|
+
`${pc4.green(pc4.bold("\u2705 \u6258\u7BA1\u5F0F Shell \u5DF2\u542F\u52A8"))}
|
|
924
1168
|
|
|
925
|
-
${
|
|
1169
|
+
${pc4.white("Local: ")} ${pc4.cyan(pc4.underline(localUrl))}`,
|
|
926
1170
|
"Shell Success"
|
|
927
1171
|
);
|
|
928
1172
|
} catch (e) {
|
|
@@ -935,7 +1179,7 @@ ${pc3.white("Local: ")} ${pc3.cyan(pc3.underline(localUrl))}`,
|
|
|
935
1179
|
static async startAppDevServer(appDir, version, customPort) {
|
|
936
1180
|
logger.info("\u6B63\u5728\u542F\u52A8\u5E94\u7528...");
|
|
937
1181
|
const versionPath = Sandbox.getVersionPath(version);
|
|
938
|
-
const sandboxNodeModules =
|
|
1182
|
+
const sandboxNodeModules = path10.join(versionPath, "node_modules");
|
|
939
1183
|
const coreAlias = Sandbox.getCoreAlias(version);
|
|
940
1184
|
const { createServer, loadConfigFromFile } = await import("vite");
|
|
941
1185
|
try {
|
|
@@ -949,14 +1193,22 @@ ${pc3.white("Local: ")} ${pc3.cyan(pc3.underline(localUrl))}`,
|
|
|
949
1193
|
alias: {
|
|
950
1194
|
...coreAlias,
|
|
951
1195
|
// 补充常用的基础依赖映射,防止用户 vite.config.ts 中的插件找不到依赖
|
|
952
|
-
"react":
|
|
953
|
-
"react-dom":
|
|
954
|
-
"@vitejs/plugin-react":
|
|
1196
|
+
"react": path10.join(sandboxNodeModules, "react"),
|
|
1197
|
+
"react-dom": path10.join(sandboxNodeModules, "react-dom"),
|
|
1198
|
+
"@vitejs/plugin-react": path10.join(sandboxNodeModules, "@vitejs/plugin-react")
|
|
955
1199
|
}
|
|
956
1200
|
},
|
|
957
1201
|
server: {
|
|
958
1202
|
port: customPort || 3e3,
|
|
959
1203
|
host: true,
|
|
1204
|
+
watch: {
|
|
1205
|
+
// 关键:排除沙箱和软链目录,防止 Vite 挂起
|
|
1206
|
+
ignored: [
|
|
1207
|
+
"**/.chatbi/**",
|
|
1208
|
+
"**/node_modules/**",
|
|
1209
|
+
Sandbox.getRoot()
|
|
1210
|
+
]
|
|
1211
|
+
},
|
|
960
1212
|
fs: {
|
|
961
1213
|
allow: [
|
|
962
1214
|
Sandbox.getRoot(),
|
|
@@ -970,9 +1222,9 @@ ${pc3.white("Local: ")} ${pc3.cyan(pc3.underline(localUrl))}`,
|
|
|
970
1222
|
await server.listen();
|
|
971
1223
|
const localUrl = `http://localhost:${server.config.server.port}/`;
|
|
972
1224
|
printBox(
|
|
973
|
-
`${
|
|
1225
|
+
`${pc4.green(pc4.bold("\u2705 \u5E94\u7528\u5DF2\u6210\u529F\u542F\u52A8"))}
|
|
974
1226
|
|
|
975
|
-
${
|
|
1227
|
+
${pc4.white("Local: ")} ${pc4.cyan(pc4.underline(localUrl))}`,
|
|
976
1228
|
"App Success"
|
|
977
1229
|
);
|
|
978
1230
|
} catch (e) {
|
|
@@ -989,18 +1241,18 @@ __export(build_exports, {
|
|
|
989
1241
|
build: () => build
|
|
990
1242
|
});
|
|
991
1243
|
import { execa as execa2 } from "execa";
|
|
992
|
-
import
|
|
993
|
-
import
|
|
994
|
-
import
|
|
1244
|
+
import fs9 from "fs-extra";
|
|
1245
|
+
import path11 from "path";
|
|
1246
|
+
import pc5 from "picocolors";
|
|
995
1247
|
import { build as tsupBuild } from "tsup";
|
|
996
1248
|
async function build(options) {
|
|
997
1249
|
const cwd = process.cwd();
|
|
998
|
-
const pkgPath =
|
|
999
|
-
if (!
|
|
1250
|
+
const pkgPath = path11.join(cwd, "package.json");
|
|
1251
|
+
if (!fs9.existsSync(pkgPath)) {
|
|
1000
1252
|
logger.error(`\u5728 ${cwd} \u4E2D\u672A\u627E\u5230 package.json`);
|
|
1001
1253
|
return;
|
|
1002
1254
|
}
|
|
1003
|
-
const pkg = await
|
|
1255
|
+
const pkg = await fs9.readJson(pkgPath);
|
|
1004
1256
|
if (options.force) {
|
|
1005
1257
|
const spinnerClean = createSpinner("\u6B63\u5728\u6E05\u7406\u7F13\u5B58\u73AF\u5883...").start();
|
|
1006
1258
|
try {
|
|
@@ -1012,24 +1264,24 @@ async function build(options) {
|
|
|
1012
1264
|
}
|
|
1013
1265
|
}
|
|
1014
1266
|
const version = await CoreKit.resolveVersion(cwd);
|
|
1015
|
-
logger.info(`\u6B63\u5728\u6784\u5EFA\u9879\u76EE: ${
|
|
1267
|
+
logger.info(`\u6B63\u5728\u6784\u5EFA\u9879\u76EE: ${pc5.bold(pkg.name || "unnamed")} (\u5185\u6838\u7248\u672C: ${version})
|
|
1016
1268
|
`);
|
|
1017
1269
|
const spinner = createSpinner("\u6B63\u5728\u51C6\u5907\u6784\u5EFA\u73AF\u5883...").start();
|
|
1018
1270
|
spinner.text = "\u6B63\u5728\u540C\u6B65\u6C99\u7BB1\u5185\u6838...";
|
|
1019
1271
|
await Sandbox.prepare(version, options.force);
|
|
1020
|
-
if (pkg.workspaces ||
|
|
1272
|
+
if (pkg.workspaces || fs9.existsSync(path11.join(cwd, "pnpm-workspace.yaml"))) {
|
|
1021
1273
|
spinner.text = "\u68C0\u6D4B\u5230 Monorepo\uFF0C\u6B63\u5728\u521D\u59CB\u5316\u6839\u76EE\u5F55\u4E0A\u4E0B\u6587...";
|
|
1022
1274
|
await Sandbox.injectContext(cwd, version);
|
|
1023
1275
|
spinner.text = "\u6B63\u5728\u540C\u6B65\u5B50\u5305\u4E0A\u4E0B\u6587...";
|
|
1024
1276
|
const subDirs = ["apps", "plugins", "packages"];
|
|
1025
1277
|
for (const dir of subDirs) {
|
|
1026
|
-
const dirPath =
|
|
1027
|
-
if (
|
|
1028
|
-
const entries = await
|
|
1278
|
+
const dirPath = path11.join(cwd, dir);
|
|
1279
|
+
if (fs9.existsSync(dirPath)) {
|
|
1280
|
+
const entries = await fs9.readdir(dirPath, { withFileTypes: true });
|
|
1029
1281
|
for (const entry2 of entries) {
|
|
1030
1282
|
if (entry2.isDirectory()) {
|
|
1031
|
-
const subPkgPath =
|
|
1032
|
-
if (
|
|
1283
|
+
const subPkgPath = path11.join(dirPath, entry2.name);
|
|
1284
|
+
if (fs9.existsSync(path11.join(subPkgPath, "package.json"))) {
|
|
1033
1285
|
await Sandbox.injectContext(subPkgPath, version);
|
|
1034
1286
|
}
|
|
1035
1287
|
}
|
|
@@ -1043,7 +1295,7 @@ async function build(options) {
|
|
|
1043
1295
|
if (pkg.scripts && pkg.scripts.build && !process.env.CHATBI_CLI_INTERNAL) {
|
|
1044
1296
|
const buildScript = pkg.scripts.build;
|
|
1045
1297
|
if (!buildScript.includes("chatbi-cli build") && !buildScript.includes("chatbi build")) {
|
|
1046
|
-
logger.info(`\u68C0\u6D4B\u5230\u81EA\u5B9A\u4E49 build \u811A\u672C\uFF0C\u6B63\u5728\u6267\u884C: ${
|
|
1298
|
+
logger.info(`\u68C0\u6D4B\u5230\u81EA\u5B9A\u4E49 build \u811A\u672C\uFF0C\u6B63\u5728\u6267\u884C: ${pc5.cyan("npm run build")}`);
|
|
1047
1299
|
const args = ["run", "build"];
|
|
1048
1300
|
if (options.watch) {
|
|
1049
1301
|
args.push("--", "--watch");
|
|
@@ -1067,7 +1319,7 @@ async function build(options) {
|
|
|
1067
1319
|
const coreAlias = Sandbox.getCoreAlias(version);
|
|
1068
1320
|
await viteBuild({
|
|
1069
1321
|
root: cwd,
|
|
1070
|
-
configFile:
|
|
1322
|
+
configFile: fs9.existsSync(path11.join(cwd, "vite.config.ts")) ? void 0 : false,
|
|
1071
1323
|
resolve: {
|
|
1072
1324
|
alias: {
|
|
1073
1325
|
...coreAlias
|
|
@@ -1091,45 +1343,32 @@ async function build(options) {
|
|
|
1091
1343
|
});
|
|
1092
1344
|
if (!options.watch) {
|
|
1093
1345
|
printBox(
|
|
1094
|
-
|
|
1346
|
+
pc5.green(pc5.bold("\u2728 \u5E94\u7528\u6784\u5EFA\u6210\u529F!")) + "\n\n" + pc5.white("\u4EA7\u7269\u76EE\u5F55: ") + pc5.cyan("dist"),
|
|
1095
1347
|
"Build Success"
|
|
1096
1348
|
);
|
|
1097
1349
|
}
|
|
1098
1350
|
return;
|
|
1099
1351
|
}
|
|
1100
1352
|
let entry = ["src/index.ts"];
|
|
1101
|
-
if (
|
|
1353
|
+
if (fs9.existsSync(path11.join(cwd, "src/index.tsx"))) {
|
|
1102
1354
|
entry = ["src/index.tsx"];
|
|
1103
|
-
} else if (!
|
|
1355
|
+
} else if (!fs9.existsSync(path11.join(cwd, "src/index.ts"))) {
|
|
1104
1356
|
logger.error("\u672A\u627E\u5230\u5165\u53E3\u6587\u4EF6\u3002\u671F\u671B src/index.ts \u6216 src/index.tsx");
|
|
1105
1357
|
return;
|
|
1106
1358
|
}
|
|
1107
1359
|
const isPlugin = mode === "plugin";
|
|
1360
|
+
const userConfig = await ConfigManager.loadTsupConfig(cwd);
|
|
1361
|
+
if (Object.keys(userConfig).length > 0) {
|
|
1362
|
+
logger.info(`\u5DF2\u52A0\u8F7D\u672C\u5730\u6784\u5EFA\u914D\u7F6E`);
|
|
1363
|
+
}
|
|
1108
1364
|
if (!options.watch) {
|
|
1109
|
-
await
|
|
1110
|
-
const tsbuildinfo =
|
|
1111
|
-
if (
|
|
1112
|
-
await
|
|
1365
|
+
await fs9.remove(path11.join(cwd, "dist"));
|
|
1366
|
+
const tsbuildinfo = path11.join(cwd, "tsconfig.tsbuildinfo");
|
|
1367
|
+
if (fs9.existsSync(tsbuildinfo)) {
|
|
1368
|
+
await fs9.remove(tsbuildinfo);
|
|
1113
1369
|
}
|
|
1114
1370
|
}
|
|
1115
|
-
const external = [
|
|
1116
|
-
"react",
|
|
1117
|
-
"react-dom",
|
|
1118
|
-
"react/jsx-runtime",
|
|
1119
|
-
"react-is",
|
|
1120
|
-
"antd",
|
|
1121
|
-
"@ant-design/icons",
|
|
1122
|
-
"@ant-design/x",
|
|
1123
|
-
...Object.keys(pkg.dependencies || {}),
|
|
1124
|
-
...Object.keys(pkg.peerDependencies || {})
|
|
1125
|
-
];
|
|
1126
1371
|
if (isPlugin) {
|
|
1127
|
-
const coreDeps = Sandbox.CORE_PACKAGES;
|
|
1128
|
-
coreDeps.forEach((dep) => {
|
|
1129
|
-
if (!external.includes(dep)) {
|
|
1130
|
-
external.push(dep);
|
|
1131
|
-
}
|
|
1132
|
-
});
|
|
1133
1372
|
}
|
|
1134
1373
|
const commonConfig = {
|
|
1135
1374
|
entry,
|
|
@@ -1138,16 +1377,32 @@ async function build(options) {
|
|
|
1138
1377
|
sourcemap: false,
|
|
1139
1378
|
target: "esnext",
|
|
1140
1379
|
platform: isPlugin ? "browser" : "node",
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1380
|
+
...userConfig,
|
|
1381
|
+
// 合并用户配置
|
|
1382
|
+
external: [
|
|
1383
|
+
.../* @__PURE__ */ new Set([
|
|
1384
|
+
"react",
|
|
1385
|
+
"react-dom",
|
|
1386
|
+
"react/jsx-runtime",
|
|
1387
|
+
"react-is",
|
|
1388
|
+
"antd",
|
|
1389
|
+
"@ant-design/icons",
|
|
1390
|
+
"@ant-design/x",
|
|
1391
|
+
...Object.keys(pkg.dependencies || {}),
|
|
1392
|
+
...Object.keys(pkg.peerDependencies || {}),
|
|
1393
|
+
...isPlugin ? Sandbox.CORE_PACKAGES : [],
|
|
1394
|
+
...Array.isArray(userConfig.external) ? userConfig.external : []
|
|
1395
|
+
])
|
|
1396
|
+
],
|
|
1397
|
+
minify: userConfig.minify !== void 0 ? userConfig.minify : !options.watch,
|
|
1398
|
+
// 优先使用用户配置
|
|
1144
1399
|
watch: options.watch,
|
|
1145
1400
|
silent: true,
|
|
1146
|
-
esbuildOptions(
|
|
1147
|
-
|
|
1401
|
+
esbuildOptions(esbuildOpts) {
|
|
1402
|
+
esbuildOpts.logOverride = {
|
|
1148
1403
|
"empty-import-meta": "silent"
|
|
1149
1404
|
};
|
|
1150
|
-
|
|
1405
|
+
esbuildOpts.external = esbuildOpts.external || [];
|
|
1151
1406
|
const forceExternal = [
|
|
1152
1407
|
"react",
|
|
1153
1408
|
"react-dom",
|
|
@@ -1157,10 +1412,13 @@ async function build(options) {
|
|
|
1157
1412
|
...Sandbox.CORE_PACKAGES
|
|
1158
1413
|
];
|
|
1159
1414
|
forceExternal.forEach((dep) => {
|
|
1160
|
-
if (!
|
|
1161
|
-
|
|
1415
|
+
if (!esbuildOpts.external.includes(dep)) {
|
|
1416
|
+
esbuildOpts.external.push(dep);
|
|
1162
1417
|
}
|
|
1163
1418
|
});
|
|
1419
|
+
if (typeof userConfig.esbuildOptions === "function") {
|
|
1420
|
+
userConfig.esbuildOptions(esbuildOpts);
|
|
1421
|
+
}
|
|
1164
1422
|
}
|
|
1165
1423
|
};
|
|
1166
1424
|
const buildSpinner = createSpinner("\u6B63\u5728\u7F16\u8BD1\u6E90\u7801...").start();
|
|
@@ -1181,25 +1439,7 @@ async function build(options) {
|
|
|
1181
1439
|
define: {
|
|
1182
1440
|
"import.meta.env": "process.env"
|
|
1183
1441
|
},
|
|
1184
|
-
esbuildOptions
|
|
1185
|
-
options2.logOverride = {
|
|
1186
|
-
"empty-import-meta": "silent"
|
|
1187
|
-
};
|
|
1188
|
-
options2.external = options2.external || [];
|
|
1189
|
-
const forceExternal = [
|
|
1190
|
-
"react",
|
|
1191
|
-
"react-dom",
|
|
1192
|
-
"antd",
|
|
1193
|
-
"@ant-design/icons",
|
|
1194
|
-
"@ant-design/x",
|
|
1195
|
-
...Sandbox.CORE_PACKAGES
|
|
1196
|
-
];
|
|
1197
|
-
forceExternal.forEach((dep) => {
|
|
1198
|
-
if (!options2.external.includes(dep)) {
|
|
1199
|
-
options2.external.push(dep);
|
|
1200
|
-
}
|
|
1201
|
-
});
|
|
1202
|
-
}
|
|
1442
|
+
esbuildOptions: commonConfig.esbuildOptions
|
|
1203
1443
|
});
|
|
1204
1444
|
} else {
|
|
1205
1445
|
buildSpinner.text = "\u6B63\u5728\u7F16\u8BD1\u6E90\u7801...";
|
|
@@ -1215,15 +1455,15 @@ async function build(options) {
|
|
|
1215
1455
|
if (!options.watch) {
|
|
1216
1456
|
const dtsSpinner = createSpinner("\u6B63\u5728\u751F\u6210\u7C7B\u578B\u5B9A\u4E49...").start();
|
|
1217
1457
|
try {
|
|
1218
|
-
const localTsc =
|
|
1219
|
-
const sandboxTsc =
|
|
1458
|
+
const localTsc = path11.join(cwd, "node_modules/.bin/tsc");
|
|
1459
|
+
const sandboxTsc = path11.join(Sandbox.getVersionPath(version), "node_modules/.bin/tsc");
|
|
1220
1460
|
let tscBin = "tsc";
|
|
1221
|
-
if (
|
|
1461
|
+
if (fs9.existsSync(localTsc)) {
|
|
1222
1462
|
tscBin = localTsc;
|
|
1223
|
-
} else if (
|
|
1463
|
+
} else if (fs9.existsSync(sandboxTsc)) {
|
|
1224
1464
|
tscBin = sandboxTsc;
|
|
1225
1465
|
} else {
|
|
1226
|
-
if (
|
|
1466
|
+
if (fs9.existsSync(path11.join(cwd, "pnpm-lock.yaml"))) {
|
|
1227
1467
|
await execa2("pnpm", ["exec", "tsc", "--build", "tsconfig.json"]);
|
|
1228
1468
|
dtsSpinner.succeed("\u7C7B\u578B\u5B9A\u4E49\u751F\u6210\u5B8C\u6210");
|
|
1229
1469
|
} else {
|
|
@@ -1239,7 +1479,7 @@ async function build(options) {
|
|
|
1239
1479
|
dtsSpinner.warn("\u7C7B\u578B\u751F\u6210\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u9879\u76EE\u4E2D\u7684 tsconfig.json \u914D\u7F6E");
|
|
1240
1480
|
}
|
|
1241
1481
|
printBox(
|
|
1242
|
-
|
|
1482
|
+
pc5.green(pc5.bold("\u2728 \u6784\u5EFA\u5B8C\u6210!")) + "\n\n" + pc5.white("\u4EA7\u7269\u76EE\u5F55: ") + pc5.cyan("dist") + "\n" + pc5.white("\u6784\u5EFA\u6A21\u5F0F: ") + pc5.cyan(isPlugin ? "Plugin" : "Library"),
|
|
1243
1483
|
"Build Success"
|
|
1244
1484
|
);
|
|
1245
1485
|
}
|
|
@@ -1250,6 +1490,7 @@ var init_build = __esm({
|
|
|
1250
1490
|
init_esm_shims();
|
|
1251
1491
|
init_sandbox();
|
|
1252
1492
|
init_corekit();
|
|
1493
|
+
init_config();
|
|
1253
1494
|
init_utils();
|
|
1254
1495
|
}
|
|
1255
1496
|
});
|
|
@@ -1259,17 +1500,17 @@ var sync_exports = {};
|
|
|
1259
1500
|
__export(sync_exports, {
|
|
1260
1501
|
sync: () => sync
|
|
1261
1502
|
});
|
|
1262
|
-
import
|
|
1263
|
-
import
|
|
1264
|
-
import
|
|
1503
|
+
import fs10 from "fs-extra";
|
|
1504
|
+
import path12 from "path";
|
|
1505
|
+
import pc6 from "picocolors";
|
|
1265
1506
|
async function sync(options = {}) {
|
|
1266
1507
|
const cwd = options.cwd || process.cwd();
|
|
1267
|
-
const pkgPath =
|
|
1268
|
-
if (!
|
|
1508
|
+
const pkgPath = path12.join(cwd, "package.json");
|
|
1509
|
+
if (!fs10.existsSync(pkgPath)) {
|
|
1269
1510
|
logger.error("\u672A\u627E\u5230 package.json\u3002\u8BF7\u5728\u9879\u76EE\u6839\u76EE\u5F55\u4E0B\u8FD0\u884C\u3002");
|
|
1270
1511
|
return;
|
|
1271
1512
|
}
|
|
1272
|
-
const pkg = await
|
|
1513
|
+
const pkg = await fs10.readJson(pkgPath);
|
|
1273
1514
|
let version = options.version;
|
|
1274
1515
|
if (!version) {
|
|
1275
1516
|
version = await CoreKit.resolveVersion(cwd);
|
|
@@ -1284,8 +1525,8 @@ async function sync(options = {}) {
|
|
|
1284
1525
|
await Sandbox.prepare(version, options.force);
|
|
1285
1526
|
mainSpinner.text = "\u6B63\u5728\u751F\u6210\u865A\u62DF\u4E0A\u4E0B\u6587...";
|
|
1286
1527
|
if (options.version) {
|
|
1287
|
-
const versionFilePath =
|
|
1288
|
-
await
|
|
1528
|
+
const versionFilePath = path12.join(cwd, ".chatbi-version");
|
|
1529
|
+
await fs10.writeFile(versionFilePath, version, "utf-8");
|
|
1289
1530
|
}
|
|
1290
1531
|
await Sandbox.injectContext(cwd, version);
|
|
1291
1532
|
let modified = false;
|
|
@@ -1307,19 +1548,19 @@ async function sync(options = {}) {
|
|
|
1307
1548
|
if (modified) {
|
|
1308
1549
|
pkg.dependencies = deps;
|
|
1309
1550
|
pkg.devDependencies = devDeps;
|
|
1310
|
-
await
|
|
1551
|
+
await fs10.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
1311
1552
|
mainSpinner.succeed("\u5185\u6838\u540C\u6B65\u5B8C\u6210 (\u4F9D\u8D56\u5DF2\u4F18\u5316)");
|
|
1312
1553
|
} else {
|
|
1313
1554
|
mainSpinner.succeed("\u5185\u6838\u540C\u6B65\u5B8C\u6210");
|
|
1314
1555
|
}
|
|
1315
1556
|
if (!options.silent) {
|
|
1316
1557
|
printBox(
|
|
1317
|
-
`${
|
|
1558
|
+
`${pc6.green(pc6.bold("\u2728 \u5185\u6838\u540C\u6B65\u6210\u529F!"))}
|
|
1318
1559
|
|
|
1319
|
-
${
|
|
1320
|
-
${
|
|
1560
|
+
${pc6.white("\u5F53\u524D\u7248\u672C: ")} ${pc6.cyan(version)}
|
|
1561
|
+
${pc6.white("\u6C99\u7BB1\u8DEF\u5F84: ")} ${pc6.gray(Sandbox.getVersionPath(version))}
|
|
1321
1562
|
|
|
1322
|
-
${
|
|
1563
|
+
${pc6.white("\u63D0\u793A: ")} \u9879\u76EE\u73B0\u5728\u901A\u8FC7\u865A\u62DF\u522B\u540D\u5F15\u7528\u6838\u5FC3\u5305\uFF0C\u65E0\u9700\u663E\u5F0F\u5B89\u88C5\u4F9D\u8D56\u3002`,
|
|
1323
1564
|
"Sync Success"
|
|
1324
1565
|
);
|
|
1325
1566
|
}
|
|
@@ -1339,13 +1580,12 @@ var init_exports = {};
|
|
|
1339
1580
|
__export(init_exports, {
|
|
1340
1581
|
init: () => init
|
|
1341
1582
|
});
|
|
1342
|
-
import
|
|
1343
|
-
import
|
|
1344
|
-
import
|
|
1345
|
-
import Handlebars2 from "handlebars";
|
|
1583
|
+
import fs11 from "fs-extra";
|
|
1584
|
+
import path13 from "path";
|
|
1585
|
+
import pc7 from "picocolors";
|
|
1346
1586
|
import prompts2 from "prompts";
|
|
1347
1587
|
async function init(options) {
|
|
1348
|
-
let { name,
|
|
1588
|
+
let { name, pluginType = "business", theme = DEFAULT_CONFIG.THEME, projectType, includeApp, includePlugin, cwd } = options;
|
|
1349
1589
|
const response = await prompts2([
|
|
1350
1590
|
// ... (prompts remain the same)
|
|
1351
1591
|
{
|
|
@@ -1415,32 +1655,33 @@ async function init(options) {
|
|
|
1415
1655
|
const finalIncludePlugin = includePlugin !== void 0 ? includePlugin : response.includePlugin !== void 0 ? response.includePlugin : true;
|
|
1416
1656
|
const isAppIncluded = finalIncludeApp;
|
|
1417
1657
|
const isPluginIncluded = finalIncludePlugin;
|
|
1418
|
-
const rootDir = process.cwd();
|
|
1419
|
-
const targetDir =
|
|
1420
|
-
if (
|
|
1658
|
+
const rootDir = cwd || process.cwd();
|
|
1659
|
+
const targetDir = path13.resolve(rootDir, name);
|
|
1660
|
+
if (fs11.existsSync(targetDir)) {
|
|
1421
1661
|
logger.error(`\u76EE\u5F55 ${name} \u5DF2\u5B58\u5728\u3002`);
|
|
1422
1662
|
return;
|
|
1423
1663
|
}
|
|
1424
|
-
logger.info(`\u6B63\u5728\u521D\u59CB\u5316\u9879\u76EE: ${
|
|
1425
|
-
logger.info(
|
|
1664
|
+
logger.info(`\u6B63\u5728\u521D\u59CB\u5316\u9879\u76EE: ${pc7.bold(name)}...`);
|
|
1665
|
+
logger.info(pc7.gray(`\u7C7B\u578B: ${projectType} | \u4E3B\u9898: ${theme || "N/A"}`));
|
|
1426
1666
|
console.log("");
|
|
1427
1667
|
try {
|
|
1428
1668
|
const myCliRoot = await getCliRoot();
|
|
1429
|
-
const cliPkg = await
|
|
1669
|
+
const cliPkg = await fs11.readJson(path13.join(myCliRoot, "package.json"));
|
|
1430
1670
|
const cliVersion = cliPkg.version;
|
|
1431
|
-
|
|
1432
|
-
const kernelVersionFile =
|
|
1433
|
-
if (
|
|
1434
|
-
|
|
1671
|
+
const config = { coreSource: "npm" };
|
|
1672
|
+
const kernelVersionFile = path13.join(myCliRoot, SANDBOX_CONFIG.LOCK_FILE);
|
|
1673
|
+
if (fs11.existsSync(kernelVersionFile)) {
|
|
1674
|
+
config.coreVersion = (await fs11.readFile(kernelVersionFile, "utf-8")).trim();
|
|
1435
1675
|
}
|
|
1676
|
+
const kernelVersion = await ConfigManager.resolveCoreDependency(config);
|
|
1436
1677
|
const renderTemplate = async (templateName, destDir, extraData = {}) => {
|
|
1437
|
-
const srcDir =
|
|
1438
|
-
if (!
|
|
1678
|
+
const srcDir = path13.join(myCliRoot, "templates", templateName);
|
|
1679
|
+
if (!fs11.existsSync(srcDir)) {
|
|
1439
1680
|
throw new Error(`\u627E\u4E0D\u5230\u6A21\u677F: ${templateName}\uFF0C\u8BF7\u68C0\u67E5\u8DEF\u5F84 ${srcDir} \u662F\u5426\u6B63\u786E\u3002`);
|
|
1440
1681
|
}
|
|
1441
|
-
await
|
|
1682
|
+
await fs11.ensureDir(destDir);
|
|
1442
1683
|
const templateData = {
|
|
1443
|
-
name:
|
|
1684
|
+
name: path13.basename(destDir),
|
|
1444
1685
|
projectName: name,
|
|
1445
1686
|
// Original project name from CLI argument
|
|
1446
1687
|
projectTitle: name.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" "),
|
|
@@ -1457,45 +1698,10 @@ async function init(options) {
|
|
|
1457
1698
|
isApp: projectType === "app" || isAppIncluded,
|
|
1458
1699
|
// Zero Dependency Mode: No explicit core path needed in package.json
|
|
1459
1700
|
// tsconfig extends the virtual paths config
|
|
1460
|
-
tsconfigPath: projectType === "monorepo" ?
|
|
1701
|
+
tsconfigPath: projectType === "monorepo" ? `../../${SANDBOX_CONFIG.DIRS.CACHE}/tsconfig.json` : `./${SANDBOX_CONFIG.DIRS.CACHE}/tsconfig.json`,
|
|
1461
1702
|
...extraData
|
|
1462
1703
|
};
|
|
1463
|
-
|
|
1464
|
-
const files = await fs7.readdir(currentSrc);
|
|
1465
|
-
for (const file of files) {
|
|
1466
|
-
if (file === ".DS_Store") continue;
|
|
1467
|
-
const srcPath = path8.join(currentSrc, file);
|
|
1468
|
-
const stats = await fs7.stat(srcPath);
|
|
1469
|
-
if (stats.isDirectory()) {
|
|
1470
|
-
const destPath = path8.join(currentDest, file);
|
|
1471
|
-
await fs7.ensureDir(destPath);
|
|
1472
|
-
await processFiles(srcPath, destPath);
|
|
1473
|
-
} else if (file.endsWith(".hbs")) {
|
|
1474
|
-
const content = await fs7.readFile(srcPath, "utf-8");
|
|
1475
|
-
let result = content;
|
|
1476
|
-
const hasHandlebarsVars = content.includes("{{");
|
|
1477
|
-
if (hasHandlebarsVars) {
|
|
1478
|
-
try {
|
|
1479
|
-
const safeContent = content.replace(/\{\{(?!\s*([#/]?(?:if|else|each|with|unless|name|version|projectName|projectTitle|projectVersion|cliVersion|tsconfigPath|theme|isNebula|isGlass|isBusiness|isApp|isShell|pluginName|pluginPackageName|pluginVersion|pluginDisplayName|pluginDescription|pluginClassName|pluginPath|pluginFolderName|pluginType|pluginId|className))\b)/g, "\\{{");
|
|
1480
|
-
const templateFn = Handlebars2.compile(safeContent);
|
|
1481
|
-
result = templateFn(templateData);
|
|
1482
|
-
} catch (e) {
|
|
1483
|
-
result = content;
|
|
1484
|
-
for (const [key, val] of Object.entries(templateData)) {
|
|
1485
|
-
const regex = new RegExp(`\\{\\{\\s*${key}\\s*\\}\\}`, "g");
|
|
1486
|
-
result = result.replace(regex, String(val));
|
|
1487
|
-
}
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
const destPath = path8.join(currentDest, file.replace(/\.hbs$/, ""));
|
|
1491
|
-
await fs7.outputFile(destPath, result);
|
|
1492
|
-
} else {
|
|
1493
|
-
const destPath = path8.join(currentDest, file);
|
|
1494
|
-
await fs7.copy(srcPath, destPath);
|
|
1495
|
-
}
|
|
1496
|
-
}
|
|
1497
|
-
};
|
|
1498
|
-
await processFiles(srcDir, destDir);
|
|
1704
|
+
await SandboxRenderer.renderDirectory(srcDir, destDir, templateData);
|
|
1499
1705
|
};
|
|
1500
1706
|
const spinner = createSpinner("\u6B63\u5728\u751F\u6210\u9879\u76EE\u7ED3\u6784...").start();
|
|
1501
1707
|
if (projectType === "monorepo") {
|
|
@@ -1503,12 +1709,12 @@ async function init(options) {
|
|
|
1503
1709
|
await renderTemplate("monorepo", targetDir, { name });
|
|
1504
1710
|
if (isAppIncluded) {
|
|
1505
1711
|
spinner.text = "\u6B63\u5728\u751F\u6210 Host App...";
|
|
1506
|
-
const appDir =
|
|
1712
|
+
const appDir = path13.join(targetDir, "apps", "main");
|
|
1507
1713
|
await renderTemplate("app", appDir, { name: "@chatbi-v/main" });
|
|
1508
1714
|
}
|
|
1509
1715
|
if (isPluginIncluded) {
|
|
1510
1716
|
spinner.text = "\u6B63\u5728\u751F\u6210 Demo Plugin...";
|
|
1511
|
-
const pluginDir =
|
|
1717
|
+
const pluginDir = path13.join(targetDir, "plugins", "plugin-demo");
|
|
1512
1718
|
await renderTemplate("plugin", pluginDir, {
|
|
1513
1719
|
name: "@chatbi-v/plugin-demo",
|
|
1514
1720
|
pluginId: "demo",
|
|
@@ -1550,15 +1756,15 @@ async function init(options) {
|
|
|
1550
1756
|
const cliConfig = {
|
|
1551
1757
|
coreVersion: kernelVersion
|
|
1552
1758
|
};
|
|
1553
|
-
await
|
|
1759
|
+
await fs11.writeJson(path13.join(targetDir, "chatbi.config.json"), cliConfig, { spaces: 2 });
|
|
1554
1760
|
configSpinner.succeed("\u9879\u76EE\u914D\u7F6E\u751F\u6210\u5B8C\u6210");
|
|
1555
1761
|
printBox(
|
|
1556
|
-
`${
|
|
1762
|
+
`${pc7.green(pc7.bold("\u2728 \u9879\u76EE\u5DF2\u6210\u529F\u521B\u5EFA!"))}
|
|
1557
1763
|
|
|
1558
|
-
${
|
|
1559
|
-
${
|
|
1560
|
-
${
|
|
1561
|
-
${
|
|
1764
|
+
${pc7.white("\u63A5\u4E0B\u6765\u4F60\u53EF\u4EE5:")}
|
|
1765
|
+
${pc7.cyan(` cd ${name}`)}
|
|
1766
|
+
${pc7.cyan(" pnpm install")}
|
|
1767
|
+
${pc7.cyan(" pnpm dev")}`,
|
|
1562
1768
|
"Success"
|
|
1563
1769
|
);
|
|
1564
1770
|
} catch (error) {
|
|
@@ -1572,6 +1778,9 @@ var init_init = __esm({
|
|
|
1572
1778
|
init_esm_shims();
|
|
1573
1779
|
init_utils();
|
|
1574
1780
|
init_sync();
|
|
1781
|
+
init_constants();
|
|
1782
|
+
init_config();
|
|
1783
|
+
init_SandboxRenderer();
|
|
1575
1784
|
}
|
|
1576
1785
|
});
|
|
1577
1786
|
|
|
@@ -1580,34 +1789,34 @@ var fetch_exports = {};
|
|
|
1580
1789
|
__export(fetch_exports, {
|
|
1581
1790
|
fetch: () => fetch
|
|
1582
1791
|
});
|
|
1583
|
-
import
|
|
1584
|
-
import
|
|
1792
|
+
import path18 from "path";
|
|
1793
|
+
import pc13 from "picocolors";
|
|
1585
1794
|
import { execa as execa4 } from "execa";
|
|
1586
1795
|
async function fetch(version, options = {}) {
|
|
1587
|
-
const fetchSpinner = createSpinner(`\u6B63\u5728\u83B7\u53D6\u5185\u6838\u7248\u672C ${
|
|
1796
|
+
const fetchSpinner = createSpinner(`\u6B63\u5728\u83B7\u53D6\u5185\u6838\u7248\u672C ${pc13.cyan(version)}...`).start();
|
|
1588
1797
|
const versionPath = await Sandbox.prepare(version, true);
|
|
1589
|
-
fetchSpinner.succeed(`\u5185\u6838\u7248\u672C ${
|
|
1798
|
+
fetchSpinner.succeed(`\u5185\u6838\u7248\u672C ${pc13.cyan(version)} \u83B7\u53D6\u6210\u529F`);
|
|
1590
1799
|
if (options.pack) {
|
|
1591
1800
|
const packSpinner = createSpinner("\u6B63\u5728\u6253\u5305\u79BB\u7EBF\u8D44\u6E90...").start();
|
|
1592
1801
|
const tgzName = `chatbi-core-${version}.tgz`;
|
|
1593
|
-
const tgzPath =
|
|
1802
|
+
const tgzPath = path18.resolve(process.cwd(), tgzName);
|
|
1594
1803
|
await execa4("tar", [
|
|
1595
1804
|
"-czf",
|
|
1596
1805
|
tgzPath,
|
|
1597
1806
|
"-C",
|
|
1598
|
-
|
|
1599
|
-
|
|
1807
|
+
path18.dirname(versionPath),
|
|
1808
|
+
path18.basename(versionPath)
|
|
1600
1809
|
]);
|
|
1601
1810
|
packSpinner.succeed("\u79BB\u7EBF\u8D44\u6E90\u6253\u5305\u5B8C\u6210");
|
|
1602
1811
|
printBox(
|
|
1603
|
-
`${
|
|
1812
|
+
`${pc13.green(pc13.bold("\u2728 \u79BB\u7EBF\u5305\u5DF2\u751F\u6210!"))}
|
|
1604
1813
|
|
|
1605
|
-
${
|
|
1606
|
-
${
|
|
1814
|
+
${pc13.white("\u6587\u4EF6\u8DEF\u5F84: ")} ${pc13.cyan(tgzPath)}
|
|
1815
|
+
${pc13.white("\u5B89\u88C5\u547D\u4EE4: ")} ${pc13.gray(`chatbi install ${tgzName}`)}`,
|
|
1607
1816
|
"Pack Success"
|
|
1608
1817
|
);
|
|
1609
1818
|
} else {
|
|
1610
|
-
logger.success(`\u5185\u6838\u7248\u672C ${
|
|
1819
|
+
logger.success(`\u5185\u6838\u7248\u672C ${pc13.cyan(version)} \u5DF2\u51C6\u5907\u5C31\u7EEA\u3002`);
|
|
1611
1820
|
}
|
|
1612
1821
|
}
|
|
1613
1822
|
var init_fetch = __esm({
|
|
@@ -1624,24 +1833,24 @@ var bench_exports = {};
|
|
|
1624
1833
|
__export(bench_exports, {
|
|
1625
1834
|
bench: () => bench
|
|
1626
1835
|
});
|
|
1627
|
-
import
|
|
1628
|
-
import
|
|
1629
|
-
import
|
|
1836
|
+
import pc15 from "picocolors";
|
|
1837
|
+
import fs17 from "fs-extra";
|
|
1838
|
+
import path20 from "path";
|
|
1630
1839
|
import os2 from "os";
|
|
1631
1840
|
async function bench() {
|
|
1632
1841
|
logger.info("\u6B63\u5728\u542F\u52A8 CLI \u6027\u80FD\u57FA\u51C6\u6D4B\u8BD5...");
|
|
1633
1842
|
const results = [];
|
|
1634
|
-
const tmpDir =
|
|
1635
|
-
await
|
|
1843
|
+
const tmpDir = path20.join(os2.tmpdir(), `chatbi-bench-${Date.now()}`);
|
|
1844
|
+
await fs17.ensureDir(tmpDir);
|
|
1636
1845
|
try {
|
|
1637
1846
|
const initSpinner = createSpinner("\u6B63\u5728\u6D4B\u8BD5: \u521D\u59CB\u5316\u63D2\u4EF6\u9879\u76EE (init)...").start();
|
|
1638
1847
|
const startInit = Date.now();
|
|
1639
1848
|
const { init: init2 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
|
1640
|
-
const testProjDir =
|
|
1849
|
+
const testProjDir = path20.join(tmpDir, "bench-proj");
|
|
1641
1850
|
await init2({ name: "bench-proj", projectType: "plugin", cwd: tmpDir });
|
|
1642
1851
|
const endInit = Date.now();
|
|
1643
1852
|
const initTime = (endInit - startInit) / 1e3;
|
|
1644
|
-
initSpinner.succeed(`\u521D\u59CB\u5316\u5B8C\u6210: ${
|
|
1853
|
+
initSpinner.succeed(`\u521D\u59CB\u5316\u5B8C\u6210: ${pc15.cyan(initTime.toFixed(2) + "s")}`);
|
|
1645
1854
|
results.push({
|
|
1646
1855
|
scene: "\u521D\u59CB\u5316\u63D2\u4EF6\u9879\u76EE (init)",
|
|
1647
1856
|
target: "\u2264 5.0 s",
|
|
@@ -1653,7 +1862,7 @@ async function bench() {
|
|
|
1653
1862
|
await sync2({ cwd: testProjDir });
|
|
1654
1863
|
const endSync = Date.now();
|
|
1655
1864
|
const syncTime = (endSync - startSync) / 1e3;
|
|
1656
|
-
syncSpinner.succeed(`\u540C\u6B65\u5B8C\u6210: ${
|
|
1865
|
+
syncSpinner.succeed(`\u540C\u6B65\u5B8C\u6210: ${pc15.cyan(syncTime.toFixed(2) + "s")}`);
|
|
1657
1866
|
results.push({
|
|
1658
1867
|
scene: "\u6C99\u7BB1\u73AF\u5883\u540C\u6B65 (sync)",
|
|
1659
1868
|
target: "\u2264 2.0 s",
|
|
@@ -1668,20 +1877,20 @@ async function bench() {
|
|
|
1668
1877
|
process.chdir(originalCwd);
|
|
1669
1878
|
const endBuild = Date.now();
|
|
1670
1879
|
const buildTime = (endBuild - startBuild) / 1e3;
|
|
1671
|
-
buildSpinner.succeed(`\u6784\u5EFA\u5B8C\u6210: ${
|
|
1880
|
+
buildSpinner.succeed(`\u6784\u5EFA\u5B8C\u6210: ${pc15.cyan(buildTime.toFixed(2) + "s")}`);
|
|
1672
1881
|
results.push({
|
|
1673
1882
|
scene: "\u63D2\u4EF6\u9879\u76EE\u6784\u5EFA (build)",
|
|
1674
1883
|
target: "\u2264 10.0 s",
|
|
1675
1884
|
actual: `${buildTime.toFixed(2)} s`
|
|
1676
1885
|
});
|
|
1677
1886
|
printBox(
|
|
1678
|
-
`${
|
|
1887
|
+
`${pc15.green(pc15.bold("\u2728 \u57FA\u51C6\u6D4B\u8BD5\u5B8C\u6210!"))}
|
|
1679
1888
|
|
|
1680
|
-
` + results.map((r) => `${
|
|
1889
|
+
` + results.map((r) => `${pc15.white(r.scene.padEnd(20))}: ${pc15.cyan(r.actual)} (\u76EE\u6807 ${r.target})`).join("\n"),
|
|
1681
1890
|
"Benchmark Results"
|
|
1682
1891
|
);
|
|
1683
1892
|
} finally {
|
|
1684
|
-
await
|
|
1893
|
+
await fs17.remove(tmpDir);
|
|
1685
1894
|
}
|
|
1686
1895
|
}
|
|
1687
1896
|
var init_bench = __esm({
|
|
@@ -1696,7 +1905,7 @@ var init_bench = __esm({
|
|
|
1696
1905
|
init_esm_shims();
|
|
1697
1906
|
init_build();
|
|
1698
1907
|
import cac from "cac";
|
|
1699
|
-
import
|
|
1908
|
+
import pc16 from "picocolors";
|
|
1700
1909
|
import figlet from "figlet";
|
|
1701
1910
|
import gradient from "gradient-string";
|
|
1702
1911
|
import boxen2 from "boxen";
|
|
@@ -1716,20 +1925,26 @@ init_init();
|
|
|
1716
1925
|
init_esm_shims();
|
|
1717
1926
|
init_utils();
|
|
1718
1927
|
init_config();
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
import
|
|
1928
|
+
init_constants();
|
|
1929
|
+
init_SandboxRenderer();
|
|
1930
|
+
import fs12 from "fs-extra";
|
|
1931
|
+
import path14 from "path";
|
|
1932
|
+
import pc8 from "picocolors";
|
|
1722
1933
|
import prompts3 from "prompts";
|
|
1723
|
-
import
|
|
1934
|
+
import { createRequire as createRequire3 } from "module";
|
|
1935
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
1936
|
+
var _require2 = createRequire3(import.meta.url);
|
|
1937
|
+
var _filename2 = fileURLToPath3(import.meta.url);
|
|
1938
|
+
var _dirname2 = path14.dirname(_filename2);
|
|
1724
1939
|
async function add(options) {
|
|
1725
1940
|
let { name, type, displayName, description } = options;
|
|
1726
1941
|
const cwd = process.cwd();
|
|
1727
|
-
const pkgPath =
|
|
1728
|
-
if (!
|
|
1942
|
+
const pkgPath = path14.join(cwd, "package.json");
|
|
1943
|
+
if (!fs12.existsSync(pkgPath)) {
|
|
1729
1944
|
logger.error("\u672A\u627E\u5230 package.json\u3002\u8BF7\u5728 ChatBI-V \u9879\u76EE\u6839\u76EE\u5F55\u4E0B\u8FD0\u884C\u6B64\u547D\u4EE4\u3002");
|
|
1730
1945
|
return;
|
|
1731
1946
|
}
|
|
1732
|
-
const pkg = await
|
|
1947
|
+
const pkg = await fs12.readJson(pkgPath);
|
|
1733
1948
|
const isMonorepo = pkg.workspaces && (pkg.workspaces.includes("plugins/*") || pkg.workspaces.packages?.includes("plugins/*"));
|
|
1734
1949
|
if (!isMonorepo) {
|
|
1735
1950
|
logger.error("\u5F53\u524D\u4E0D\u662F Monorepo \u9879\u76EE\uFF0C\u65E0\u6CD5\u6DFB\u52A0\u63D2\u4EF6 (\u8BF7\u5728\u5305\u542B plugins/ \u5DE5\u4F5C\u7A7A\u95F4\u7684\u9879\u76EE\u4E2D\u8FD0\u884C)");
|
|
@@ -1780,31 +1995,22 @@ async function add(options) {
|
|
|
1780
1995
|
cleanName = cleanName.replace(/-plugin$/, "");
|
|
1781
1996
|
}
|
|
1782
1997
|
const folderName = cleanName.startsWith("plugin-") ? cleanName : `plugin-${cleanName}`;
|
|
1783
|
-
const pluginDir =
|
|
1784
|
-
if (
|
|
1998
|
+
const pluginDir = path14.resolve(cwd, "plugins", folderName);
|
|
1999
|
+
if (fs12.existsSync(pluginDir)) {
|
|
1785
2000
|
logger.error(`\u63D2\u4EF6\u76EE\u5F55 ${folderName} \u5DF2\u5B58\u5728\u3002`);
|
|
1786
2001
|
return;
|
|
1787
2002
|
}
|
|
1788
|
-
const spinner = createSpinner(`\u6B63\u5728\u6DFB\u52A0\u65B0\u63D2\u4EF6: ${
|
|
2003
|
+
const spinner = createSpinner(`\u6B63\u5728\u6DFB\u52A0\u65B0\u63D2\u4EF6: ${pc8.bold(name)}...`).start();
|
|
1789
2004
|
const myCliRoot = await getCliRoot();
|
|
1790
|
-
const templateDir =
|
|
1791
|
-
if (!
|
|
2005
|
+
const templateDir = path14.join(myCliRoot, "templates/plugin");
|
|
2006
|
+
if (!fs12.existsSync(templateDir)) {
|
|
1792
2007
|
spinner.fail("\u627E\u4E0D\u5230\u63D2\u4EF6\u6A21\u677F");
|
|
1793
2008
|
throw new Error(`\u627E\u4E0D\u5230\u63D2\u4EF6\u6A21\u677F: ${templateDir}`);
|
|
1794
2009
|
}
|
|
1795
2010
|
const targetDir = pluginDir;
|
|
1796
2011
|
spinner.text = "\u6B63\u5728\u52A0\u8F7D\u914D\u7F6E...";
|
|
1797
2012
|
const config = await ConfigManager.loadConfig(cwd);
|
|
1798
|
-
const
|
|
1799
|
-
let corePath = "file:../../.chatbi/core";
|
|
1800
|
-
if (coreSource === "npm") {
|
|
1801
|
-
if (!config.coreVersion) {
|
|
1802
|
-
const cliPkg = await fs8.readJson(path9.join(myCliRoot, "package.json"));
|
|
1803
|
-
corePath = cliPkg.version;
|
|
1804
|
-
} else {
|
|
1805
|
-
corePath = config.coreVersion;
|
|
1806
|
-
}
|
|
1807
|
-
}
|
|
2013
|
+
const corePath = await ConfigManager.resolveCoreDependency(config, pluginDir);
|
|
1808
2014
|
const data = {
|
|
1809
2015
|
// 兼容旧模板
|
|
1810
2016
|
name: `@chatbi-v/${folderName}`,
|
|
@@ -1823,55 +2029,20 @@ async function add(options) {
|
|
|
1823
2029
|
pluginPath: folderName,
|
|
1824
2030
|
pluginFolderName: folderName,
|
|
1825
2031
|
// Fix: 注入 tsconfigPath,确保 tsconfig.json 能正确 extend
|
|
1826
|
-
tsconfigPath:
|
|
1827
|
-
};
|
|
1828
|
-
const renderFile = async (src, dest) => {
|
|
1829
|
-
const content = await fs8.readFile(src, "utf-8");
|
|
1830
|
-
let result = content;
|
|
1831
|
-
const hasHandlebarsVars = content.includes("{{");
|
|
1832
|
-
if (hasHandlebarsVars) {
|
|
1833
|
-
try {
|
|
1834
|
-
const safeContent = content.replace(/\{\{(?!\s*([#/]?(?:if|else|each|with|unless|name|version|projectName|projectTitle|projectVersion|cliVersion|tsconfigPath|theme|isNebula|isGlass|isBusiness|isApp|isShell|pluginName|pluginPackageName|pluginVersion|pluginDisplayName|pluginDescription|pluginClassName|pluginPath|pluginFolderName|pluginType|pluginId|className))\b)/g, "\\{{");
|
|
1835
|
-
const templateFn = Handlebars3.compile(safeContent);
|
|
1836
|
-
result = templateFn(data);
|
|
1837
|
-
} catch (e) {
|
|
1838
|
-
result = content;
|
|
1839
|
-
for (const [key, val] of Object.entries(data)) {
|
|
1840
|
-
const regex = new RegExp(`\\{\\{\\s*${key}\\s*\\}\\}`, "g");
|
|
1841
|
-
result = result.replace(regex, String(val));
|
|
1842
|
-
}
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
1845
|
-
await fs8.outputFile(dest.replace(".hbs", ""), result);
|
|
1846
|
-
};
|
|
1847
|
-
const processTemplates = async (currentSrc, currentDest) => {
|
|
1848
|
-
const files = await fs8.readdir(currentSrc);
|
|
1849
|
-
for (const file of files) {
|
|
1850
|
-
const srcPath = path9.join(currentSrc, file);
|
|
1851
|
-
const destPath = path9.join(currentDest, file);
|
|
1852
|
-
const stats = await fs8.stat(srcPath);
|
|
1853
|
-
if (stats.isDirectory()) {
|
|
1854
|
-
await fs8.ensureDir(destPath);
|
|
1855
|
-
await processTemplates(srcPath, destPath);
|
|
1856
|
-
} else if (file.endsWith(".hbs")) {
|
|
1857
|
-
await renderFile(srcPath, destPath);
|
|
1858
|
-
} else {
|
|
1859
|
-
await fs8.copy(srcPath, destPath);
|
|
1860
|
-
}
|
|
1861
|
-
}
|
|
2032
|
+
tsconfigPath: `../../${SANDBOX_CONFIG.DIRS.CACHE}/tsconfig.json`
|
|
1862
2033
|
};
|
|
1863
2034
|
spinner.text = "\u6B63\u5728\u751F\u6210\u63D2\u4EF6\u6587\u4EF6...";
|
|
1864
|
-
await
|
|
1865
|
-
spinner.succeed(`\u63D2\u4EF6 ${
|
|
2035
|
+
await SandboxRenderer.renderDirectory(templateDir, targetDir, data);
|
|
2036
|
+
spinner.succeed(`\u63D2\u4EF6 ${pc8.bold(name)} \u6DFB\u52A0\u6210\u529F\uFF01`);
|
|
1866
2037
|
printBox(
|
|
1867
|
-
`${
|
|
2038
|
+
`${pc8.green(pc8.bold("\u2728 \u63D2\u4EF6\u521B\u5EFA\u6210\u529F!"))}
|
|
1868
2039
|
|
|
1869
|
-
${
|
|
1870
|
-
${
|
|
1871
|
-
${
|
|
2040
|
+
${pc8.white("\u9879\u76EE\u8DEF\u5F84: ")} ${pc8.cyan(`plugins/${folderName}`)}
|
|
2041
|
+
${pc8.white("\u63D2\u4EF6 ID: ")} ${pc8.cyan(cleanName)}
|
|
2042
|
+
${pc8.white("\u63D2\u4EF6\u7C7B\u578B: ")} ${pc8.cyan(type)}
|
|
1872
2043
|
|
|
1873
|
-
${
|
|
1874
|
-
${
|
|
2044
|
+
${pc8.white("\u63A5\u4E0B\u6765\u4F60\u53EF\u4EE5:")}
|
|
2045
|
+
${pc8.cyan(" pnpm dev")} \u542F\u52A8\u5F00\u53D1\u73AF\u5883\u67E5\u770B\u6548\u679C`,
|
|
1875
2046
|
"Plugin Created"
|
|
1876
2047
|
);
|
|
1877
2048
|
}
|
|
@@ -1879,16 +2050,16 @@ ${pc7.cyan(" pnpm dev")} \u542F\u52A8\u5F00\u53D1\u73AF\u5883\u67E5\u770B\u654
|
|
|
1879
2050
|
// src/commands/gl.ts
|
|
1880
2051
|
init_esm_shims();
|
|
1881
2052
|
init_utils();
|
|
1882
|
-
import
|
|
1883
|
-
import
|
|
1884
|
-
import
|
|
2053
|
+
import fs13 from "fs-extra";
|
|
2054
|
+
import path15 from "path";
|
|
2055
|
+
import pc9 from "picocolors";
|
|
1885
2056
|
import prompts4 from "prompts";
|
|
1886
2057
|
import { execa as execa3 } from "execa";
|
|
1887
2058
|
async function gl(options) {
|
|
1888
2059
|
const { type: initialType, prompt: initialPrompt } = options;
|
|
1889
2060
|
const cwd = process.cwd();
|
|
1890
|
-
const pkgPath =
|
|
1891
|
-
if (!
|
|
2061
|
+
const pkgPath = path15.join(cwd, "package.json");
|
|
2062
|
+
if (!fs13.existsSync(pkgPath)) {
|
|
1892
2063
|
logger.error("\u672A\u627E\u5230 package.json\u3002\u8BF7\u5728 ChatBI-V \u9879\u76EE\u6839\u76EE\u5F55\u4E0B\u8FD0\u884C\u6B64\u547D\u4EE4\u3002");
|
|
1893
2064
|
return;
|
|
1894
2065
|
}
|
|
@@ -1927,7 +2098,7 @@ async function gl(options) {
|
|
|
1927
2098
|
logger.error("\u9700\u6C42\u63CF\u8FF0\u4E0D\u80FD\u4E3A\u7A7A\u3002");
|
|
1928
2099
|
return;
|
|
1929
2100
|
}
|
|
1930
|
-
logger.info(`\u6B63\u5728\u547C\u53EB AI \u5F15\u64CE [\u6A21\u5F0F: ${
|
|
2101
|
+
logger.info(`\u6B63\u5728\u547C\u53EB AI \u5F15\u64CE [\u6A21\u5F0F: ${pc9.bold(genType)}]...`);
|
|
1931
2102
|
const toolsContext = `
|
|
1932
2103
|
[Available Tools & Capabilities]
|
|
1933
2104
|
- Tool: plugin -> For creating new feature modules. Requires: name, type (business|system).
|
|
@@ -1990,7 +2161,7 @@ If not, use the SLOT_REQUIRED format.`.trim();
|
|
|
1990
2161
|
}
|
|
1991
2162
|
}
|
|
1992
2163
|
if (slots.length > 0) {
|
|
1993
|
-
logger.info(
|
|
2164
|
+
logger.info(pc9.yellow("\n\u{1F4DD} AI \u9700\u8981\u66F4\u591A\u4FE1\u606F\u4EE5\u7EE7\u7EED:"));
|
|
1994
2165
|
const answers = await prompts4(slots, {
|
|
1995
2166
|
onCancel: () => process.exit(0)
|
|
1996
2167
|
});
|
|
@@ -2012,7 +2183,7 @@ Please proceed with generation based on these answers.`;
|
|
|
2012
2183
|
spinner.stop();
|
|
2013
2184
|
if (error.code === "ENOENT") {
|
|
2014
2185
|
logger.error("\u672A\u5728\u7CFB\u7EDF\u4E2D\u627E\u5230 `gemini-cli` \u547D\u4EE4\u3002");
|
|
2015
|
-
logger.info(
|
|
2186
|
+
logger.info(pc9.yellow("\u8BF7\u786E\u4FDD\u5DF2\u5B89\u88C5 gemini-cli \u5E76\u5C06\u5176\u6DFB\u52A0\u5230\u7CFB\u7EDF PATH \u4E2D\u3002"));
|
|
2016
2187
|
} else {
|
|
2017
2188
|
logger.error(`AI \u751F\u6210\u8FC7\u7A0B\u4E2D\u51FA\u9519: ${error.message}`);
|
|
2018
2189
|
}
|
|
@@ -2029,16 +2200,16 @@ init_esm_shims();
|
|
|
2029
2200
|
init_utils();
|
|
2030
2201
|
init_sandbox();
|
|
2031
2202
|
init_corekit();
|
|
2032
|
-
import
|
|
2033
|
-
import
|
|
2034
|
-
import
|
|
2203
|
+
import fs14 from "fs-extra";
|
|
2204
|
+
import path16 from "path";
|
|
2205
|
+
import pc10 from "picocolors";
|
|
2035
2206
|
import glob from "fast-glob";
|
|
2036
2207
|
async function doctor(options = {}) {
|
|
2037
2208
|
logger.info("\u6B63\u5728\u8BCA\u65AD\u9879\u76EE\u5065\u5EB7\u72B6\u51B5...\n");
|
|
2038
2209
|
const cwd = process.cwd();
|
|
2039
2210
|
let hasIssues = false;
|
|
2040
2211
|
const issues = [];
|
|
2041
|
-
logger.info(
|
|
2212
|
+
logger.info(pc10.bold("Step 1: \u68C0\u67E5\u57FA\u7840\u73AF\u5883..."));
|
|
2042
2213
|
const nodeVersion = process.version;
|
|
2043
2214
|
if (parseInt(nodeVersion.slice(1).split(".")[0]) < 18) {
|
|
2044
2215
|
logger.error(`Node.js \u7248\u672C\u592A\u4F4E: ${nodeVersion} (\u8981\u6C42 >=18)`);
|
|
@@ -2054,41 +2225,41 @@ async function doctor(options = {}) {
|
|
|
2054
2225
|
} catch (e) {
|
|
2055
2226
|
logger.warn("\u672A\u68C0\u6D4B\u5230 pnpm\uFF0C\u5EFA\u8BAE\u5B89\u88C5\u4EE5\u83B7\u5F97\u6700\u4F73\u4F53\u9A8C");
|
|
2056
2227
|
}
|
|
2057
|
-
logger.info(
|
|
2228
|
+
logger.info(pc10.bold("\nStep 2: \u68C0\u67E5\u5185\u6838\u6C99\u7BB1\u73AF\u5883..."));
|
|
2058
2229
|
const version = await CoreKit.resolveVersion(cwd);
|
|
2059
2230
|
const versionPath = Sandbox.getVersionPath(version);
|
|
2060
|
-
if (!
|
|
2231
|
+
if (!fs14.existsSync(versionPath)) {
|
|
2061
2232
|
logger.error(`\u5185\u6838\u6C99\u7BB1\u7248\u672C ${version} \u5C1A\u672A\u5B89\u88C5`);
|
|
2062
|
-
console.log(
|
|
2233
|
+
console.log(pc10.gray(` \u5EFA\u8BAE\u8FD0\u884C 'chatbi sync' \u6216 'chatbi use ${version}' \u8FDB\u884C\u5B89\u88C5\u3002`));
|
|
2063
2234
|
hasIssues = true;
|
|
2064
2235
|
issues.push(`\u5185\u6838\u6C99\u7BB1\u672A\u5B89\u88C5 (${version})`);
|
|
2065
2236
|
} else {
|
|
2066
2237
|
logger.success(`\u5185\u6838\u6C99\u7BB1\u5C31\u7EEA (\u7248\u672C: ${version})`);
|
|
2067
|
-
const sandboxNm =
|
|
2068
|
-
if (!
|
|
2238
|
+
const sandboxNm = path16.join(versionPath, "node_modules");
|
|
2239
|
+
if (!fs14.existsSync(sandboxNm)) {
|
|
2069
2240
|
logger.warn("\u6C99\u7BB1\u4F9D\u8D56\u672A\u5B89\u88C5\uFF0C\u5C06\u5BFC\u81F4\u6784\u5EFA\u5931\u8D25");
|
|
2070
2241
|
hasIssues = true;
|
|
2071
2242
|
issues.push("\u6C99\u7BB1\u4F9D\u8D56\u7F3A\u5931");
|
|
2072
2243
|
}
|
|
2073
2244
|
const missingDeps = [];
|
|
2074
2245
|
for (const dep of Sandbox.CORE_PACKAGES) {
|
|
2075
|
-
if (!
|
|
2246
|
+
if (!fs14.existsSync(path16.join(sandboxNm, dep))) {
|
|
2076
2247
|
missingDeps.push(dep);
|
|
2077
2248
|
}
|
|
2078
2249
|
}
|
|
2079
2250
|
if (missingDeps.length > 0) {
|
|
2080
2251
|
}
|
|
2081
2252
|
}
|
|
2082
|
-
logger.info(
|
|
2083
|
-
const chatbiDir =
|
|
2084
|
-
if (!
|
|
2253
|
+
logger.info(pc10.bold("\nStep 3: \u68C0\u67E5\u865A\u62DF\u4F9D\u8D56\u6620\u5C04..."));
|
|
2254
|
+
const chatbiDir = path16.join(cwd, ".chatbi");
|
|
2255
|
+
if (!fs14.existsSync(chatbiDir)) {
|
|
2085
2256
|
logger.warn("\u672A\u53D1\u73B0\u865A\u62DF\u4F9D\u8D56\u914D\u7F6E (.chatbi \u76EE\u5F55)");
|
|
2086
2257
|
hasIssues = true;
|
|
2087
2258
|
issues.push("\u7F3A\u5931 .chatbi \u76EE\u5F55");
|
|
2088
2259
|
} else {
|
|
2089
|
-
const pathsJson =
|
|
2090
|
-
const aliasJson =
|
|
2091
|
-
if (!
|
|
2260
|
+
const pathsJson = path16.join(chatbiDir, "tsconfig.paths.json");
|
|
2261
|
+
const aliasJson = path16.join(chatbiDir, "vite.alias.json");
|
|
2262
|
+
if (!fs14.existsSync(pathsJson) || !fs14.existsSync(aliasJson)) {
|
|
2092
2263
|
logger.warn("\u865A\u62DF\u4F9D\u8D56\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B8C\u6574");
|
|
2093
2264
|
hasIssues = true;
|
|
2094
2265
|
issues.push("\u865A\u62DF\u4F9D\u8D56\u914D\u7F6E\u4E0D\u5B8C\u6574");
|
|
@@ -2096,10 +2267,10 @@ async function doctor(options = {}) {
|
|
|
2096
2267
|
logger.success("\u865A\u62DF\u4F9D\u8D56\u914D\u7F6E\u5DF2\u751F\u6210");
|
|
2097
2268
|
}
|
|
2098
2269
|
}
|
|
2099
|
-
const tsConfigPath =
|
|
2100
|
-
if (
|
|
2270
|
+
const tsConfigPath = path16.join(cwd, "tsconfig.json");
|
|
2271
|
+
if (fs14.existsSync(tsConfigPath)) {
|
|
2101
2272
|
try {
|
|
2102
|
-
const tsConfig = await
|
|
2273
|
+
const tsConfig = await fs14.readJson(tsConfigPath);
|
|
2103
2274
|
const extendsPath = tsConfig.extends;
|
|
2104
2275
|
const expectedPaths = ["./.chatbi/tsconfig.paths.json", ".chatbi/tsconfig.paths.json"];
|
|
2105
2276
|
let hasExtend = false;
|
|
@@ -2119,14 +2290,14 @@ async function doctor(options = {}) {
|
|
|
2119
2290
|
logger.error("\u89E3\u6790 tsconfig.json \u5931\u8D25");
|
|
2120
2291
|
}
|
|
2121
2292
|
}
|
|
2122
|
-
const viteConfigPath =
|
|
2123
|
-
if (
|
|
2124
|
-
const content = await
|
|
2293
|
+
const viteConfigPath = path16.join(cwd, "vite.config.ts");
|
|
2294
|
+
if (fs14.existsSync(viteConfigPath)) {
|
|
2295
|
+
const content = await fs14.readFile(viteConfigPath, "utf-8");
|
|
2125
2296
|
if (!content.includes("vite.alias.json")) {
|
|
2126
2297
|
logger.warn("vite.config.ts \u53EF\u80FD\u672A\u52A0\u8F7D\u865A\u62DF\u522B\u540D\u914D\u7F6E");
|
|
2127
2298
|
}
|
|
2128
2299
|
}
|
|
2129
|
-
logger.info(
|
|
2300
|
+
logger.info(pc10.bold("\nStep 4: \u626B\u63CF\u4EE3\u7801\u89C4\u5219..."));
|
|
2130
2301
|
const rules = [
|
|
2131
2302
|
{
|
|
2132
2303
|
id: "plugin-lifecycle-init",
|
|
@@ -2146,7 +2317,7 @@ async function doctor(options = {}) {
|
|
|
2146
2317
|
if (files.length > 0) {
|
|
2147
2318
|
const scanSpinner = createSpinner(`\u6B63\u5728\u626B\u63CF ${files.length} \u4E2A\u6587\u4EF6...`).start();
|
|
2148
2319
|
for (const file of files) {
|
|
2149
|
-
const content = await
|
|
2320
|
+
const content = await fs14.readFile(file, "utf-8");
|
|
2150
2321
|
for (const rule of rules) {
|
|
2151
2322
|
if (rule.pattern.test(content)) {
|
|
2152
2323
|
codeIssues.push({
|
|
@@ -2162,7 +2333,7 @@ async function doctor(options = {}) {
|
|
|
2162
2333
|
scanSpinner.fail(`\u53D1\u73B0 ${codeIssues.length} \u4E2A\u4EE3\u7801\u89C4\u8303\u95EE\u9898`);
|
|
2163
2334
|
hasIssues = true;
|
|
2164
2335
|
codeIssues.forEach((issue) => {
|
|
2165
|
-
const relativePath =
|
|
2336
|
+
const relativePath = path16.relative(cwd, issue.file);
|
|
2166
2337
|
issues.push(`\u4EE3\u7801\u89C4\u8303 [${issue.ruleId}]: ${relativePath}`);
|
|
2167
2338
|
});
|
|
2168
2339
|
} else {
|
|
@@ -2171,26 +2342,26 @@ async function doctor(options = {}) {
|
|
|
2171
2342
|
}
|
|
2172
2343
|
if (!hasIssues) {
|
|
2173
2344
|
printBox(
|
|
2174
|
-
|
|
2345
|
+
pc10.green(pc10.bold("\u2728 \u8BCA\u65AD\u5B8C\u6210\uFF1A\u9879\u76EE\u4E00\u5207\u6B63\u5E38\uFF01")),
|
|
2175
2346
|
"Doctor Report"
|
|
2176
2347
|
);
|
|
2177
2348
|
} else {
|
|
2178
|
-
const issueList = issues.map((i) =>
|
|
2349
|
+
const issueList = issues.map((i) => pc10.red(`\u2022 ${i}`)).join("\n");
|
|
2179
2350
|
printBox(
|
|
2180
|
-
`${
|
|
2351
|
+
`${pc10.yellow(pc10.bold("\u26A0\uFE0F \u8BCA\u65AD\u5B8C\u6210\uFF1A\u53D1\u73B0\u4EE5\u4E0B\u95EE\u9898"))}
|
|
2181
2352
|
|
|
2182
2353
|
${issueList}
|
|
2183
2354
|
|
|
2184
|
-
${
|
|
2355
|
+
${pc10.cyan("\u5EFA\u8BAE\u6839\u636E\u63D0\u793A\u8FDB\u884C\u4FEE\u590D")}`,
|
|
2185
2356
|
"Doctor Report"
|
|
2186
2357
|
);
|
|
2187
2358
|
if (options.fix) {
|
|
2188
2359
|
if (codeIssues.length > 0) {
|
|
2189
2360
|
const fixSpinner = createSpinner("\u6B63\u5728\u4FEE\u590D\u4EE3\u7801\u89C4\u8303\u95EE\u9898...").start();
|
|
2190
2361
|
for (const issue of codeIssues) {
|
|
2191
|
-
const content = await
|
|
2362
|
+
const content = await fs14.readFile(issue.file, "utf-8");
|
|
2192
2363
|
const newContent = issue.rule.fix(content);
|
|
2193
|
-
await
|
|
2364
|
+
await fs14.writeFile(issue.file, newContent);
|
|
2194
2365
|
}
|
|
2195
2366
|
fixSpinner.succeed("\u4EE3\u7801\u4FEE\u590D\u5B8C\u6210");
|
|
2196
2367
|
}
|
|
@@ -2206,20 +2377,20 @@ ${pc9.cyan("\u5EFA\u8BAE\u6839\u636E\u63D0\u793A\u8FDB\u884C\u4FEE\u590D")}`,
|
|
|
2206
2377
|
init_esm_shims();
|
|
2207
2378
|
init_corekit();
|
|
2208
2379
|
init_utils();
|
|
2209
|
-
import
|
|
2380
|
+
import pc11 from "picocolors";
|
|
2210
2381
|
async function discover() {
|
|
2211
2382
|
const cwd = process.cwd();
|
|
2212
2383
|
const spinner = createSpinner("\u6B63\u5728\u626B\u63CF\u9879\u76EE\u4E2D\u7684\u63D2\u4EF6...").start();
|
|
2213
2384
|
const plugins = await CoreKit.discoverPlugins(cwd);
|
|
2214
2385
|
if (plugins.length === 0) {
|
|
2215
2386
|
spinner.warn("\u672A\u53D1\u73B0\u4EFB\u4F55\u63D2\u4EF6");
|
|
2216
|
-
logger.info(
|
|
2387
|
+
logger.info(pc11.gray("\u8BF7\u786E\u4FDD\u63D2\u4EF6\u4F4D\u4E8E plugins/ \u76EE\u5F55\u4E0B\uFF0C\u4E14\u5305\u542B package.json\u3002"));
|
|
2217
2388
|
} else {
|
|
2218
|
-
spinner.succeed(`\u53D1\u73B0\u4E86 ${
|
|
2219
|
-
const pluginList = plugins.map((p) => `- ${
|
|
2220
|
-
${
|
|
2389
|
+
spinner.succeed(`\u53D1\u73B0\u4E86 ${pc11.cyan(plugins.length)} \u4E2A\u63D2\u4EF6`);
|
|
2390
|
+
const pluginList = plugins.map((p) => `- ${pc11.bold(p.name)} ${pc11.gray(`(${p.id})`)}
|
|
2391
|
+
${pc11.gray(p.path)}`).join("\n\n");
|
|
2221
2392
|
printBox(
|
|
2222
|
-
`${
|
|
2393
|
+
`${pc11.green(pc11.bold("\u2728 \u63D2\u4EF6\u626B\u63CF\u7ED3\u679C"))}
|
|
2223
2394
|
|
|
2224
2395
|
${pluginList}`,
|
|
2225
2396
|
"Plugin Discovery"
|
|
@@ -2232,7 +2403,7 @@ init_esm_shims();
|
|
|
2232
2403
|
init_corekit();
|
|
2233
2404
|
init_sandbox();
|
|
2234
2405
|
init_utils();
|
|
2235
|
-
import
|
|
2406
|
+
import pc12 from "picocolors";
|
|
2236
2407
|
async function ls() {
|
|
2237
2408
|
const versions = await CoreKit.listVersions();
|
|
2238
2409
|
const currentVersion = await CoreKit.resolveVersion(process.cwd());
|
|
@@ -2246,22 +2417,22 @@ async function ls() {
|
|
|
2246
2417
|
const isProjectCurrent = v === currentVersion;
|
|
2247
2418
|
let prefix = " ";
|
|
2248
2419
|
if (isProjectCurrent) {
|
|
2249
|
-
prefix =
|
|
2420
|
+
prefix = pc12.green(" *");
|
|
2250
2421
|
} else if (isGlobalCurrent) {
|
|
2251
|
-
prefix =
|
|
2422
|
+
prefix = pc12.blue(" >");
|
|
2252
2423
|
}
|
|
2253
2424
|
let suffix = "";
|
|
2254
2425
|
if (isProjectCurrent && isGlobalCurrent) {
|
|
2255
|
-
suffix =
|
|
2426
|
+
suffix = pc12.gray(" (\u5F53\u524D\u9879\u76EE & \u5168\u5C40)");
|
|
2256
2427
|
} else if (isProjectCurrent) {
|
|
2257
|
-
suffix =
|
|
2428
|
+
suffix = pc12.gray(" (\u5F53\u524D\u9879\u76EE)");
|
|
2258
2429
|
} else if (isGlobalCurrent) {
|
|
2259
|
-
suffix =
|
|
2430
|
+
suffix = pc12.gray(" (\u5168\u5C40)");
|
|
2260
2431
|
}
|
|
2261
|
-
return `${prefix} ${
|
|
2432
|
+
return `${prefix} ${pc12.white(v)}${suffix}`;
|
|
2262
2433
|
}).join("\n");
|
|
2263
2434
|
printBox(
|
|
2264
|
-
list +
|
|
2435
|
+
list + pc12.gray("\n\n\u63D0\u793A: * \u5F53\u524D\u9879\u76EE\u4F7F\u7528, > \u5168\u5C40\u9ED8\u8BA4\u4F7F\u7528"),
|
|
2265
2436
|
"Kernel Versions"
|
|
2266
2437
|
);
|
|
2267
2438
|
}
|
|
@@ -2274,8 +2445,8 @@ init_sandbox();
|
|
|
2274
2445
|
init_corekit();
|
|
2275
2446
|
init_sync();
|
|
2276
2447
|
init_utils();
|
|
2277
|
-
import
|
|
2278
|
-
import
|
|
2448
|
+
import fs15 from "fs-extra";
|
|
2449
|
+
import path17 from "path";
|
|
2279
2450
|
async function use(version, options = {}) {
|
|
2280
2451
|
const versions = await CoreKit.listVersions();
|
|
2281
2452
|
if (!versions.includes(version)) {
|
|
@@ -2287,8 +2458,8 @@ async function use(version, options = {}) {
|
|
|
2287
2458
|
logger.success(`\u5DF2\u5207\u6362\u5168\u5C40\u5185\u6838\u7248\u672C\u81F3: ${version}`);
|
|
2288
2459
|
} else {
|
|
2289
2460
|
const cwd = process.cwd();
|
|
2290
|
-
const versionFilePath =
|
|
2291
|
-
await
|
|
2461
|
+
const versionFilePath = path17.join(cwd, ".chatbi-version");
|
|
2462
|
+
await fs15.writeFile(versionFilePath, version, "utf-8");
|
|
2292
2463
|
logger.success(`\u5DF2\u5207\u6362\u5F53\u524D\u9879\u76EE\u5185\u6838\u7248\u672C\u4E3A: ${version}`);
|
|
2293
2464
|
}
|
|
2294
2465
|
await sync({ version, force: false });
|
|
@@ -2301,16 +2472,16 @@ init_fetch();
|
|
|
2301
2472
|
init_esm_shims();
|
|
2302
2473
|
init_sandbox();
|
|
2303
2474
|
init_utils();
|
|
2304
|
-
import
|
|
2305
|
-
import
|
|
2306
|
-
import
|
|
2475
|
+
import fs16 from "fs-extra";
|
|
2476
|
+
import path19 from "path";
|
|
2477
|
+
import pc14 from "picocolors";
|
|
2307
2478
|
import { execa as execa5 } from "execa";
|
|
2308
2479
|
async function install(target) {
|
|
2309
|
-
if (target.endsWith(".tgz") &&
|
|
2310
|
-
const spinner = createSpinner(`\u6B63\u5728\u5B89\u88C5\u672C\u5730\u79BB\u7EBF\u5305: ${
|
|
2480
|
+
if (target.endsWith(".tgz") && fs16.existsSync(target)) {
|
|
2481
|
+
const spinner = createSpinner(`\u6B63\u5728\u5B89\u88C5\u672C\u5730\u79BB\u7EBF\u5305: ${pc14.bold(target)}...`).start();
|
|
2311
2482
|
try {
|
|
2312
|
-
const tgzPath =
|
|
2313
|
-
const match =
|
|
2483
|
+
const tgzPath = path19.resolve(target);
|
|
2484
|
+
const match = path19.basename(target).match(/chatbi-core-(.+)\.tgz/);
|
|
2314
2485
|
let version = "unknown";
|
|
2315
2486
|
if (match) {
|
|
2316
2487
|
version = match[1];
|
|
@@ -2320,7 +2491,7 @@ async function install(target) {
|
|
|
2320
2491
|
version = `local-${Date.now()}`;
|
|
2321
2492
|
}
|
|
2322
2493
|
const versionRoot = Sandbox.getVersionRoot();
|
|
2323
|
-
await
|
|
2494
|
+
await fs16.ensureDir(versionRoot);
|
|
2324
2495
|
spinner.text = "\u6B63\u5728\u89E3\u538B\u6587\u4EF6...";
|
|
2325
2496
|
await execa5("tar", ["-xzf", tgzPath, "-C", versionRoot]);
|
|
2326
2497
|
spinner.succeed(`\u672C\u5730\u5305\u5DF2\u5B89\u88C5\u81F3\u6C99\u7BB1: ${version}`);
|
|
@@ -2328,7 +2499,7 @@ async function install(target) {
|
|
|
2328
2499
|
await Sandbox.prepare(version);
|
|
2329
2500
|
spinner.succeed("\u5185\u6838\u73AF\u5883\u5C31\u7EEA");
|
|
2330
2501
|
printBox(
|
|
2331
|
-
|
|
2502
|
+
pc14.green(pc14.bold("\u2728 \u672C\u5730\u5185\u6838\u5B89\u88C5\u6210\u529F!")) + "\n\n" + pc14.white("\u7248\u672C: ") + pc14.cyan(version) + "\n" + pc14.white("\u8DEF\u5F84: ") + pc14.gray(Sandbox.getVersionPath(version)),
|
|
2332
2503
|
"Install Success"
|
|
2333
2504
|
);
|
|
2334
2505
|
} catch (e) {
|
|
@@ -2341,10 +2512,18 @@ async function install(target) {
|
|
|
2341
2512
|
}
|
|
2342
2513
|
}
|
|
2343
2514
|
|
|
2515
|
+
// src/commands/clean.ts
|
|
2516
|
+
init_esm_shims();
|
|
2517
|
+
init_sandbox();
|
|
2518
|
+
async function clean(options) {
|
|
2519
|
+
const cwd = process.cwd();
|
|
2520
|
+
await Sandbox.clean(cwd, options.deep);
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2344
2523
|
// package.json
|
|
2345
2524
|
var package_default = {
|
|
2346
2525
|
name: "@chatbi-v/cli",
|
|
2347
|
-
version: "2.0.
|
|
2526
|
+
version: "2.0.6",
|
|
2348
2527
|
description: "Standardized CLI tooling for ChatBI Monorepo",
|
|
2349
2528
|
type: "module",
|
|
2350
2529
|
main: "dist/index.js",
|
|
@@ -2403,7 +2582,7 @@ var showHeader = () => {
|
|
|
2403
2582
|
const title = figlet.textSync("ChatBI-V CLI", { font: "Standard" });
|
|
2404
2583
|
console.log(gradient.pastel.multiline(title));
|
|
2405
2584
|
console.log(
|
|
2406
|
-
boxen2(
|
|
2585
|
+
boxen2(pc16.cyan(`ChatBI-V \u7EDF\u4E00\u5F00\u53D1\u5DE5\u5177 v${package_default.version}`), {
|
|
2407
2586
|
padding: 0,
|
|
2408
2587
|
margin: { top: 1, bottom: 1 },
|
|
2409
2588
|
borderStyle: "round",
|
|
@@ -2461,13 +2640,14 @@ cli.command("list", "\u5217\u51FA\u6240\u6709\u5DF2\u5B89\u88C5\u7684\u5185\u683
|
|
|
2461
2640
|
cli.command("use <version>", "\u5207\u6362\u5F53\u524D\u9879\u76EE\u4F7F\u7528\u7684\u5185\u6838\u7248\u672C").alias("u").option("--global", "\u5207\u6362\u5168\u5C40\u9ED8\u8BA4\u5185\u6838\u7248\u672C").action(wrapAction(use, "use"));
|
|
2462
2641
|
cli.command("gl", "\u4F7F\u7528 AI \u811A\u624B\u67B6\u751F\u6210\u4EE3\u7801\u6216\u6587\u6863").option("-t, --type <type>", "\u751F\u6210\u7C7B\u578B (plugin|util|doc|component)").option("-p, --prompt <prompt>", "AI \u9700\u6C42\u63CF\u8FF0").action(wrapAction(gl, "gl"));
|
|
2463
2642
|
cli.command("discover", "\u626B\u63CF\u5E76\u53D1\u73B0\u5F53\u524D\u9879\u76EE\u4E2D\u7684\u63D2\u4EF6").action(wrapAction(discover, "discover"));
|
|
2643
|
+
cli.command("clean", "\u6E05\u7406 CLI \u4EA7\u751F\u7684\u7F13\u5B58\u76EE\u5F55").alias("cl").option("--deep", "\u6DF1\u5EA6\u6E05\u7406 (\u5305\u542B\u6240\u6709\u5B50\u5305\u7684 .chatbi \u76EE\u5F55\u53CA\u5168\u5C40\u6C99\u7BB1\u6839\u76EE\u5F55)").action(wrapAction(clean, "clean"));
|
|
2464
2644
|
cli.command("bench", "\u8FD0\u884C CLI \u6027\u80FD\u57FA\u51C6\u6D4B\u8BD5").action(wrapAction(async () => {
|
|
2465
2645
|
const { bench: bench2 } = await Promise.resolve().then(() => (init_bench(), bench_exports));
|
|
2466
2646
|
await bench2();
|
|
2467
2647
|
}, "bench"));
|
|
2468
2648
|
cli.help((sections) => {
|
|
2469
2649
|
showHeader();
|
|
2470
|
-
sections[0].body =
|
|
2650
|
+
sections[0].body = pc16.white("ChatBI-V \u5F00\u53D1\u8005\u547D\u4EE4\u884C\u5DE5\u5177\uFF0C\u52A9\u529B\u5FEB\u901F\u5F00\u53D1\u548C\u6784\u5EFA\u63D2\u4EF6\u3002");
|
|
2471
2651
|
});
|
|
2472
2652
|
cli.version(package_default.version);
|
|
2473
2653
|
if (process.argv.length <= 2) {
|