@chatbi-v/cli 2.0.2 → 2.0.4
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/bin/chatbi-cli.js +1 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2464 -188
- package/package.json +6 -3
- package/templates/app/package.json.hbs +5 -2
- package/templates/plugin/package.json.hbs +5 -5
- package/templates/plugin/tsconfig.json.hbs +1 -1
- package/dist/bench-ACSHVGHE.mjs +0 -77
- package/dist/build-UB4D3WNI.mjs +0 -11
- package/dist/chunk-4OD6C56P.mjs +0 -89
- package/dist/chunk-7A54IJI5.mjs +0 -6368
- package/dist/chunk-LJFX6MNO.mjs +0 -255
- package/dist/chunk-SBGVKO4C.mjs +0 -2255
- package/dist/chunk-TX5M36S5.mjs +0 -55
- package/dist/chunk-V7IEPMC4.mjs +0 -52
- package/dist/chunk-WCPZB47I.mjs +0 -262
- package/dist/chunk-WIVHOK75.mjs +0 -5292
- package/dist/chunk-Y24V4GQG.mjs +0 -9577
- package/dist/commands/add.js +0 -182
- package/dist/commands/bench.js +0 -100
- package/dist/commands/build.js +0 -290
- package/dist/commands/dev.js +0 -8
- package/dist/commands/discover.js +0 -25
- package/dist/commands/doctor.js +0 -231
- package/dist/commands/fetch.js +0 -41
- package/dist/commands/gl.js +0 -151
- package/dist/commands/init.js +0 -253
- package/dist/commands/install.js +0 -85
- package/dist/commands/ls.js +0 -46
- package/dist/commands/sync.js +0 -78
- package/dist/commands/use.js +0 -31
- package/dist/config.js +0 -70
- package/dist/corekit.js +0 -370
- package/dist/execa-METROS6Z.mjs +0 -17
- package/dist/fetch-7X2UFWIV.mjs +0 -10
- package/dist/index.cjs +0 -27278
- package/dist/index.mjs +0 -2769
- package/dist/init-QFRFYEA5.mjs +0 -12
- package/dist/sandbox.js +0 -522
- package/dist/sync-7HPKGVFY.mjs +0 -11
- package/dist/utils.js +0 -99
package/dist/init-QFRFYEA5.mjs
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
init
|
|
3
|
-
} from "./chunk-LJFX6MNO.mjs";
|
|
4
|
-
import "./chunk-4OD6C56P.mjs";
|
|
5
|
-
import "./chunk-WIVHOK75.mjs";
|
|
6
|
-
import "./chunk-7A54IJI5.mjs";
|
|
7
|
-
import "./chunk-SBGVKO4C.mjs";
|
|
8
|
-
import "./chunk-Y24V4GQG.mjs";
|
|
9
|
-
import "./chunk-TX5M36S5.mjs";
|
|
10
|
-
export {
|
|
11
|
-
init
|
|
12
|
-
};
|
package/dist/sandbox.js
DELETED
|
@@ -1,522 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Sandbox = void 0;
|
|
7
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const os_1 = __importDefault(require("os"));
|
|
10
|
-
const picocolors_1 = __importDefault(require("picocolors"));
|
|
11
|
-
const execa_1 = require("execa");
|
|
12
|
-
const handlebars_1 = __importDefault(require("handlebars"));
|
|
13
|
-
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
14
|
-
const utils_1 = require("./utils");
|
|
15
|
-
/**
|
|
16
|
-
* 沙箱环境管理器 (The Container)
|
|
17
|
-
* 负责物理隔离、依赖安装、文件系统操作
|
|
18
|
-
*/
|
|
19
|
-
class Sandbox {
|
|
20
|
-
static getRoot() {
|
|
21
|
-
return this.BASE_DIR;
|
|
22
|
-
}
|
|
23
|
-
static getVersionRoot() {
|
|
24
|
-
return path_1.default.join(this.BASE_DIR, 'versions');
|
|
25
|
-
}
|
|
26
|
-
static getVersionPath(version) {
|
|
27
|
-
if (version === 'current') {
|
|
28
|
-
return path_1.default.join(this.BASE_DIR, 'versions', 'current');
|
|
29
|
-
}
|
|
30
|
-
return path_1.default.join(this.BASE_DIR, 'versions', version);
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* 准备内核沙箱环境 (安装/更新)
|
|
34
|
-
*/
|
|
35
|
-
static async prepare(version, force = false) {
|
|
36
|
-
const versionPath = this.getVersionPath(version);
|
|
37
|
-
// 如果已存在且不强制更新,则跳过
|
|
38
|
-
if (fs_extra_1.default.existsSync(versionPath) && !force) {
|
|
39
|
-
// 检查 node_modules 是否完整 (至少要有 tailwindcss 和 react-router-dom 这种关键依赖)
|
|
40
|
-
if (fs_extra_1.default.existsSync(path_1.default.join(versionPath, 'node_modules/tailwindcss')) &&
|
|
41
|
-
fs_extra_1.default.existsSync(path_1.default.join(versionPath, 'node_modules/react-router-dom'))) {
|
|
42
|
-
return versionPath;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
if (fs_extra_1.default.existsSync(versionPath)) {
|
|
46
|
-
await fs_extra_1.default.remove(path_1.default.join(versionPath, 'node_modules'));
|
|
47
|
-
await fs_extra_1.default.remove(path_1.default.join(versionPath, 'pnpm-lock.yaml'));
|
|
48
|
-
}
|
|
49
|
-
await fs_extra_1.default.ensureDir(versionPath);
|
|
50
|
-
const spinner = (0, utils_1.createSpinner)(`正在初始化内核沙箱 ${picocolors_1.default.cyan(version)}...`).start();
|
|
51
|
-
// 1. 生成 package.json
|
|
52
|
-
try {
|
|
53
|
-
const rootPkgJson = {
|
|
54
|
-
name: `chatbi-sandbox-${version}`,
|
|
55
|
-
private: true,
|
|
56
|
-
dependencies: {},
|
|
57
|
-
devDependencies: {
|
|
58
|
-
"tailwindcss": "^3.4.1",
|
|
59
|
-
"autoprefixer": "^10.4.17",
|
|
60
|
-
"postcss": "^8.4.35",
|
|
61
|
-
"vite": "^5.0.8",
|
|
62
|
-
"@vitejs/plugin-react": "^4.2.1",
|
|
63
|
-
"less": "^4.2.0",
|
|
64
|
-
"typescript": "^5.3.3",
|
|
65
|
-
"@types/react": "^18.3.1",
|
|
66
|
-
"@types/react-dom": "^18.3.1",
|
|
67
|
-
"@types/node": "^20.11.20"
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
// 2. 添加核心包
|
|
71
|
-
for (const pkgName of Sandbox.CORE_PACKAGES) {
|
|
72
|
-
rootPkgJson.dependencies[pkgName] = pkgName === '@chatbi-v/core' ? version : 'latest';
|
|
73
|
-
}
|
|
74
|
-
// 3. 添加运行时依赖
|
|
75
|
-
for (const pkgName of Sandbox.RUNTIME_DEPS) {
|
|
76
|
-
if (!rootPkgJson.dependencies[pkgName]) {
|
|
77
|
-
rootPkgJson.dependencies[pkgName] = 'latest';
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
// 版本修正
|
|
81
|
-
rootPkgJson.dependencies['react'] = '^18.3.1';
|
|
82
|
-
rootPkgJson.dependencies['react-dom'] = '^18.3.1';
|
|
83
|
-
rootPkgJson.dependencies['antd'] = '^5.20.0';
|
|
84
|
-
await fs_extra_1.default.writeJson(path_1.default.join(versionPath, 'package.json'), rootPkgJson, { spaces: 2 });
|
|
85
|
-
await fs_extra_1.default.writeFile(path_1.default.join(versionPath, '.npmrc'), 'shamefully-hoist=true\nauto-install-peers=true\n');
|
|
86
|
-
spinner.text = picocolors_1.default.gray(' 🔍 检查本地开发环境...');
|
|
87
|
-
// 4. 尝试 Link 本地源码 (Monorepo 场景)
|
|
88
|
-
const isLocalDev = await this.tryLinkLocalPackages(versionPath);
|
|
89
|
-
// 5. 执行安装
|
|
90
|
-
const installArgs = ['install'];
|
|
91
|
-
if (isLocalDev) {
|
|
92
|
-
installArgs.push('--no-frozen-lockfile');
|
|
93
|
-
}
|
|
94
|
-
spinner.text = picocolors_1.default.gray(` ⏳ 执行 pnpm ${installArgs.join(' ')}...`);
|
|
95
|
-
await (0, execa_1.execa)('pnpm', installArgs, { cwd: versionPath });
|
|
96
|
-
spinner.text = picocolors_1.default.gray(' 🎨 同步 Shell 模板...');
|
|
97
|
-
// 6. 确保 Shell 模板存在
|
|
98
|
-
await this.ensureShell(version, force);
|
|
99
|
-
spinner.succeed(picocolors_1.default.green(`内核沙箱 ${version} 初始化成功`));
|
|
100
|
-
}
|
|
101
|
-
catch (e) {
|
|
102
|
-
spinner.fail(picocolors_1.default.red(`内核沙箱初始化失败: ${e.message}`));
|
|
103
|
-
throw e;
|
|
104
|
-
}
|
|
105
|
-
return versionPath;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* 确保 Shell 模板已同步到沙箱
|
|
109
|
-
*/
|
|
110
|
-
static async ensureShell(version, force = false) {
|
|
111
|
-
const versionPath = this.getVersionPath(version);
|
|
112
|
-
const shellDestDir = path_1.default.join(versionPath, 'shell');
|
|
113
|
-
// 检查是否需要重新渲染:不存在,或者强制,或者关键文件(tsconfig.paths.json)不存在
|
|
114
|
-
const needsRender = force || !fs_extra_1.default.existsSync(shellDestDir) || !fs_extra_1.default.existsSync(path_1.default.join(shellDestDir, 'tsconfig.paths.json'));
|
|
115
|
-
if (!needsRender) {
|
|
116
|
-
return shellDestDir;
|
|
117
|
-
}
|
|
118
|
-
const cliRoot = await (0, utils_1.getCliRoot)();
|
|
119
|
-
const shellTemplateDir = path_1.default.join(cliRoot, 'templates', 'app'); // 复用 App 模板作为 Shell
|
|
120
|
-
if (fs_extra_1.default.existsSync(shellTemplateDir)) {
|
|
121
|
-
await fs_extra_1.default.remove(shellDestDir);
|
|
122
|
-
// 确保 empty 目录存在,防止 Vite Alias 报错
|
|
123
|
-
await fs_extra_1.default.ensureDir(path_1.default.join(shellDestDir, 'empty'));
|
|
124
|
-
// 获取内核版本 (用于模板渲染)
|
|
125
|
-
let kernelVersion = version;
|
|
126
|
-
const templateData = {
|
|
127
|
-
name: 'chatbi-shell',
|
|
128
|
-
projectName: 'chatbi-shell',
|
|
129
|
-
projectTitle: 'ChatBI Shell',
|
|
130
|
-
projectVersion: '0.1.0',
|
|
131
|
-
version: kernelVersion,
|
|
132
|
-
cliVersion: version,
|
|
133
|
-
theme: 'standard',
|
|
134
|
-
isNebula: false,
|
|
135
|
-
isGlass: false,
|
|
136
|
-
isBusiness: true,
|
|
137
|
-
isApp: true,
|
|
138
|
-
isShell: true,
|
|
139
|
-
tsconfigPath: './tsconfig.paths.json'
|
|
140
|
-
};
|
|
141
|
-
await this.renderDirectory(shellTemplateDir, shellDestDir, templateData);
|
|
142
|
-
// 补全 tsconfig.paths.json,防止 Vite 报错
|
|
143
|
-
const tsConfigPaths = {
|
|
144
|
-
compilerOptions: {
|
|
145
|
-
baseUrl: ".",
|
|
146
|
-
paths: {
|
|
147
|
-
"@/*": ["./src/*"]
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
await fs_extra_1.default.writeJson(path_1.default.join(shellDestDir, 'tsconfig.paths.json'), tsConfigPaths, { spaces: 2 });
|
|
152
|
-
}
|
|
153
|
-
return shellDestDir;
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* 递归渲染目录模板
|
|
157
|
-
*/
|
|
158
|
-
static async renderDirectory(srcDir, destDir, data) {
|
|
159
|
-
const entries = await fs_extra_1.default.readdir(srcDir, { withFileTypes: true });
|
|
160
|
-
for (const entry of entries) {
|
|
161
|
-
const srcPath = path_1.default.join(srcDir, entry.name);
|
|
162
|
-
const destPath = path_1.default.join(destDir, entry.name.replace(/\.hbs$/, ''));
|
|
163
|
-
if (entry.isDirectory()) {
|
|
164
|
-
await fs_extra_1.default.ensureDir(destPath);
|
|
165
|
-
await this.renderDirectory(srcPath, destPath, data);
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
if (entry.name.endsWith('.hbs')) {
|
|
169
|
-
const content = await fs_extra_1.default.readFile(srcPath, 'utf-8');
|
|
170
|
-
// 启发式判断:包含 {{ 即视为 Handlebars 模板
|
|
171
|
-
// 放宽判断条件,支持 {{#if}} 等块级语法
|
|
172
|
-
const hasHandlebarsVars = content.includes('{{');
|
|
173
|
-
if (hasHandlebarsVars) {
|
|
174
|
-
try {
|
|
175
|
-
// 针对可能包含 React {{ }} 的文件,做一个简单的预处理
|
|
176
|
-
// 只有当 {{ 后面紧跟着 Handlebars 关键字或变量名时,才保留;否则转义
|
|
177
|
-
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, '\\{{');
|
|
178
|
-
const template = handlebars_1.default.compile(safeContent);
|
|
179
|
-
const result = template(data);
|
|
180
|
-
await fs_extra_1.default.outputFile(destPath, result);
|
|
181
|
-
}
|
|
182
|
-
catch (e) {
|
|
183
|
-
// 编译失败则降级为正则替换 (仅支持简单变量)
|
|
184
|
-
let result = content;
|
|
185
|
-
for (const [key, val] of Object.entries(data)) {
|
|
186
|
-
const regex = new RegExp(`\\{\\{\\s*${key}\\s*\\}\\}`, 'g');
|
|
187
|
-
result = result.replace(regex, String(val));
|
|
188
|
-
}
|
|
189
|
-
await fs_extra_1.default.outputFile(destPath, result);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
// 没有变量则直接拷贝(去掉 .hbs 后缀)
|
|
194
|
-
await fs_extra_1.default.outputFile(destPath, content);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
198
|
-
await fs_extra_1.default.copy(srcPath, destPath);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* 注入项目虚拟上下文 (tsconfig, alias)
|
|
205
|
-
*/
|
|
206
|
-
static async injectContext(projectRoot, version) {
|
|
207
|
-
const chatbiDir = path_1.default.join(projectRoot, '.chatbi');
|
|
208
|
-
await fs_extra_1.default.ensureDir(chatbiDir);
|
|
209
|
-
const versionPath = this.getVersionPath(version);
|
|
210
|
-
const sandboxNodeModules = path_1.default.join(versionPath, 'node_modules');
|
|
211
|
-
// 1. 生成 tsconfig.json (Extends Sandbox Base + Paths)
|
|
212
|
-
const corePaths = {};
|
|
213
|
-
// Add Core Packages
|
|
214
|
-
for (const pkgName of Sandbox.CORE_PACKAGES) {
|
|
215
|
-
// Use relative path to .chatbi/node_modules
|
|
216
|
-
corePaths[pkgName] = [`./node_modules/${pkgName}`];
|
|
217
|
-
corePaths[`${pkgName}/*`] = [`./node_modules/${pkgName}/*`];
|
|
218
|
-
}
|
|
219
|
-
// Add Runtime Deps (for App/Plugin to resolve dependencies from Sandbox)
|
|
220
|
-
for (const pkgName of Sandbox.RUNTIME_DEPS) {
|
|
221
|
-
// Use relative path to .chatbi/node_modules
|
|
222
|
-
corePaths[pkgName] = [`./node_modules/${pkgName}`];
|
|
223
|
-
corePaths[`${pkgName}/*`] = [`./node_modules/${pkgName}/*`];
|
|
224
|
-
// Explicitly map types for common packages that don't have built-in types
|
|
225
|
-
if (['react', 'react-dom', 'node'].includes(pkgName)) {
|
|
226
|
-
const typeName = pkgName === 'node' ? 'node' : pkgName;
|
|
227
|
-
corePaths[`@types/${typeName}`] = [`./node_modules/@types/${typeName}`];
|
|
228
|
-
corePaths[`@types/${typeName}/*`] = [`./node_modules/@types/${typeName}/*`];
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
// Add explicit mapping for @types to help TS resolution
|
|
232
|
-
corePaths['@types/*'] = ['./node_modules/@types/*'];
|
|
233
|
-
// Add mapping for vite/client to support client types
|
|
234
|
-
corePaths['vite/client'] = ['./node_modules/vite/client.d.ts'];
|
|
235
|
-
// 基础配置路径 (Absolute Path to Sandbox)
|
|
236
|
-
const baseConfigPath = path_1.default.join(sandboxNodeModules, '@chatbi-v/tsconfig/base.json');
|
|
237
|
-
// 读取项目原有配置以保留 (这里我们主要关注 paths)
|
|
238
|
-
// Fix: explicitly set @/* to point to project src from .chatbi folder (../src/*)
|
|
239
|
-
let projectPaths = { "@/*": ["../src/*"] };
|
|
240
|
-
const tsConfig = {
|
|
241
|
-
extends: baseConfigPath,
|
|
242
|
-
compilerOptions: {
|
|
243
|
-
baseUrl: ".",
|
|
244
|
-
moduleResolution: "bundler",
|
|
245
|
-
skipLibCheck: true,
|
|
246
|
-
// Fix: Use relative path to the symlinked node_modules in .chatbi
|
|
247
|
-
// This is much more robust as it works relative to the config file (.chatbi/tsconfig.json)
|
|
248
|
-
typeRoots: [
|
|
249
|
-
"./node_modules/@types"
|
|
250
|
-
],
|
|
251
|
-
// Crucial for symlinked node_modules: treat them as if they are in the project
|
|
252
|
-
preserveSymlinks: true,
|
|
253
|
-
paths: {
|
|
254
|
-
...corePaths,
|
|
255
|
-
...projectPaths,
|
|
256
|
-
// Fallback: Try to find anything else in the virtual node_modules
|
|
257
|
-
"*": ["./node_modules/*"]
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
};
|
|
261
|
-
// 写入 .chatbi/tsconfig.json
|
|
262
|
-
await fs_extra_1.default.writeJson(path_1.default.join(chatbiDir, 'tsconfig.json'), tsConfig, { spaces: 2 });
|
|
263
|
-
// 为了兼容旧逻辑,同时也写入 tsconfig.paths.json (可选,但为了保险起见)
|
|
264
|
-
await fs_extra_1.default.writeJson(path_1.default.join(chatbiDir, 'tsconfig.paths.json'), { compilerOptions: tsConfig.compilerOptions }, { spaces: 2 });
|
|
265
|
-
// 3. 关键修复:创建 .chatbi/node_modules 软链接指向沙箱
|
|
266
|
-
// 这让 tsc 能通过相对路径标准地找到 @types 和包
|
|
267
|
-
const virtualNodeModules = path_1.default.join(chatbiDir, 'node_modules');
|
|
268
|
-
if (fs_extra_1.default.existsSync(virtualNodeModules)) {
|
|
269
|
-
await fs_extra_1.default.remove(virtualNodeModules);
|
|
270
|
-
}
|
|
271
|
-
// Windows 上可能需要管理员权限,但在 Mac/Linux 上通常没问题
|
|
272
|
-
try {
|
|
273
|
-
await fs_extra_1.default.ensureSymlink(sandboxNodeModules, virtualNodeModules, 'dir');
|
|
274
|
-
// 4. 更进一步:在项目根目录创建 node_modules 软链
|
|
275
|
-
// 这是让 TS 和 Vite "开箱即用" 的终极方案
|
|
276
|
-
// 只有当根目录没有 node_modules 时才创建,避免覆盖用户手动安装的依赖
|
|
277
|
-
const rootNodeModules = path_1.default.join(projectRoot, 'node_modules');
|
|
278
|
-
if (!fs_extra_1.default.existsSync(rootNodeModules)) {
|
|
279
|
-
try {
|
|
280
|
-
await fs_extra_1.default.ensureSymlink(sandboxNodeModules, rootNodeModules, 'dir');
|
|
281
|
-
}
|
|
282
|
-
catch (linkErr) {
|
|
283
|
-
// 如果根目录软链创建失败,尝试在每个 app 目录下创建
|
|
284
|
-
const appsDir = path_1.default.join(projectRoot, 'apps');
|
|
285
|
-
if (fs_extra_1.default.existsSync(appsDir)) {
|
|
286
|
-
const appDirs = await (0, fast_glob_1.default)('*', { cwd: appsDir, onlyDirectories: true, absolute: true });
|
|
287
|
-
for (const appDir of appDirs) {
|
|
288
|
-
const appNm = path_1.default.join(appDir, 'node_modules');
|
|
289
|
-
if (!fs_extra_1.default.existsSync(appNm)) {
|
|
290
|
-
await fs_extra_1.default.ensureSymlink(sandboxNodeModules, appNm, 'dir').catch(() => { });
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
catch (e) {
|
|
298
|
-
// 降级:如果软链失败,至少我们还有 paths 映射
|
|
299
|
-
utils_1.logger.warn(`无法创建虚拟 node_modules 链接: ${e.message}`);
|
|
300
|
-
}
|
|
301
|
-
// 2. 注入 .gitignore
|
|
302
|
-
const gitignorePath = path_1.default.join(projectRoot, '.gitignore');
|
|
303
|
-
if (fs_extra_1.default.existsSync(gitignorePath)) {
|
|
304
|
-
let content = await fs_extra_1.default.readFile(gitignorePath, 'utf-8');
|
|
305
|
-
if (!content.includes('.chatbi')) {
|
|
306
|
-
await fs_extra_1.default.appendFile(gitignorePath, '\n# ChatBI\n.chatbi\n');
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* 获取核心库的 Vite Alias 配置
|
|
312
|
-
*/
|
|
313
|
-
static getCoreAlias(version) {
|
|
314
|
-
const versionPath = this.getVersionPath(version);
|
|
315
|
-
const sandboxNodeModules = path_1.default.join(versionPath, 'node_modules');
|
|
316
|
-
const aliases = {};
|
|
317
|
-
for (const pkg of this.CORE_PACKAGES) {
|
|
318
|
-
aliases[pkg] = path_1.default.join(sandboxNodeModules, pkg);
|
|
319
|
-
}
|
|
320
|
-
return aliases;
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* 尝试将本地包 Link 到沙箱中 (模拟安装)
|
|
324
|
-
*/
|
|
325
|
-
static async tryLinkLocalPackages(versionPath) {
|
|
326
|
-
try {
|
|
327
|
-
const cliRoot = await (0, utils_1.getCliRoot)();
|
|
328
|
-
// 假设 CLI 在 packages/cli,往上找两级是 Monorepo Root
|
|
329
|
-
// 如果 CLI 是全局安装的,这个逻辑可能需要调整,或者通过查找 .git/pnpm-workspace.yaml 来确定 root
|
|
330
|
-
let projectRoot = path_1.default.resolve(cliRoot, '../../..');
|
|
331
|
-
// 如果找不到 packages 目录,可能是在更深或更浅的位置,或者根本不是 Monorepo
|
|
332
|
-
// 尝试向上查找 pnpm-workspace.yaml
|
|
333
|
-
let currentDir = cliRoot;
|
|
334
|
-
while (currentDir !== path_1.default.parse(currentDir).root) {
|
|
335
|
-
if (fs_extra_1.default.existsSync(path_1.default.join(currentDir, 'pnpm-workspace.yaml'))) {
|
|
336
|
-
projectRoot = currentDir;
|
|
337
|
-
break;
|
|
338
|
-
}
|
|
339
|
-
currentDir = path_1.default.dirname(currentDir);
|
|
340
|
-
}
|
|
341
|
-
// 检查多个可能的本地路径
|
|
342
|
-
const possiblePackagesDirs = [
|
|
343
|
-
path_1.default.join(projectRoot, 'packages'),
|
|
344
|
-
// 兼容某些特殊结构,比如 chatbi-v 仓库
|
|
345
|
-
path_1.default.resolve(projectRoot, '../chatbi-v/packages')
|
|
346
|
-
];
|
|
347
|
-
// 扫描 packages 下的所有包并构建名称到路径的映射
|
|
348
|
-
const localPackages = {};
|
|
349
|
-
// 使用 fast-glob 优化扫描逻辑,查找所有 package.json
|
|
350
|
-
const patterns = possiblePackagesDirs
|
|
351
|
-
.filter(dir => fs_extra_1.default.existsSync(dir))
|
|
352
|
-
.map(dir => path_1.default.join(dir, '**/package.json'));
|
|
353
|
-
if (patterns.length > 0) {
|
|
354
|
-
const pkgJsonFiles = await (0, fast_glob_1.default)(patterns, {
|
|
355
|
-
ignore: ['**/node_modules/**', '**/dist/**', '**/.git/**'],
|
|
356
|
-
absolute: true,
|
|
357
|
-
deep: 5 // 允许一定的嵌套深度
|
|
358
|
-
});
|
|
359
|
-
for (const pkgJsonPath of pkgJsonFiles) {
|
|
360
|
-
try {
|
|
361
|
-
const pkgJson = await fs_extra_1.default.readJson(pkgJsonPath);
|
|
362
|
-
if (this.CORE_PACKAGES.includes(pkgJson.name) || this.RUNTIME_DEPS.includes(pkgJson.name)) {
|
|
363
|
-
localPackages[pkgJson.name] = path_1.default.dirname(pkgJsonPath);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
catch (e) {
|
|
367
|
-
// 忽略解析错误
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
if (Object.keys(localPackages).length === 0) {
|
|
372
|
-
// console.log(pc.gray(` ℹ️ 未在本地找到任何核心包,将从 NPM 下载`));
|
|
373
|
-
return false;
|
|
374
|
-
}
|
|
375
|
-
// 使用 boxen 显示本地包链接摘要
|
|
376
|
-
const linkSummary = Object.entries(localPackages)
|
|
377
|
-
.map(([name, pkgPath]) => `${picocolors_1.default.cyan(name.padEnd(30))} -> ${picocolors_1.default.gray(pkgPath)}`)
|
|
378
|
-
.join('\n');
|
|
379
|
-
(0, utils_1.printBox)(picocolors_1.default.green('🔗 已检测到本地开发环境,将链接以下核心包:\n\n') + linkSummary, 'Monorepo Link Mode');
|
|
380
|
-
// 在修改 package.json 之前,先手动在 node_modules 下创建软链接
|
|
381
|
-
// 这样可以确保即使不运行 pnpm install,Vite 别名指向这些目录也是有效的
|
|
382
|
-
const sandboxNodeModules = path_1.default.join(versionPath, 'node_modules');
|
|
383
|
-
await fs_extra_1.default.ensureDir(sandboxNodeModules);
|
|
384
|
-
for (const [name, pkgPath] of Object.entries(localPackages)) {
|
|
385
|
-
const targetLinkPath = path_1.default.join(sandboxNodeModules, name);
|
|
386
|
-
// 确保父目录存在 (针对 @chatbi-v/core 这种 scoped 包)
|
|
387
|
-
await fs_extra_1.default.ensureDir(path_1.default.dirname(targetLinkPath));
|
|
388
|
-
try {
|
|
389
|
-
// 如果存在且是软链,先删除
|
|
390
|
-
const stats = await fs_extra_1.default.lstat(targetLinkPath).catch(() => null);
|
|
391
|
-
if (stats) {
|
|
392
|
-
await fs_extra_1.default.remove(targetLinkPath);
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
catch (e) { }
|
|
396
|
-
await fs_extra_1.default.symlink(pkgPath, targetLinkPath, 'dir');
|
|
397
|
-
// logger.info(`已链接本地包: ${name} -> ${pkgPath}`);
|
|
398
|
-
}
|
|
399
|
-
// 修改沙箱的 package.json,将这些包的版本改为 link: 协议
|
|
400
|
-
const sandboxPkgJsonPath = path_1.default.join(versionPath, 'package.json');
|
|
401
|
-
const sandboxPkgJson = await fs_extra_1.default.readJson(sandboxPkgJsonPath);
|
|
402
|
-
const sections = ['dependencies', 'devDependencies'];
|
|
403
|
-
let modified = false;
|
|
404
|
-
for (const section of sections) {
|
|
405
|
-
if (sandboxPkgJson[section]) {
|
|
406
|
-
for (const [name, pkgPath] of Object.entries(localPackages)) {
|
|
407
|
-
if (sandboxPkgJson[section][name]) {
|
|
408
|
-
sandboxPkgJson[section][name] = `link:${pkgPath}`;
|
|
409
|
-
modified = true;
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
if (modified) {
|
|
415
|
-
await fs_extra_1.default.writeJson(sandboxPkgJsonPath, sandboxPkgJson, { spaces: 2 });
|
|
416
|
-
}
|
|
417
|
-
return true;
|
|
418
|
-
}
|
|
419
|
-
catch (e) {
|
|
420
|
-
console.warn(picocolors_1.default.yellow(` ⚠️ Link 本地源码失败,将尝试从 NPM 安装: ${e.message}`));
|
|
421
|
-
return false;
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
/**
|
|
425
|
-
* 切换全局当前使用的内核版本
|
|
426
|
-
*/
|
|
427
|
-
static async useVersion(version) {
|
|
428
|
-
const versionRoot = this.getVersionRoot();
|
|
429
|
-
const currentLinkPath = path_1.default.join(versionRoot, 'current');
|
|
430
|
-
const targetPath = this.getVersionPath(version);
|
|
431
|
-
if (!fs_extra_1.default.existsSync(targetPath)) {
|
|
432
|
-
throw new Error(`版本 ${version} 尚未安装`);
|
|
433
|
-
}
|
|
434
|
-
if (fs_extra_1.default.existsSync(currentLinkPath)) {
|
|
435
|
-
await fs_extra_1.default.remove(currentLinkPath);
|
|
436
|
-
}
|
|
437
|
-
await fs_extra_1.default.symlink(targetPath, currentLinkPath, 'dir');
|
|
438
|
-
}
|
|
439
|
-
/**
|
|
440
|
-
* 可视化展示沙箱状态
|
|
441
|
-
*/
|
|
442
|
-
static async visualizeStatus(projectRoot) {
|
|
443
|
-
const version = await this.getCurrentVersion(projectRoot);
|
|
444
|
-
const versionPath = this.getVersionPath(version);
|
|
445
|
-
const isInstalled = fs_extra_1.default.existsSync(versionPath);
|
|
446
|
-
const sandboxNm = path_1.default.join(versionPath, 'node_modules');
|
|
447
|
-
let statusText = '';
|
|
448
|
-
statusText += `${picocolors_1.default.bold('当前内核版本:')} ${picocolors_1.default.cyan(version)}\n`;
|
|
449
|
-
statusText += `${picocolors_1.default.bold('沙箱安装路径:')} ${picocolors_1.default.gray(versionPath)}\n`;
|
|
450
|
-
statusText += `${picocolors_1.default.bold('安装状态:')} ${isInstalled ? picocolors_1.default.green('已就绪') : picocolors_1.default.red('未安装')}\n`;
|
|
451
|
-
if (isInstalled) {
|
|
452
|
-
const corePkgs = this.CORE_PACKAGES.map(pkg => {
|
|
453
|
-
const pkgPath = path_1.default.join(sandboxNm, pkg);
|
|
454
|
-
const exists = fs_extra_1.default.existsSync(pkgPath);
|
|
455
|
-
let linkTarget = '';
|
|
456
|
-
if (exists) {
|
|
457
|
-
try {
|
|
458
|
-
const stats = fs_extra_1.default.lstatSync(pkgPath);
|
|
459
|
-
if (stats.isSymbolicLink()) {
|
|
460
|
-
linkTarget = ` -> ${picocolors_1.default.yellow(fs_extra_1.default.readlinkSync(pkgPath))}`;
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
catch (e) { }
|
|
464
|
-
}
|
|
465
|
-
return ` ${exists ? picocolors_1.default.green('✓') : picocolors_1.default.red('✗')} ${pkg.padEnd(30)}${linkTarget}`;
|
|
466
|
-
}).join('\n');
|
|
467
|
-
statusText += `\n${picocolors_1.default.bold('核心组件状态:')}\n${corePkgs}`;
|
|
468
|
-
}
|
|
469
|
-
(0, utils_1.printBox)(statusText, 'ChatBI 内核可观测性面板');
|
|
470
|
-
}
|
|
471
|
-
/**
|
|
472
|
-
* 获取当前项目使用的内核版本
|
|
473
|
-
*/
|
|
474
|
-
static async getCurrentVersion(projectRoot) {
|
|
475
|
-
// 逻辑参考 CoreKit.resolveVersion,但为了解耦我们在这里简单实现
|
|
476
|
-
// 或者直接从 Sandbox.CORE_PACKAGES 的 package.json 中读
|
|
477
|
-
try {
|
|
478
|
-
const chatbiDir = path_1.default.join(projectRoot, '.chatbi');
|
|
479
|
-
const tsconfigPath = path_1.default.join(chatbiDir, 'tsconfig.json');
|
|
480
|
-
if (fs_extra_1.default.existsSync(tsconfigPath)) {
|
|
481
|
-
const tsconfig = await fs_extra_1.default.readJson(tsconfigPath);
|
|
482
|
-
// 尝试从路径中解析版本
|
|
483
|
-
if (tsconfig.extends && tsconfig.extends.includes('/versions/')) {
|
|
484
|
-
const parts = tsconfig.extends.split('/');
|
|
485
|
-
const vIdx = parts.indexOf('versions');
|
|
486
|
-
if (vIdx !== -1 && parts[vIdx + 1]) {
|
|
487
|
-
return parts[vIdx + 1];
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
catch (e) { }
|
|
493
|
-
return 'current';
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
exports.Sandbox = Sandbox;
|
|
497
|
-
Sandbox.BASE_DIR = path_1.default.join(os_1.default.homedir(), '.chatbi-v-core');
|
|
498
|
-
Sandbox.CORE_PACKAGES = [
|
|
499
|
-
'@chatbi-v/core',
|
|
500
|
-
'@chatbi-v/mocks',
|
|
501
|
-
'@chatbi-v/tsconfig',
|
|
502
|
-
'@chatbi-v/tailwind-config',
|
|
503
|
-
'@chatbi-v/plugin-theme-manager',
|
|
504
|
-
'@chatbi-v/plugin-layout-transform',
|
|
505
|
-
'@chatbi-v/plugin-system-monitor'
|
|
506
|
-
];
|
|
507
|
-
Sandbox.RUNTIME_DEPS = [
|
|
508
|
-
'@ant-design/x',
|
|
509
|
-
'@ant-design/icons',
|
|
510
|
-
'antd',
|
|
511
|
-
'react',
|
|
512
|
-
'react-dom',
|
|
513
|
-
'lucide-react',
|
|
514
|
-
'framer-motion',
|
|
515
|
-
'clsx',
|
|
516
|
-
'tailwind-merge',
|
|
517
|
-
'react-router-dom',
|
|
518
|
-
'zustand',
|
|
519
|
-
'axios',
|
|
520
|
-
'less',
|
|
521
|
-
'vite'
|
|
522
|
-
];
|
package/dist/sync-7HPKGVFY.mjs
DELETED
package/dist/utils.js
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getCliRoot = exports.findPackageRoot = exports.printBox = exports.createSpinner = exports.logger = exports._dirname = void 0;
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
|
-
const picocolors_1 = __importDefault(require("picocolors"));
|
|
10
|
-
const ora_1 = __importDefault(require("ora"));
|
|
11
|
-
const boxen_1 = __importDefault(require("boxen"));
|
|
12
|
-
const _require = require;
|
|
13
|
-
const _filename = __filename;
|
|
14
|
-
exports._dirname = __dirname;
|
|
15
|
-
/**
|
|
16
|
-
* 统一的日志工具
|
|
17
|
-
*/
|
|
18
|
-
exports.logger = {
|
|
19
|
-
info: (msg) => console.log(picocolors_1.default.cyan(`ℹ ${msg}`)),
|
|
20
|
-
success: (msg) => console.log(picocolors_1.default.green(`✔ ${msg}`)),
|
|
21
|
-
warn: (msg) => console.log(picocolors_1.default.yellow(`⚠ ${msg}`)),
|
|
22
|
-
error: (msg, err) => {
|
|
23
|
-
console.error(picocolors_1.default.red(`\n❌ ${msg}`));
|
|
24
|
-
if (err) {
|
|
25
|
-
if (err instanceof Error) {
|
|
26
|
-
console.error(picocolors_1.default.gray(err.stack || err.message));
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
console.error(picocolors_1.default.gray(String(err)));
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
bold: (msg) => picocolors_1.default.bold(msg),
|
|
34
|
-
cyan: (msg) => picocolors_1.default.cyan(msg),
|
|
35
|
-
green: (msg) => picocolors_1.default.green(msg),
|
|
36
|
-
yellow: (msg) => picocolors_1.default.yellow(msg),
|
|
37
|
-
red: (msg) => picocolors_1.default.red(msg),
|
|
38
|
-
gray: (msg) => picocolors_1.default.gray(msg),
|
|
39
|
-
};
|
|
40
|
-
/**
|
|
41
|
-
* 创建进度条
|
|
42
|
-
*/
|
|
43
|
-
const createSpinner = (msg) => (0, ora_1.default)({
|
|
44
|
-
text: picocolors_1.default.cyan(msg),
|
|
45
|
-
color: 'cyan'
|
|
46
|
-
});
|
|
47
|
-
exports.createSpinner = createSpinner;
|
|
48
|
-
/**
|
|
49
|
-
* 打印装饰框
|
|
50
|
-
*/
|
|
51
|
-
const printBox = (msg, title, options = {}) => {
|
|
52
|
-
console.log('\n' + (0, boxen_1.default)(msg, {
|
|
53
|
-
padding: 1,
|
|
54
|
-
borderStyle: 'round',
|
|
55
|
-
borderColor: 'cyan',
|
|
56
|
-
title,
|
|
57
|
-
titleAlignment: 'center',
|
|
58
|
-
...options
|
|
59
|
-
}));
|
|
60
|
-
};
|
|
61
|
-
exports.printBox = printBox;
|
|
62
|
-
const findPackageRoot = (pkgName) => {
|
|
63
|
-
// 尝试标准解析 (针对已安装到 node_modules 的情况)
|
|
64
|
-
try {
|
|
65
|
-
const pkgPath = _require.resolve(`${pkgName}/package.json`);
|
|
66
|
-
return path_1.default.dirname(pkgPath);
|
|
67
|
-
}
|
|
68
|
-
catch (e) {
|
|
69
|
-
if (pkgName === '@chatbi-v/cli') {
|
|
70
|
-
return path_1.default.resolve(exports._dirname, '../../');
|
|
71
|
-
}
|
|
72
|
-
// 尝试在 CLI 自身的 node_modules 中查找
|
|
73
|
-
const localPath = path_1.default.resolve(exports._dirname, '../../node_modules', pkgName);
|
|
74
|
-
if (fs_extra_1.default.existsSync(localPath)) {
|
|
75
|
-
return localPath;
|
|
76
|
-
}
|
|
77
|
-
throw new Error(`无法找到包 ${pkgName},请确保已通过 pnpm/npm 安装。`);
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
exports.findPackageRoot = findPackageRoot;
|
|
81
|
-
const getCliRoot = async () => {
|
|
82
|
-
let myCliRoot = '';
|
|
83
|
-
let checkDir = exports._dirname;
|
|
84
|
-
while (checkDir !== path_1.default.parse(checkDir).root) {
|
|
85
|
-
if (fs_extra_1.default.existsSync(path_1.default.join(checkDir, 'package.json'))) {
|
|
86
|
-
const pkg = await fs_extra_1.default.readJson(path_1.default.join(checkDir, 'package.json'));
|
|
87
|
-
if (pkg.name === '@chatbi-v/cli') {
|
|
88
|
-
myCliRoot = checkDir;
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
checkDir = path_1.default.dirname(checkDir);
|
|
93
|
-
}
|
|
94
|
-
if (!myCliRoot) {
|
|
95
|
-
myCliRoot = (0, exports.findPackageRoot)('@chatbi-v/cli');
|
|
96
|
-
}
|
|
97
|
-
return myCliRoot;
|
|
98
|
-
};
|
|
99
|
-
exports.getCliRoot = getCliRoot;
|