@chatbi-v/cli 2.0.4 → 2.0.5
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 +941 -761
- package/package.json +1 -1
- 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
|
@@ -14,12 +14,12 @@ var __export = (target, all) => {
|
|
|
14
14
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
//
|
|
17
|
+
// ../../../chatbi-v/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
18
|
import path from "path";
|
|
19
19
|
import { fileURLToPath } from "url";
|
|
20
20
|
var getFilename, getDirname, __dirname;
|
|
21
21
|
var init_esm_shims = __esm({
|
|
22
|
-
"
|
|
22
|
+
"../../../chatbi-v/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
23
|
"use strict";
|
|
24
24
|
getFilename = () => fileURLToPath(import.meta.url);
|
|
25
25
|
getDirname = () => path.dirname(getFilename());
|
|
@@ -84,11 +84,7 @@ var init_utils = __esm({
|
|
|
84
84
|
if (pkgName === "@chatbi-v/cli") {
|
|
85
85
|
return path2.resolve(_dirname, "../../");
|
|
86
86
|
}
|
|
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`);
|
|
87
|
+
return null;
|
|
92
88
|
}
|
|
93
89
|
};
|
|
94
90
|
getCliRoot = async () => {
|
|
@@ -105,269 +101,299 @@ var init_utils = __esm({
|
|
|
105
101
|
checkDir = path2.dirname(checkDir);
|
|
106
102
|
}
|
|
107
103
|
if (!myCliRoot) {
|
|
108
|
-
myCliRoot = findPackageRoot("@chatbi-v/cli");
|
|
104
|
+
myCliRoot = findPackageRoot("@chatbi-v/cli") || "";
|
|
109
105
|
}
|
|
110
106
|
return myCliRoot;
|
|
111
107
|
};
|
|
112
108
|
}
|
|
113
109
|
});
|
|
114
110
|
|
|
115
|
-
// src/
|
|
116
|
-
import fs2 from "fs-extra";
|
|
111
|
+
// src/constants.ts
|
|
117
112
|
import path3 from "path";
|
|
118
113
|
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"() {
|
|
114
|
+
var SANDBOX_CONFIG, GLOBAL_PATHS, DEPENDENCY_VERSIONS, DEFAULT_CONFIG;
|
|
115
|
+
var init_constants = __esm({
|
|
116
|
+
"src/constants.ts"() {
|
|
126
117
|
"use strict";
|
|
127
118
|
init_esm_shims();
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
119
|
+
SANDBOX_CONFIG = {
|
|
120
|
+
/** 用户主目录下的沙箱根目录名 */
|
|
121
|
+
BASE_NAME: ".chatbi-v-core",
|
|
122
|
+
/** 内部子目录结构 */
|
|
123
|
+
DIRS: {
|
|
124
|
+
VERSIONS: "versions",
|
|
125
|
+
CURRENT: "current",
|
|
126
|
+
CACHE: ".chatbi"
|
|
127
|
+
},
|
|
128
|
+
/** 关键标识文件 */
|
|
129
|
+
LOCK_FILE: ".chatbi-version"
|
|
130
|
+
};
|
|
131
|
+
GLOBAL_PATHS = {
|
|
132
|
+
/** 沙箱根路径 */
|
|
133
|
+
BASE_DIR: path3.join(os.homedir(), SANDBOX_CONFIG.BASE_NAME),
|
|
134
|
+
/** Monorepo 扫描目录 */
|
|
135
|
+
MONOREPO_ROOTS: ["apps", "plugins", "packages"]
|
|
136
|
+
};
|
|
137
|
+
DEPENDENCY_VERSIONS = {
|
|
138
|
+
// 基础框架
|
|
139
|
+
"react": "^18.3.1",
|
|
140
|
+
"react-dom": "^18.3.1",
|
|
141
|
+
"antd": "^5.20.0",
|
|
142
|
+
// 构建工具
|
|
143
|
+
"vite": "^5.0.8",
|
|
144
|
+
"typescript": "^5.3.3",
|
|
145
|
+
"tailwindcss": "^3.4.1",
|
|
146
|
+
"autoprefixer": "^10.4.17",
|
|
147
|
+
"postcss": "^8.4.35",
|
|
148
|
+
"less": "^4.2.0",
|
|
149
|
+
// 类型定义
|
|
150
|
+
"@types/react": "^18.3.1",
|
|
151
|
+
"@types/react-dom": "^18.3.1",
|
|
152
|
+
"@types/node": "^20.11.20",
|
|
153
|
+
"@vitejs/plugin-react": "^4.2.1"
|
|
154
|
+
};
|
|
155
|
+
DEFAULT_CONFIG = {
|
|
156
|
+
/** 支持的配置文件名 */
|
|
157
|
+
CONFIG_FILES: [
|
|
158
|
+
"chatbi.config.ts",
|
|
159
|
+
"chatbi.config.js",
|
|
160
|
+
"chatbi.config.json",
|
|
161
|
+
".chatbirc"
|
|
162
|
+
],
|
|
163
|
+
/** 默认 UI 主题 */
|
|
164
|
+
THEME: "standard"
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// src/sandbox/SandboxPath.ts
|
|
170
|
+
import path4 from "path";
|
|
171
|
+
import fs2 from "fs-extra";
|
|
172
|
+
var SandboxPath;
|
|
173
|
+
var init_SandboxPath = __esm({
|
|
174
|
+
"src/sandbox/SandboxPath.ts"() {
|
|
175
|
+
"use strict";
|
|
176
|
+
init_esm_shims();
|
|
177
|
+
init_constants();
|
|
178
|
+
SandboxPath = class {
|
|
144
179
|
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
|
-
];
|
|
180
|
+
/**
|
|
181
|
+
* 沙箱的基础存储目录,通常位于用户主目录下的 .chatbi-v-core
|
|
182
|
+
*/
|
|
183
|
+
this.BASE_DIR = GLOBAL_PATHS.BASE_DIR;
|
|
161
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* 获取沙箱根目录
|
|
187
|
+
* @returns 沙箱根目录的绝对路径
|
|
188
|
+
*/
|
|
162
189
|
static getRoot() {
|
|
163
190
|
return this.BASE_DIR;
|
|
164
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* 获取存储所有版本的根目录
|
|
194
|
+
* @returns versions 目录的绝对路径
|
|
195
|
+
*/
|
|
165
196
|
static getVersionRoot() {
|
|
166
|
-
return
|
|
197
|
+
return path4.join(this.BASE_DIR, SANDBOX_CONFIG.DIRS.VERSIONS);
|
|
167
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* 获取指定版本的沙箱路径
|
|
201
|
+
* @param version 版本号,或者 'current' 表示当前激活版本
|
|
202
|
+
* @returns 对应版本的绝对路径
|
|
203
|
+
*/
|
|
168
204
|
static getVersionPath(version) {
|
|
169
|
-
if (version ===
|
|
170
|
-
return
|
|
205
|
+
if (version === SANDBOX_CONFIG.DIRS.CURRENT) {
|
|
206
|
+
return path4.join(this.BASE_DIR, SANDBOX_CONFIG.DIRS.VERSIONS, SANDBOX_CONFIG.DIRS.CURRENT);
|
|
171
207
|
}
|
|
172
|
-
return
|
|
208
|
+
return path4.join(this.BASE_DIR, SANDBOX_CONFIG.DIRS.VERSIONS, version);
|
|
173
209
|
}
|
|
174
210
|
/**
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
* @param
|
|
211
|
+
* 递归向上查找工作区根目录
|
|
212
|
+
* 识别标准:包含 pnpm-workspace.yaml 或 package.json 中定义了 workspaces
|
|
213
|
+
* @param cwd 起始查找目录
|
|
214
|
+
* @returns 查找到的工作区根目录路径,若未找到则返回 cwd
|
|
178
215
|
*/
|
|
179
|
-
static async
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const pkgPath = path3.join(cwd, "package.json");
|
|
216
|
+
static async getWorkspaceRoot(cwd) {
|
|
217
|
+
let current = cwd;
|
|
218
|
+
while (current !== path4.parse(current).root) {
|
|
219
|
+
const pkgPath = path4.join(current, "package.json");
|
|
220
|
+
const pnpmWorkspacePath = path4.join(current, "pnpm-workspace.yaml");
|
|
221
|
+
if (fs2.existsSync(pnpmWorkspacePath)) return current;
|
|
186
222
|
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
|
-
}
|
|
223
|
+
try {
|
|
224
|
+
const pkg = await fs2.readJson(pkgPath);
|
|
225
|
+
if (pkg.workspaces) return current;
|
|
226
|
+
} catch (e) {
|
|
204
227
|
}
|
|
205
228
|
}
|
|
229
|
+
current = path4.dirname(current);
|
|
206
230
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
231
|
+
return cwd;
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// src/sandbox/SandboxRenderer.ts
|
|
238
|
+
import fs3 from "fs-extra";
|
|
239
|
+
import path5 from "path";
|
|
240
|
+
import Handlebars from "handlebars";
|
|
241
|
+
var SandboxRenderer;
|
|
242
|
+
var init_SandboxRenderer = __esm({
|
|
243
|
+
"src/sandbox/SandboxRenderer.ts"() {
|
|
244
|
+
"use strict";
|
|
245
|
+
init_esm_shims();
|
|
246
|
+
Handlebars.registerHelper("json", (obj) => JSON.stringify(obj, null, 2));
|
|
247
|
+
Handlebars.registerHelper("eq", (a, b) => a === b);
|
|
248
|
+
SandboxRenderer = class {
|
|
249
|
+
static {
|
|
250
|
+
/**
|
|
251
|
+
* 需要转义的模板关键字列表
|
|
252
|
+
* 只有匹配这些关键字的 {{ }} 才会被 Handlebars 处理,其余(如 React 的 {{ style }})将被转义跳过
|
|
253
|
+
*/
|
|
254
|
+
this.TEMPLATE_KEYWORDS = [
|
|
255
|
+
"name",
|
|
256
|
+
"version",
|
|
257
|
+
"projectName",
|
|
258
|
+
"projectTitle",
|
|
259
|
+
"projectVersion",
|
|
260
|
+
"cliVersion",
|
|
261
|
+
"tsconfigPath",
|
|
262
|
+
"theme",
|
|
263
|
+
"isNebula",
|
|
264
|
+
"isGlass",
|
|
265
|
+
"isBusiness",
|
|
266
|
+
"isApp",
|
|
267
|
+
"isShell",
|
|
268
|
+
"pluginName",
|
|
269
|
+
"pluginPackageName",
|
|
270
|
+
"pluginVersion",
|
|
271
|
+
"pluginDisplayName",
|
|
272
|
+
"pluginDescription",
|
|
273
|
+
"pluginClassName",
|
|
274
|
+
"pluginPath",
|
|
275
|
+
"pluginFolderName",
|
|
276
|
+
"pluginType",
|
|
277
|
+
"pluginId",
|
|
278
|
+
"className",
|
|
279
|
+
"dependencies",
|
|
280
|
+
"devDependencies",
|
|
281
|
+
"json"
|
|
282
|
+
];
|
|
210
283
|
}
|
|
211
284
|
/**
|
|
212
|
-
*
|
|
285
|
+
* 递归渲染目录模板
|
|
286
|
+
* @param srcDir 模板源目录
|
|
287
|
+
* @param destDir 目标输出目录
|
|
288
|
+
* @param data 渲染模板所需的变量上下文
|
|
213
289
|
*/
|
|
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");
|
|
290
|
+
static async renderDirectory(srcDir, destDir, data) {
|
|
291
|
+
if (!fs3.existsSync(srcDir)) return;
|
|
292
|
+
const entries = await fs3.readdir(srcDir, { withFileTypes: true });
|
|
293
|
+
for (const entry of entries) {
|
|
294
|
+
const srcPath = path5.join(srcDir, entry.name);
|
|
295
|
+
const destPath = path5.join(destDir, entry.name.replace(/\.hbs$/, ""));
|
|
296
|
+
if (entry.isDirectory()) {
|
|
297
|
+
await fs3.ensureDir(destPath);
|
|
298
|
+
await this.renderDirectory(srcPath, destPath, data);
|
|
299
|
+
} else {
|
|
300
|
+
await this.renderFile(srcPath, destPath, data);
|
|
263
301
|
}
|
|
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
302
|
}
|
|
273
|
-
return versionPath;
|
|
274
303
|
}
|
|
275
304
|
/**
|
|
276
|
-
*
|
|
305
|
+
* 渲染单个文件
|
|
277
306
|
*/
|
|
278
|
-
static async
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
return shellDestDir;
|
|
307
|
+
static async renderFile(srcPath, destPath, data) {
|
|
308
|
+
const isTemplate = srcPath.endsWith(".hbs");
|
|
309
|
+
if (!isTemplate) {
|
|
310
|
+
await fs3.copy(srcPath, destPath);
|
|
311
|
+
return;
|
|
284
312
|
}
|
|
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 });
|
|
313
|
+
const content = await fs3.readFile(srcPath, "utf-8");
|
|
314
|
+
if (!content.includes("{{")) {
|
|
315
|
+
await fs3.outputFile(destPath, content);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
319
|
+
const keywordsPattern = this.TEMPLATE_KEYWORDS.join("|");
|
|
320
|
+
const safeContent = content.replace(
|
|
321
|
+
new RegExp(`\\{\\{(?!\\{)(?!\\s*([#/]?(?:${keywordsPattern}))\\b)`, "g"),
|
|
322
|
+
"\\{{"
|
|
323
|
+
);
|
|
324
|
+
const template = Handlebars.compile(safeContent);
|
|
325
|
+
const result = template(data);
|
|
326
|
+
await fs3.outputFile(destPath, result);
|
|
327
|
+
} catch (e) {
|
|
328
|
+
let result = content;
|
|
329
|
+
for (const [key, val] of Object.entries(data)) {
|
|
330
|
+
const regex = new RegExp(`\\{\\{\\s*${key}\\s*\\}\\}`, "g");
|
|
331
|
+
result = result.replace(regex, typeof val === "object" ? JSON.stringify(val) : String(val));
|
|
332
|
+
}
|
|
333
|
+
await fs3.outputFile(destPath, result);
|
|
316
334
|
}
|
|
317
|
-
return shellDestDir;
|
|
318
335
|
}
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
// src/sandbox/SandboxContext.ts
|
|
341
|
+
import fs4 from "fs-extra";
|
|
342
|
+
import path6 from "path";
|
|
343
|
+
var SandboxContext;
|
|
344
|
+
var init_SandboxContext = __esm({
|
|
345
|
+
"src/sandbox/SandboxContext.ts"() {
|
|
346
|
+
"use strict";
|
|
347
|
+
init_esm_shims();
|
|
348
|
+
init_SandboxPath();
|
|
349
|
+
init_constants();
|
|
350
|
+
SandboxContext = class {
|
|
319
351
|
/**
|
|
320
|
-
*
|
|
352
|
+
* 注入项目虚拟上下文
|
|
353
|
+
* 包括:
|
|
354
|
+
* 1. 确定集中式 .chatbi 存放位置并处理子包软链
|
|
355
|
+
* 2. 生成适配沙箱的 tsconfig.json (配置路径别名)
|
|
356
|
+
* 3. 软链接沙箱的 node_modules 到项目 .chatbi 目录下
|
|
357
|
+
* 4. 确保 .chatbi 被加入 .gitignore
|
|
358
|
+
*
|
|
359
|
+
* @param projectRoot 当前项目根目录
|
|
360
|
+
* @param version 内核版本号
|
|
361
|
+
* @param corePackages 核心包名列表
|
|
362
|
+
* @param runtimeDeps 运行时依赖包名列表
|
|
321
363
|
*/
|
|
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);
|
|
364
|
+
static async inject(projectRoot, version, corePackages, runtimeDeps) {
|
|
365
|
+
const workspaceRoot = await SandboxPath.getWorkspaceRoot(projectRoot);
|
|
366
|
+
const chatbiDir = path6.join(workspaceRoot, SANDBOX_CONFIG.DIRS.CACHE);
|
|
367
|
+
await fs4.ensureDir(chatbiDir);
|
|
368
|
+
if (workspaceRoot !== projectRoot) {
|
|
369
|
+
const localChatbi = path6.join(projectRoot, SANDBOX_CONFIG.DIRS.CACHE);
|
|
370
|
+
try {
|
|
371
|
+
const stats = await fs4.lstat(localChatbi).catch(() => null);
|
|
372
|
+
if (stats) {
|
|
373
|
+
if (stats.isSymbolicLink()) {
|
|
374
|
+
const linkTarget = await fs4.readlink(localChatbi);
|
|
375
|
+
if (linkTarget !== chatbiDir) {
|
|
376
|
+
await fs4.remove(localChatbi);
|
|
377
|
+
await fs4.symlink(chatbiDir, localChatbi, "dir");
|
|
347
378
|
}
|
|
348
379
|
} else {
|
|
349
|
-
await
|
|
380
|
+
await fs4.remove(localChatbi);
|
|
381
|
+
await fs4.symlink(chatbiDir, localChatbi, "dir");
|
|
350
382
|
}
|
|
351
383
|
} else {
|
|
352
|
-
await
|
|
384
|
+
await fs4.symlink(chatbiDir, localChatbi, "dir");
|
|
353
385
|
}
|
|
386
|
+
} catch (e) {
|
|
354
387
|
}
|
|
355
388
|
}
|
|
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");
|
|
389
|
+
const versionPath = SandboxPath.getVersionPath(version);
|
|
390
|
+
const sandboxNodeModules = path6.join(versionPath, "node_modules");
|
|
365
391
|
const corePaths = {};
|
|
366
|
-
for (const pkgName of
|
|
392
|
+
for (const pkgName of corePackages) {
|
|
367
393
|
corePaths[pkgName] = [`./node_modules/${pkgName}`];
|
|
368
394
|
corePaths[`${pkgName}/*`] = [`./node_modules/${pkgName}/*`];
|
|
369
395
|
}
|
|
370
|
-
for (const pkgName of
|
|
396
|
+
for (const pkgName of runtimeDeps) {
|
|
371
397
|
corePaths[pkgName] = [`./node_modules/${pkgName}`];
|
|
372
398
|
corePaths[`${pkgName}/*`] = [`./node_modules/${pkgName}/*`];
|
|
373
399
|
if (["react", "react-dom", "node"].includes(pkgName)) {
|
|
@@ -378,152 +404,119 @@ var init_sandbox = __esm({
|
|
|
378
404
|
}
|
|
379
405
|
corePaths["@types/*"] = ["./node_modules/@types/*"];
|
|
380
406
|
corePaths["vite/client"] = ["./node_modules/vite/client.d.ts"];
|
|
381
|
-
const baseConfigPath =
|
|
382
|
-
let projectPaths = { "@/*": ["../src/*"] };
|
|
407
|
+
const baseConfigPath = path6.join(sandboxNodeModules, "@chatbi-v/tsconfig/base.json");
|
|
383
408
|
const tsConfig = {
|
|
384
409
|
extends: baseConfigPath,
|
|
385
410
|
compilerOptions: {
|
|
386
411
|
baseUrl: ".",
|
|
387
412
|
moduleResolution: "bundler",
|
|
388
413
|
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
|
|
414
|
+
typeRoots: ["./node_modules/@types"],
|
|
395
415
|
preserveSymlinks: true,
|
|
396
416
|
paths: {
|
|
397
417
|
...corePaths,
|
|
398
|
-
|
|
399
|
-
// Fallback: Try to find anything else in the virtual node_modules
|
|
418
|
+
"@/*": ["../src/*"],
|
|
400
419
|
"*": ["./node_modules/*"]
|
|
401
420
|
}
|
|
402
421
|
}
|
|
403
422
|
};
|
|
404
|
-
await
|
|
405
|
-
await
|
|
406
|
-
const virtualNodeModules =
|
|
407
|
-
if (
|
|
408
|
-
return;
|
|
409
|
-
}
|
|
410
|
-
try {
|
|
423
|
+
await fs4.writeJson(path6.join(chatbiDir, "tsconfig.json"), tsConfig, { spaces: 2 });
|
|
424
|
+
await fs4.writeJson(path6.join(chatbiDir, "tsconfig.paths.json"), { compilerOptions: tsConfig.compilerOptions }, { spaces: 2 });
|
|
425
|
+
const virtualNodeModules = path6.join(chatbiDir, "node_modules");
|
|
426
|
+
if (fs4.existsSync(sandboxNodeModules)) {
|
|
411
427
|
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);
|
|
428
|
+
await fs4.remove(virtualNodeModules).catch(() => {
|
|
429
|
+
});
|
|
430
|
+
await fs4.ensureSymlink(sandboxNodeModules, virtualNodeModules, "dir");
|
|
423
431
|
} catch (e) {
|
|
424
432
|
}
|
|
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
433
|
}
|
|
444
|
-
const gitignorePath =
|
|
445
|
-
if (
|
|
446
|
-
let content = await
|
|
447
|
-
if (!content.includes(
|
|
448
|
-
await
|
|
434
|
+
const gitignorePath = path6.join(workspaceRoot, ".gitignore");
|
|
435
|
+
if (fs4.existsSync(gitignorePath)) {
|
|
436
|
+
let content = await fs4.readFile(gitignorePath, "utf-8");
|
|
437
|
+
if (!content.includes(SANDBOX_CONFIG.DIRS.CACHE)) {
|
|
438
|
+
await fs4.appendFile(gitignorePath, `
|
|
439
|
+
# ChatBI
|
|
440
|
+
${SANDBOX_CONFIG.DIRS.CACHE}
|
|
441
|
+
`);
|
|
449
442
|
}
|
|
450
443
|
}
|
|
451
444
|
}
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
// src/sandbox/SandboxPkgManager.ts
|
|
450
|
+
import fs5 from "fs-extra";
|
|
451
|
+
import path7 from "path";
|
|
452
|
+
import pc2 from "picocolors";
|
|
453
|
+
import fg from "fast-glob";
|
|
454
|
+
var SandboxPkgManager;
|
|
455
|
+
var init_SandboxPkgManager = __esm({
|
|
456
|
+
"src/sandbox/SandboxPkgManager.ts"() {
|
|
457
|
+
"use strict";
|
|
458
|
+
init_esm_shims();
|
|
459
|
+
init_utils();
|
|
460
|
+
init_SandboxPath();
|
|
461
|
+
SandboxPkgManager = class {
|
|
452
462
|
/**
|
|
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 到沙箱中 (模拟安装)
|
|
463
|
+
* 尝试将本地开发环境的包 Link 到沙箱中 (模拟安装)
|
|
464
|
+
* 用于 Monorepo 场景下,让沙箱直接使用最新的本地源码
|
|
465
|
+
* @param versionPath 沙箱版本的存储路径
|
|
466
|
+
* @param corePackages 核心包名列表
|
|
467
|
+
* @param runtimeDeps 运行时依赖包名列表
|
|
468
|
+
* @returns 是否成功 Link 了至少一个包
|
|
466
469
|
*/
|
|
467
|
-
static async tryLinkLocalPackages(versionPath) {
|
|
470
|
+
static async tryLinkLocalPackages(versionPath, corePackages, runtimeDeps) {
|
|
468
471
|
try {
|
|
469
472
|
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);
|
|
473
|
+
const projectRoot = await SandboxPath.getWorkspaceRoot(cliRoot);
|
|
474
|
+
if (projectRoot === cliRoot && !fs5.existsSync(path7.join(projectRoot, "pnpm-workspace.yaml"))) {
|
|
475
|
+
return false;
|
|
478
476
|
}
|
|
479
477
|
const possiblePackagesDirs = [
|
|
480
|
-
|
|
481
|
-
//
|
|
482
|
-
|
|
478
|
+
path7.join(projectRoot, "packages"),
|
|
479
|
+
// 兼容旧版或其他可能的路径结构
|
|
480
|
+
path7.resolve(projectRoot, "../chatbi-v/packages")
|
|
483
481
|
];
|
|
484
482
|
const localPackages = {};
|
|
485
|
-
const patterns = possiblePackagesDirs.filter((dir) =>
|
|
483
|
+
const patterns = possiblePackagesDirs.filter((dir) => fs5.existsSync(dir)).map((dir) => path7.join(dir, "**/package.json"));
|
|
486
484
|
if (patterns.length > 0) {
|
|
487
485
|
const pkgJsonFiles = await fg(patterns, {
|
|
488
486
|
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"],
|
|
489
487
|
absolute: true,
|
|
490
488
|
deep: 5
|
|
491
|
-
// 允许一定的嵌套深度
|
|
492
489
|
});
|
|
493
490
|
for (const pkgJsonPath of pkgJsonFiles) {
|
|
494
491
|
try {
|
|
495
|
-
const pkgJson = await
|
|
496
|
-
if (
|
|
497
|
-
localPackages[pkgJson.name] =
|
|
492
|
+
const pkgJson = await fs5.readJson(pkgJsonPath);
|
|
493
|
+
if (corePackages.includes(pkgJson.name) || runtimeDeps.includes(pkgJson.name)) {
|
|
494
|
+
localPackages[pkgJson.name] = path7.dirname(pkgJsonPath);
|
|
498
495
|
}
|
|
499
496
|
} catch (e) {
|
|
500
497
|
}
|
|
501
498
|
}
|
|
502
499
|
}
|
|
503
|
-
if (Object.keys(localPackages).length === 0)
|
|
504
|
-
return false;
|
|
505
|
-
}
|
|
500
|
+
if (Object.keys(localPackages).length === 0) return false;
|
|
506
501
|
const linkSummary = Object.entries(localPackages).map(([name, pkgPath]) => `${pc2.cyan(name.padEnd(30))} -> ${pc2.gray(pkgPath)}`).join("\n");
|
|
507
502
|
printBox(
|
|
508
503
|
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
504
|
"Monorepo Link Mode"
|
|
510
505
|
);
|
|
511
|
-
const sandboxNodeModules =
|
|
512
|
-
await
|
|
506
|
+
const sandboxNodeModules = path7.join(versionPath, "node_modules");
|
|
507
|
+
await fs5.ensureDir(sandboxNodeModules);
|
|
513
508
|
for (const [name, pkgPath] of Object.entries(localPackages)) {
|
|
514
|
-
const targetLinkPath =
|
|
515
|
-
await
|
|
509
|
+
const targetLinkPath = path7.join(sandboxNodeModules, name);
|
|
510
|
+
await fs5.ensureDir(path7.dirname(targetLinkPath));
|
|
516
511
|
try {
|
|
517
|
-
const stats = await
|
|
518
|
-
if (stats)
|
|
519
|
-
await fs2.remove(targetLinkPath);
|
|
520
|
-
}
|
|
512
|
+
const stats = await fs5.lstat(targetLinkPath).catch(() => null);
|
|
513
|
+
if (stats) await fs5.remove(targetLinkPath);
|
|
521
514
|
} catch (e) {
|
|
522
515
|
}
|
|
523
|
-
await
|
|
516
|
+
await fs5.symlink(pkgPath, targetLinkPath, "dir");
|
|
524
517
|
}
|
|
525
|
-
const sandboxPkgJsonPath =
|
|
526
|
-
const sandboxPkgJson = await
|
|
518
|
+
const sandboxPkgJsonPath = path7.join(versionPath, "package.json");
|
|
519
|
+
const sandboxPkgJson = await fs5.readJson(sandboxPkgJsonPath);
|
|
527
520
|
const sections = ["dependencies", "devDependencies"];
|
|
528
521
|
let modified = false;
|
|
529
522
|
for (const section of sections) {
|
|
@@ -536,95 +529,287 @@ var init_sandbox = __esm({
|
|
|
536
529
|
}
|
|
537
530
|
}
|
|
538
531
|
}
|
|
539
|
-
if (modified) {
|
|
540
|
-
await fs2.writeJson(sandboxPkgJsonPath, sandboxPkgJson, { spaces: 2 });
|
|
541
|
-
}
|
|
532
|
+
if (modified) await fs5.writeJson(sandboxPkgJsonPath, sandboxPkgJson, { spaces: 2 });
|
|
542
533
|
return true;
|
|
543
534
|
} catch (e) {
|
|
544
535
|
console.warn(pc2.yellow(` \u26A0\uFE0F Link \u672C\u5730\u6E90\u7801\u5931\u8D25\uFF0C\u5C06\u5C1D\u8BD5\u4ECE NPM \u5B89\u88C5: ${e.message}`));
|
|
545
536
|
return false;
|
|
546
537
|
}
|
|
547
538
|
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
// src/sandbox.ts
|
|
544
|
+
import fs6 from "fs-extra";
|
|
545
|
+
import path8 from "path";
|
|
546
|
+
import pc3 from "picocolors";
|
|
547
|
+
import fg2 from "fast-glob";
|
|
548
|
+
import { execa } from "execa";
|
|
549
|
+
var Sandbox;
|
|
550
|
+
var init_sandbox = __esm({
|
|
551
|
+
"src/sandbox.ts"() {
|
|
552
|
+
"use strict";
|
|
553
|
+
init_esm_shims();
|
|
554
|
+
init_utils();
|
|
555
|
+
init_SandboxPath();
|
|
556
|
+
init_SandboxRenderer();
|
|
557
|
+
init_SandboxContext();
|
|
558
|
+
init_SandboxPkgManager();
|
|
559
|
+
init_constants();
|
|
560
|
+
Sandbox = class {
|
|
561
|
+
static {
|
|
562
|
+
/** 核心源码包列表 */
|
|
563
|
+
this.CORE_PACKAGES = [
|
|
564
|
+
"@chatbi-v/core",
|
|
565
|
+
"@chatbi-v/mocks",
|
|
566
|
+
"@chatbi-v/tsconfig",
|
|
567
|
+
"@chatbi-v/tailwind-config",
|
|
568
|
+
"@chatbi-v/plugin-theme-manager",
|
|
569
|
+
"@chatbi-v/plugin-layout-transform",
|
|
570
|
+
"@chatbi-v/plugin-system-monitor"
|
|
571
|
+
];
|
|
572
|
+
}
|
|
573
|
+
static {
|
|
574
|
+
/** 运行时必须依赖 */
|
|
575
|
+
this.RUNTIME_DEPS = [
|
|
576
|
+
"@ant-design/x",
|
|
577
|
+
"@ant-design/icons",
|
|
578
|
+
"antd",
|
|
579
|
+
"react",
|
|
580
|
+
"react-dom",
|
|
581
|
+
"lucide-react",
|
|
582
|
+
"framer-motion",
|
|
583
|
+
"clsx",
|
|
584
|
+
"tailwind-merge",
|
|
585
|
+
"react-router-dom",
|
|
586
|
+
"zustand",
|
|
587
|
+
"axios",
|
|
588
|
+
"less",
|
|
589
|
+
"vite"
|
|
590
|
+
];
|
|
591
|
+
}
|
|
592
|
+
/** 获取沙箱根目录 */
|
|
593
|
+
static getRoot() {
|
|
594
|
+
return SandboxPath.getRoot();
|
|
595
|
+
}
|
|
596
|
+
/** 获取所有版本的根目录 */
|
|
597
|
+
static getVersionRoot() {
|
|
598
|
+
return SandboxPath.getVersionRoot();
|
|
599
|
+
}
|
|
600
|
+
/** 获取指定版本的沙箱路径 */
|
|
601
|
+
static getVersionPath(version) {
|
|
602
|
+
return SandboxPath.getVersionPath(version);
|
|
603
|
+
}
|
|
604
|
+
/** 获取项目的工作区根目录 (Monorepo 支持) */
|
|
605
|
+
static async getWorkspaceRoot(cwd) {
|
|
606
|
+
return SandboxPath.getWorkspaceRoot(cwd);
|
|
607
|
+
}
|
|
608
|
+
/** 清理指定版本的沙箱物理文件 */
|
|
609
|
+
static async cleanVersion(version) {
|
|
610
|
+
const versionPath = this.getVersionPath(version);
|
|
611
|
+
if (fs6.existsSync(versionPath)) {
|
|
612
|
+
await fs6.remove(versionPath);
|
|
560
613
|
}
|
|
561
|
-
await fs2.symlink(targetPath, currentLinkPath, "dir");
|
|
562
614
|
}
|
|
563
615
|
/**
|
|
564
|
-
*
|
|
616
|
+
* 优雅清理缓存环境
|
|
617
|
+
* @param cwd 当前项目路径
|
|
618
|
+
* @param deep 是否执行深度清理
|
|
565
619
|
*/
|
|
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
|
-
|
|
620
|
+
static async clean(cwd, deep = false) {
|
|
621
|
+
const spinner = createSpinner("\u6B63\u5728\u6E05\u7406\u7F13\u5B58\u76EE\u5F55...").start();
|
|
622
|
+
try {
|
|
623
|
+
const workspaceRoot = await this.getWorkspaceRoot(cwd);
|
|
624
|
+
let cleanedCount = 0;
|
|
625
|
+
const cachePatterns = [
|
|
626
|
+
path8.join(workspaceRoot, `**/${SANDBOX_CONFIG.DIRS.CACHE}`)
|
|
627
|
+
];
|
|
628
|
+
const cacheDirs = await fg2(cachePatterns, {
|
|
629
|
+
onlyFiles: false,
|
|
630
|
+
// 允许匹配文件和符号链接
|
|
631
|
+
absolute: true,
|
|
632
|
+
ignore: ["**/node_modules/**"],
|
|
633
|
+
dot: true
|
|
634
|
+
// 确保能匹配到以 . 开头的目录
|
|
635
|
+
});
|
|
636
|
+
for (const dir of cacheDirs) {
|
|
637
|
+
const stats = await fs6.lstat(dir).catch(() => null);
|
|
638
|
+
if (stats) {
|
|
639
|
+
await fs6.remove(dir);
|
|
640
|
+
cleanedCount++;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
if (deep) {
|
|
644
|
+
const distPatterns = [
|
|
645
|
+
path8.join(workspaceRoot, "**/dist")
|
|
646
|
+
];
|
|
647
|
+
const distDirs = await fg2(distPatterns, {
|
|
648
|
+
onlyFiles: false,
|
|
649
|
+
absolute: true,
|
|
650
|
+
ignore: [
|
|
651
|
+
"**/node_modules/**",
|
|
652
|
+
"**/packages/cli/dist/**",
|
|
653
|
+
// 保护 CLI 自身构建产物
|
|
654
|
+
"**/.git/**"
|
|
655
|
+
]
|
|
656
|
+
});
|
|
657
|
+
for (const dir of distDirs) {
|
|
658
|
+
const stats = await fs6.lstat(dir).catch(() => null);
|
|
659
|
+
if (stats) {
|
|
660
|
+
const hasPkg = fs6.existsSync(path8.join(path8.dirname(dir), "package.json"));
|
|
661
|
+
if (hasPkg) {
|
|
662
|
+
await fs6.remove(dir);
|
|
663
|
+
cleanedCount++;
|
|
588
664
|
}
|
|
589
|
-
} catch (e) {
|
|
590
665
|
}
|
|
591
666
|
}
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
667
|
+
const globalRoot = this.getRoot();
|
|
668
|
+
if (fs6.existsSync(globalRoot)) {
|
|
669
|
+
await fs6.remove(globalRoot);
|
|
670
|
+
cleanedCount++;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
spinner.succeed(pc3.green(`\u6E05\u7406\u5B8C\u6210\uFF0C\u5171\u6E05\u7406 ${cleanedCount} \u4E2A\u9879\u76EE/\u7F13\u5B58\u76EE\u5F55`));
|
|
674
|
+
} catch (e) {
|
|
675
|
+
spinner.fail(pc3.red(`\u6E05\u7406\u5931\u8D25: ${e.message}`));
|
|
597
676
|
}
|
|
598
|
-
printBox(statusText, "ChatBI \u5185\u6838\u53EF\u89C2\u6D4B\u6027\u9762\u677F");
|
|
599
677
|
}
|
|
600
678
|
/**
|
|
601
|
-
*
|
|
679
|
+
* 准备内核沙箱环境 (安装/更新)
|
|
602
680
|
*/
|
|
603
|
-
static async
|
|
681
|
+
static async prepare(version, force = false) {
|
|
682
|
+
const versionPath = this.getVersionPath(version);
|
|
683
|
+
if (!force && fs6.existsSync(path8.join(versionPath, "node_modules/tailwindcss"))) {
|
|
684
|
+
return versionPath;
|
|
685
|
+
}
|
|
686
|
+
if (fs6.existsSync(versionPath)) {
|
|
687
|
+
await fs6.remove(path8.join(versionPath, "node_modules"));
|
|
688
|
+
}
|
|
689
|
+
await fs6.ensureDir(versionPath);
|
|
690
|
+
const spinner = createSpinner(`\u6B63\u5728\u521D\u59CB\u5316\u5185\u6838\u6C99\u7BB1 ${pc3.cyan(version)}...`).start();
|
|
604
691
|
try {
|
|
605
|
-
const
|
|
606
|
-
const
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
if (vIdx !== -1 && parts[vIdx + 1]) {
|
|
613
|
-
return parts[vIdx + 1];
|
|
614
|
-
}
|
|
615
|
-
}
|
|
692
|
+
const cliRoot = await getCliRoot();
|
|
693
|
+
const dependencies = {};
|
|
694
|
+
for (const pkg of this.RUNTIME_DEPS) {
|
|
695
|
+
dependencies[pkg] = DEPENDENCY_VERSIONS[pkg] || "latest";
|
|
696
|
+
}
|
|
697
|
+
for (const pkg of this.CORE_PACKAGES) {
|
|
698
|
+
dependencies[pkg] = pkg === "@chatbi-v/core" ? version : "latest";
|
|
616
699
|
}
|
|
700
|
+
const templateData = {
|
|
701
|
+
version,
|
|
702
|
+
dependencies,
|
|
703
|
+
devDependencies: DEPENDENCY_VERSIONS
|
|
704
|
+
};
|
|
705
|
+
await SandboxRenderer.renderDirectory(
|
|
706
|
+
path8.join(cliRoot, "templates/sandbox"),
|
|
707
|
+
versionPath,
|
|
708
|
+
templateData
|
|
709
|
+
);
|
|
710
|
+
spinner.text = pc3.gray(" \u{1F50D} \u68C0\u67E5\u672C\u5730\u5F00\u53D1\u73AF\u5883...");
|
|
711
|
+
const isLocalDev = await SandboxPkgManager.tryLinkLocalPackages(versionPath, this.CORE_PACKAGES, this.RUNTIME_DEPS);
|
|
712
|
+
const installArgs = isLocalDev ? ["install", "--no-frozen-lockfile"] : ["install"];
|
|
713
|
+
spinner.text = pc3.gray(` \u23F3 \u6267\u884C pnpm ${installArgs.join(" ")}...`);
|
|
714
|
+
await execa("pnpm", installArgs, { cwd: versionPath });
|
|
715
|
+
spinner.text = pc3.gray(" \u{1F3A8} \u540C\u6B65 Shell \u6A21\u677F...");
|
|
716
|
+
await this.ensureShell(version, force);
|
|
717
|
+
spinner.succeed(pc3.green(`\u5185\u6838\u6C99\u7BB1 ${version} \u521D\u59CB\u5316\u6210\u529F`));
|
|
617
718
|
} catch (e) {
|
|
719
|
+
spinner.fail(pc3.red(`\u5185\u6838\u6C99\u7BB1\u521D\u59CB\u5316\u5931\u8D25: ${e.message}`));
|
|
720
|
+
throw e;
|
|
618
721
|
}
|
|
619
|
-
return
|
|
722
|
+
return versionPath;
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* 确保 Shell 模板已同步到沙箱
|
|
726
|
+
*/
|
|
727
|
+
static async ensureShell(version, force = false) {
|
|
728
|
+
const versionPath = this.getVersionPath(version);
|
|
729
|
+
const shellDestDir = path8.join(versionPath, "shell");
|
|
730
|
+
if (!force && fs6.existsSync(path8.join(shellDestDir, "tsconfig.paths.json"))) {
|
|
731
|
+
return shellDestDir;
|
|
732
|
+
}
|
|
733
|
+
const cliRoot = await getCliRoot();
|
|
734
|
+
const shellTemplateDir = path8.join(cliRoot, "templates/app");
|
|
735
|
+
if (fs6.existsSync(shellTemplateDir)) {
|
|
736
|
+
await fs6.remove(shellDestDir);
|
|
737
|
+
const templateData = {
|
|
738
|
+
name: "chatbi-shell",
|
|
739
|
+
version,
|
|
740
|
+
cliVersion: version,
|
|
741
|
+
theme: DEFAULT_CONFIG.THEME,
|
|
742
|
+
isShell: true,
|
|
743
|
+
isBusiness: true,
|
|
744
|
+
tsconfigPath: "./tsconfig.paths.json"
|
|
745
|
+
};
|
|
746
|
+
await SandboxRenderer.renderDirectory(shellTemplateDir, shellDestDir, templateData);
|
|
747
|
+
await fs6.writeJson(path8.join(shellDestDir, "tsconfig.paths.json"), {
|
|
748
|
+
compilerOptions: { baseUrl: ".", paths: { "@/*": ["./src/*"] } }
|
|
749
|
+
}, { spaces: 2 });
|
|
750
|
+
}
|
|
751
|
+
return shellDestDir;
|
|
752
|
+
}
|
|
753
|
+
/** 注入项目虚拟上下文 */
|
|
754
|
+
static async injectContext(projectRoot, version) {
|
|
755
|
+
return SandboxContext.inject(projectRoot, version, this.CORE_PACKAGES, this.RUNTIME_DEPS);
|
|
756
|
+
}
|
|
757
|
+
/** 获取核心库的 Vite Alias 配置 */
|
|
758
|
+
static getCoreAlias(version) {
|
|
759
|
+
const versionPath = this.getVersionPath(version);
|
|
760
|
+
const sandboxNodeModules = path8.join(versionPath, "node_modules");
|
|
761
|
+
return Object.fromEntries(this.CORE_PACKAGES.map((pkg) => [pkg, path8.join(sandboxNodeModules, pkg)]));
|
|
762
|
+
}
|
|
763
|
+
/** 切换内核版本 */
|
|
764
|
+
static async useVersion(version) {
|
|
765
|
+
const versionRoot = this.getVersionRoot();
|
|
766
|
+
const currentLink = path8.join(versionRoot, SANDBOX_CONFIG.DIRS.CURRENT);
|
|
767
|
+
const targetPath = this.getVersionPath(version);
|
|
768
|
+
if (!fs6.existsSync(targetPath)) throw new Error(`\u7248\u672C ${version} \u4E0D\u5B58\u5728`);
|
|
769
|
+
if (fs6.existsSync(currentLink)) await fs6.remove(currentLink);
|
|
770
|
+
await fs6.ensureSymlink(targetPath, currentLink, "dir");
|
|
771
|
+
}
|
|
772
|
+
/** 解析版本号 */
|
|
773
|
+
static async resolveVersion(version) {
|
|
774
|
+
if (!version || version === "latest" || version === "current") {
|
|
775
|
+
const currentLink = path8.join(this.getVersionRoot(), SANDBOX_CONFIG.DIRS.CURRENT);
|
|
776
|
+
if (fs6.existsSync(currentLink)) {
|
|
777
|
+
return path8.basename(await fs6.readlink(currentLink));
|
|
778
|
+
}
|
|
779
|
+
const versions = await this.listVersions();
|
|
780
|
+
return versions[0] || "1.0.0";
|
|
781
|
+
}
|
|
782
|
+
return version;
|
|
783
|
+
}
|
|
784
|
+
/** 列出所有已安装版本 */
|
|
785
|
+
static async listVersions() {
|
|
786
|
+
const versionRoot = this.getVersionRoot();
|
|
787
|
+
if (!fs6.existsSync(versionRoot)) return [];
|
|
788
|
+
const dirs = await fs6.readdir(versionRoot);
|
|
789
|
+
return dirs.filter((d) => d !== SANDBOX_CONFIG.DIRS.CURRENT && !d.startsWith(".")).sort().reverse();
|
|
790
|
+
}
|
|
791
|
+
/** 可视化展示沙箱状态 */
|
|
792
|
+
static async visualizeStatus(cwd) {
|
|
793
|
+
const workspaceRoot = await this.getWorkspaceRoot(cwd);
|
|
794
|
+
const isMonorepo = workspaceRoot !== cwd;
|
|
795
|
+
const currentVersion = await this.resolveVersion("current");
|
|
796
|
+
const versions = await this.listVersions();
|
|
797
|
+
const statusInfo = [
|
|
798
|
+
`${pc3.bold("\u9879\u76EE\u8DEF\u5F84:")} ${pc3.cyan(cwd)}`,
|
|
799
|
+
`${pc3.bold("\u67B6\u6784\u6A21\u5F0F:")} ${isMonorepo ? pc3.yellow("Monorepo") : pc3.green("Standalone")}`,
|
|
800
|
+
`${pc3.bold("\u5F53\u524D\u5185\u6838:")} ${pc3.green(currentVersion)}`,
|
|
801
|
+
`${pc3.bold("\u5DF2\u88C5\u7248\u672C:")} ${pc3.gray(versions.join(", ") || "none")}`,
|
|
802
|
+
`${pc3.bold("\u6C99\u7BB1\u6839\u76EE\u5F55:")} ${pc3.gray(this.getRoot())}`
|
|
803
|
+
].join("\n");
|
|
804
|
+
printBox(statusInfo, "ChatBI Sandbox Status");
|
|
620
805
|
}
|
|
621
806
|
};
|
|
622
807
|
}
|
|
623
808
|
});
|
|
624
809
|
|
|
625
810
|
// src/config.ts
|
|
626
|
-
import
|
|
627
|
-
import
|
|
811
|
+
import fs7 from "fs-extra";
|
|
812
|
+
import path9 from "path";
|
|
628
813
|
import { createJiti } from "jiti";
|
|
629
814
|
var ConfigManager;
|
|
630
815
|
var init_config = __esm({
|
|
@@ -632,15 +817,11 @@ var init_config = __esm({
|
|
|
632
817
|
"use strict";
|
|
633
818
|
init_esm_shims();
|
|
634
819
|
init_utils();
|
|
820
|
+
init_constants();
|
|
821
|
+
init_utils();
|
|
635
822
|
ConfigManager = class {
|
|
636
823
|
static {
|
|
637
|
-
this.CONFIG_FILES =
|
|
638
|
-
"chatbi.config.ts",
|
|
639
|
-
"chatbi.config.js",
|
|
640
|
-
"chatbi.config.json",
|
|
641
|
-
".chatbirc",
|
|
642
|
-
".chatbirc.json"
|
|
643
|
-
];
|
|
824
|
+
this.CONFIG_FILES = DEFAULT_CONFIG.CONFIG_FILES;
|
|
644
825
|
}
|
|
645
826
|
/**
|
|
646
827
|
* 加载项目配置
|
|
@@ -648,10 +829,10 @@ var init_config = __esm({
|
|
|
648
829
|
*/
|
|
649
830
|
static async loadConfig(cwd = process.cwd()) {
|
|
650
831
|
const config = {};
|
|
651
|
-
const versionFilePath =
|
|
652
|
-
if (
|
|
832
|
+
const versionFilePath = path9.join(cwd, SANDBOX_CONFIG.LOCK_FILE);
|
|
833
|
+
if (fs7.existsSync(versionFilePath)) {
|
|
653
834
|
try {
|
|
654
|
-
const version = (await
|
|
835
|
+
const version = (await fs7.readFile(versionFilePath, "utf-8")).trim();
|
|
655
836
|
if (version) {
|
|
656
837
|
config.coreVersion = version;
|
|
657
838
|
}
|
|
@@ -660,15 +841,15 @@ var init_config = __esm({
|
|
|
660
841
|
}
|
|
661
842
|
const jiti = createJiti(cwd);
|
|
662
843
|
for (const file of this.CONFIG_FILES) {
|
|
663
|
-
const configPath =
|
|
664
|
-
if (
|
|
844
|
+
const configPath = path9.join(cwd, file);
|
|
845
|
+
if (fs7.existsSync(configPath)) {
|
|
665
846
|
try {
|
|
666
847
|
let projectConfig = {};
|
|
667
848
|
if (file.endsWith(".ts") || file.endsWith(".js")) {
|
|
668
849
|
const mod = await jiti.import(configPath, { default: true });
|
|
669
850
|
projectConfig = mod.default || mod || {};
|
|
670
851
|
} else if (file.endsWith(".json") || file.startsWith(".chatbirc")) {
|
|
671
|
-
projectConfig = await
|
|
852
|
+
projectConfig = await fs7.readJson(configPath);
|
|
672
853
|
}
|
|
673
854
|
return {
|
|
674
855
|
...projectConfig,
|
|
@@ -681,16 +862,76 @@ var init_config = __esm({
|
|
|
681
862
|
}
|
|
682
863
|
return config;
|
|
683
864
|
}
|
|
865
|
+
/**
|
|
866
|
+
* 解析核心依赖的具体路径或版本号
|
|
867
|
+
* @param config 项目配置
|
|
868
|
+
* @param relativeTo 相对路径(用于 local 模式下的 file: 协议生成)
|
|
869
|
+
*/
|
|
870
|
+
static async resolveCoreDependency(config, relativeTo = ".") {
|
|
871
|
+
const { coreSource = "local", coreVersion } = config;
|
|
872
|
+
if (coreSource === "npm") {
|
|
873
|
+
if (coreVersion) return coreVersion;
|
|
874
|
+
const cliRoot = await getCliRoot();
|
|
875
|
+
const cliPkg = await fs7.readJson(path9.join(cliRoot, "package.json"));
|
|
876
|
+
return cliPkg.version;
|
|
877
|
+
}
|
|
878
|
+
const sandboxCorePath = path9.join(SANDBOX_CONFIG.DIRS.CACHE, "core");
|
|
879
|
+
const cwd = process.cwd();
|
|
880
|
+
const absoluteRelativeTo = path9.isAbsolute(relativeTo) ? relativeTo : path9.resolve(cwd, relativeTo);
|
|
881
|
+
const absoluteProjectRoot = cwd;
|
|
882
|
+
const relativePath = path9.relative(absoluteRelativeTo, path9.join(absoluteProjectRoot, sandboxCorePath));
|
|
883
|
+
return `file:${relativePath}`;
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* 加载 tsup 配置
|
|
887
|
+
* @param cwd 项目根目录
|
|
888
|
+
*/
|
|
889
|
+
static async loadTsupConfig(cwd = process.cwd()) {
|
|
890
|
+
const TSUP_CONFIG_FILES = [
|
|
891
|
+
"tsup.config.ts",
|
|
892
|
+
"tsup.config.js",
|
|
893
|
+
"tsup.config.cjs",
|
|
894
|
+
"tsup.config.mjs",
|
|
895
|
+
"tsup.config.json"
|
|
896
|
+
];
|
|
897
|
+
const jiti = createJiti(cwd);
|
|
898
|
+
for (const file of TSUP_CONFIG_FILES) {
|
|
899
|
+
const configPath = path9.join(cwd, file);
|
|
900
|
+
if (fs7.existsSync(configPath)) {
|
|
901
|
+
try {
|
|
902
|
+
if (file.endsWith(".json")) {
|
|
903
|
+
return await fs7.readJson(configPath);
|
|
904
|
+
} else {
|
|
905
|
+
const mod = await jiti.import(configPath, { default: true });
|
|
906
|
+
return mod.default || mod || {};
|
|
907
|
+
}
|
|
908
|
+
} catch (e) {
|
|
909
|
+
logger.warn(`\u52A0\u8F7D tsup \u914D\u7F6E\u6587\u4EF6 ${file} \u5931\u8D25: ${e.message}`);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
const pkgPath = path9.join(cwd, "package.json");
|
|
914
|
+
if (fs7.existsSync(pkgPath)) {
|
|
915
|
+
try {
|
|
916
|
+
const pkg = await fs7.readJson(pkgPath);
|
|
917
|
+
if (pkg.tsup) {
|
|
918
|
+
return pkg.tsup;
|
|
919
|
+
}
|
|
920
|
+
} catch (e) {
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
return {};
|
|
924
|
+
}
|
|
684
925
|
};
|
|
685
926
|
}
|
|
686
927
|
});
|
|
687
928
|
|
|
688
929
|
// src/corekit.ts
|
|
689
|
-
import
|
|
690
|
-
import
|
|
691
|
-
import
|
|
930
|
+
import path10 from "path";
|
|
931
|
+
import fs8 from "fs-extra";
|
|
932
|
+
import pc4 from "picocolors";
|
|
692
933
|
import prompts from "prompts";
|
|
693
|
-
import
|
|
934
|
+
import fg3 from "fast-glob";
|
|
694
935
|
var CoreKit;
|
|
695
936
|
var init_corekit = __esm({
|
|
696
937
|
"src/corekit.ts"() {
|
|
@@ -704,20 +945,20 @@ var init_corekit = __esm({
|
|
|
704
945
|
* 解析项目模式
|
|
705
946
|
*/
|
|
706
947
|
static async detectMode(cwd) {
|
|
707
|
-
const pkgPath =
|
|
708
|
-
if (!
|
|
709
|
-
const pkg = await
|
|
710
|
-
if (pkg.workspaces ||
|
|
948
|
+
const pkgPath = path10.join(cwd, "package.json");
|
|
949
|
+
if (!fs8.existsSync(pkgPath)) return "app";
|
|
950
|
+
const pkg = await fs8.readJson(pkgPath);
|
|
951
|
+
if (pkg.workspaces || fs8.existsSync(path10.join(cwd, "pnpm-workspace.yaml"))) {
|
|
711
952
|
return "monorepo";
|
|
712
953
|
}
|
|
713
954
|
if (pkg.chatbi?.type === "plugin" || pkg.plugin === true) return "plugin";
|
|
714
955
|
if (pkg.chatbi?.type === "app") return "app";
|
|
715
|
-
const pluginEntries = await
|
|
956
|
+
const pluginEntries = await fg3(["index.plugin.{ts,js}", "src/index.plugin.{ts,js}"], { cwd });
|
|
716
957
|
if (pluginEntries.length > 0) return "plugin";
|
|
717
|
-
if (
|
|
958
|
+
if (fs8.existsSync(path10.join(cwd, "index.html"))) {
|
|
718
959
|
return "app";
|
|
719
960
|
}
|
|
720
|
-
if (
|
|
961
|
+
if (fs8.existsSync(path10.join(cwd, "src/index.ts")) || fs8.existsSync(path10.join(cwd, "src/index.tsx"))) {
|
|
721
962
|
if (pkg.bin) return "lib";
|
|
722
963
|
if (pkg.peerDependencies?.react && !pkg.dependencies?.react) return "plugin";
|
|
723
964
|
return "lib";
|
|
@@ -735,18 +976,18 @@ var init_corekit = __esm({
|
|
|
735
976
|
}
|
|
736
977
|
try {
|
|
737
978
|
const cliRoot = await getCliRoot();
|
|
738
|
-
const cliVersionFile =
|
|
739
|
-
if (
|
|
740
|
-
const version = (await
|
|
979
|
+
const cliVersionFile = path10.join(cliRoot, ".chatbi-version");
|
|
980
|
+
if (fs8.existsSync(cliVersionFile)) {
|
|
981
|
+
const version = (await fs8.readFile(cliVersionFile, "utf-8")).trim();
|
|
741
982
|
if (version) return version;
|
|
742
983
|
}
|
|
743
984
|
} catch (e) {
|
|
744
985
|
}
|
|
745
|
-
const currentLinkPath =
|
|
746
|
-
if (
|
|
986
|
+
const currentLinkPath = path10.join(Sandbox.getVersionRoot(), "current");
|
|
987
|
+
if (fs8.existsSync(currentLinkPath)) {
|
|
747
988
|
try {
|
|
748
|
-
const realPath = await
|
|
749
|
-
return
|
|
989
|
+
const realPath = await fs8.realpath(currentLinkPath);
|
|
990
|
+
return path10.basename(realPath);
|
|
750
991
|
} catch (e) {
|
|
751
992
|
}
|
|
752
993
|
}
|
|
@@ -758,8 +999,8 @@ var init_corekit = __esm({
|
|
|
758
999
|
*/
|
|
759
1000
|
static async listVersions() {
|
|
760
1001
|
const versionsDir = Sandbox.getVersionRoot();
|
|
761
|
-
if (!
|
|
762
|
-
const dirs = await
|
|
1002
|
+
if (!fs8.existsSync(versionsDir)) return [];
|
|
1003
|
+
const dirs = await fg3("*", {
|
|
763
1004
|
cwd: versionsDir,
|
|
764
1005
|
onlyDirectories: true,
|
|
765
1006
|
deep: 1
|
|
@@ -770,18 +1011,18 @@ var init_corekit = __esm({
|
|
|
770
1011
|
* 自动发现项目中的插件
|
|
771
1012
|
*/
|
|
772
1013
|
static async discoverPlugins(rootDir) {
|
|
773
|
-
const pluginsDir =
|
|
774
|
-
if (!
|
|
775
|
-
const pkgFiles = await
|
|
1014
|
+
const pluginsDir = path10.join(rootDir, "plugins");
|
|
1015
|
+
if (!fs8.existsSync(pluginsDir)) return [];
|
|
1016
|
+
const pkgFiles = await fg3("*/package.json", { cwd: pluginsDir, absolute: true });
|
|
776
1017
|
const plugins = [];
|
|
777
1018
|
for (const pkgPath of pkgFiles) {
|
|
778
1019
|
try {
|
|
779
|
-
const pkg = await
|
|
780
|
-
const pluginPath =
|
|
1020
|
+
const pkg = await fs8.readJson(pkgPath);
|
|
1021
|
+
const pluginPath = path10.dirname(pkgPath);
|
|
781
1022
|
plugins.push({
|
|
782
|
-
name: pkg.name ||
|
|
1023
|
+
name: pkg.name || path10.basename(pluginPath),
|
|
783
1024
|
path: pluginPath,
|
|
784
|
-
id:
|
|
1025
|
+
id: path10.basename(pluginPath)
|
|
785
1026
|
});
|
|
786
1027
|
} catch (e) {
|
|
787
1028
|
}
|
|
@@ -795,19 +1036,19 @@ var init_corekit = __esm({
|
|
|
795
1036
|
const mode = await this.detectMode(cwd);
|
|
796
1037
|
const version = await this.resolveVersion(cwd);
|
|
797
1038
|
printBox(
|
|
798
|
-
`${
|
|
1039
|
+
`${pc4.cyan(pc4.bold("\u{1F680} ChatBI Dev Server"))}
|
|
799
1040
|
|
|
800
|
-
${
|
|
801
|
-
${
|
|
802
|
-
${
|
|
1041
|
+
${pc4.gray("Mode: ")} ${pc4.yellow(mode)}
|
|
1042
|
+
${pc4.gray("Kernel: ")} ${pc4.green(version)}
|
|
1043
|
+
${pc4.gray("Root: ")} ${pc4.white(cwd)}`,
|
|
803
1044
|
"Dev Server"
|
|
804
1045
|
);
|
|
805
1046
|
const spinner = createSpinner("\u6B63\u5728\u51C6\u5907\u6C99\u7BB1\u73AF\u5883...").start();
|
|
806
1047
|
try {
|
|
807
1048
|
await Sandbox.prepare(version);
|
|
808
|
-
spinner.text =
|
|
1049
|
+
spinner.text = pc4.cyan("\u6B63\u5728\u6CE8\u5165\u865A\u62DF\u4E0A\u4E0B\u6587...");
|
|
809
1050
|
await Sandbox.injectContext(cwd, version);
|
|
810
|
-
spinner.succeed(
|
|
1051
|
+
spinner.succeed(pc4.green("\u73AF\u5883\u5C31\u7EEA"));
|
|
811
1052
|
if (mode === "plugin") {
|
|
812
1053
|
await this.startPluginDevServer(cwd, version, options.port);
|
|
813
1054
|
} else if (mode === "app") {
|
|
@@ -816,22 +1057,22 @@ ${pc3.gray("Root: ")} ${pc3.white(cwd)}`,
|
|
|
816
1057
|
await this.startMonorepoDevServer(cwd, version, options.port);
|
|
817
1058
|
}
|
|
818
1059
|
} catch (e) {
|
|
819
|
-
spinner.fail(
|
|
1060
|
+
spinner.fail(pc4.red(`\u542F\u52A8\u5931\u8D25: ${e.message}`));
|
|
820
1061
|
}
|
|
821
1062
|
}
|
|
822
1063
|
/**
|
|
823
1064
|
* 启动 Monorepo 开发服务器
|
|
824
1065
|
*/
|
|
825
1066
|
static async startMonorepoDevServer(rootDir, version, customPort) {
|
|
826
|
-
const appsDir =
|
|
827
|
-
if (!
|
|
1067
|
+
const appsDir = path10.join(rootDir, "apps");
|
|
1068
|
+
if (!fs8.existsSync(appsDir)) {
|
|
828
1069
|
logger.warn("\u5F53\u524D Monorepo \u4E0B\u672A\u627E\u5230 apps/ \u76EE\u5F55");
|
|
829
1070
|
return;
|
|
830
1071
|
}
|
|
831
|
-
const pkgFiles = await
|
|
1072
|
+
const pkgFiles = await fg3("*/package.json", { cwd: appsDir, absolute: true });
|
|
832
1073
|
const apps = pkgFiles.map((pkgPath) => ({
|
|
833
|
-
name:
|
|
834
|
-
path:
|
|
1074
|
+
name: path10.basename(path10.dirname(pkgPath)),
|
|
1075
|
+
path: path10.dirname(pkgPath)
|
|
835
1076
|
}));
|
|
836
1077
|
if (apps.length === 0) {
|
|
837
1078
|
logger.warn("\u5F53\u524D Monorepo \u4E0B\u672A\u627E\u5230\u4EFB\u4F55\u5E94\u7528 (apps/)");
|
|
@@ -858,14 +1099,14 @@ ${pc3.gray("Root: ")} ${pc3.white(cwd)}`,
|
|
|
858
1099
|
const shellPort = customPort || 5173;
|
|
859
1100
|
const sandboxRoot = Sandbox.getRoot();
|
|
860
1101
|
const versionPath = Sandbox.getVersionPath(version);
|
|
861
|
-
const sandboxNodeModules =
|
|
1102
|
+
const sandboxNodeModules = path10.join(versionPath, "node_modules");
|
|
862
1103
|
const shellDir = await Sandbox.ensureShell(version);
|
|
863
1104
|
const coreAlias = Sandbox.getCoreAlias(version);
|
|
864
|
-
const tailwindPath =
|
|
865
|
-
const autoprefixerPath =
|
|
866
|
-
let pluginEntry =
|
|
867
|
-
if (!
|
|
868
|
-
pluginEntry =
|
|
1105
|
+
const tailwindPath = path10.join(sandboxNodeModules, "tailwindcss");
|
|
1106
|
+
const autoprefixerPath = path10.join(sandboxNodeModules, "autoprefixer");
|
|
1107
|
+
let pluginEntry = path10.join(pluginDir, "src/index.tsx");
|
|
1108
|
+
if (!fs8.existsSync(pluginEntry)) {
|
|
1109
|
+
pluginEntry = path10.join(pluginDir, "src/index.ts");
|
|
869
1110
|
}
|
|
870
1111
|
const define = {
|
|
871
1112
|
"process.env.CHATBI_PLUGIN_PATH": JSON.stringify(pluginDir)
|
|
@@ -879,12 +1120,12 @@ ${pc3.gray("Root: ")} ${pc3.white(cwd)}`,
|
|
|
879
1120
|
postcss: {
|
|
880
1121
|
plugins: [
|
|
881
1122
|
__require(tailwindPath)({
|
|
882
|
-
presets: [__require(
|
|
1123
|
+
presets: [__require(path10.join(sandboxNodeModules, "@chatbi-v/tailwind-config"))],
|
|
883
1124
|
darkMode: "class",
|
|
884
1125
|
content: [
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
1126
|
+
path10.join(shellDir, "index.html"),
|
|
1127
|
+
path10.join(shellDir, "src/**/*.{ts,tsx}"),
|
|
1128
|
+
path10.join(pluginDir, "src/**/*.{ts,tsx}")
|
|
888
1129
|
]
|
|
889
1130
|
}),
|
|
890
1131
|
__require(autoprefixerPath)
|
|
@@ -894,25 +1135,33 @@ ${pc3.gray("Root: ")} ${pc3.white(cwd)}`,
|
|
|
894
1135
|
server: {
|
|
895
1136
|
port: shellPort,
|
|
896
1137
|
host: true,
|
|
1138
|
+
watch: {
|
|
1139
|
+
// 关键:排除沙箱和软链目录,防止 Vite 挂起
|
|
1140
|
+
ignored: [
|
|
1141
|
+
"**/.chatbi/**",
|
|
1142
|
+
"**/node_modules/**",
|
|
1143
|
+
Sandbox.getRoot()
|
|
1144
|
+
]
|
|
1145
|
+
},
|
|
897
1146
|
fs: {
|
|
898
1147
|
allow: [
|
|
899
1148
|
sandboxRoot,
|
|
900
1149
|
pluginDir,
|
|
901
|
-
|
|
1150
|
+
path10.resolve(pluginDir, "../../")
|
|
902
1151
|
]
|
|
903
1152
|
}
|
|
904
1153
|
},
|
|
905
1154
|
resolve: {
|
|
906
1155
|
alias: {
|
|
907
1156
|
...coreAlias,
|
|
908
|
-
"react":
|
|
909
|
-
"react-dom":
|
|
910
|
-
"@":
|
|
1157
|
+
"react": path10.join(sandboxNodeModules, "react"),
|
|
1158
|
+
"react-dom": path10.join(sandboxNodeModules, "react-dom"),
|
|
1159
|
+
"@": path10.join(shellDir, "src"),
|
|
911
1160
|
// 关键:将虚拟模块指向用户插件
|
|
912
1161
|
"virtual:user-plugin": pluginEntry,
|
|
913
1162
|
// 防止 glob 报错,提供空的映射
|
|
914
|
-
"@chatbi-plugins":
|
|
915
|
-
"@chatbi-apps":
|
|
1163
|
+
"@chatbi-plugins": path10.join(shellDir, "empty"),
|
|
1164
|
+
"@chatbi-apps": path10.join(shellDir, "empty")
|
|
916
1165
|
}
|
|
917
1166
|
},
|
|
918
1167
|
define
|
|
@@ -920,9 +1169,9 @@ ${pc3.gray("Root: ")} ${pc3.white(cwd)}`,
|
|
|
920
1169
|
await server.listen();
|
|
921
1170
|
const localUrl = `http://localhost:${shellPort}/`;
|
|
922
1171
|
printBox(
|
|
923
|
-
`${
|
|
1172
|
+
`${pc4.green(pc4.bold("\u2705 \u6258\u7BA1\u5F0F Shell \u5DF2\u542F\u52A8"))}
|
|
924
1173
|
|
|
925
|
-
${
|
|
1174
|
+
${pc4.white("Local: ")} ${pc4.cyan(pc4.underline(localUrl))}`,
|
|
926
1175
|
"Shell Success"
|
|
927
1176
|
);
|
|
928
1177
|
} catch (e) {
|
|
@@ -935,7 +1184,7 @@ ${pc3.white("Local: ")} ${pc3.cyan(pc3.underline(localUrl))}`,
|
|
|
935
1184
|
static async startAppDevServer(appDir, version, customPort) {
|
|
936
1185
|
logger.info("\u6B63\u5728\u542F\u52A8\u5E94\u7528...");
|
|
937
1186
|
const versionPath = Sandbox.getVersionPath(version);
|
|
938
|
-
const sandboxNodeModules =
|
|
1187
|
+
const sandboxNodeModules = path10.join(versionPath, "node_modules");
|
|
939
1188
|
const coreAlias = Sandbox.getCoreAlias(version);
|
|
940
1189
|
const { createServer, loadConfigFromFile } = await import("vite");
|
|
941
1190
|
try {
|
|
@@ -949,14 +1198,22 @@ ${pc3.white("Local: ")} ${pc3.cyan(pc3.underline(localUrl))}`,
|
|
|
949
1198
|
alias: {
|
|
950
1199
|
...coreAlias,
|
|
951
1200
|
// 补充常用的基础依赖映射,防止用户 vite.config.ts 中的插件找不到依赖
|
|
952
|
-
"react":
|
|
953
|
-
"react-dom":
|
|
954
|
-
"@vitejs/plugin-react":
|
|
1201
|
+
"react": path10.join(sandboxNodeModules, "react"),
|
|
1202
|
+
"react-dom": path10.join(sandboxNodeModules, "react-dom"),
|
|
1203
|
+
"@vitejs/plugin-react": path10.join(sandboxNodeModules, "@vitejs/plugin-react")
|
|
955
1204
|
}
|
|
956
1205
|
},
|
|
957
1206
|
server: {
|
|
958
1207
|
port: customPort || 3e3,
|
|
959
1208
|
host: true,
|
|
1209
|
+
watch: {
|
|
1210
|
+
// 关键:排除沙箱和软链目录,防止 Vite 挂起
|
|
1211
|
+
ignored: [
|
|
1212
|
+
"**/.chatbi/**",
|
|
1213
|
+
"**/node_modules/**",
|
|
1214
|
+
Sandbox.getRoot()
|
|
1215
|
+
]
|
|
1216
|
+
},
|
|
960
1217
|
fs: {
|
|
961
1218
|
allow: [
|
|
962
1219
|
Sandbox.getRoot(),
|
|
@@ -970,9 +1227,9 @@ ${pc3.white("Local: ")} ${pc3.cyan(pc3.underline(localUrl))}`,
|
|
|
970
1227
|
await server.listen();
|
|
971
1228
|
const localUrl = `http://localhost:${server.config.server.port}/`;
|
|
972
1229
|
printBox(
|
|
973
|
-
`${
|
|
1230
|
+
`${pc4.green(pc4.bold("\u2705 \u5E94\u7528\u5DF2\u6210\u529F\u542F\u52A8"))}
|
|
974
1231
|
|
|
975
|
-
${
|
|
1232
|
+
${pc4.white("Local: ")} ${pc4.cyan(pc4.underline(localUrl))}`,
|
|
976
1233
|
"App Success"
|
|
977
1234
|
);
|
|
978
1235
|
} catch (e) {
|
|
@@ -989,18 +1246,18 @@ __export(build_exports, {
|
|
|
989
1246
|
build: () => build
|
|
990
1247
|
});
|
|
991
1248
|
import { execa as execa2 } from "execa";
|
|
992
|
-
import
|
|
993
|
-
import
|
|
994
|
-
import
|
|
1249
|
+
import fs9 from "fs-extra";
|
|
1250
|
+
import path11 from "path";
|
|
1251
|
+
import pc5 from "picocolors";
|
|
995
1252
|
import { build as tsupBuild } from "tsup";
|
|
996
1253
|
async function build(options) {
|
|
997
1254
|
const cwd = process.cwd();
|
|
998
|
-
const pkgPath =
|
|
999
|
-
if (!
|
|
1255
|
+
const pkgPath = path11.join(cwd, "package.json");
|
|
1256
|
+
if (!fs9.existsSync(pkgPath)) {
|
|
1000
1257
|
logger.error(`\u5728 ${cwd} \u4E2D\u672A\u627E\u5230 package.json`);
|
|
1001
1258
|
return;
|
|
1002
1259
|
}
|
|
1003
|
-
const pkg = await
|
|
1260
|
+
const pkg = await fs9.readJson(pkgPath);
|
|
1004
1261
|
if (options.force) {
|
|
1005
1262
|
const spinnerClean = createSpinner("\u6B63\u5728\u6E05\u7406\u7F13\u5B58\u73AF\u5883...").start();
|
|
1006
1263
|
try {
|
|
@@ -1012,24 +1269,24 @@ async function build(options) {
|
|
|
1012
1269
|
}
|
|
1013
1270
|
}
|
|
1014
1271
|
const version = await CoreKit.resolveVersion(cwd);
|
|
1015
|
-
logger.info(`\u6B63\u5728\u6784\u5EFA\u9879\u76EE: ${
|
|
1272
|
+
logger.info(`\u6B63\u5728\u6784\u5EFA\u9879\u76EE: ${pc5.bold(pkg.name || "unnamed")} (\u5185\u6838\u7248\u672C: ${version})
|
|
1016
1273
|
`);
|
|
1017
1274
|
const spinner = createSpinner("\u6B63\u5728\u51C6\u5907\u6784\u5EFA\u73AF\u5883...").start();
|
|
1018
1275
|
spinner.text = "\u6B63\u5728\u540C\u6B65\u6C99\u7BB1\u5185\u6838...";
|
|
1019
1276
|
await Sandbox.prepare(version, options.force);
|
|
1020
|
-
if (pkg.workspaces ||
|
|
1277
|
+
if (pkg.workspaces || fs9.existsSync(path11.join(cwd, "pnpm-workspace.yaml"))) {
|
|
1021
1278
|
spinner.text = "\u68C0\u6D4B\u5230 Monorepo\uFF0C\u6B63\u5728\u521D\u59CB\u5316\u6839\u76EE\u5F55\u4E0A\u4E0B\u6587...";
|
|
1022
1279
|
await Sandbox.injectContext(cwd, version);
|
|
1023
1280
|
spinner.text = "\u6B63\u5728\u540C\u6B65\u5B50\u5305\u4E0A\u4E0B\u6587...";
|
|
1024
1281
|
const subDirs = ["apps", "plugins", "packages"];
|
|
1025
1282
|
for (const dir of subDirs) {
|
|
1026
|
-
const dirPath =
|
|
1027
|
-
if (
|
|
1028
|
-
const entries = await
|
|
1283
|
+
const dirPath = path11.join(cwd, dir);
|
|
1284
|
+
if (fs9.existsSync(dirPath)) {
|
|
1285
|
+
const entries = await fs9.readdir(dirPath, { withFileTypes: true });
|
|
1029
1286
|
for (const entry2 of entries) {
|
|
1030
1287
|
if (entry2.isDirectory()) {
|
|
1031
|
-
const subPkgPath =
|
|
1032
|
-
if (
|
|
1288
|
+
const subPkgPath = path11.join(dirPath, entry2.name);
|
|
1289
|
+
if (fs9.existsSync(path11.join(subPkgPath, "package.json"))) {
|
|
1033
1290
|
await Sandbox.injectContext(subPkgPath, version);
|
|
1034
1291
|
}
|
|
1035
1292
|
}
|
|
@@ -1043,7 +1300,7 @@ async function build(options) {
|
|
|
1043
1300
|
if (pkg.scripts && pkg.scripts.build && !process.env.CHATBI_CLI_INTERNAL) {
|
|
1044
1301
|
const buildScript = pkg.scripts.build;
|
|
1045
1302
|
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: ${
|
|
1303
|
+
logger.info(`\u68C0\u6D4B\u5230\u81EA\u5B9A\u4E49 build \u811A\u672C\uFF0C\u6B63\u5728\u6267\u884C: ${pc5.cyan("npm run build")}`);
|
|
1047
1304
|
const args = ["run", "build"];
|
|
1048
1305
|
if (options.watch) {
|
|
1049
1306
|
args.push("--", "--watch");
|
|
@@ -1067,7 +1324,7 @@ async function build(options) {
|
|
|
1067
1324
|
const coreAlias = Sandbox.getCoreAlias(version);
|
|
1068
1325
|
await viteBuild({
|
|
1069
1326
|
root: cwd,
|
|
1070
|
-
configFile:
|
|
1327
|
+
configFile: fs9.existsSync(path11.join(cwd, "vite.config.ts")) ? void 0 : false,
|
|
1071
1328
|
resolve: {
|
|
1072
1329
|
alias: {
|
|
1073
1330
|
...coreAlias
|
|
@@ -1091,45 +1348,32 @@ async function build(options) {
|
|
|
1091
1348
|
});
|
|
1092
1349
|
if (!options.watch) {
|
|
1093
1350
|
printBox(
|
|
1094
|
-
|
|
1351
|
+
pc5.green(pc5.bold("\u2728 \u5E94\u7528\u6784\u5EFA\u6210\u529F!")) + "\n\n" + pc5.white("\u4EA7\u7269\u76EE\u5F55: ") + pc5.cyan("dist"),
|
|
1095
1352
|
"Build Success"
|
|
1096
1353
|
);
|
|
1097
1354
|
}
|
|
1098
1355
|
return;
|
|
1099
1356
|
}
|
|
1100
1357
|
let entry = ["src/index.ts"];
|
|
1101
|
-
if (
|
|
1358
|
+
if (fs9.existsSync(path11.join(cwd, "src/index.tsx"))) {
|
|
1102
1359
|
entry = ["src/index.tsx"];
|
|
1103
|
-
} else if (!
|
|
1360
|
+
} else if (!fs9.existsSync(path11.join(cwd, "src/index.ts"))) {
|
|
1104
1361
|
logger.error("\u672A\u627E\u5230\u5165\u53E3\u6587\u4EF6\u3002\u671F\u671B src/index.ts \u6216 src/index.tsx");
|
|
1105
1362
|
return;
|
|
1106
1363
|
}
|
|
1107
1364
|
const isPlugin = mode === "plugin";
|
|
1365
|
+
const userConfig = await ConfigManager.loadTsupConfig(cwd);
|
|
1366
|
+
if (Object.keys(userConfig).length > 0) {
|
|
1367
|
+
logger.info(`\u5DF2\u52A0\u8F7D\u672C\u5730\u6784\u5EFA\u914D\u7F6E`);
|
|
1368
|
+
}
|
|
1108
1369
|
if (!options.watch) {
|
|
1109
|
-
await
|
|
1110
|
-
const tsbuildinfo =
|
|
1111
|
-
if (
|
|
1112
|
-
await
|
|
1370
|
+
await fs9.remove(path11.join(cwd, "dist"));
|
|
1371
|
+
const tsbuildinfo = path11.join(cwd, "tsconfig.tsbuildinfo");
|
|
1372
|
+
if (fs9.existsSync(tsbuildinfo)) {
|
|
1373
|
+
await fs9.remove(tsbuildinfo);
|
|
1113
1374
|
}
|
|
1114
1375
|
}
|
|
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
1376
|
if (isPlugin) {
|
|
1127
|
-
const coreDeps = Sandbox.CORE_PACKAGES;
|
|
1128
|
-
coreDeps.forEach((dep) => {
|
|
1129
|
-
if (!external.includes(dep)) {
|
|
1130
|
-
external.push(dep);
|
|
1131
|
-
}
|
|
1132
|
-
});
|
|
1133
1377
|
}
|
|
1134
1378
|
const commonConfig = {
|
|
1135
1379
|
entry,
|
|
@@ -1138,16 +1382,32 @@ async function build(options) {
|
|
|
1138
1382
|
sourcemap: false,
|
|
1139
1383
|
target: "esnext",
|
|
1140
1384
|
platform: isPlugin ? "browser" : "node",
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1385
|
+
...userConfig,
|
|
1386
|
+
// 合并用户配置
|
|
1387
|
+
external: [
|
|
1388
|
+
.../* @__PURE__ */ new Set([
|
|
1389
|
+
"react",
|
|
1390
|
+
"react-dom",
|
|
1391
|
+
"react/jsx-runtime",
|
|
1392
|
+
"react-is",
|
|
1393
|
+
"antd",
|
|
1394
|
+
"@ant-design/icons",
|
|
1395
|
+
"@ant-design/x",
|
|
1396
|
+
...Object.keys(pkg.dependencies || {}),
|
|
1397
|
+
...Object.keys(pkg.peerDependencies || {}),
|
|
1398
|
+
...isPlugin ? Sandbox.CORE_PACKAGES : [],
|
|
1399
|
+
...Array.isArray(userConfig.external) ? userConfig.external : []
|
|
1400
|
+
])
|
|
1401
|
+
],
|
|
1402
|
+
minify: userConfig.minify !== void 0 ? userConfig.minify : !options.watch,
|
|
1403
|
+
// 优先使用用户配置
|
|
1144
1404
|
watch: options.watch,
|
|
1145
1405
|
silent: true,
|
|
1146
|
-
esbuildOptions(
|
|
1147
|
-
|
|
1406
|
+
esbuildOptions(esbuildOpts) {
|
|
1407
|
+
esbuildOpts.logOverride = {
|
|
1148
1408
|
"empty-import-meta": "silent"
|
|
1149
1409
|
};
|
|
1150
|
-
|
|
1410
|
+
esbuildOpts.external = esbuildOpts.external || [];
|
|
1151
1411
|
const forceExternal = [
|
|
1152
1412
|
"react",
|
|
1153
1413
|
"react-dom",
|
|
@@ -1157,10 +1417,13 @@ async function build(options) {
|
|
|
1157
1417
|
...Sandbox.CORE_PACKAGES
|
|
1158
1418
|
];
|
|
1159
1419
|
forceExternal.forEach((dep) => {
|
|
1160
|
-
if (!
|
|
1161
|
-
|
|
1420
|
+
if (!esbuildOpts.external.includes(dep)) {
|
|
1421
|
+
esbuildOpts.external.push(dep);
|
|
1162
1422
|
}
|
|
1163
1423
|
});
|
|
1424
|
+
if (typeof userConfig.esbuildOptions === "function") {
|
|
1425
|
+
userConfig.esbuildOptions(esbuildOpts);
|
|
1426
|
+
}
|
|
1164
1427
|
}
|
|
1165
1428
|
};
|
|
1166
1429
|
const buildSpinner = createSpinner("\u6B63\u5728\u7F16\u8BD1\u6E90\u7801...").start();
|
|
@@ -1181,25 +1444,7 @@ async function build(options) {
|
|
|
1181
1444
|
define: {
|
|
1182
1445
|
"import.meta.env": "process.env"
|
|
1183
1446
|
},
|
|
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
|
-
}
|
|
1447
|
+
esbuildOptions: commonConfig.esbuildOptions
|
|
1203
1448
|
});
|
|
1204
1449
|
} else {
|
|
1205
1450
|
buildSpinner.text = "\u6B63\u5728\u7F16\u8BD1\u6E90\u7801...";
|
|
@@ -1215,15 +1460,15 @@ async function build(options) {
|
|
|
1215
1460
|
if (!options.watch) {
|
|
1216
1461
|
const dtsSpinner = createSpinner("\u6B63\u5728\u751F\u6210\u7C7B\u578B\u5B9A\u4E49...").start();
|
|
1217
1462
|
try {
|
|
1218
|
-
const localTsc =
|
|
1219
|
-
const sandboxTsc =
|
|
1463
|
+
const localTsc = path11.join(cwd, "node_modules/.bin/tsc");
|
|
1464
|
+
const sandboxTsc = path11.join(Sandbox.getVersionPath(version), "node_modules/.bin/tsc");
|
|
1220
1465
|
let tscBin = "tsc";
|
|
1221
|
-
if (
|
|
1466
|
+
if (fs9.existsSync(localTsc)) {
|
|
1222
1467
|
tscBin = localTsc;
|
|
1223
|
-
} else if (
|
|
1468
|
+
} else if (fs9.existsSync(sandboxTsc)) {
|
|
1224
1469
|
tscBin = sandboxTsc;
|
|
1225
1470
|
} else {
|
|
1226
|
-
if (
|
|
1471
|
+
if (fs9.existsSync(path11.join(cwd, "pnpm-lock.yaml"))) {
|
|
1227
1472
|
await execa2("pnpm", ["exec", "tsc", "--build", "tsconfig.json"]);
|
|
1228
1473
|
dtsSpinner.succeed("\u7C7B\u578B\u5B9A\u4E49\u751F\u6210\u5B8C\u6210");
|
|
1229
1474
|
} else {
|
|
@@ -1239,7 +1484,7 @@ async function build(options) {
|
|
|
1239
1484
|
dtsSpinner.warn("\u7C7B\u578B\u751F\u6210\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u9879\u76EE\u4E2D\u7684 tsconfig.json \u914D\u7F6E");
|
|
1240
1485
|
}
|
|
1241
1486
|
printBox(
|
|
1242
|
-
|
|
1487
|
+
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
1488
|
"Build Success"
|
|
1244
1489
|
);
|
|
1245
1490
|
}
|
|
@@ -1250,6 +1495,7 @@ var init_build = __esm({
|
|
|
1250
1495
|
init_esm_shims();
|
|
1251
1496
|
init_sandbox();
|
|
1252
1497
|
init_corekit();
|
|
1498
|
+
init_config();
|
|
1253
1499
|
init_utils();
|
|
1254
1500
|
}
|
|
1255
1501
|
});
|
|
@@ -1259,17 +1505,17 @@ var sync_exports = {};
|
|
|
1259
1505
|
__export(sync_exports, {
|
|
1260
1506
|
sync: () => sync
|
|
1261
1507
|
});
|
|
1262
|
-
import
|
|
1263
|
-
import
|
|
1264
|
-
import
|
|
1508
|
+
import fs10 from "fs-extra";
|
|
1509
|
+
import path12 from "path";
|
|
1510
|
+
import pc6 from "picocolors";
|
|
1265
1511
|
async function sync(options = {}) {
|
|
1266
1512
|
const cwd = options.cwd || process.cwd();
|
|
1267
|
-
const pkgPath =
|
|
1268
|
-
if (!
|
|
1513
|
+
const pkgPath = path12.join(cwd, "package.json");
|
|
1514
|
+
if (!fs10.existsSync(pkgPath)) {
|
|
1269
1515
|
logger.error("\u672A\u627E\u5230 package.json\u3002\u8BF7\u5728\u9879\u76EE\u6839\u76EE\u5F55\u4E0B\u8FD0\u884C\u3002");
|
|
1270
1516
|
return;
|
|
1271
1517
|
}
|
|
1272
|
-
const pkg = await
|
|
1518
|
+
const pkg = await fs10.readJson(pkgPath);
|
|
1273
1519
|
let version = options.version;
|
|
1274
1520
|
if (!version) {
|
|
1275
1521
|
version = await CoreKit.resolveVersion(cwd);
|
|
@@ -1284,8 +1530,8 @@ async function sync(options = {}) {
|
|
|
1284
1530
|
await Sandbox.prepare(version, options.force);
|
|
1285
1531
|
mainSpinner.text = "\u6B63\u5728\u751F\u6210\u865A\u62DF\u4E0A\u4E0B\u6587...";
|
|
1286
1532
|
if (options.version) {
|
|
1287
|
-
const versionFilePath =
|
|
1288
|
-
await
|
|
1533
|
+
const versionFilePath = path12.join(cwd, ".chatbi-version");
|
|
1534
|
+
await fs10.writeFile(versionFilePath, version, "utf-8");
|
|
1289
1535
|
}
|
|
1290
1536
|
await Sandbox.injectContext(cwd, version);
|
|
1291
1537
|
let modified = false;
|
|
@@ -1307,19 +1553,19 @@ async function sync(options = {}) {
|
|
|
1307
1553
|
if (modified) {
|
|
1308
1554
|
pkg.dependencies = deps;
|
|
1309
1555
|
pkg.devDependencies = devDeps;
|
|
1310
|
-
await
|
|
1556
|
+
await fs10.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
1311
1557
|
mainSpinner.succeed("\u5185\u6838\u540C\u6B65\u5B8C\u6210 (\u4F9D\u8D56\u5DF2\u4F18\u5316)");
|
|
1312
1558
|
} else {
|
|
1313
1559
|
mainSpinner.succeed("\u5185\u6838\u540C\u6B65\u5B8C\u6210");
|
|
1314
1560
|
}
|
|
1315
1561
|
if (!options.silent) {
|
|
1316
1562
|
printBox(
|
|
1317
|
-
`${
|
|
1563
|
+
`${pc6.green(pc6.bold("\u2728 \u5185\u6838\u540C\u6B65\u6210\u529F!"))}
|
|
1318
1564
|
|
|
1319
|
-
${
|
|
1320
|
-
${
|
|
1565
|
+
${pc6.white("\u5F53\u524D\u7248\u672C: ")} ${pc6.cyan(version)}
|
|
1566
|
+
${pc6.white("\u6C99\u7BB1\u8DEF\u5F84: ")} ${pc6.gray(Sandbox.getVersionPath(version))}
|
|
1321
1567
|
|
|
1322
|
-
${
|
|
1568
|
+
${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
1569
|
"Sync Success"
|
|
1324
1570
|
);
|
|
1325
1571
|
}
|
|
@@ -1339,13 +1585,12 @@ var init_exports = {};
|
|
|
1339
1585
|
__export(init_exports, {
|
|
1340
1586
|
init: () => init
|
|
1341
1587
|
});
|
|
1342
|
-
import
|
|
1343
|
-
import
|
|
1344
|
-
import
|
|
1345
|
-
import Handlebars2 from "handlebars";
|
|
1588
|
+
import fs11 from "fs-extra";
|
|
1589
|
+
import path13 from "path";
|
|
1590
|
+
import pc7 from "picocolors";
|
|
1346
1591
|
import prompts2 from "prompts";
|
|
1347
1592
|
async function init(options) {
|
|
1348
|
-
let { name,
|
|
1593
|
+
let { name, pluginType = "business", theme = DEFAULT_CONFIG.THEME, projectType, includeApp, includePlugin, cwd } = options;
|
|
1349
1594
|
const response = await prompts2([
|
|
1350
1595
|
// ... (prompts remain the same)
|
|
1351
1596
|
{
|
|
@@ -1415,32 +1660,33 @@ async function init(options) {
|
|
|
1415
1660
|
const finalIncludePlugin = includePlugin !== void 0 ? includePlugin : response.includePlugin !== void 0 ? response.includePlugin : true;
|
|
1416
1661
|
const isAppIncluded = finalIncludeApp;
|
|
1417
1662
|
const isPluginIncluded = finalIncludePlugin;
|
|
1418
|
-
const rootDir = process.cwd();
|
|
1419
|
-
const targetDir =
|
|
1420
|
-
if (
|
|
1663
|
+
const rootDir = cwd || process.cwd();
|
|
1664
|
+
const targetDir = path13.resolve(rootDir, name);
|
|
1665
|
+
if (fs11.existsSync(targetDir)) {
|
|
1421
1666
|
logger.error(`\u76EE\u5F55 ${name} \u5DF2\u5B58\u5728\u3002`);
|
|
1422
1667
|
return;
|
|
1423
1668
|
}
|
|
1424
|
-
logger.info(`\u6B63\u5728\u521D\u59CB\u5316\u9879\u76EE: ${
|
|
1425
|
-
logger.info(
|
|
1669
|
+
logger.info(`\u6B63\u5728\u521D\u59CB\u5316\u9879\u76EE: ${pc7.bold(name)}...`);
|
|
1670
|
+
logger.info(pc7.gray(`\u7C7B\u578B: ${projectType} | \u4E3B\u9898: ${theme || "N/A"}`));
|
|
1426
1671
|
console.log("");
|
|
1427
1672
|
try {
|
|
1428
1673
|
const myCliRoot = await getCliRoot();
|
|
1429
|
-
const cliPkg = await
|
|
1674
|
+
const cliPkg = await fs11.readJson(path13.join(myCliRoot, "package.json"));
|
|
1430
1675
|
const cliVersion = cliPkg.version;
|
|
1431
|
-
|
|
1432
|
-
const kernelVersionFile =
|
|
1433
|
-
if (
|
|
1434
|
-
|
|
1676
|
+
const config = { coreSource: "npm" };
|
|
1677
|
+
const kernelVersionFile = path13.join(myCliRoot, SANDBOX_CONFIG.LOCK_FILE);
|
|
1678
|
+
if (fs11.existsSync(kernelVersionFile)) {
|
|
1679
|
+
config.coreVersion = (await fs11.readFile(kernelVersionFile, "utf-8")).trim();
|
|
1435
1680
|
}
|
|
1681
|
+
const kernelVersion = await ConfigManager.resolveCoreDependency(config);
|
|
1436
1682
|
const renderTemplate = async (templateName, destDir, extraData = {}) => {
|
|
1437
|
-
const srcDir =
|
|
1438
|
-
if (!
|
|
1683
|
+
const srcDir = path13.join(myCliRoot, "templates", templateName);
|
|
1684
|
+
if (!fs11.existsSync(srcDir)) {
|
|
1439
1685
|
throw new Error(`\u627E\u4E0D\u5230\u6A21\u677F: ${templateName}\uFF0C\u8BF7\u68C0\u67E5\u8DEF\u5F84 ${srcDir} \u662F\u5426\u6B63\u786E\u3002`);
|
|
1440
1686
|
}
|
|
1441
|
-
await
|
|
1687
|
+
await fs11.ensureDir(destDir);
|
|
1442
1688
|
const templateData = {
|
|
1443
|
-
name:
|
|
1689
|
+
name: path13.basename(destDir),
|
|
1444
1690
|
projectName: name,
|
|
1445
1691
|
// Original project name from CLI argument
|
|
1446
1692
|
projectTitle: name.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" "),
|
|
@@ -1457,45 +1703,10 @@ async function init(options) {
|
|
|
1457
1703
|
isApp: projectType === "app" || isAppIncluded,
|
|
1458
1704
|
// Zero Dependency Mode: No explicit core path needed in package.json
|
|
1459
1705
|
// tsconfig extends the virtual paths config
|
|
1460
|
-
tsconfigPath: projectType === "monorepo" ?
|
|
1706
|
+
tsconfigPath: projectType === "monorepo" ? `../../${SANDBOX_CONFIG.DIRS.CACHE}/tsconfig.json` : `./${SANDBOX_CONFIG.DIRS.CACHE}/tsconfig.json`,
|
|
1461
1707
|
...extraData
|
|
1462
1708
|
};
|
|
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);
|
|
1709
|
+
await SandboxRenderer.renderDirectory(srcDir, destDir, templateData);
|
|
1499
1710
|
};
|
|
1500
1711
|
const spinner = createSpinner("\u6B63\u5728\u751F\u6210\u9879\u76EE\u7ED3\u6784...").start();
|
|
1501
1712
|
if (projectType === "monorepo") {
|
|
@@ -1503,12 +1714,12 @@ async function init(options) {
|
|
|
1503
1714
|
await renderTemplate("monorepo", targetDir, { name });
|
|
1504
1715
|
if (isAppIncluded) {
|
|
1505
1716
|
spinner.text = "\u6B63\u5728\u751F\u6210 Host App...";
|
|
1506
|
-
const appDir =
|
|
1717
|
+
const appDir = path13.join(targetDir, "apps", "main");
|
|
1507
1718
|
await renderTemplate("app", appDir, { name: "@chatbi-v/main" });
|
|
1508
1719
|
}
|
|
1509
1720
|
if (isPluginIncluded) {
|
|
1510
1721
|
spinner.text = "\u6B63\u5728\u751F\u6210 Demo Plugin...";
|
|
1511
|
-
const pluginDir =
|
|
1722
|
+
const pluginDir = path13.join(targetDir, "plugins", "plugin-demo");
|
|
1512
1723
|
await renderTemplate("plugin", pluginDir, {
|
|
1513
1724
|
name: "@chatbi-v/plugin-demo",
|
|
1514
1725
|
pluginId: "demo",
|
|
@@ -1550,15 +1761,15 @@ async function init(options) {
|
|
|
1550
1761
|
const cliConfig = {
|
|
1551
1762
|
coreVersion: kernelVersion
|
|
1552
1763
|
};
|
|
1553
|
-
await
|
|
1764
|
+
await fs11.writeJson(path13.join(targetDir, "chatbi.config.json"), cliConfig, { spaces: 2 });
|
|
1554
1765
|
configSpinner.succeed("\u9879\u76EE\u914D\u7F6E\u751F\u6210\u5B8C\u6210");
|
|
1555
1766
|
printBox(
|
|
1556
|
-
`${
|
|
1767
|
+
`${pc7.green(pc7.bold("\u2728 \u9879\u76EE\u5DF2\u6210\u529F\u521B\u5EFA!"))}
|
|
1557
1768
|
|
|
1558
|
-
${
|
|
1559
|
-
${
|
|
1560
|
-
${
|
|
1561
|
-
${
|
|
1769
|
+
${pc7.white("\u63A5\u4E0B\u6765\u4F60\u53EF\u4EE5:")}
|
|
1770
|
+
${pc7.cyan(` cd ${name}`)}
|
|
1771
|
+
${pc7.cyan(" pnpm install")}
|
|
1772
|
+
${pc7.cyan(" pnpm dev")}`,
|
|
1562
1773
|
"Success"
|
|
1563
1774
|
);
|
|
1564
1775
|
} catch (error) {
|
|
@@ -1572,6 +1783,9 @@ var init_init = __esm({
|
|
|
1572
1783
|
init_esm_shims();
|
|
1573
1784
|
init_utils();
|
|
1574
1785
|
init_sync();
|
|
1786
|
+
init_constants();
|
|
1787
|
+
init_config();
|
|
1788
|
+
init_SandboxRenderer();
|
|
1575
1789
|
}
|
|
1576
1790
|
});
|
|
1577
1791
|
|
|
@@ -1580,34 +1794,34 @@ var fetch_exports = {};
|
|
|
1580
1794
|
__export(fetch_exports, {
|
|
1581
1795
|
fetch: () => fetch
|
|
1582
1796
|
});
|
|
1583
|
-
import
|
|
1584
|
-
import
|
|
1797
|
+
import path18 from "path";
|
|
1798
|
+
import pc13 from "picocolors";
|
|
1585
1799
|
import { execa as execa4 } from "execa";
|
|
1586
1800
|
async function fetch(version, options = {}) {
|
|
1587
|
-
const fetchSpinner = createSpinner(`\u6B63\u5728\u83B7\u53D6\u5185\u6838\u7248\u672C ${
|
|
1801
|
+
const fetchSpinner = createSpinner(`\u6B63\u5728\u83B7\u53D6\u5185\u6838\u7248\u672C ${pc13.cyan(version)}...`).start();
|
|
1588
1802
|
const versionPath = await Sandbox.prepare(version, true);
|
|
1589
|
-
fetchSpinner.succeed(`\u5185\u6838\u7248\u672C ${
|
|
1803
|
+
fetchSpinner.succeed(`\u5185\u6838\u7248\u672C ${pc13.cyan(version)} \u83B7\u53D6\u6210\u529F`);
|
|
1590
1804
|
if (options.pack) {
|
|
1591
1805
|
const packSpinner = createSpinner("\u6B63\u5728\u6253\u5305\u79BB\u7EBF\u8D44\u6E90...").start();
|
|
1592
1806
|
const tgzName = `chatbi-core-${version}.tgz`;
|
|
1593
|
-
const tgzPath =
|
|
1807
|
+
const tgzPath = path18.resolve(process.cwd(), tgzName);
|
|
1594
1808
|
await execa4("tar", [
|
|
1595
1809
|
"-czf",
|
|
1596
1810
|
tgzPath,
|
|
1597
1811
|
"-C",
|
|
1598
|
-
|
|
1599
|
-
|
|
1812
|
+
path18.dirname(versionPath),
|
|
1813
|
+
path18.basename(versionPath)
|
|
1600
1814
|
]);
|
|
1601
1815
|
packSpinner.succeed("\u79BB\u7EBF\u8D44\u6E90\u6253\u5305\u5B8C\u6210");
|
|
1602
1816
|
printBox(
|
|
1603
|
-
`${
|
|
1817
|
+
`${pc13.green(pc13.bold("\u2728 \u79BB\u7EBF\u5305\u5DF2\u751F\u6210!"))}
|
|
1604
1818
|
|
|
1605
|
-
${
|
|
1606
|
-
${
|
|
1819
|
+
${pc13.white("\u6587\u4EF6\u8DEF\u5F84: ")} ${pc13.cyan(tgzPath)}
|
|
1820
|
+
${pc13.white("\u5B89\u88C5\u547D\u4EE4: ")} ${pc13.gray(`chatbi install ${tgzName}`)}`,
|
|
1607
1821
|
"Pack Success"
|
|
1608
1822
|
);
|
|
1609
1823
|
} else {
|
|
1610
|
-
logger.success(`\u5185\u6838\u7248\u672C ${
|
|
1824
|
+
logger.success(`\u5185\u6838\u7248\u672C ${pc13.cyan(version)} \u5DF2\u51C6\u5907\u5C31\u7EEA\u3002`);
|
|
1611
1825
|
}
|
|
1612
1826
|
}
|
|
1613
1827
|
var init_fetch = __esm({
|
|
@@ -1624,24 +1838,24 @@ var bench_exports = {};
|
|
|
1624
1838
|
__export(bench_exports, {
|
|
1625
1839
|
bench: () => bench
|
|
1626
1840
|
});
|
|
1627
|
-
import
|
|
1628
|
-
import
|
|
1629
|
-
import
|
|
1841
|
+
import pc15 from "picocolors";
|
|
1842
|
+
import fs17 from "fs-extra";
|
|
1843
|
+
import path20 from "path";
|
|
1630
1844
|
import os2 from "os";
|
|
1631
1845
|
async function bench() {
|
|
1632
1846
|
logger.info("\u6B63\u5728\u542F\u52A8 CLI \u6027\u80FD\u57FA\u51C6\u6D4B\u8BD5...");
|
|
1633
1847
|
const results = [];
|
|
1634
|
-
const tmpDir =
|
|
1635
|
-
await
|
|
1848
|
+
const tmpDir = path20.join(os2.tmpdir(), `chatbi-bench-${Date.now()}`);
|
|
1849
|
+
await fs17.ensureDir(tmpDir);
|
|
1636
1850
|
try {
|
|
1637
1851
|
const initSpinner = createSpinner("\u6B63\u5728\u6D4B\u8BD5: \u521D\u59CB\u5316\u63D2\u4EF6\u9879\u76EE (init)...").start();
|
|
1638
1852
|
const startInit = Date.now();
|
|
1639
1853
|
const { init: init2 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
|
1640
|
-
const testProjDir =
|
|
1854
|
+
const testProjDir = path20.join(tmpDir, "bench-proj");
|
|
1641
1855
|
await init2({ name: "bench-proj", projectType: "plugin", cwd: tmpDir });
|
|
1642
1856
|
const endInit = Date.now();
|
|
1643
1857
|
const initTime = (endInit - startInit) / 1e3;
|
|
1644
|
-
initSpinner.succeed(`\u521D\u59CB\u5316\u5B8C\u6210: ${
|
|
1858
|
+
initSpinner.succeed(`\u521D\u59CB\u5316\u5B8C\u6210: ${pc15.cyan(initTime.toFixed(2) + "s")}`);
|
|
1645
1859
|
results.push({
|
|
1646
1860
|
scene: "\u521D\u59CB\u5316\u63D2\u4EF6\u9879\u76EE (init)",
|
|
1647
1861
|
target: "\u2264 5.0 s",
|
|
@@ -1653,7 +1867,7 @@ async function bench() {
|
|
|
1653
1867
|
await sync2({ cwd: testProjDir });
|
|
1654
1868
|
const endSync = Date.now();
|
|
1655
1869
|
const syncTime = (endSync - startSync) / 1e3;
|
|
1656
|
-
syncSpinner.succeed(`\u540C\u6B65\u5B8C\u6210: ${
|
|
1870
|
+
syncSpinner.succeed(`\u540C\u6B65\u5B8C\u6210: ${pc15.cyan(syncTime.toFixed(2) + "s")}`);
|
|
1657
1871
|
results.push({
|
|
1658
1872
|
scene: "\u6C99\u7BB1\u73AF\u5883\u540C\u6B65 (sync)",
|
|
1659
1873
|
target: "\u2264 2.0 s",
|
|
@@ -1668,20 +1882,20 @@ async function bench() {
|
|
|
1668
1882
|
process.chdir(originalCwd);
|
|
1669
1883
|
const endBuild = Date.now();
|
|
1670
1884
|
const buildTime = (endBuild - startBuild) / 1e3;
|
|
1671
|
-
buildSpinner.succeed(`\u6784\u5EFA\u5B8C\u6210: ${
|
|
1885
|
+
buildSpinner.succeed(`\u6784\u5EFA\u5B8C\u6210: ${pc15.cyan(buildTime.toFixed(2) + "s")}`);
|
|
1672
1886
|
results.push({
|
|
1673
1887
|
scene: "\u63D2\u4EF6\u9879\u76EE\u6784\u5EFA (build)",
|
|
1674
1888
|
target: "\u2264 10.0 s",
|
|
1675
1889
|
actual: `${buildTime.toFixed(2)} s`
|
|
1676
1890
|
});
|
|
1677
1891
|
printBox(
|
|
1678
|
-
`${
|
|
1892
|
+
`${pc15.green(pc15.bold("\u2728 \u57FA\u51C6\u6D4B\u8BD5\u5B8C\u6210!"))}
|
|
1679
1893
|
|
|
1680
|
-
` + results.map((r) => `${
|
|
1894
|
+
` + results.map((r) => `${pc15.white(r.scene.padEnd(20))}: ${pc15.cyan(r.actual)} (\u76EE\u6807 ${r.target})`).join("\n"),
|
|
1681
1895
|
"Benchmark Results"
|
|
1682
1896
|
);
|
|
1683
1897
|
} finally {
|
|
1684
|
-
await
|
|
1898
|
+
await fs17.remove(tmpDir);
|
|
1685
1899
|
}
|
|
1686
1900
|
}
|
|
1687
1901
|
var init_bench = __esm({
|
|
@@ -1696,7 +1910,7 @@ var init_bench = __esm({
|
|
|
1696
1910
|
init_esm_shims();
|
|
1697
1911
|
init_build();
|
|
1698
1912
|
import cac from "cac";
|
|
1699
|
-
import
|
|
1913
|
+
import pc16 from "picocolors";
|
|
1700
1914
|
import figlet from "figlet";
|
|
1701
1915
|
import gradient from "gradient-string";
|
|
1702
1916
|
import boxen2 from "boxen";
|
|
@@ -1716,20 +1930,21 @@ init_init();
|
|
|
1716
1930
|
init_esm_shims();
|
|
1717
1931
|
init_utils();
|
|
1718
1932
|
init_config();
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
import
|
|
1933
|
+
init_constants();
|
|
1934
|
+
init_SandboxRenderer();
|
|
1935
|
+
import fs12 from "fs-extra";
|
|
1936
|
+
import path14 from "path";
|
|
1937
|
+
import pc8 from "picocolors";
|
|
1722
1938
|
import prompts3 from "prompts";
|
|
1723
|
-
import Handlebars3 from "handlebars";
|
|
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.5",
|
|
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) {
|