@nbreak/sdk 0.1.0

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,821 @@
1
+ import { ALL_EXTENSION_TYPES, validateManifest } from "@nbreak/shared";
2
+ //#region \0rolldown/runtime.js
3
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
4
+ //#endregion
5
+ //#region src/templates/component.js
6
+ var import___vite_browser_external = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
7
+ module.exports = {};
8
+ })))();
9
+ /**
10
+ * 组件扩展模板
11
+ */
12
+ function componentTemplate(name) {
13
+ const componentName = name.replace(/[^a-zA-Z0-9]/g, "");
14
+ return {
15
+ "src/index.js": `import { defineComponentExtension } from '@nbreak/sdk';
16
+ import Component from './${componentName}.vue';
17
+ import schema from './schema.js';
18
+ import defaults from './defaults.js';
19
+
20
+ export default defineComponentExtension({
21
+ type: '${name}',
22
+ name: '${name}',
23
+ category: 'charts',
24
+ component: Component,
25
+ schema,
26
+ defaults,
27
+ tags: ['自定义'],
28
+ icon: 'AppstoreOutlined',
29
+ description: '${name} 自定义组件',
30
+ });
31
+ `,
32
+ [`src/${componentName}.vue`]: `<template>
33
+ <div class="${name}-container">
34
+ <h3>{{ title }}</h3>
35
+ <p>{{ content }}</p>
36
+ </div>
37
+ </template>
38
+
39
+ <script setup>
40
+ defineProps({
41
+ title: { type: String, default: '默认标题' },
42
+ content: { type: String, default: '默认内容' },
43
+ color: { type: String, default: '#1890ff' },
44
+ });
45
+ <\/script>
46
+
47
+ <style scoped>
48
+ .${name}-container {
49
+ padding: 16px;
50
+ border: 1px solid rgba(255,255,255,0.1);
51
+ border-radius: 8px;
52
+ }
53
+ </style>
54
+ `,
55
+ "src/schema.js": `export default [
56
+ {
57
+ key: 'title',
58
+ label: '标题',
59
+ type: 'text',
60
+ group: '基础',
61
+ default: '默认标题',
62
+ },
63
+ {
64
+ key: 'content',
65
+ label: '内容',
66
+ type: 'textarea',
67
+ group: '基础',
68
+ default: '默认内容',
69
+ },
70
+ {
71
+ key: 'color',
72
+ label: '主色',
73
+ type: 'color',
74
+ group: '样式',
75
+ default: '#1890ff',
76
+ },
77
+ ];
78
+ `,
79
+ "src/defaults.js": `export default {
80
+ title: '默认标题',
81
+ content: '默认内容',
82
+ color: '#1890ff',
83
+ };
84
+ `
85
+ };
86
+ }
87
+ //#endregion
88
+ //#region src/templates/theme.js
89
+ /**
90
+ * 主题扩展模板
91
+ */
92
+ function themeTemplate(name) {
93
+ return {
94
+ "src/index.js": `import { defineThemeExtension } from '@nbreak/sdk';
95
+ import tokens from './tokens.js';
96
+
97
+ export default defineThemeExtension({
98
+ id: '${name}',
99
+ name: '${name} 主题',
100
+ tokens,
101
+ isDark: true,
102
+ description: '${name} 自定义主题',
103
+ });
104
+ `,
105
+ "src/tokens.js": `export default {
106
+ '--ds-color-primary': '#1890ff',
107
+ '--ds-color-success': '#52c41a',
108
+ '--ds-color-warning': '#faad14',
109
+ '--ds-color-error': '#f5222d',
110
+ '--ds-color-text': 'rgba(255,255,255,0.85)',
111
+ '--ds-color-text-secondary': 'rgba(255,255,255,0.65)',
112
+ '--ds-color-bg': '#0a1628',
113
+ '--ds-color-bg-secondary': '#0d1f3c',
114
+ '--ds-color-border': 'rgba(255,255,255,0.1)',
115
+ '--ds-font-size-base': '14px',
116
+ '--ds-font-size-lg': '16px',
117
+ '--ds-font-size-sm': '12px',
118
+ '--ds-border-radius': '6px',
119
+ '--ds-spacing-base': '8px',
120
+ };
121
+ `
122
+ };
123
+ }
124
+ //#endregion
125
+ //#region src/templates/datasource.js
126
+ /**
127
+ * 数据源扩展模板
128
+ */
129
+ function datasourceTemplate(name) {
130
+ return {
131
+ "src/index.js": `import { defineDataSourceExtension } from '@nbreak/sdk';
132
+ import configSchema from './schema.js';
133
+ import defaults from './defaults.js';
134
+
135
+ class ${pascalCase(name)}Adapter {
136
+ async fetchData(config) {
137
+ // TODO: 实现 ${name} 数据获取逻辑
138
+ // config 包含数据源配置项
139
+ // 返回 { data: any, meta?: { total, page } }
140
+ return {
141
+ data: [
142
+ { label: '示例 A', value: 100 },
143
+ { label: '示例 B', value: 200 },
144
+ ],
145
+ };
146
+ }
147
+
148
+ async subscribe(config, callback) {
149
+ // TODO: 实现实时数据订阅(如需要)
150
+ // 调用 callback(data) 推送数据
151
+ // 返回取消订阅函数
152
+ return () => {};
153
+ }
154
+
155
+ async test(config) {
156
+ // 测试连接是否可用
157
+ try {
158
+ await this.fetchData(config);
159
+ return { success: true, message: '连接成功' };
160
+ } catch (e) {
161
+ return { success: false, message: e.message };
162
+ }
163
+ }
164
+ }
165
+
166
+ export default defineDataSourceExtension({
167
+ type: '${name}',
168
+ name: '${name} 数据源',
169
+ adapter: new ${pascalCase(name)}Adapter(),
170
+ configSchema,
171
+ defaults,
172
+ description: '${name} 自定义数据源',
173
+ });
174
+ `,
175
+ "src/schema.js": `export default [
176
+ {
177
+ key: 'url',
178
+ label: '接口地址',
179
+ type: 'text',
180
+ group: '基础',
181
+ default: 'https://api.example.com/data',
182
+ required: true,
183
+ },
184
+ {
185
+ key: 'method',
186
+ label: '请求方法',
187
+ type: 'select',
188
+ group: '基础',
189
+ default: 'GET',
190
+ options: [
191
+ { label: 'GET', value: 'GET' },
192
+ { label: 'POST', value: 'POST' },
193
+ ],
194
+ },
195
+ {
196
+ key: 'headers',
197
+ label: '请求头',
198
+ type: 'json',
199
+ group: '高级',
200
+ default: {},
201
+ },
202
+ ];
203
+ `,
204
+ "src/defaults.js": `export default {
205
+ url: 'https://api.example.com/data',
206
+ method: 'GET',
207
+ headers: {},
208
+ params: {},
209
+ };
210
+ `
211
+ };
212
+ }
213
+ function pascalCase(str) {
214
+ return str.replace(/(^|[^a-zA-Z0-9])([a-z])/g, (_, __, c) => c.toUpperCase());
215
+ }
216
+ //#endregion
217
+ //#region src/templates/template.js
218
+ /**
219
+ * 模板扩展模板
220
+ */
221
+ function templateTemplate(name) {
222
+ return {
223
+ "src/index.js": `import { defineTemplateExtension } from '@nbreak/sdk';
224
+ import pages from './pages.js';
225
+
226
+ export default defineTemplateExtension({
227
+ id: '${name}',
228
+ name: '${name} 模板',
229
+ pages,
230
+ thumbnail: '',
231
+ canvasConfig: {
232
+ width: 1920,
233
+ height: 1080,
234
+ background: '#0a1628',
235
+ },
236
+ description: '${name} 自定义模板',
237
+ });
238
+ `,
239
+ "src/pages.js": `export default [
240
+ {
241
+ id: 'page-1',
242
+ name: '主页面',
243
+ components: [
244
+ {
245
+ id: 'comp-title',
246
+ type: 'text',
247
+ x: 0,
248
+ y: 0,
249
+ width: 1920,
250
+ height: 80,
251
+ props: {
252
+ content: '${name}',
253
+ fontSize: 32,
254
+ color: '#1890ff',
255
+ textAlign: 'center',
256
+ },
257
+ },
258
+ ],
259
+ },
260
+ ];
261
+ `
262
+ };
263
+ }
264
+ //#endregion
265
+ //#region src/templates/action.js
266
+ /**
267
+ * 动作扩展模板
268
+ */
269
+ function actionTemplate(name) {
270
+ return {
271
+ "src/index.js": `import { defineActionExtension } from '@nbreak/sdk';
272
+ import schema from './schema.js';
273
+
274
+ async function handler(params, context) {
275
+ // params: 用户配置的动作参数
276
+ // context: { componentId, event, data, store, eventBus }
277
+ // TODO: 实现 ${name} 动作逻辑
278
+
279
+ console.log('[${name} Action]', { params, context });
280
+
281
+ // 示例:更新组件数据
282
+ if (context.componentId && params.targetData) {
283
+ context.eventBus.emit('component:updateData', {
284
+ componentId: context.componentId,
285
+ data: params.targetData,
286
+ });
287
+ }
288
+
289
+ return { success: true };
290
+ }
291
+
292
+ export default defineActionExtension({
293
+ actionType: '${name}',
294
+ handler,
295
+ schema,
296
+ category: 'general',
297
+ description: '${name} 自定义动作',
298
+ });
299
+ `,
300
+ "src/schema.js": `export default [
301
+ {
302
+ key: 'targetData',
303
+ label: '目标数据',
304
+ type: 'json',
305
+ group: '参数',
306
+ default: {},
307
+ },
308
+ {
309
+ key: 'message',
310
+ label: '提示消息',
311
+ type: 'text',
312
+ group: '参数',
313
+ default: '',
314
+ },
315
+ ];
316
+ `
317
+ };
318
+ }
319
+ //#endregion
320
+ //#region src/templates/propertyField.js
321
+ /**
322
+ * 属性字段扩展模板
323
+ */
324
+ function propertyFieldTemplate(name) {
325
+ return {
326
+ "src/index.js": `import { definePropertyFieldExtension } from '@nbreak/sdk';
327
+ import Editor from './Editor.vue';
328
+
329
+ export default definePropertyFieldExtension({
330
+ fieldType: '${name}',
331
+ editor: Editor,
332
+ defaultValue: () => null,
333
+ serialize: (value) => value,
334
+ deserialize: (value) => value,
335
+ description: '${name} 自定义属性编辑器',
336
+ });
337
+ `,
338
+ "src/Editor.vue": `<template>
339
+ <div class="ds-field-${name}">
340
+ <input
341
+ :value="modelValue"
342
+ @input="$emit('update:modelValue', $event.target.value)"
343
+ :placeholder="placeholder"
344
+ class="ds-field-input"
345
+ />
346
+ </div>
347
+ </template>
348
+
349
+ <script setup>
350
+ defineProps({
351
+ modelValue: { default: null },
352
+ field: { type: Object, default: () => ({}) },
353
+ placeholder: { type: String, default: '' },
354
+ });
355
+
356
+ defineEmits(['update:modelValue']);
357
+ <\/script>
358
+
359
+ <style scoped>
360
+ .ds-field-${name} {
361
+ width: 100%;
362
+ }
363
+
364
+ .ds-field-input {
365
+ width: 100%;
366
+ padding: 4px 8px;
367
+ border: 1px solid rgba(255,255,255,0.2);
368
+ border-radius: 4px;
369
+ background: rgba(0,0,0,0.2);
370
+ color: inherit;
371
+ font-size: 13px;
372
+ }
373
+
374
+ .ds-field-input:focus {
375
+ outline: none;
376
+ border-color: #1890ff;
377
+ }
378
+ </style>
379
+ `
380
+ };
381
+ }
382
+ //#endregion
383
+ //#region src/templates/shared.js
384
+ /**
385
+ * 共享模板文件(所有扩展类型都有)
386
+ */
387
+ function sharedFiles(name, type) {
388
+ const pkgName = name.startsWith("@") ? name : `datascreen-${type}-${name}`;
389
+ return {
390
+ "package.json": JSON.stringify({
391
+ name: pkgName,
392
+ version: "0.1.0",
393
+ description: `DataScreen ${type} extension: ${name}`,
394
+ type: "module",
395
+ main: "./dist/index.js",
396
+ module: "./dist/index.mjs",
397
+ types: "./dist/index.d.ts",
398
+ files: ["dist", "datascreen.extension.json"],
399
+ scripts: {
400
+ build: "vite build",
401
+ dev: "vite build --watch"
402
+ },
403
+ datascreen: {
404
+ type,
405
+ displayName: name
406
+ },
407
+ dependencies: { "@nbreak/sdk": "^0.1.0" },
408
+ peerDependencies: { "@nbreak/core": "^0.1.0" },
409
+ publishConfig: { access: "public" }
410
+ }, null, 2) + "\n",
411
+ "datascreen.extension.json": JSON.stringify({
412
+ name: pkgName,
413
+ version: "0.1.0",
414
+ type,
415
+ entry: "./dist/index.js",
416
+ module: "./dist/index.mjs",
417
+ types: "./dist/index.d.ts",
418
+ datascreenVersion: ">=0.1.0",
419
+ dependencies: { "@nbreak/core": "^0.1.0" },
420
+ displayName: name,
421
+ description: `DataScreen ${type} extension`
422
+ }, null, 2) + "\n",
423
+ "vite.config.js": `import { defineConfig } from 'vite';
424
+
425
+ export default defineConfig({
426
+ build: {
427
+ outDir: 'dist',
428
+ sourcemap: true,
429
+ target: 'es2020',
430
+ minify: false,
431
+ lib: {
432
+ entry: 'src/index.js',
433
+ formats: ['es', 'cjs'],
434
+ fileName: (format) => format === 'es' ? 'index.mjs' : 'index.js',
435
+ },
436
+ rollupOptions: {
437
+ external: ['@nbreak/sdk', '@nbreak/core', '@nbreak/shared', 'vue'],
438
+ output: { exports: 'named' },
439
+ },
440
+ },
441
+ });
442
+ `,
443
+ ".gitignore": `node_modules/
444
+ dist/
445
+ *.tgz
446
+ .DS_Store
447
+ `,
448
+ "README.md": `# ${pkgName}
449
+
450
+ DataScreen ${type} extension: ${name}
451
+
452
+ ## 开发
453
+
454
+ \`\`\`bash
455
+ pnpm install
456
+ pnpm build
457
+ \`\`\`
458
+
459
+ ## 发布
460
+
461
+ \`\`\`bash
462
+ npm publish
463
+ \`\`\`
464
+ `
465
+ };
466
+ }
467
+ //#endregion
468
+ //#region src/templates/index.js
469
+ /**
470
+ * 扩展项目模板生成器
471
+ *
472
+ * 为 6 种扩展类型生成完整的项目脚手架
473
+ */
474
+ var TEMPLATE_MAP = {
475
+ component: componentTemplate,
476
+ theme: themeTemplate,
477
+ datasource: datasourceTemplate,
478
+ template: templateTemplate,
479
+ action: actionTemplate,
480
+ "property-field": propertyFieldTemplate
481
+ };
482
+ /**
483
+ * 生成扩展项目模板
484
+ * @param {string} type - 扩展类型
485
+ * @param {string} name - 扩展名称
486
+ * @returns {Object} 文件路径到内容的映射
487
+ */
488
+ function generateExtensionTemplate(type, name) {
489
+ const generator = TEMPLATE_MAP[type];
490
+ if (!generator) throw new Error(`未知扩展类型: ${type}`);
491
+ const specificFiles = generator(name);
492
+ return {
493
+ ...sharedFiles(name, type),
494
+ ...specificFiles
495
+ };
496
+ }
497
+ //#endregion
498
+ //#region src/cli/commands/init.js
499
+ /**
500
+ * datascreen init <type> <name> [path]
501
+ *
502
+ * 脚手架生成扩展项目
503
+ */
504
+ function initCommand(args) {
505
+ const [type, name, targetPath] = args;
506
+ if (!type || !name) {
507
+ console.error("用法: datascreen init <type> <name> [path]");
508
+ console.error(`type 可选: ${ALL_EXTENSION_TYPES.join(", ")}`);
509
+ process.exit(1);
510
+ }
511
+ if (!ALL_EXTENSION_TYPES.includes(type)) {
512
+ console.error(`无效的扩展类型: ${type}`);
513
+ console.error(`可选类型: ${ALL_EXTENSION_TYPES.join(", ")}`);
514
+ process.exit(1);
515
+ }
516
+ const target = (0, import___vite_browser_external.resolve)(process.cwd(), targetPath || name);
517
+ if ((0, import___vite_browser_external.existsSync)(target)) {
518
+ console.error(`目标目录已存在: ${target}`);
519
+ process.exit(1);
520
+ }
521
+ console.log(`正在生成 ${type} 扩展: ${name}`);
522
+ console.log(`目标目录: ${target}`);
523
+ const files = generateExtensionTemplate(type, name);
524
+ for (const [filePath, content] of Object.entries(files)) {
525
+ const fullPath = (0, import___vite_browser_external.join)(target, filePath);
526
+ const dir = (0, import___vite_browser_external.dirname)(fullPath);
527
+ if (!(0, import___vite_browser_external.existsSync)(dir)) (0, import___vite_browser_external.mkdirSync)(dir, { recursive: true });
528
+ (0, import___vite_browser_external.writeFileSync)(fullPath, content, "utf-8");
529
+ console.log(` 创建: ${filePath}`);
530
+ }
531
+ console.log("\n扩展项目已生成!");
532
+ console.log("\n后续步骤:");
533
+ console.log(` cd ${name}`);
534
+ console.log(` pnpm install`);
535
+ console.log(` pnpm build`);
536
+ console.log(` npm publish # 发布到 npm`);
537
+ }
538
+ //#endregion
539
+ //#region src/manifest-node.js
540
+ /**
541
+ * @nbreak/sdk - Node-only Manifest 工具
542
+ *
543
+ * 这些函数依赖 node:fs / node:path,只能在 Node 环境(CLI / 服务端)使用。
544
+ * 浏览器侧请使用 manifest.js 中的 checkCompatibility / generateManifestTemplate。
545
+ *
546
+ * 拆分原因:原本与浏览器安全函数混在 manifest.js 中,
547
+ * 顶层 `import 'node:fs'` 会被 Vite 静态打包并 externalize,
548
+ * 导致浏览器运行时抛出 "Module node:fs has been externalized for browser" 错误。
549
+ */
550
+ /**
551
+ * 从文件读取 manifest
552
+ * @param {string} manifestPath - datascreen.extension.json 路径
553
+ * @returns {Object|null}
554
+ */
555
+ function readManifest(manifestPath) {
556
+ const absPath = (0, import___vite_browser_external.resolve)(process.cwd(), manifestPath);
557
+ if (!(0, import___vite_browser_external.existsSync)(absPath)) return null;
558
+ try {
559
+ const content = (0, import___vite_browser_external.readFileSync)(absPath, "utf-8");
560
+ return JSON.parse(content);
561
+ } catch (e) {
562
+ console.error(`[DataScreen SDK] 读取 manifest 失败: ${manifestPath}`, e);
563
+ return null;
564
+ }
565
+ }
566
+ /**
567
+ * 校验 manifest 文件
568
+ * @param {string} manifestPath
569
+ * @returns {{valid: boolean, errors: Array, warnings: Array, manifest: Object|null}}
570
+ */
571
+ function validateManifestFile(manifestPath) {
572
+ const manifest = readManifest(manifestPath);
573
+ if (!manifest) return {
574
+ valid: false,
575
+ errors: [`无法读取 manifest 文件: ${manifestPath}`],
576
+ warnings: [],
577
+ manifest: null
578
+ };
579
+ return {
580
+ ...validateManifest(manifest),
581
+ manifest
582
+ };
583
+ }
584
+ //#endregion
585
+ //#region src/cli/commands/build.js
586
+ /**
587
+ * datascreen build [path]
588
+ *
589
+ * 构建扩展包
590
+ * 调用 Vite 库模式构建,自动注入 manifest
591
+ */
592
+ function buildCommand(args) {
593
+ const [targetPath = "."] = args;
594
+ const cwd = (0, import___vite_browser_external.resolve)(process.cwd(), targetPath);
595
+ const manifestPath = join$2(cwd, "datascreen.extension.json");
596
+ if ((0, import___vite_browser_external.existsSync)(manifestPath)) {
597
+ console.log("校验 manifest...");
598
+ const result = validateManifestFile(manifestPath);
599
+ if (!result.valid) {
600
+ console.error("manifest 校验失败:");
601
+ result.errors.forEach((e) => console.error(` - ${e}`));
602
+ process.exit(1);
603
+ }
604
+ if (result.warnings.length > 0) {
605
+ console.warn("manifest 警告:");
606
+ result.warnings.forEach((w) => console.warn(` - ${w}`));
607
+ }
608
+ console.log("manifest 校验通过");
609
+ } else console.warn("未找到 datascreen.extension.json,跳过 manifest 校验");
610
+ if (!(0, import___vite_browser_external.existsSync)(join$2(cwd, "vite.config.js"))) {
611
+ console.error("未找到 vite.config.js,无法构建");
612
+ console.error("请确保在扩展项目根目录运行此命令,或使用 datascreen init 生成项目");
613
+ process.exit(1);
614
+ }
615
+ if (!(0, import___vite_browser_external.existsSync)(join$2(cwd, "package.json"))) {
616
+ console.error("未找到 package.json");
617
+ process.exit(1);
618
+ }
619
+ console.log("开始构建...");
620
+ const result = (0, import___vite_browser_external.spawnSync)("npx", ["vite", "build"], {
621
+ cwd,
622
+ stdio: "inherit",
623
+ shell: true
624
+ });
625
+ if (result.status !== 0) {
626
+ console.error("构建失败");
627
+ process.exit(result.status || 1);
628
+ }
629
+ console.log("构建成功!");
630
+ if ((0, import___vite_browser_external.existsSync)(manifestPath)) {
631
+ const manifest = JSON.parse((0, import___vite_browser_external.readFileSync)(manifestPath, "utf-8"));
632
+ console.log(`扩展: ${manifest.name}@${manifest.version} (${manifest.type})`);
633
+ }
634
+ }
635
+ function join$2(...paths) {
636
+ return paths.reduce((acc, p) => acc + "/" + p).replace(/\/+/g, "/");
637
+ }
638
+ //#endregion
639
+ //#region src/cli/commands/pack.js
640
+ /**
641
+ * datascreen pack [path]
642
+ *
643
+ * 打包扩展为 npm tarball
644
+ */
645
+ function packCommand(args) {
646
+ const [targetPath = "."] = args;
647
+ const cwd = (0, import___vite_browser_external.resolve)(process.cwd(), targetPath);
648
+ const manifestPath = join$1(cwd, "datascreen.extension.json");
649
+ if ((0, import___vite_browser_external.existsSync)(manifestPath)) {
650
+ console.log("校验 manifest...");
651
+ const result = validateManifestFile(manifestPath);
652
+ if (!result.valid) {
653
+ console.error("manifest 校验失败:");
654
+ result.errors.forEach((e) => console.error(` - ${e}`));
655
+ process.exit(1);
656
+ }
657
+ console.log("manifest 校验通过");
658
+ }
659
+ const distPath = join$1(cwd, "dist");
660
+ if (!(0, import___vite_browser_external.existsSync)(distPath)) {
661
+ console.error("未找到 dist 目录,请先运行 datascreen build");
662
+ process.exit(1);
663
+ }
664
+ if ((0, import___vite_browser_external.existsSync)(manifestPath)) {
665
+ const manifest = JSON.parse((0, import___vite_browser_external.readFileSync)(manifestPath, "utf-8"));
666
+ (0, import___vite_browser_external.writeFileSync)(join$1(distPath, "datascreen.extension.json"), JSON.stringify(manifest, null, 2), "utf-8");
667
+ console.log("已复制 manifest 到 dist");
668
+ }
669
+ console.log("打包中...");
670
+ const result = (0, import___vite_browser_external.spawnSync)("npm", ["pack"], {
671
+ cwd,
672
+ stdio: "inherit",
673
+ shell: true
674
+ });
675
+ if (result.status !== 0) {
676
+ console.error("打包失败");
677
+ process.exit(result.status || 1);
678
+ }
679
+ console.log("打包成功!");
680
+ console.log("生成文件: <name>-<version>.tgz");
681
+ console.log("发布到 npm: npm publish");
682
+ }
683
+ function join$1(...paths) {
684
+ return paths.reduce((acc, p) => acc + "/" + p).replace(/\/+/g, "/");
685
+ }
686
+ //#endregion
687
+ //#region src/cli/commands/list.js
688
+ /**
689
+ * datascreen list
690
+ *
691
+ * 列出当前项目的扩展信息
692
+ */
693
+ function listCommand(args) {
694
+ const [targetPath = "."] = args;
695
+ const cwd = (0, import___vite_browser_external.resolve)(process.cwd(), targetPath);
696
+ const manifestPath = join(cwd, "datascreen.extension.json");
697
+ const pkgPath = join(cwd, "package.json");
698
+ let manifest = null;
699
+ let pkg = null;
700
+ if ((0, import___vite_browser_external.existsSync)(manifestPath)) manifest = JSON.parse((0, import___vite_browser_external.readFileSync)(manifestPath, "utf-8"));
701
+ if ((0, import___vite_browser_external.existsSync)(pkgPath)) pkg = JSON.parse((0, import___vite_browser_external.readFileSync)(pkgPath, "utf-8"));
702
+ if (!manifest && !pkg) {
703
+ console.error("未找到 datascreen.extension.json 或 package.json");
704
+ process.exit(1);
705
+ }
706
+ console.log("\n=== DataScreen 扩展信息 ===\n");
707
+ if (manifest) {
708
+ console.log(`名称: ${manifest.name}`);
709
+ console.log(`版本: ${manifest.version}`);
710
+ console.log(`类型: ${manifest.type}`);
711
+ console.log(`入口: ${manifest.entry}`);
712
+ console.log(`显示名: ${manifest.displayName || manifest.name}`);
713
+ console.log(`描述: ${manifest.description || "-"}`);
714
+ console.log(`兼容版本: ${manifest.datascreenVersion || "-"}`);
715
+ } else if (pkg) {
716
+ console.log(`包名: ${pkg.name}`);
717
+ console.log(`版本: ${pkg.version}`);
718
+ const ds = pkg.datascreen || {};
719
+ console.log(`类型: ${ds.type || "(未声明)"}`);
720
+ console.log(`入口: ${pkg.main || "-"}`);
721
+ }
722
+ const distPath = join(cwd, "dist");
723
+ if ((0, import___vite_browser_external.existsSync)(distPath)) {
724
+ const files = (0, import___vite_browser_external.readdirSync)(distPath);
725
+ console.log(`\n构建产物 (${distPath}):`);
726
+ files.forEach((f) => console.log(` - ${f}`));
727
+ } else console.log("\n(未构建,运行 datascreen build)");
728
+ }
729
+ function join(...paths) {
730
+ return paths.reduce((acc, p) => acc + "/" + p).replace(/\/+/g, "/");
731
+ }
732
+ //#endregion
733
+ //#region src/cli/commands/validate.js
734
+ /**
735
+ * datascreen validate [manifestPath]
736
+ *
737
+ * 校验 manifest 文件
738
+ */
739
+ function validateCommand(args) {
740
+ const [manifestPath = "datascreen.extension.json"] = args;
741
+ console.log(`校验 manifest: ${manifestPath}`);
742
+ const result = validateManifestFile(manifestPath);
743
+ if (result.errors.length > 0) {
744
+ console.error("\n错误:");
745
+ result.errors.forEach((e) => console.error(` ✗ ${e}`));
746
+ }
747
+ if (result.warnings.length > 0) {
748
+ console.warn("\n警告:");
749
+ result.warnings.forEach((w) => console.warn(` ⚠ ${w}`));
750
+ }
751
+ if (result.valid) {
752
+ console.log("\n✓ manifest 校验通过");
753
+ if (result.manifest) {
754
+ console.log(` 名称: ${result.manifest.name}`);
755
+ console.log(` 版本: ${result.manifest.version}`);
756
+ console.log(` 类型: ${result.manifest.type}`);
757
+ }
758
+ process.exit(0);
759
+ } else {
760
+ console.log("\n✗ manifest 校验失败");
761
+ process.exit(1);
762
+ }
763
+ }
764
+ //#endregion
765
+ //#region src/cli/index.js
766
+ /**
767
+ * DataScreen CLI 主入口
768
+ */
769
+ var VERSION = "0.1.0";
770
+ var HELP_TEXT = `
771
+ DataScreen CLI v${VERSION}
772
+
773
+ 用法:
774
+ datascreen <command> [options]
775
+
776
+ 命令:
777
+ init <type> <name> [path] 生成扩展项目(type: component/theme/datasource/template/action/property-field)
778
+ build [path] 构建扩展包
779
+ pack [path] 打包为 npm tarball
780
+ list 列出当前项目的扩展
781
+ validate [manifestPath] 校验 manifest 文件
782
+
783
+ 示例:
784
+ datascreen init component my-chart
785
+ datascreen init theme my-theme ./packages/my-theme
786
+ datascreen build
787
+ datascreen pack
788
+ datascreen validate ./datascreen.extension.json
789
+
790
+ 选项:
791
+ -h, --help 显示帮助
792
+ -v, --version 显示版本
793
+ `;
794
+ function runCli(args) {
795
+ const [command, ...rest] = args;
796
+ if (!command || command === "-h" || command === "--help") {
797
+ console.log(HELP_TEXT);
798
+ return;
799
+ }
800
+ if (command === "-v" || command === "--version") {
801
+ console.log(VERSION);
802
+ return;
803
+ }
804
+ const handler = {
805
+ init: initCommand,
806
+ build: buildCommand,
807
+ pack: packCommand,
808
+ list: listCommand,
809
+ validate: validateCommand
810
+ }[command];
811
+ if (!handler) {
812
+ console.error(`未知命令: ${command}`);
813
+ console.log(HELP_TEXT);
814
+ process.exit(1);
815
+ }
816
+ handler(rest);
817
+ }
818
+ //#endregion
819
+ export { runCli };
820
+
821
+ //# sourceMappingURL=index.js.map