@chatbi-v/cli 1.0.2

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.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/index.mjs'
package/dist/index.js ADDED
@@ -0,0 +1,604 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+
25
+ // src/index.ts
26
+ var import_cac = __toESM(require("cac"));
27
+ var import_picocolors3 = __toESM(require("picocolors"));
28
+
29
+ // src/commands/build.ts
30
+ var import_fs_extra = __toESM(require("fs-extra"));
31
+ var import_path = __toESM(require("path"));
32
+ var import_picocolors = __toESM(require("picocolors"));
33
+ var import_tsup = require("tsup");
34
+ async function build(options) {
35
+ const cwd = process.cwd();
36
+ const pkgPath = import_path.default.join(cwd, "package.json");
37
+ if (!import_fs_extra.default.existsSync(pkgPath)) {
38
+ console.error(import_picocolors.default.red(`No package.json found in ${cwd}`));
39
+ return;
40
+ }
41
+ const pkg = await import_fs_extra.default.readJson(pkgPath);
42
+ console.log(import_picocolors.default.cyan(`Building ${pkg.name || "package"}...`));
43
+ let entry = ["src/index.ts"];
44
+ if (import_fs_extra.default.existsSync(import_path.default.join(cwd, "src/index.tsx"))) {
45
+ entry = ["src/index.tsx"];
46
+ }
47
+ const isPlugin = pkg.plugin === true;
48
+ if (!options.watch) {
49
+ await import_fs_extra.default.remove(import_path.default.join(cwd, "dist"));
50
+ const tsbuildinfo = import_path.default.join(cwd, "tsconfig.tsbuildinfo");
51
+ if (import_fs_extra.default.existsSync(tsbuildinfo)) {
52
+ await import_fs_extra.default.remove(tsbuildinfo);
53
+ }
54
+ }
55
+ const external = [
56
+ "react",
57
+ "react-dom",
58
+ "react/jsx-runtime",
59
+ "react-is",
60
+ "antd",
61
+ "@ant-design/icons",
62
+ "@ant-design/x",
63
+ ...Object.keys(pkg.dependencies || {}),
64
+ ...Object.keys(pkg.peerDependencies || {})
65
+ ];
66
+ if (isPlugin) {
67
+ const coreDeps = [
68
+ "@chatbi-v/core",
69
+ "@chatbi-v/domain",
70
+ "@chatbi-v/mocks",
71
+ "@chatbi-x/xcml"
72
+ ];
73
+ coreDeps.forEach((dep) => {
74
+ if (!external.includes(dep)) {
75
+ external.push(dep);
76
+ }
77
+ });
78
+ }
79
+ const commonConfig = {
80
+ entry,
81
+ dts: false,
82
+ clean: false,
83
+ // Don't clean here, handle it manually or only on first build
84
+ sourcemap: false,
85
+ target: "esnext",
86
+ external,
87
+ watch: options.watch,
88
+ silent: false,
89
+ esbuildOptions(options2) {
90
+ options2.logOverride = {
91
+ "empty-import-meta": "silent"
92
+ };
93
+ }
94
+ };
95
+ if (isPlugin) {
96
+ console.log(import_picocolors.default.cyan("Building ESM format..."));
97
+ await (0, import_tsup.build)({
98
+ ...commonConfig,
99
+ clean: false,
100
+ format: ["esm"],
101
+ outExtension: () => ({ js: ".mjs" })
102
+ });
103
+ console.log(import_picocolors.default.cyan("Building IIFE format (Plugin)..."));
104
+ await (0, import_tsup.build)({
105
+ ...commonConfig,
106
+ clean: false,
107
+ format: ["iife"],
108
+ globalName: pkg.name.replace(/[^a-zA-Z0-9]/g, "_"),
109
+ outExtension: () => ({ js: ".plugin.js" }),
110
+ platform: "browser",
111
+ define: {
112
+ "import.meta.env": "process.env"
113
+ }
114
+ });
115
+ } else {
116
+ await (0, import_tsup.build)({
117
+ ...commonConfig,
118
+ clean: false,
119
+ format: ["cjs", "esm"],
120
+ outExtension({ format }) {
121
+ return { js: format === "esm" ? ".mjs" : ".cjs" };
122
+ }
123
+ });
124
+ }
125
+ if (!options.watch) {
126
+ console.log(import_picocolors.default.cyan("Generating type definitions..."));
127
+ try {
128
+ const { execa } = await import("execa");
129
+ await execa("pnpm", ["exec", "tsc", "--build", "tsconfig.json"], { stdio: "inherit" });
130
+ console.log(import_picocolors.default.green("Type definitions generated."));
131
+ } catch (e) {
132
+ console.error(import_picocolors.default.red("Failed to generate type definitions."));
133
+ throw e;
134
+ }
135
+ }
136
+ }
137
+
138
+ // src/commands/init.ts
139
+ var import_fs_extra2 = __toESM(require("fs-extra"));
140
+ var import_path2 = __toESM(require("path"));
141
+ var import_picocolors2 = __toESM(require("picocolors"));
142
+ var import_module = require("module");
143
+ var import_url = require("url");
144
+ var import_meta = {};
145
+ var require2 = (0, import_module.createRequire)(import_meta.url);
146
+ var __filename = (0, import_url.fileURLToPath)(import_meta.url);
147
+ var __dirname = import_path2.default.dirname(__filename);
148
+ async function init(options) {
149
+ const { name } = options;
150
+ const rootDir = process.cwd();
151
+ const targetDir = import_path2.default.resolve(rootDir, name);
152
+ if (import_fs_extra2.default.existsSync(targetDir)) {
153
+ console.error(import_picocolors2.default.red(`Directory ${name} already exists.`));
154
+ return;
155
+ }
156
+ console.log(import_picocolors2.default.cyan(`\u{1F680} Initializing new business plugin project: ${name}...`));
157
+ try {
158
+ const findPackageRoot = (pkgName) => {
159
+ try {
160
+ const pkgPath = require2.resolve(`${pkgName}/package.json`);
161
+ return import_path2.default.dirname(pkgPath);
162
+ } catch (e) {
163
+ if (pkgName === "@chatbi-v/cli") {
164
+ return import_path2.default.resolve(__dirname, "../../");
165
+ }
166
+ throw new Error(`\u65E0\u6CD5\u627E\u5230\u5305 ${pkgName} \u7684\u6839\u76EE\u5F55\uFF0C\u8BF7\u786E\u4FDD\u5DF2\u901A\u8FC7 npm \u5B89\u88C5\u8BE5\u5305\u3002`);
167
+ }
168
+ };
169
+ await import_fs_extra2.default.ensureDir(targetDir);
170
+ await import_fs_extra2.default.ensureDir(import_path2.default.join(targetDir, "apps/main/src/hooks"));
171
+ await import_fs_extra2.default.ensureDir(import_path2.default.join(targetDir, "apps/main/src/providers"));
172
+ await import_fs_extra2.default.ensureDir(import_path2.default.join(targetDir, "plugins/demo-plugin/src"));
173
+ await import_fs_extra2.default.ensureDir(import_path2.default.join(targetDir, ".chatbi/core"));
174
+ await import_fs_extra2.default.ensureDir(import_path2.default.join(targetDir, ".chatbi/plugins"));
175
+ console.log(import_picocolors2.default.blue("\u{1F4E6} \u6B63\u5728\u51C6\u5907\u79BB\u7EBF SDK..."));
176
+ const corePath = findPackageRoot("@chatbi-v/core");
177
+ const coreDist = import_path2.default.join(corePath, "dist");
178
+ if (import_fs_extra2.default.existsSync(coreDist)) {
179
+ await import_fs_extra2.default.ensureDir(import_path2.default.join(targetDir, ".chatbi/core/dist"));
180
+ await import_fs_extra2.default.copy(coreDist, import_path2.default.join(targetDir, ".chatbi/core/dist"));
181
+ await import_fs_extra2.default.copy(import_path2.default.join(corePath, "package.json"), import_path2.default.join(targetDir, ".chatbi/core/package.json"));
182
+ } else {
183
+ console.warn(import_picocolors2.default.yellow(`\u26A0\uFE0F \u8B66\u544A: \u672A\u627E\u5230 @chatbi-v/core \u7684\u6784\u5EFA\u4EA7\u7269 (dist)\uFF0C\u8BF7\u786E\u4FDD\u5DF2\u8FD0\u884C build\u3002`));
184
+ }
185
+ const pluginsToCopy = [
186
+ "@chatbi-v/plugin-theme-manager",
187
+ "@chatbi-v/plugin-system-user",
188
+ "@chatbi-v/plugin-system-monitor"
189
+ ];
190
+ for (const pkgName of pluginsToCopy) {
191
+ const pRoot = findPackageRoot(pkgName);
192
+ const shortName = pkgName.replace("@chatbi-v/plugin-", "");
193
+ const pDist = import_path2.default.join(pRoot, "dist");
194
+ const pPkg = import_path2.default.join(pRoot, "package.json");
195
+ if (import_fs_extra2.default.existsSync(pDist)) {
196
+ await import_fs_extra2.default.ensureDir(import_path2.default.join(targetDir, `.chatbi/plugins/${shortName}/dist`));
197
+ await import_fs_extra2.default.copy(pDist, import_path2.default.join(targetDir, `.chatbi/plugins/${shortName}/dist`));
198
+ await import_fs_extra2.default.copy(pPkg, import_path2.default.join(targetDir, `.chatbi/plugins/${shortName}/package.json`));
199
+ } else {
200
+ console.warn(import_picocolors2.default.yellow(`\u26A0\uFE0F \u8B66\u544A: \u672A\u627E\u5230\u63D2\u4EF6 ${pkgName} \u7684\u6784\u5EFA\u4EA7\u7269 (dist)\u3002`));
201
+ }
202
+ }
203
+ await import_fs_extra2.default.writeJson(import_path2.default.join(targetDir, "package.json"), {
204
+ name,
205
+ private: true,
206
+ version: "1.0.0",
207
+ type: "module",
208
+ scripts: {
209
+ "dev": "pnpm --filter @chatbi-v/main dev",
210
+ "build": "pnpm -r build",
211
+ "create:plugin": "node scripts/create-plugin.js"
212
+ },
213
+ workspaces: [
214
+ "apps/*",
215
+ "plugins/*"
216
+ ],
217
+ devDependencies: {
218
+ "typescript": "^5.0.0",
219
+ "@chatbi-v/cli": "link:./.chatbi/cli",
220
+ "vite": "^5.4.0",
221
+ "@vitejs/plugin-react": "^4.3.1",
222
+ "tailwindcss": "^3.4.0",
223
+ "postcss": "^8.4.0",
224
+ "autoprefixer": "^10.4.0",
225
+ "pnpm": ">=9.0.0"
226
+ }
227
+ }, { spaces: 2 });
228
+ await import_fs_extra2.default.writeFile(import_path2.default.join(targetDir, "pnpm-workspace.yaml"), `packages:
229
+ - 'apps/*'
230
+ - 'plugins/*'
231
+ `);
232
+ console.log(import_picocolors2.default.blue("\u{1F5A5}\uFE0F \u6B63\u5728\u751F\u6210\u5BBF\u4E3B\u5E94\u7528\u6846\u67B6..."));
233
+ const mainPkg = {
234
+ name: "@chatbi-v/main",
235
+ private: true,
236
+ type: "module",
237
+ scripts: {
238
+ "dev": "vite",
239
+ "build": "vite build"
240
+ },
241
+ dependencies: {
242
+ "react": "^18.3.1",
243
+ "react-dom": "^18.3.1",
244
+ "antd": "^5.20.0",
245
+ "@ant-design/icons": "^5.2.6",
246
+ "@chatbi-v/core": "link:../../.chatbi/core"
247
+ },
248
+ devDependencies: {
249
+ "@vitejs/plugin-react": "^4.3.1"
250
+ }
251
+ };
252
+ await import_fs_extra2.default.writeJson(import_path2.default.join(targetDir, "apps/main/package.json"), mainPkg, { spaces: 2 });
253
+ await import_fs_extra2.default.writeFile(import_path2.default.join(targetDir, "apps/main/index.html"), `
254
+ <!DOCTYPE html>
255
+ <html lang="en">
256
+ <head>
257
+ <meta charset="UTF-8" />
258
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
259
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
260
+ <title>ChatBI Business Plugin Host</title>
261
+ </head>
262
+ <body>
263
+ <div id="root"></div>
264
+ <script type="module" src="/src/main.tsx"></script>
265
+ </body>
266
+ </html>
267
+ `);
268
+ await import_fs_extra2.default.writeFile(import_path2.default.join(targetDir, "apps/main/vite.config.ts"), `
269
+ import { defineConfig } from 'vite'
270
+ import react from '@vitejs/plugin-react'
271
+ import path from 'path'
272
+
273
+ export default defineConfig({
274
+ plugins: [react()],
275
+ resolve: {
276
+ alias: {
277
+ '@chatbi-v/core': path.resolve(__dirname, '../../.chatbi/core')
278
+ }
279
+ }
280
+ })
281
+ `);
282
+ await import_fs_extra2.default.writeFile(import_path2.default.join(targetDir, "apps/main/src/main.tsx"), `
283
+ import React from 'react'
284
+ import ReactDOM from 'react-dom/client'
285
+ import App from './App'
286
+ import './index.css'
287
+
288
+ ReactDOM.createRoot(document.getElementById('root')!).render(
289
+ <React.StrictMode>
290
+ <App />
291
+ </React.StrictMode>,
292
+ )
293
+ `);
294
+ await import_fs_extra2.default.writeFile(import_path2.default.join(targetDir, "apps/main/src/App.tsx"), `
295
+ import React from 'react'
296
+ import { usePluginLoader } from './hooks/usePluginLoader'
297
+ import { PluginSlot, Slot } from '@chatbi-v/core'
298
+
299
+ const App: React.FC = () => {
300
+ const { pluginsLoaded } = usePluginLoader()
301
+
302
+ if (!pluginsLoaded) {
303
+ return <div>Loading plugins and kernel...</div>
304
+ }
305
+
306
+ return (
307
+ <div className="app-container">
308
+ <h1>ChatBI Business Plugin Host</h1>
309
+ <div className="main-layout">
310
+ <aside>
311
+ <PluginSlot name={Slot.Sidebar} />
312
+ </aside>
313
+ <main>
314
+ <PluginSlot name={Slot.MainContent} />
315
+ </main>
316
+ </div>
317
+ </div>
318
+ )
319
+ }
320
+
321
+ export default App
322
+ `);
323
+ await import_fs_extra2.default.writeFile(import_path2.default.join(targetDir, "apps/main/src/hooks/usePluginLoader.ts"), `
324
+ import { usePluginLoader as useCoreLoader } from '@chatbi-v/core'
325
+ import { useMemo } from 'react'
326
+
327
+ export const usePluginLoader = () => {
328
+ const options = useMemo(() => ({
329
+ pluginConfigs: {
330
+ 'demo-plugin': { enabled: true }
331
+ },
332
+ sharedContext: { api: {} }
333
+ }), [])
334
+
335
+ return useCoreLoader(options)
336
+ }
337
+ `);
338
+ console.log(import_picocolors2.default.blue("\u{1F9E9} \u6B63\u5728\u751F\u6210\u793A\u4F8B\u4E1A\u52A1\u63D2\u4EF6..."));
339
+ await import_fs_extra2.default.ensureDir(import_path2.default.join(targetDir, "plugins/demo-plugin/src"));
340
+ await import_fs_extra2.default.writeJson(import_path2.default.join(targetDir, "plugins/demo-plugin/tsconfig.json"), {
341
+ extends: "../../tsconfig.json",
342
+ compilerOptions: {
343
+ baseUrl: ".",
344
+ paths: {
345
+ "@/*": ["./src/*"]
346
+ }
347
+ },
348
+ include: ["src"]
349
+ }, { spaces: 2 });
350
+ const demoPkg = {
351
+ name: "@chatbi-v/plugin-demo",
352
+ version: "1.0.0",
353
+ type: "module",
354
+ plugin: true,
355
+ dependencies: {
356
+ "@chatbi-v/core": "link:../../.chatbi/core"
357
+ }
358
+ };
359
+ await import_fs_extra2.default.writeJson(import_path2.default.join(targetDir, "plugins/demo-plugin/package.json"), demoPkg, { spaces: 2 });
360
+ await import_fs_extra2.default.writeFile(import_path2.default.join(targetDir, "plugins/demo-plugin/src/index.tsx"), `
361
+ import React from 'react'
362
+ import { Plugin, PluginContext, Slot } from '@chatbi-v/core'
363
+
364
+ export class DemoPlugin implements Plugin {
365
+ id = 'demo-plugin'
366
+ metadata = {
367
+ name: 'Demo Business Plugin',
368
+ version: '1.0.0',
369
+ type: 'business',
370
+ extensions: [
371
+ {
372
+ slot: Slot.MainContent,
373
+ component: () => <div style={{ padding: 20, border: '1px solid #ccc' }}>Hello from Demo Plugin!</div>
374
+ }
375
+ ]
376
+ }
377
+
378
+ onLoad(context: PluginContext) {
379
+ context.logger?.info('Demo Plugin Loaded')
380
+ }
381
+ }
382
+
383
+ export default new DemoPlugin()
384
+ `);
385
+ console.log(import_picocolors2.default.blue("\u{1F4DC} \u6B63\u5728\u590D\u5236\u5F00\u53D1\u5DE5\u5177\u811A\u672C..."));
386
+ await import_fs_extra2.default.ensureDir(import_path2.default.join(targetDir, "scripts"));
387
+ let createPluginScript = null;
388
+ let currentSearchDir = __dirname;
389
+ while (currentSearchDir !== import_path2.default.parse(currentSearchDir).root) {
390
+ const potentialPath = import_path2.default.resolve(currentSearchDir, "scripts/create-plugin.js");
391
+ if (import_fs_extra2.default.existsSync(potentialPath)) {
392
+ createPluginScript = potentialPath;
393
+ break;
394
+ }
395
+ currentSearchDir = import_path2.default.dirname(currentSearchDir);
396
+ }
397
+ if (createPluginScript) {
398
+ await import_fs_extra2.default.copy(createPluginScript, import_path2.default.join(targetDir, "scripts/create-plugin.js"));
399
+ } else {
400
+ await import_fs_extra2.default.writeFile(import_path2.default.join(targetDir, "scripts/create-plugin.js"), `
401
+ import fs from 'fs-extra'
402
+ import path from 'path'
403
+
404
+ const name = process.argv[2]
405
+ if (!name) {
406
+ console.error('\u8BF7\u63D0\u4F9B\u63D2\u4EF6\u540D\u79F0')
407
+ process.exit(1)
408
+ }
409
+
410
+ const pluginDir = path.resolve(process.cwd(), 'plugins', name)
411
+ await fs.ensureDir(path.join(pluginDir, 'src'))
412
+
413
+ console.log(\`\u63D2\u4EF6 \${name} \u521B\u5EFA\u6210\u529F!\`)
414
+ `);
415
+ }
416
+ console.log(import_picocolors2.default.blue("\u{1F6E0}\uFE0F \u6B63\u5728\u51C6\u5907\u79BB\u7EBF CLI \u5DE5\u5177..."));
417
+ const cliSourceDir = findPackageRoot("@chatbi-v/cli");
418
+ const cliTargetDir = import_path2.default.join(targetDir, ".chatbi/cli");
419
+ await import_fs_extra2.default.ensureDir(import_path2.default.join(cliTargetDir, "dist"));
420
+ if (import_fs_extra2.default.existsSync(import_path2.default.join(cliSourceDir, "dist"))) {
421
+ await import_fs_extra2.default.copy(import_path2.default.join(cliSourceDir, "dist"), import_path2.default.join(cliTargetDir, "dist"));
422
+ await import_fs_extra2.default.copy(import_path2.default.join(cliSourceDir, "package.json"), import_path2.default.join(cliTargetDir, "package.json"));
423
+ if (import_fs_extra2.default.existsSync(import_path2.default.join(cliSourceDir, "bin"))) {
424
+ await import_fs_extra2.default.ensureDir(import_path2.default.join(cliTargetDir, "bin"));
425
+ await import_fs_extra2.default.copy(import_path2.default.join(cliSourceDir, "bin"), import_path2.default.join(cliTargetDir, "bin"));
426
+ }
427
+ } else {
428
+ console.warn(import_picocolors2.default.yellow("\u26A0\uFE0F \u8B66\u544A: \u672A\u627E\u5230 @chatbi-v/cli \u7684\u6784\u5EFA\u4EA7\u7269 (dist)\u3002"));
429
+ }
430
+ await import_fs_extra2.default.writeJson(import_path2.default.join(targetDir, "apps/main/tsconfig.json"), {
431
+ extends: "../../tsconfig.json",
432
+ compilerOptions: {
433
+ baseUrl: ".",
434
+ paths: {
435
+ "@/*": ["./src/*"]
436
+ }
437
+ },
438
+ include: ["src"]
439
+ }, { spaces: 2 });
440
+ await import_fs_extra2.default.writeFile(import_path2.default.join(targetDir, "apps/main/src/index.css"), `
441
+ @tailwind base;
442
+ @tailwind components;
443
+ @tailwind utilities;
444
+
445
+ :root {
446
+ --layout-sidebar-width: 260px;
447
+ --layout-gap: 16px;
448
+ }
449
+
450
+ body {
451
+ margin: 0;
452
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
453
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
454
+ sans-serif;
455
+ -webkit-font-smoothing: antialiased;
456
+ -moz-osx-font-smoothing: grayscale;
457
+ }
458
+ `);
459
+ await import_fs_extra2.default.writeFile(import_path2.default.join(targetDir, "apps/main/tailwind.config.cjs"), `
460
+ /** @type {import('tailwindcss').Config} */
461
+ module.exports = {
462
+ content: [
463
+ "./index.html",
464
+ "./src/**/*.{js,ts,jsx,tsx}",
465
+ "../../plugins/**/*.{js,ts,jsx,tsx}",
466
+ "../../.chatbi/plugins/**/*.{js,ts,jsx,tsx}"
467
+ ],
468
+ theme: {
469
+ extend: {
470
+ colors: {
471
+ primary: '#6366f1',
472
+ }
473
+ },
474
+ },
475
+ plugins: [],
476
+ }
477
+ `);
478
+ await import_fs_extra2.default.writeFile(import_path2.default.join(targetDir, "apps/main/postcss.config.cjs"), `
479
+ module.exports = {
480
+ plugins: {
481
+ tailwindcss: {},
482
+ autoprefixer: {},
483
+ },
484
+ }
485
+ `);
486
+ await import_fs_extra2.default.writeFile(import_path2.default.join(targetDir, "apps/main/src/hooks/usePluginLoader.ts"), `
487
+ import { usePluginLoader as useCoreLoader } from '@chatbi-v/core'
488
+ import { useMemo } from 'react'
489
+
490
+ // \u79BB\u7EBF\u63D2\u4EF6\u6CE8\u518C\u8868
491
+ const offlineRegistry = {
492
+ 'theme-manager': () => import('../../../.chatbi/plugins/theme-manager/dist/index.mjs'),
493
+ 'system-user': () => import('../../../.chatbi/plugins/system-user/dist/index.mjs'),
494
+ 'system-monitor': () => import('../../../.chatbi/plugins/system-monitor/dist/index.mjs'),
495
+ 'demo-plugin': () => import('../../../plugins/demo-plugin/src/index')
496
+ }
497
+
498
+ export const usePluginLoader = () => {
499
+ const options = useMemo(() => ({
500
+ pluginConfigs: {
501
+ 'theme-manager': { enabled: true },
502
+ 'system-user': { enabled: true },
503
+ 'system-monitor': { enabled: true },
504
+ 'demo-plugin': { enabled: true }
505
+ },
506
+ registry: offlineRegistry,
507
+ sharedContext: { api: {} }
508
+ }), [])
509
+
510
+ return useCoreLoader(options)
511
+ }
512
+ `);
513
+ await import_fs_extra2.default.writeJson(import_path2.default.join(targetDir, "tsconfig.json"), {
514
+ compilerOptions: {
515
+ target: "ESNext",
516
+ useDefineForClassFields: true,
517
+ lib: ["DOM", "DOM.Iterable", "ESNext"],
518
+ allowJs: false,
519
+ skipLibCheck: true,
520
+ esModuleInterop: false,
521
+ allowSyntheticDefaultImports: true,
522
+ strict: true,
523
+ forceConsistentCasingInFileNames: true,
524
+ module: "ESNext",
525
+ moduleResolution: "Node",
526
+ resolveJsonModule: true,
527
+ isolatedModules: true,
528
+ noEmit: true,
529
+ jsx: "react-jsx",
530
+ baseUrl: ".",
531
+ paths: {
532
+ "@chatbi-v/core": ["./.chatbi/core"]
533
+ }
534
+ },
535
+ include: ["apps/main/src", "plugins/*/src"]
536
+ }, { spaces: 2 });
537
+ await import_fs_extra2.default.writeFile(import_path2.default.join(targetDir, "README.md"), `
538
+ # ${name}
539
+
540
+ \u57FA\u4E8E ChatBI-V SDK \u521D\u59CB\u5316\u7684\u4E1A\u52A1\u63D2\u4EF6\u9879\u76EE\u3002
541
+
542
+ ## \u9879\u76EE\u7ED3\u6784
543
+
544
+ - \`apps/main\`: \u5BBF\u4E3B\u5E94\u7528\uFF0C\u7528\u4E8E\u9A8C\u8BC1\u63D2\u4EF6\u529F\u80FD\u3002
545
+ - \`plugins/\`: \u4E1A\u52A1\u63D2\u4EF6\u6E90\u7801\u76EE\u5F55\u3002
546
+ - \`.chatbi/\`: \u79BB\u7EBF SDK \u8D44\u6E90\uFF08\u6838\u5FC3\u5305\u3001\u6807\u51C6\u63D2\u4EF6\u3001CLI \u5DE5\u5177\uFF09\u3002
547
+
548
+ ## \u5FEB\u901F\u5F00\u59CB
549
+
550
+ 1. \u5B89\u88C5\u4F9D\u8D56:
551
+ \`\`\`bash
552
+ pnpm install
553
+ \`\`\`
554
+
555
+ 2. \u542F\u52A8\u5F00\u53D1\u670D\u52A1\u5668:
556
+ \`\`\`bash
557
+ pnpm dev
558
+ \`\`\`
559
+
560
+ 3. \u521B\u5EFA\u65B0\u63D2\u4EF6:
561
+ \`\`\`bash
562
+ pnpm create:plugin <plugin-name>
563
+ \`\`\`
564
+
565
+ ## \u63D2\u4EF6\u5F00\u53D1
566
+
567
+ \u53C2\u8003 \`plugins/demo-plugin\` \u793A\u4F8B\u3002
568
+ `);
569
+ console.log(`
570
+ \u2705 \u9879\u76EE ${import_picocolors2.default.green(name)} \u521D\u59CB\u5316\u6210\u529F!`);
571
+ console.log(import_picocolors2.default.cyan(`
572
+ \u540E\u7EED\u6B65\u9AA4:`));
573
+ console.log(import_picocolors2.default.white(` 1. cd ${name}`));
574
+ console.log(import_picocolors2.default.white(` 2. pnpm install`));
575
+ console.log(import_picocolors2.default.white(` 3. pnpm dev`));
576
+ } catch (error) {
577
+ console.error(import_picocolors2.default.red("Failed to initialize project:"), error);
578
+ throw error;
579
+ }
580
+ }
581
+
582
+ // src/index.ts
583
+ var cli = (0, import_cac.default)("chatbi-cli");
584
+ cli.command("build", "Build the current package").option("--watch", "Watch mode").action(async (options) => {
585
+ try {
586
+ await build(options);
587
+ } catch (e) {
588
+ console.error(import_picocolors3.default.red("Build failed"));
589
+ console.error(e);
590
+ process.exit(1);
591
+ }
592
+ });
593
+ cli.command("init <name>", "Initialize a new business plugin project").action(async (name) => {
594
+ try {
595
+ await init({ name });
596
+ } catch (e) {
597
+ console.error(import_picocolors3.default.red("Initialization failed"));
598
+ console.error(e);
599
+ process.exit(1);
600
+ }
601
+ });
602
+ cli.help();
603
+ cli.version("1.0.0");
604
+ cli.parse();
package/dist/index.mjs ADDED
@@ -0,0 +1,579 @@
1
+ // src/index.ts
2
+ import cac from "cac";
3
+ import pc3 from "picocolors";
4
+
5
+ // src/commands/build.ts
6
+ import fs from "fs-extra";
7
+ import path from "path";
8
+ import pc from "picocolors";
9
+ import { build as tsupBuild } from "tsup";
10
+ async function build(options) {
11
+ const cwd = process.cwd();
12
+ const pkgPath = path.join(cwd, "package.json");
13
+ if (!fs.existsSync(pkgPath)) {
14
+ console.error(pc.red(`No package.json found in ${cwd}`));
15
+ return;
16
+ }
17
+ const pkg = await fs.readJson(pkgPath);
18
+ console.log(pc.cyan(`Building ${pkg.name || "package"}...`));
19
+ let entry = ["src/index.ts"];
20
+ if (fs.existsSync(path.join(cwd, "src/index.tsx"))) {
21
+ entry = ["src/index.tsx"];
22
+ }
23
+ const isPlugin = pkg.plugin === true;
24
+ if (!options.watch) {
25
+ await fs.remove(path.join(cwd, "dist"));
26
+ const tsbuildinfo = path.join(cwd, "tsconfig.tsbuildinfo");
27
+ if (fs.existsSync(tsbuildinfo)) {
28
+ await fs.remove(tsbuildinfo);
29
+ }
30
+ }
31
+ const external = [
32
+ "react",
33
+ "react-dom",
34
+ "react/jsx-runtime",
35
+ "react-is",
36
+ "antd",
37
+ "@ant-design/icons",
38
+ "@ant-design/x",
39
+ ...Object.keys(pkg.dependencies || {}),
40
+ ...Object.keys(pkg.peerDependencies || {})
41
+ ];
42
+ if (isPlugin) {
43
+ const coreDeps = [
44
+ "@chatbi-v/core",
45
+ "@chatbi-v/domain",
46
+ "@chatbi-v/mocks",
47
+ "@chatbi-x/xcml"
48
+ ];
49
+ coreDeps.forEach((dep) => {
50
+ if (!external.includes(dep)) {
51
+ external.push(dep);
52
+ }
53
+ });
54
+ }
55
+ const commonConfig = {
56
+ entry,
57
+ dts: false,
58
+ clean: false,
59
+ // Don't clean here, handle it manually or only on first build
60
+ sourcemap: false,
61
+ target: "esnext",
62
+ external,
63
+ watch: options.watch,
64
+ silent: false,
65
+ esbuildOptions(options2) {
66
+ options2.logOverride = {
67
+ "empty-import-meta": "silent"
68
+ };
69
+ }
70
+ };
71
+ if (isPlugin) {
72
+ console.log(pc.cyan("Building ESM format..."));
73
+ await tsupBuild({
74
+ ...commonConfig,
75
+ clean: false,
76
+ format: ["esm"],
77
+ outExtension: () => ({ js: ".mjs" })
78
+ });
79
+ console.log(pc.cyan("Building IIFE format (Plugin)..."));
80
+ await tsupBuild({
81
+ ...commonConfig,
82
+ clean: false,
83
+ format: ["iife"],
84
+ globalName: pkg.name.replace(/[^a-zA-Z0-9]/g, "_"),
85
+ outExtension: () => ({ js: ".plugin.js" }),
86
+ platform: "browser",
87
+ define: {
88
+ "import.meta.env": "process.env"
89
+ }
90
+ });
91
+ } else {
92
+ await tsupBuild({
93
+ ...commonConfig,
94
+ clean: false,
95
+ format: ["cjs", "esm"],
96
+ outExtension({ format }) {
97
+ return { js: format === "esm" ? ".mjs" : ".cjs" };
98
+ }
99
+ });
100
+ }
101
+ if (!options.watch) {
102
+ console.log(pc.cyan("Generating type definitions..."));
103
+ try {
104
+ const { execa } = await import("execa");
105
+ await execa("pnpm", ["exec", "tsc", "--build", "tsconfig.json"], { stdio: "inherit" });
106
+ console.log(pc.green("Type definitions generated."));
107
+ } catch (e) {
108
+ console.error(pc.red("Failed to generate type definitions."));
109
+ throw e;
110
+ }
111
+ }
112
+ }
113
+
114
+ // src/commands/init.ts
115
+ import fs2 from "fs-extra";
116
+ import path2 from "path";
117
+ import pc2 from "picocolors";
118
+ import { createRequire } from "module";
119
+ import { fileURLToPath } from "url";
120
+ var require2 = createRequire(import.meta.url);
121
+ var __filename = fileURLToPath(import.meta.url);
122
+ var __dirname = path2.dirname(__filename);
123
+ async function init(options) {
124
+ const { name } = options;
125
+ const rootDir = process.cwd();
126
+ const targetDir = path2.resolve(rootDir, name);
127
+ if (fs2.existsSync(targetDir)) {
128
+ console.error(pc2.red(`Directory ${name} already exists.`));
129
+ return;
130
+ }
131
+ console.log(pc2.cyan(`\u{1F680} Initializing new business plugin project: ${name}...`));
132
+ try {
133
+ const findPackageRoot = (pkgName) => {
134
+ try {
135
+ const pkgPath = require2.resolve(`${pkgName}/package.json`);
136
+ return path2.dirname(pkgPath);
137
+ } catch (e) {
138
+ if (pkgName === "@chatbi-v/cli") {
139
+ return path2.resolve(__dirname, "../../");
140
+ }
141
+ throw new Error(`\u65E0\u6CD5\u627E\u5230\u5305 ${pkgName} \u7684\u6839\u76EE\u5F55\uFF0C\u8BF7\u786E\u4FDD\u5DF2\u901A\u8FC7 npm \u5B89\u88C5\u8BE5\u5305\u3002`);
142
+ }
143
+ };
144
+ await fs2.ensureDir(targetDir);
145
+ await fs2.ensureDir(path2.join(targetDir, "apps/main/src/hooks"));
146
+ await fs2.ensureDir(path2.join(targetDir, "apps/main/src/providers"));
147
+ await fs2.ensureDir(path2.join(targetDir, "plugins/demo-plugin/src"));
148
+ await fs2.ensureDir(path2.join(targetDir, ".chatbi/core"));
149
+ await fs2.ensureDir(path2.join(targetDir, ".chatbi/plugins"));
150
+ console.log(pc2.blue("\u{1F4E6} \u6B63\u5728\u51C6\u5907\u79BB\u7EBF SDK..."));
151
+ const corePath = findPackageRoot("@chatbi-v/core");
152
+ const coreDist = path2.join(corePath, "dist");
153
+ if (fs2.existsSync(coreDist)) {
154
+ await fs2.ensureDir(path2.join(targetDir, ".chatbi/core/dist"));
155
+ await fs2.copy(coreDist, path2.join(targetDir, ".chatbi/core/dist"));
156
+ await fs2.copy(path2.join(corePath, "package.json"), path2.join(targetDir, ".chatbi/core/package.json"));
157
+ } else {
158
+ console.warn(pc2.yellow(`\u26A0\uFE0F \u8B66\u544A: \u672A\u627E\u5230 @chatbi-v/core \u7684\u6784\u5EFA\u4EA7\u7269 (dist)\uFF0C\u8BF7\u786E\u4FDD\u5DF2\u8FD0\u884C build\u3002`));
159
+ }
160
+ const pluginsToCopy = [
161
+ "@chatbi-v/plugin-theme-manager",
162
+ "@chatbi-v/plugin-system-user",
163
+ "@chatbi-v/plugin-system-monitor"
164
+ ];
165
+ for (const pkgName of pluginsToCopy) {
166
+ const pRoot = findPackageRoot(pkgName);
167
+ const shortName = pkgName.replace("@chatbi-v/plugin-", "");
168
+ const pDist = path2.join(pRoot, "dist");
169
+ const pPkg = path2.join(pRoot, "package.json");
170
+ if (fs2.existsSync(pDist)) {
171
+ await fs2.ensureDir(path2.join(targetDir, `.chatbi/plugins/${shortName}/dist`));
172
+ await fs2.copy(pDist, path2.join(targetDir, `.chatbi/plugins/${shortName}/dist`));
173
+ await fs2.copy(pPkg, path2.join(targetDir, `.chatbi/plugins/${shortName}/package.json`));
174
+ } else {
175
+ console.warn(pc2.yellow(`\u26A0\uFE0F \u8B66\u544A: \u672A\u627E\u5230\u63D2\u4EF6 ${pkgName} \u7684\u6784\u5EFA\u4EA7\u7269 (dist)\u3002`));
176
+ }
177
+ }
178
+ await fs2.writeJson(path2.join(targetDir, "package.json"), {
179
+ name,
180
+ private: true,
181
+ version: "1.0.0",
182
+ type: "module",
183
+ scripts: {
184
+ "dev": "pnpm --filter @chatbi-v/main dev",
185
+ "build": "pnpm -r build",
186
+ "create:plugin": "node scripts/create-plugin.js"
187
+ },
188
+ workspaces: [
189
+ "apps/*",
190
+ "plugins/*"
191
+ ],
192
+ devDependencies: {
193
+ "typescript": "^5.0.0",
194
+ "@chatbi-v/cli": "link:./.chatbi/cli",
195
+ "vite": "^5.4.0",
196
+ "@vitejs/plugin-react": "^4.3.1",
197
+ "tailwindcss": "^3.4.0",
198
+ "postcss": "^8.4.0",
199
+ "autoprefixer": "^10.4.0",
200
+ "pnpm": ">=9.0.0"
201
+ }
202
+ }, { spaces: 2 });
203
+ await fs2.writeFile(path2.join(targetDir, "pnpm-workspace.yaml"), `packages:
204
+ - 'apps/*'
205
+ - 'plugins/*'
206
+ `);
207
+ console.log(pc2.blue("\u{1F5A5}\uFE0F \u6B63\u5728\u751F\u6210\u5BBF\u4E3B\u5E94\u7528\u6846\u67B6..."));
208
+ const mainPkg = {
209
+ name: "@chatbi-v/main",
210
+ private: true,
211
+ type: "module",
212
+ scripts: {
213
+ "dev": "vite",
214
+ "build": "vite build"
215
+ },
216
+ dependencies: {
217
+ "react": "^18.3.1",
218
+ "react-dom": "^18.3.1",
219
+ "antd": "^5.20.0",
220
+ "@ant-design/icons": "^5.2.6",
221
+ "@chatbi-v/core": "link:../../.chatbi/core"
222
+ },
223
+ devDependencies: {
224
+ "@vitejs/plugin-react": "^4.3.1"
225
+ }
226
+ };
227
+ await fs2.writeJson(path2.join(targetDir, "apps/main/package.json"), mainPkg, { spaces: 2 });
228
+ await fs2.writeFile(path2.join(targetDir, "apps/main/index.html"), `
229
+ <!DOCTYPE html>
230
+ <html lang="en">
231
+ <head>
232
+ <meta charset="UTF-8" />
233
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
234
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
235
+ <title>ChatBI Business Plugin Host</title>
236
+ </head>
237
+ <body>
238
+ <div id="root"></div>
239
+ <script type="module" src="/src/main.tsx"></script>
240
+ </body>
241
+ </html>
242
+ `);
243
+ await fs2.writeFile(path2.join(targetDir, "apps/main/vite.config.ts"), `
244
+ import { defineConfig } from 'vite'
245
+ import react from '@vitejs/plugin-react'
246
+ import path from 'path'
247
+
248
+ export default defineConfig({
249
+ plugins: [react()],
250
+ resolve: {
251
+ alias: {
252
+ '@chatbi-v/core': path.resolve(__dirname, '../../.chatbi/core')
253
+ }
254
+ }
255
+ })
256
+ `);
257
+ await fs2.writeFile(path2.join(targetDir, "apps/main/src/main.tsx"), `
258
+ import React from 'react'
259
+ import ReactDOM from 'react-dom/client'
260
+ import App from './App'
261
+ import './index.css'
262
+
263
+ ReactDOM.createRoot(document.getElementById('root')!).render(
264
+ <React.StrictMode>
265
+ <App />
266
+ </React.StrictMode>,
267
+ )
268
+ `);
269
+ await fs2.writeFile(path2.join(targetDir, "apps/main/src/App.tsx"), `
270
+ import React from 'react'
271
+ import { usePluginLoader } from './hooks/usePluginLoader'
272
+ import { PluginSlot, Slot } from '@chatbi-v/core'
273
+
274
+ const App: React.FC = () => {
275
+ const { pluginsLoaded } = usePluginLoader()
276
+
277
+ if (!pluginsLoaded) {
278
+ return <div>Loading plugins and kernel...</div>
279
+ }
280
+
281
+ return (
282
+ <div className="app-container">
283
+ <h1>ChatBI Business Plugin Host</h1>
284
+ <div className="main-layout">
285
+ <aside>
286
+ <PluginSlot name={Slot.Sidebar} />
287
+ </aside>
288
+ <main>
289
+ <PluginSlot name={Slot.MainContent} />
290
+ </main>
291
+ </div>
292
+ </div>
293
+ )
294
+ }
295
+
296
+ export default App
297
+ `);
298
+ await fs2.writeFile(path2.join(targetDir, "apps/main/src/hooks/usePluginLoader.ts"), `
299
+ import { usePluginLoader as useCoreLoader } from '@chatbi-v/core'
300
+ import { useMemo } from 'react'
301
+
302
+ export const usePluginLoader = () => {
303
+ const options = useMemo(() => ({
304
+ pluginConfigs: {
305
+ 'demo-plugin': { enabled: true }
306
+ },
307
+ sharedContext: { api: {} }
308
+ }), [])
309
+
310
+ return useCoreLoader(options)
311
+ }
312
+ `);
313
+ console.log(pc2.blue("\u{1F9E9} \u6B63\u5728\u751F\u6210\u793A\u4F8B\u4E1A\u52A1\u63D2\u4EF6..."));
314
+ await fs2.ensureDir(path2.join(targetDir, "plugins/demo-plugin/src"));
315
+ await fs2.writeJson(path2.join(targetDir, "plugins/demo-plugin/tsconfig.json"), {
316
+ extends: "../../tsconfig.json",
317
+ compilerOptions: {
318
+ baseUrl: ".",
319
+ paths: {
320
+ "@/*": ["./src/*"]
321
+ }
322
+ },
323
+ include: ["src"]
324
+ }, { spaces: 2 });
325
+ const demoPkg = {
326
+ name: "@chatbi-v/plugin-demo",
327
+ version: "1.0.0",
328
+ type: "module",
329
+ plugin: true,
330
+ dependencies: {
331
+ "@chatbi-v/core": "link:../../.chatbi/core"
332
+ }
333
+ };
334
+ await fs2.writeJson(path2.join(targetDir, "plugins/demo-plugin/package.json"), demoPkg, { spaces: 2 });
335
+ await fs2.writeFile(path2.join(targetDir, "plugins/demo-plugin/src/index.tsx"), `
336
+ import React from 'react'
337
+ import { Plugin, PluginContext, Slot } from '@chatbi-v/core'
338
+
339
+ export class DemoPlugin implements Plugin {
340
+ id = 'demo-plugin'
341
+ metadata = {
342
+ name: 'Demo Business Plugin',
343
+ version: '1.0.0',
344
+ type: 'business',
345
+ extensions: [
346
+ {
347
+ slot: Slot.MainContent,
348
+ component: () => <div style={{ padding: 20, border: '1px solid #ccc' }}>Hello from Demo Plugin!</div>
349
+ }
350
+ ]
351
+ }
352
+
353
+ onLoad(context: PluginContext) {
354
+ context.logger?.info('Demo Plugin Loaded')
355
+ }
356
+ }
357
+
358
+ export default new DemoPlugin()
359
+ `);
360
+ console.log(pc2.blue("\u{1F4DC} \u6B63\u5728\u590D\u5236\u5F00\u53D1\u5DE5\u5177\u811A\u672C..."));
361
+ await fs2.ensureDir(path2.join(targetDir, "scripts"));
362
+ let createPluginScript = null;
363
+ let currentSearchDir = __dirname;
364
+ while (currentSearchDir !== path2.parse(currentSearchDir).root) {
365
+ const potentialPath = path2.resolve(currentSearchDir, "scripts/create-plugin.js");
366
+ if (fs2.existsSync(potentialPath)) {
367
+ createPluginScript = potentialPath;
368
+ break;
369
+ }
370
+ currentSearchDir = path2.dirname(currentSearchDir);
371
+ }
372
+ if (createPluginScript) {
373
+ await fs2.copy(createPluginScript, path2.join(targetDir, "scripts/create-plugin.js"));
374
+ } else {
375
+ await fs2.writeFile(path2.join(targetDir, "scripts/create-plugin.js"), `
376
+ import fs from 'fs-extra'
377
+ import path from 'path'
378
+
379
+ const name = process.argv[2]
380
+ if (!name) {
381
+ console.error('\u8BF7\u63D0\u4F9B\u63D2\u4EF6\u540D\u79F0')
382
+ process.exit(1)
383
+ }
384
+
385
+ const pluginDir = path.resolve(process.cwd(), 'plugins', name)
386
+ await fs.ensureDir(path.join(pluginDir, 'src'))
387
+
388
+ console.log(\`\u63D2\u4EF6 \${name} \u521B\u5EFA\u6210\u529F!\`)
389
+ `);
390
+ }
391
+ console.log(pc2.blue("\u{1F6E0}\uFE0F \u6B63\u5728\u51C6\u5907\u79BB\u7EBF CLI \u5DE5\u5177..."));
392
+ const cliSourceDir = findPackageRoot("@chatbi-v/cli");
393
+ const cliTargetDir = path2.join(targetDir, ".chatbi/cli");
394
+ await fs2.ensureDir(path2.join(cliTargetDir, "dist"));
395
+ if (fs2.existsSync(path2.join(cliSourceDir, "dist"))) {
396
+ await fs2.copy(path2.join(cliSourceDir, "dist"), path2.join(cliTargetDir, "dist"));
397
+ await fs2.copy(path2.join(cliSourceDir, "package.json"), path2.join(cliTargetDir, "package.json"));
398
+ if (fs2.existsSync(path2.join(cliSourceDir, "bin"))) {
399
+ await fs2.ensureDir(path2.join(cliTargetDir, "bin"));
400
+ await fs2.copy(path2.join(cliSourceDir, "bin"), path2.join(cliTargetDir, "bin"));
401
+ }
402
+ } else {
403
+ console.warn(pc2.yellow("\u26A0\uFE0F \u8B66\u544A: \u672A\u627E\u5230 @chatbi-v/cli \u7684\u6784\u5EFA\u4EA7\u7269 (dist)\u3002"));
404
+ }
405
+ await fs2.writeJson(path2.join(targetDir, "apps/main/tsconfig.json"), {
406
+ extends: "../../tsconfig.json",
407
+ compilerOptions: {
408
+ baseUrl: ".",
409
+ paths: {
410
+ "@/*": ["./src/*"]
411
+ }
412
+ },
413
+ include: ["src"]
414
+ }, { spaces: 2 });
415
+ await fs2.writeFile(path2.join(targetDir, "apps/main/src/index.css"), `
416
+ @tailwind base;
417
+ @tailwind components;
418
+ @tailwind utilities;
419
+
420
+ :root {
421
+ --layout-sidebar-width: 260px;
422
+ --layout-gap: 16px;
423
+ }
424
+
425
+ body {
426
+ margin: 0;
427
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
428
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
429
+ sans-serif;
430
+ -webkit-font-smoothing: antialiased;
431
+ -moz-osx-font-smoothing: grayscale;
432
+ }
433
+ `);
434
+ await fs2.writeFile(path2.join(targetDir, "apps/main/tailwind.config.cjs"), `
435
+ /** @type {import('tailwindcss').Config} */
436
+ module.exports = {
437
+ content: [
438
+ "./index.html",
439
+ "./src/**/*.{js,ts,jsx,tsx}",
440
+ "../../plugins/**/*.{js,ts,jsx,tsx}",
441
+ "../../.chatbi/plugins/**/*.{js,ts,jsx,tsx}"
442
+ ],
443
+ theme: {
444
+ extend: {
445
+ colors: {
446
+ primary: '#6366f1',
447
+ }
448
+ },
449
+ },
450
+ plugins: [],
451
+ }
452
+ `);
453
+ await fs2.writeFile(path2.join(targetDir, "apps/main/postcss.config.cjs"), `
454
+ module.exports = {
455
+ plugins: {
456
+ tailwindcss: {},
457
+ autoprefixer: {},
458
+ },
459
+ }
460
+ `);
461
+ await fs2.writeFile(path2.join(targetDir, "apps/main/src/hooks/usePluginLoader.ts"), `
462
+ import { usePluginLoader as useCoreLoader } from '@chatbi-v/core'
463
+ import { useMemo } from 'react'
464
+
465
+ // \u79BB\u7EBF\u63D2\u4EF6\u6CE8\u518C\u8868
466
+ const offlineRegistry = {
467
+ 'theme-manager': () => import('../../../.chatbi/plugins/theme-manager/dist/index.mjs'),
468
+ 'system-user': () => import('../../../.chatbi/plugins/system-user/dist/index.mjs'),
469
+ 'system-monitor': () => import('../../../.chatbi/plugins/system-monitor/dist/index.mjs'),
470
+ 'demo-plugin': () => import('../../../plugins/demo-plugin/src/index')
471
+ }
472
+
473
+ export const usePluginLoader = () => {
474
+ const options = useMemo(() => ({
475
+ pluginConfigs: {
476
+ 'theme-manager': { enabled: true },
477
+ 'system-user': { enabled: true },
478
+ 'system-monitor': { enabled: true },
479
+ 'demo-plugin': { enabled: true }
480
+ },
481
+ registry: offlineRegistry,
482
+ sharedContext: { api: {} }
483
+ }), [])
484
+
485
+ return useCoreLoader(options)
486
+ }
487
+ `);
488
+ await fs2.writeJson(path2.join(targetDir, "tsconfig.json"), {
489
+ compilerOptions: {
490
+ target: "ESNext",
491
+ useDefineForClassFields: true,
492
+ lib: ["DOM", "DOM.Iterable", "ESNext"],
493
+ allowJs: false,
494
+ skipLibCheck: true,
495
+ esModuleInterop: false,
496
+ allowSyntheticDefaultImports: true,
497
+ strict: true,
498
+ forceConsistentCasingInFileNames: true,
499
+ module: "ESNext",
500
+ moduleResolution: "Node",
501
+ resolveJsonModule: true,
502
+ isolatedModules: true,
503
+ noEmit: true,
504
+ jsx: "react-jsx",
505
+ baseUrl: ".",
506
+ paths: {
507
+ "@chatbi-v/core": ["./.chatbi/core"]
508
+ }
509
+ },
510
+ include: ["apps/main/src", "plugins/*/src"]
511
+ }, { spaces: 2 });
512
+ await fs2.writeFile(path2.join(targetDir, "README.md"), `
513
+ # ${name}
514
+
515
+ \u57FA\u4E8E ChatBI-V SDK \u521D\u59CB\u5316\u7684\u4E1A\u52A1\u63D2\u4EF6\u9879\u76EE\u3002
516
+
517
+ ## \u9879\u76EE\u7ED3\u6784
518
+
519
+ - \`apps/main\`: \u5BBF\u4E3B\u5E94\u7528\uFF0C\u7528\u4E8E\u9A8C\u8BC1\u63D2\u4EF6\u529F\u80FD\u3002
520
+ - \`plugins/\`: \u4E1A\u52A1\u63D2\u4EF6\u6E90\u7801\u76EE\u5F55\u3002
521
+ - \`.chatbi/\`: \u79BB\u7EBF SDK \u8D44\u6E90\uFF08\u6838\u5FC3\u5305\u3001\u6807\u51C6\u63D2\u4EF6\u3001CLI \u5DE5\u5177\uFF09\u3002
522
+
523
+ ## \u5FEB\u901F\u5F00\u59CB
524
+
525
+ 1. \u5B89\u88C5\u4F9D\u8D56:
526
+ \`\`\`bash
527
+ pnpm install
528
+ \`\`\`
529
+
530
+ 2. \u542F\u52A8\u5F00\u53D1\u670D\u52A1\u5668:
531
+ \`\`\`bash
532
+ pnpm dev
533
+ \`\`\`
534
+
535
+ 3. \u521B\u5EFA\u65B0\u63D2\u4EF6:
536
+ \`\`\`bash
537
+ pnpm create:plugin <plugin-name>
538
+ \`\`\`
539
+
540
+ ## \u63D2\u4EF6\u5F00\u53D1
541
+
542
+ \u53C2\u8003 \`plugins/demo-plugin\` \u793A\u4F8B\u3002
543
+ `);
544
+ console.log(`
545
+ \u2705 \u9879\u76EE ${pc2.green(name)} \u521D\u59CB\u5316\u6210\u529F!`);
546
+ console.log(pc2.cyan(`
547
+ \u540E\u7EED\u6B65\u9AA4:`));
548
+ console.log(pc2.white(` 1. cd ${name}`));
549
+ console.log(pc2.white(` 2. pnpm install`));
550
+ console.log(pc2.white(` 3. pnpm dev`));
551
+ } catch (error) {
552
+ console.error(pc2.red("Failed to initialize project:"), error);
553
+ throw error;
554
+ }
555
+ }
556
+
557
+ // src/index.ts
558
+ var cli = cac("chatbi-cli");
559
+ cli.command("build", "Build the current package").option("--watch", "Watch mode").action(async (options) => {
560
+ try {
561
+ await build(options);
562
+ } catch (e) {
563
+ console.error(pc3.red("Build failed"));
564
+ console.error(e);
565
+ process.exit(1);
566
+ }
567
+ });
568
+ cli.command("init <name>", "Initialize a new business plugin project").action(async (name) => {
569
+ try {
570
+ await init({ name });
571
+ } catch (e) {
572
+ console.error(pc3.red("Initialization failed"));
573
+ console.error(e);
574
+ process.exit(1);
575
+ }
576
+ });
577
+ cli.help();
578
+ cli.version("1.0.0");
579
+ cli.parse();
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@chatbi-v/cli",
3
+ "version": "1.0.2",
4
+ "description": "Standardized CLI tooling for ChatBI Monorepo",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "chatbi-cli": "./bin/chatbi-cli.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "bin"
12
+ ],
13
+ "publishConfig": {
14
+ "access": "public"
15
+ },
16
+ "dependencies": {
17
+ "cac": "^6.7.14",
18
+ "execa": "^8.0.1",
19
+ "fs-extra": "^11.2.0",
20
+ "picocolors": "^1.0.0",
21
+ "tsup": "^8.5.1",
22
+ "typescript": "^5.0.0",
23
+ "@chatbi-v/core": "1.0.2",
24
+ "@chatbi-v/plugin-theme-manager": "1.0.2",
25
+ "@chatbi-v/plugin-system-user": "1.0.1",
26
+ "@chatbi-v/plugin-system-monitor": "1.0.1"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^20.0.0",
30
+ "@types/fs-extra": "^11.0.0",
31
+ "tsup": "^8.5.1",
32
+ "vitest": "^1.0.0",
33
+ "@chatbi-v/tsconfig": "1.0.2"
34
+ },
35
+ "scripts": {
36
+ "build": "tsup",
37
+ "dev": "tsup --watch",
38
+ "test": "vitest"
39
+ }
40
+ }