@kanyun-ai-infra/band-cli 0.2.0 → 0.2.1

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.
Files changed (54) hide show
  1. package/bundled/official/activity/package.json +1 -1
  2. package/bundled/official/approval/package.json +1 -1
  3. package/bundled/official/artifacts/package.json +1 -1
  4. package/bundled/official/chat/dist/index.js +1 -1
  5. package/bundled/official/chat/package.json +2 -2
  6. package/bundled/official/chunks/chunk-7XYETT7C.js +1 -0
  7. package/bundled/official/comment/package.json +1 -1
  8. package/bundled/official/header/package.json +1 -1
  9. package/bundled/official/home/dist/index.js +1 -1
  10. package/bundled/official/home/package.json +2 -2
  11. package/bundled/official/layouts/package.json +1 -1
  12. package/bundled/official/library/package.json +1 -1
  13. package/bundled/official/members/dist/index.js +1 -1
  14. package/bundled/official/members/package.json +2 -2
  15. package/bundled/official/memory/package.json +1 -1
  16. package/bundled/official/native/package.json +1 -1
  17. package/bundled/official/params-form/package.json +1 -1
  18. package/bundled/official/plugins/package.json +1 -1
  19. package/bundled/official/project/dist/index.js +1 -1
  20. package/bundled/official/project/package.json +2 -2
  21. package/bundled/official/queue/package.json +1 -1
  22. package/bundled/official/settings/dist/index.js +1 -1
  23. package/bundled/official/settings/package.json +2 -2
  24. package/bundled/official/shell/dist/index.js +1 -1
  25. package/bundled/official/shell/package.json +2 -2
  26. package/bundled/official/stages/package.json +1 -1
  27. package/bundled/official/threads/dist/index.js +1 -1
  28. package/bundled/official/threads/package.json +2 -2
  29. package/bundled/official/turn-bar/package.json +1 -1
  30. package/bundled/official/turn-trace/package.json +1 -1
  31. package/bundled/official/version-switch/dist/index.js +1 -1
  32. package/bundled/official/version-switch/package.json +1 -1
  33. package/bundled/official/viewer-entity/package.json +1 -1
  34. package/bundled/official/viewer-external/package.json +1 -1
  35. package/bundled/official/viewer-image/package.json +1 -1
  36. package/bundled/official/viewer-media/package.json +1 -1
  37. package/bundled/official/viewer-storyboard/package.json +1 -1
  38. package/bundled/official/viewer-text/package.json +1 -1
  39. package/bundled/official/viewer-tool/package.json +1 -1
  40. package/bundled/official/viewer-web/package.json +1 -1
  41. package/bundled/official/viewer-web-app/package.json +1 -1
  42. package/bundled/official/workshops/dist/index.js +2 -2
  43. package/bundled/official/workshops/package.json +2 -2
  44. package/bundled/tokens/components.css +1 -1
  45. package/dev-host/app.tsx +23 -7
  46. package/dev-host/host.css +7 -0
  47. package/dist/bin.js +1 -1
  48. package/dist/{chunk-Q2XJXNVH.js → chunk-FGPWXAOA.js} +151 -19
  49. package/dist/{dev-server-Q7NTJ3QD.js → dev-server-IBR3PKDE.js} +14 -1
  50. package/dist/index.d.ts +2 -0
  51. package/dist/index.js +1 -1
  52. package/package.json +5 -4
  53. package/src/inspector-default.ts +9 -0
  54. package/bundled/official/chunks/chunk-DIL5YSVK.js +0 -1
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@kanyun-ai-infra/band-workshops",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "工坊目录、工坊详情、新建项目、新建与复制工坊、工坊设置与对话改工坊九个页面",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": "./dist/index.js"
8
8
  },
9
9
  "peerDependencies": {
10
- "@kanyun-ai-infra/band-plugin-sdk": "^2.0.0",
10
+ "@kanyun-ai-infra/band-plugin-sdk": "^2.1.0",
11
11
  "react": "^19.0.0",
12
12
  "react-dom": "^19.0.0",
13
13
  "@kanyun-ai-infra/band-shell": "*"
@@ -210,7 +210,7 @@ input.field[type="number"] { font-variant-numeric: tabular-nums; }
210
210
  /* 输入框下面一行:提示、出错、计数。计数靠右,超了写 .over(DESIGN.md「控件」) */
211
211
  .field-note { display: flex; align-items: center; gap: 6px; margin: 0; min-height: 16px; font-size: var(--fs-badge); color: var(--muted); }
212
212
  .field-note.err { color: var(--bad); }
213
- .field-count { font-family: var(--mono); }
213
+ .field-count { font-family: var(--mono); white-space: nowrap; }
214
214
  .field-note > .field-count { margin-left: auto; }
215
215
  .field-count.over { color: var(--bad); }
216
216
 
package/dev-host/app.tsx CHANGED
@@ -35,6 +35,7 @@ import * as dev from "virtual:band-dev";
35
35
  import { useEffect, useRef, useState } from "react";
36
36
  import { createRoot } from "react-dom/client";
37
37
  import { devManagers } from "../src/dev-managers.ts";
38
+ import { inspectorOpenByDefault } from "../src/inspector-default.ts";
38
39
  import { DEV_HOST_PLUGIN } from "../src/inspector-plugins.ts";
39
40
  import { loadPlugins } from "../src/load-plugins.ts";
40
41
  import { Inspector } from "./Inspector.tsx";
@@ -316,6 +317,10 @@ function focusOf(s: Selection | null): string | undefined {
316
317
  }
317
318
 
318
319
  function App() {
320
+ // 夹具栏占 300px:视口不到 1600 默认收起,免得挤坏项目页右栏;收起时仍挂着,事件与诊断照常记
321
+ const [inspectorOpen, setInspectorOpen] = useState(() =>
322
+ inspectorOpenByDefault(window.innerWidth),
323
+ );
319
324
  return (
320
325
  <div className="dev-page">
321
326
  <header className="dev-bar">
@@ -345,16 +350,27 @@ function App() {
345
350
  ) : (
346
351
  <span className="chip plain">{member.displayName}</span>
347
352
  )}
353
+ <button
354
+ type="button"
355
+ className="btn"
356
+ aria-expanded={inspectorOpen}
357
+ aria-controls="dev-inspector-slot"
358
+ onClick={() => setInspectorOpen((v) => !v)}
359
+ >
360
+ 夹具
361
+ </button>
348
362
  </header>
349
363
  <div className="dev-body">
350
364
  <ProjectPage />
351
- <Inspector
352
- ctx={hostCtx}
353
- view={view}
354
- transport={transport}
355
- problems={problems}
356
- stageViews={stageViews}
357
- />
365
+ <div id="dev-inspector-slot" className="dev-inspector-slot" hidden={!inspectorOpen}>
366
+ <Inspector
367
+ ctx={hostCtx}
368
+ view={view}
369
+ transport={transport}
370
+ problems={problems}
371
+ stageViews={stageViews}
372
+ />
373
+ </div>
358
374
  </div>
359
375
  </div>
360
376
  );
package/dev-host/host.css CHANGED
@@ -63,6 +63,13 @@ body {
63
63
  .dev-project > .band-react-surface {
64
64
  display: contents;
65
65
  }
66
+ /* 夹具栏的槽:展开时不占自己的盒子(让 aside 直接当 .dev-body 的子项),收起时整块不显示 */
67
+ .dev-inspector-slot {
68
+ display: contents;
69
+ }
70
+ .dev-inspector-slot[hidden] {
71
+ display: none;
72
+ }
66
73
  /* 锁定插件替身只标位置 */
67
74
  .dev-inspector {
68
75
  width: 300px;
package/dist/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  main
4
- } from "./chunk-Q2XJXNVH.js";
4
+ } from "./chunk-FGPWXAOA.js";
5
5
  import "./chunk-CL3FV65M.js";
6
6
  import "./chunk-XPLYTHNX.js";
7
7
  import "./chunk-LGYGWMSY.js";
@@ -646,7 +646,7 @@ import { parse } from "yaml";
646
646
  // package.json
647
647
  var package_default = {
648
648
  name: "@kanyun-ai-infra/band-cli",
649
- version: "0.2.0",
649
+ version: "0.2.1",
650
650
  description: "band \u547D\u4EE4\u884C\uFF1A\u65B0\u5EFA\u3001\u672C\u5730\u8C03\u8BD5\u3001\u6821\u9A8C\u4E0E\u53D1\u5E03 Band \u5DE5\u574A\u548C\u63D2\u4EF6",
651
651
  license: "UNLICENSED",
652
652
  type: "module",
@@ -742,11 +742,13 @@ function newPluginRepo(parentDir, packageName, opts) {
742
742
  const title = opts.title ?? name;
743
743
  const dir = join2(resolve2(parentDir), name);
744
744
  if (existsSync2(dir)) throw new NewPluginError(`${dir} \u5DF2\u7ECF\u5B58\u5728`);
745
+ const react = opts.react === true;
746
+ const entryFile = react ? "src/index.tsx" : "src/index.ts";
745
747
  const rendered = renderPluginTemplate(opts.template, {
746
748
  title,
747
749
  ...opts.stage ? { stage: opts.stage } : {},
748
750
  id: name,
749
- entry: "./src/index.ts"
751
+ entry: `./${entryFile}`
750
752
  });
751
753
  const workshop = fixtureWorkshop(packageName, opts.template, name, opts.stage);
752
754
  try {
@@ -757,14 +759,16 @@ function newPluginRepo(parentDir, packageName, opts) {
757
759
  );
758
760
  }
759
761
  const files = {
760
- "package.json": `${JSON.stringify(packageJson(packageName, title), null, 2)}
762
+ "package.json": `${JSON.stringify(packageJson(packageName, title, react), null, 2)}
763
+ `,
764
+ "tsconfig.json": `${JSON.stringify(tsconfig(react), null, 2)}
761
765
  `,
762
766
  "plugin.yaml": rendered.manifest,
763
- "src/index.ts": rendered.code,
767
+ [entryFile]: react ? reactSource(opts.template, title, opts.stage, name) : rendered.code,
764
768
  "dev/workshop.yaml": workshop,
765
769
  "dev/fixture.ts": fixtureSource(opts.template, opts.stage),
766
770
  ".gitlab-ci.yml": CI(packageName),
767
- "README.md": readme(packageName, title, opts.template, name, parsed.scope),
771
+ "README.md": readme(packageName, title, opts.template, name, parsed.scope, react),
768
772
  ".gitignore": "node_modules/\ndist/\n"
769
773
  };
770
774
  for (const [f, body] of Object.entries(files)) {
@@ -778,7 +782,8 @@ function newPluginRepo(parentDir, packageName, opts) {
778
782
  hints: [
779
783
  `cd ${dir} && npm install\uFF1A\u88C5\u4E0A band \u547D\u4EE4\u884C\u4E0E\u63D2\u4EF6 SDK\uFF08devDependencies\uFF09`,
780
784
  "npx band dev .\uFF1A\u7528 dev/ \u5939\u5177\u5DE5\u574A\u8D77\u9875\u9762\uFF0C\u672C\u4ED3\u5E93\u7684\u63D2\u4EF6\u81EA\u52A8\u88C5\u4E0A",
781
- "npx band check .\uFF1A\u6821\u9A8C\u63D2\u4EF6\u4E0E\u5939\u5177\u5DE5\u574A\u7684\u88C5\u914D",
785
+ "npx band check .\uFF1A\u6821\u9A8C\u63D2\u4EF6\u4E0E\u5939\u5177\u5DE5\u574A\u7684\u88C5\u914D\uFF08\u4E0D\u67E5\u7C7B\u578B\uFF09",
786
+ "npm run typecheck\uFF1A\u8DD1 tsc --noEmit \u67E5\u7C7B\u578B\uFF08band check \u4E0D\u67E5\uFF09",
782
787
  placementHint(opts.template, packageName, name, opts.stage),
783
788
  "\u53D1\u5E03\u8FD8\u6CA1\u63A5\u4E0A\uFF08\u63D2\u4EF6\u7531 Band \u6253\u5305\u5206\u53D1\uFF0C\u4E0D\u7ECF npm \u53D1\u5305\uFF09\uFF1A\u73B0\u5728 CI \u6A21\u677F\u53EA\u8DD1 band check"
784
789
  ]
@@ -791,7 +796,7 @@ function placementHint(template, packageName, name, stage) {
791
796
  return `\u9636\u6BB5 ${String(stage)} \u7684\u754C\u9762\u4F1A\u51FA\u73B0\u5728\u5F15\u7528\u5B83\u7684\u5DE5\u574A\u7684\u9636\u6BB5\u8BE6\u60C5\u91CC`;
792
797
  }
793
798
  var PROJECT2 = "@kanyun-ai-infra/band-project";
794
- function packageJson(packageName, title) {
799
+ function packageJson(packageName, title, react) {
795
800
  return {
796
801
  name: packageName,
797
802
  version: "0.1.0",
@@ -799,7 +804,7 @@ function packageJson(packageName, title) {
799
804
  license: "UNLICENSED",
800
805
  type: "module",
801
806
  files: ["src", "plugin.yaml", "README.md"],
802
- scripts: { dev: "band dev .", check: "band check ." },
807
+ scripts: { dev: "band dev .", check: "band check .", typecheck: "tsc --noEmit" },
803
808
  peerDependencies: {
804
809
  react: "^19.0.0",
805
810
  "react-dom": "^19.0.0",
@@ -809,10 +814,36 @@ function packageJson(packageName, title) {
809
814
  peerDependenciesMeta: { [PROJECT2]: { optional: true } },
810
815
  devDependencies: {
811
816
  "@kanyun-ai-infra/band-cli": `^${CLI_VERSION}`,
812
- "@kanyun-ai-infra/band-plugin-sdk": `^${BAND_PROTOCOL_VERSION2}`
817
+ "@kanyun-ai-infra/band-plugin-sdk": `^${BAND_PROTOCOL_VERSION2}`,
818
+ typescript: "^5.9.3",
819
+ // 用 React 写才要:宿主与 band dev 提供运行时的 React,这些只给类型检查与编辑器提示
820
+ ...react ? {
821
+ "@kanyun-ai-infra/band-plugin-react": `^${PLUGIN_REACT_RANGE}`,
822
+ "@types/react": "^19.0.0",
823
+ "@types/react-dom": "^19.0.0",
824
+ react: "^19.0.0",
825
+ "react-dom": "^19.0.0"
826
+ } : {}
813
827
  }
814
828
  };
815
829
  }
830
+ var PLUGIN_REACT_RANGE = "0.2.1";
831
+ function tsconfig(react) {
832
+ return {
833
+ compilerOptions: {
834
+ target: "ES2022",
835
+ module: "ESNext",
836
+ moduleResolution: "bundler",
837
+ lib: ["ES2023", "DOM", "DOM.Iterable"],
838
+ strict: true,
839
+ noUncheckedIndexedAccess: true,
840
+ skipLibCheck: true,
841
+ noEmit: true,
842
+ ...react ? { jsx: "react-jsx" } : {}
843
+ },
844
+ include: ["src", "dev"]
845
+ };
846
+ }
816
847
  function fixtureWorkshop(packageName, template, name, stage) {
817
848
  const head = `# \u72EC\u7ACB\u63D2\u4EF6 ${packageName} \u7684\u672C\u5730\u5939\u5177\u5DE5\u574A\uFF1Aband dev \u8D77\u9879\u76EE\u9875\u3001band check \u67E5\u88C5\u914D\u7528\uFF0C\u4E0D\u53D1\u5E03\u3001\u4E0D\u8FDB\u4EFB\u4F55\u771F\u5B9E\u5DE5\u574A\u3002
818
849
  # \u672C\u4ED3\u5E93\u7684\u63D2\u4EF6\u7531\u547D\u4EE4\u76F4\u63A5\u88C5\u4E0A\uFF0C\u4E0D\u7528\u5199\u8FDB views.plugins\u3002
@@ -856,6 +887,85 @@ views:
856
887
  `;
857
888
  }
858
889
  var q2 = (s) => JSON.stringify(s);
890
+ function reactSource(template, title, stage, id) {
891
+ const head = (what) => `/**
892
+ * ${what.replace(/\*\//g, "* /").replace(/[\r\n]+/g, " ")}
893
+ * \u53EA\u7528\u516C\u5F00 ctx\uFF1B\u672C\u5730 \`band dev\` \u8FB9\u5199\u8FB9\u770B\uFF0C\`npm run typecheck\` \u67E5\u7C7B\u578B\uFF0C\u63D0\u4EA4\u524D \`band check\`\u3002
894
+ */
895
+ `;
896
+ const imports = `import { reactMount, useCtxData } from "@kanyun-ai-infra/band-plugin-react";
897
+ import { type ProjectCtx, definePlugin } from "@kanyun-ai-infra/band-plugin-sdk";
898
+ import { useState } from "react";
899
+ `;
900
+ if (template === "panel")
901
+ return `${head(`${title}\uFF1A\u4E00\u4E2A\u9762\u677F\u3002\u663E\u793A\u5F53\u524D\u7248\u672C\u7684\u6587\u4EF6\u6570\u3002`)}${imports.replace('import { useState } from "react";\n', "")}
902
+ function Panel({ ctx }: { ctx: ProjectCtx }) {
903
+ const { data, error } = useCtxData(ctx, async () => ctx.version.current(), [], "version.*");
904
+ if (error) return <p>{error}</p>;
905
+ if (data === undefined) return <p>\u8BFB\u53D6\u4E2D\u2026</p>;
906
+ return <p>{data ? \`\u7248\u672C \${data.id}\uFF1A\${data.entries.length} \u4E2A\u6587\u4EF6\` : "\uFF08\u8FD8\u6CA1\u6709\u7248\u672C\uFF09"}</p>;
907
+ }
908
+
909
+ export default definePlugin({
910
+ surfaces: {
911
+ main: reactMount((ctx: ProjectCtx) => <Panel ctx={ctx} />),
912
+ },
913
+ });
914
+ `;
915
+ if (template === "viewer")
916
+ return `${head(`${title}\uFF1A\u4E00\u4E2A\u67E5\u770B\u5668\u3002\u5217\u51FA\u5F53\u524D\u7248\u672C\u7684\u6587\u4EF6\uFF0C\u70B9\u4E00\u4E2A\u770B\u5185\u5BB9\u3002`)}${imports}
917
+ function Viewer({ ctx }: { ctx: ProjectCtx }) {
918
+ const { data: version, error } = useCtxData(ctx, async () => ctx.version.current(), [], "version.*");
919
+ const [body, setBody] = useState("");
920
+ if (error) return <p>{error}</p>;
921
+ return (
922
+ <>
923
+ <ul>
924
+ {(version?.entries ?? []).map((e) => (
925
+ <li key={e.path}>
926
+ <button
927
+ type="button"
928
+ onClick={async () => setBody(new TextDecoder().decode(await ctx.version.readFile(e.path)))}
929
+ >
930
+ {e.path}
931
+ </button>
932
+ </li>
933
+ ))}
934
+ </ul>
935
+ <pre>{body}</pre>
936
+ </>
937
+ );
938
+ }
939
+
940
+ export default definePlugin({
941
+ surfaces: {
942
+ ${JSON.stringify(id)}: reactMount((ctx: ProjectCtx) => <Viewer ctx={ctx} />),
943
+ },
944
+ });
945
+ `;
946
+ const st = JSON.stringify(stage ?? "");
947
+ return `${head(`${title}\uFF1A\u9636\u6BB5 ${stage ?? ""} \u7684\u754C\u9762\u3002\u663E\u793A\u9636\u6BB5\u72B6\u6001\uFF0C\u53EF\u4EE5\u542F\u52A8\u3002`)}${imports.replace('import { useState } from "react";\n', "")}
948
+ const STAGE = ${st};
949
+
950
+ function StageView({ ctx }: { ctx: ProjectCtx }) {
951
+ const { data, error } = useCtxData(ctx, () => ctx.stages.get(STAGE), [], "stage.*");
952
+ return (
953
+ <>
954
+ <p>{error ?? (data ? \`\${data.stage}\uFF1A\${data.status}\` : "\u8BFB\u53D6\u4E2D\u2026")}</p>
955
+ <button type="button" onClick={() => void ctx.stages.start(STAGE)}>
956
+ \u542F\u52A8
957
+ </button>
958
+ </>
959
+ );
960
+ }
961
+
962
+ export default definePlugin({
963
+ surfaces: {
964
+ main: reactMount((ctx: ProjectCtx) => <StageView ctx={ctx} />),
965
+ },
966
+ });
967
+ `;
968
+ }
859
969
  function fixtureSource(template, stage) {
860
970
  const stages = template === "stage-view" ? ` stages: [{ stage: ${q2(stage ?? "")}, status: "ready" }],
861
971
  ` : "";
@@ -916,7 +1026,8 @@ band-check:
916
1026
  - npx band check .
917
1027
  `;
918
1028
  }
919
- function readme(packageName, title, template, name, scope) {
1029
+ function readme(packageName, title, template, name, scope, react) {
1030
+ const entry = react ? "src/index.tsx" : "src/index.ts";
920
1031
  const place = template === "panel" ? `\`views.panels\`\uFF08\u672C\u4ED3\u5E93\u7684\u5939\u5177\u653E\u5728\u53F3\u680F\uFF1A\`${packageName}/main\`\uFF09` : template === "viewer" ? `\`views.artifactTypes.<\u4EA7\u7269\u7C7B\u578B>.viewer\`\uFF08\u672C\u4ED3\u5E93\u7684\u5939\u5177\u628A \`demo\` \u7ED1\u5230 \`${packageName}/${name}\`\uFF09` : "\u5F15\u7528\u5B83\u7684\u5DE5\u574A\u7684\u6D41\u7A0B\u9636\u6BB5\u8BE6\u60C5\u91CC";
921
1032
  return `# ${packageName}
922
1033
 
@@ -928,7 +1039,8 @@ ${title}\uFF1A\u4E00\u4E2A\u72EC\u7ACB\u7684 Band \u63D2\u4EF6\uFF08\u4E0D\u5C5E
928
1039
  |---|---|
929
1040
  | \`package.json\` | \u8EAB\u4EFD\u4E0E\u7248\u672C\uFF1A\u5305\u540D\u3001\u534F\u8BAE\u8303\u56F4\uFF1BdevDependencies \u5E26 band \u547D\u4EE4\u884C\u4E0E\u63D2\u4EF6 SDK |
930
1041
  | \`plugin.yaml\` | \u89C6\u56FE\u9762\u6E05\u5355\uFF1A\u5F80\u54EA\u4E9B\u63D2\u69FD\u8D21\u732E |
931
- | \`src/index.ts\` | \u5165\u53E3\uFF0C\u9ED8\u8BA4\u5BFC\u51FA \`definePlugin({ surfaces })\` |
1042
+ | \`${entry}\` | \u5165\u53E3\uFF0C\u9ED8\u8BA4\u5BFC\u51FA \`definePlugin({ surfaces })\`${react ? "\uFF0C\u7528 `reactMount` \u6302 React \u7EC4\u4EF6" : ""} |
1043
+ | \`tsconfig.json\` | \`npm run typecheck\`\uFF08\`tsc --noEmit\`\uFF09\u7528\uFF1B\`band check\` \u4E0D\u67E5\u7C7B\u578B |
932
1044
  | \`dev/workshop.yaml\` | \u672C\u5730\u5939\u5177\u5DE5\u574A\uFF1A\u6700\u5C0F\u5B9A\u4E49\uFF0C\u53EA\u7ED9 \`band dev\` / \`band check\` \u7528\uFF0C\u4E0D\u53D1\u5E03 |
933
1045
  | \`dev/fixture.ts\` | \u5939\u5177\uFF1A\u793A\u4F8B\u4EA7\u7269\u3001\u7248\u672C\u4E0E\u6587\u4EF6 |
934
1046
  | \`.gitlab-ci.yml\` | CI \u6A21\u677F\uFF1A\u73B0\u5728\u8DD1 \`band check\`\uFF1B\u5355\u6D4B\u3001\u9632\u6CC4\u9732\u626B\u63CF\u4E0E\u53D1\u5E03\u8FDB\u884C\u4E2D |
@@ -940,7 +1052,8 @@ ${title}\uFF1A\u4E00\u4E2A\u72EC\u7ACB\u7684 Band \u63D2\u4EF6\uFF08\u4E0D\u5C5E
940
1052
  \`\`\`bash
941
1053
  npm install # \u88C5\u4E0A devDependencies \u91CC\u7684 band \u547D\u4EE4\u884C\u4E0E\u63D2\u4EF6 SDK
942
1054
  npx band dev . # \u7528 dev/ \u5939\u5177\u5DE5\u574A\u8D77\u9879\u76EE\u9875\uFF0C\u672C\u4ED3\u5E93\u7684\u63D2\u4EF6\u81EA\u52A8\u88C5\u4E0A
943
- npx band check . # \u6821\u9A8C package.json\u3001plugin.yaml \u4E0E\u5939\u5177\u5DE5\u574A\u7684\u88C5\u914D
1055
+ npx band check . # \u6821\u9A8C package.json\u3001plugin.yaml \u4E0E\u5939\u5177\u5DE5\u574A\u7684\u88C5\u914D\uFF08\u4E0D\u67E5\u4EE3\u7801\u548C\u7C7B\u578B\uFF09
1056
+ npm run typecheck # tsc --noEmit \u67E5\u7C7B\u578B
944
1057
  \`\`\`
945
1058
 
946
1059
  ## \u53D1\u5E03\uFF08\u8FDB\u884C\u4E2D\uFF09
@@ -1070,9 +1183,19 @@ var PUBLISH_LABELS = {
1070
1183
  404: "\u5DE5\u574A\u4E0D\u5B58\u5728\uFF0C\u8BF7\u68C0\u67E5 --workshop id",
1071
1184
  409: "\u53D1\u5E03\u51B2\u7A81\uFF0C\u8BF7\u786E\u8BA4\u5DE5\u574A\u53D1\u5E03\u5206\u652F\u7684\u63D0\u4EA4\u4E0E\u672C\u5730 HEAD \u4E00\u81F4"
1072
1185
  };
1186
+ async function hasCredentialsFile() {
1187
+ try {
1188
+ await readFile(join5(homedir(), ".config", "band", "credentials.json"), "utf8");
1189
+ return true;
1190
+ } catch {
1191
+ return false;
1192
+ }
1193
+ }
1073
1194
  async function connectBand(urlOption, failureLabels = PUBLISH_LABELS, needScope = "workshops:publish") {
1074
1195
  let url = urlOption ?? process.env.BAND_URL;
1075
1196
  let token = process.env.BAND_TOKEN;
1197
+ if (!url && !token && !await hasCredentialsFile())
1198
+ throw new PublishError("\u7F3A\u5C11\u670D\u52A1\u5730\u5740\uFF1A\u7528 --url <\u5730\u5740>\uFF08\u6216\u8BBE BAND_URL\uFF09\uFF0C\u5E76\u914D\u7F6E BAND_TOKEN");
1076
1199
  if (!token) {
1077
1200
  let saved;
1078
1201
  try {
@@ -1094,11 +1217,11 @@ async function connectBand(urlOption, failureLabels = PUBLISH_LABELS, needScope
1094
1217
  }
1095
1218
  if (requestedOrigin && requestedOrigin !== savedOrigin)
1096
1219
  throw new PublishError("\u76EE\u6807\u670D\u52A1\u4E0E\u7528\u6237\u51ED\u636E\u6587\u4EF6\u4E0D\u5339\u914D\uFF0C\u8BF7\u4E3A\u76EE\u6807\u670D\u52A1\u63D0\u4F9B BAND_TOKEN");
1097
- url ??= saved.url;
1220
+ if (!url) url = saved.url;
1098
1221
  token = saved.token;
1099
1222
  }
1100
- if (!url || !token || /\s/.test(token))
1101
- throw new PublishError("\u8BF7\u914D\u7F6E\u5408\u6CD5\u7684 BAND_URL \u4E0E BAND_TOKEN");
1223
+ if (!url) throw new PublishError("\u7F3A\u5C11\u670D\u52A1\u5730\u5740\uFF1A\u7528 --url <\u5730\u5740> \u6216\u8BBE BAND_URL");
1224
+ if (!token || /\s/.test(token)) throw new PublishError("\u8BF7\u914D\u7F6E\u5408\u6CD5\u7684 BAND_TOKEN");
1102
1225
  let base;
1103
1226
  try {
1104
1227
  base = new URL(url);
@@ -1820,7 +1943,7 @@ var USAGE_BASE = `\u7528\u6CD5\uFF1A
1820
1943
  band preview [\u5206\u652F\u6216\u63D0\u4EA4] [--url <Band \u670D\u52A1\u5730\u5740>] --workshop <id> [--project <\u9879\u76EE id>]
1821
1944
  band dev [\u5DE5\u574A\u4ED3\u5E93\u76EE\u5F55 | \u72EC\u7ACB\u63D2\u4EF6\u4ED3\u5E93\u76EE\u5F55] [--port 5310] [--host 127.0.0.1]
1822
1945
  band new plugin <\u540D> --template panel|viewer|stage-view [--stage <\u9636\u6BB5>] [--title <\u6807\u9898>] [--dir <\u5DE5\u574A\u4ED3\u5E93\u76EE\u5F55>]
1823
- band new plugin-repo @<\u56E2\u961F>/<\u540D> --template panel|viewer|stage-view [--stage <\u9636\u6BB5>] [--title <\u6807\u9898>] [--dir <\u7236\u76EE\u5F55>]
1946
+ band new plugin-repo @<\u56E2\u961F>/<\u540D> --template panel|viewer|stage-view [--react] [--stage <\u9636\u6BB5>] [--title <\u6807\u9898>] [--dir <\u7236\u76EE\u5F55>]
1824
1947
  band new workshop <\u76EE\u5F55> [--example video]
1825
1948
  band new skill [--dir <\u4ED3\u5E93\u76EE\u5F55>]
1826
1949
  band --version`;
@@ -1949,7 +2072,11 @@ async function main(argv) {
1949
2072
  return 0;
1950
2073
  }
1951
2074
  if (cmd === "new") {
1952
- const { args, flags } = parseArgs(rest, ["template", "stage", "title", "dir"], ["official"]);
2075
+ const { args, flags } = parseArgs(
2076
+ rest,
2077
+ ["template", "stage", "title", "dir"],
2078
+ ["official", "react"]
2079
+ );
1953
2080
  const [kind, name] = args;
1954
2081
  if (kind !== "plugin" && kind !== "plugin-repo" || !name) {
1955
2082
  console.error(usage());
@@ -1960,6 +2087,10 @@ async function main(argv) {
1960
2087
  console.error(`--template \u53EA\u80FD\u662F ${PLUGIN_TEMPLATES.join(" | ")}`);
1961
2088
  return 2;
1962
2089
  }
2090
+ if (kind === "plugin" && flags.react) {
2091
+ console.error("--react \u53EA\u7528\u4E8E band new plugin-repo\uFF08\u5DE5\u574A\u4ED3\u5E93\u91CC\u7684\u63D2\u4EF6\u81EA\u5DF1\u5199 .tsx \u5165\u53E3\uFF09");
2092
+ return 2;
2093
+ }
1963
2094
  if (kind === "plugin-repo") {
1964
2095
  if (flags.official) {
1965
2096
  console.error("--official \u53EA\u7528\u4E8E band new plugin\uFF1A\u72EC\u7ACB\u63D2\u4EF6\u4ED3\u5E93\u4E0D\u751F\u6210\u5B98\u65B9\u63D2\u4EF6");
@@ -1968,7 +2099,8 @@ async function main(argv) {
1968
2099
  const r2 = newPluginRepo(flags.dir ?? ".", name, {
1969
2100
  template,
1970
2101
  ...flags.stage ? { stage: flags.stage } : {},
1971
- ...flags.title ? { title: flags.title } : {}
2102
+ ...flags.title ? { title: flags.title } : {},
2103
+ ...flags.react ? { react: true } : {}
1972
2104
  });
1973
2105
  for (const f of r2.files) console.log(`\u2713 ${relative(flags.dir ?? ".", join7(r2.dir, f))}`);
1974
2106
  for (const h of r2.hints) console.log(`\u4E0B\u4E00\u6B65\uFF1A${h}`);
@@ -1987,7 +2119,7 @@ async function main(argv) {
1987
2119
  if (cmd === "dev") {
1988
2120
  const { args, flags } = parseArgs(rest, ["port", "host"]);
1989
2121
  const port = flags.port === void 0 ? void 0 : parsePort(flags.port);
1990
- const { startDevServer } = await import("./dev-server-Q7NTJ3QD.js");
2122
+ const { startDevServer } = await import("./dev-server-IBR3PKDE.js");
1991
2123
  const server = await startDevServer(args[0] ?? ".", {
1992
2124
  ...port !== void 0 ? { port } : {},
1993
2125
  ...flags.host ? { host: flags.host } : {}
@@ -194,9 +194,21 @@ function heartbeatPlugin(ms) {
194
194
  function bandDevPlugin(root, initial) {
195
195
  let ws = initial;
196
196
  let server;
197
+ const seenPackageJsons = /* @__PURE__ */ new Set();
198
+ const pluginPackageJsons = () => {
199
+ for (const p of ws.plugins) seenPackageJsons.add(join(dirname(p.manifestPath), "package.json"));
200
+ for (const path of seenPackageJsons)
201
+ if (!existsSync(path)) {
202
+ seenPackageJsons.delete(path);
203
+ server?.watcher.unwatch(path);
204
+ }
205
+ return [...seenPackageJsons];
206
+ };
207
+ const isViewPackageJson = (file) => /[\\/]band[\\/]views[\\/][^\\/]+[\\/]package\.json$/.test(file);
197
208
  const yamls = () => [
198
209
  ws.workshopPath,
199
210
  ...ws.plugins.map((p) => p.manifestPath),
211
+ ...pluginPackageJsons(),
200
212
  ...ws.paramsPaths
201
213
  ];
202
214
  return {
@@ -215,7 +227,8 @@ function bandDevPlugin(root, initial) {
215
227
  s.watcher.add(yamls());
216
228
  s.watcher.on("all", (_event, file) => {
217
229
  if (!file.startsWith(root)) return;
218
- if (!file.endsWith(".yaml") && !ws.paramsPaths.includes(file)) return;
230
+ if (!file.endsWith(".yaml") && !ws.paramsPaths.includes(file) && !pluginPackageJsons().includes(file) && !isViewPackageJson(file))
231
+ return;
219
232
  const mod = s.moduleGraph.getModuleById(RESOLVED);
220
233
  if (mod) s.moduleGraph.invalidateModule(mod);
221
234
  s.ws.send({ type: "full-reload" });
package/dist/index.d.ts CHANGED
@@ -33,6 +33,8 @@ interface NewPluginRepoOptions {
33
33
  stage?: string;
34
34
  /** 界面上的标题,缺省用插件名。 */
35
35
  title?: string;
36
+ /** 用 React 写:入口是 `src/index.tsx`,package.json 带 React 与 `band-plugin-react` 的开发依赖,tsconfig 开 JSX。 */
37
+ react?: boolean;
36
38
  }
37
39
  interface NewPluginRepoResult {
38
40
  /** 仓库目录(`<父目录>/<名>`)。 */
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  officialPluginCatalog,
11
11
  renderOfficialCatalog,
12
12
  writeOfficialCatalog
13
- } from "./chunk-Q2XJXNVH.js";
13
+ } from "./chunk-FGPWXAOA.js";
14
14
  import "./chunk-CL3FV65M.js";
15
15
  import {
16
16
  DevSetupError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanyun-ai-infra/band-cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "band 命令行:新建、本地调试、校验与发布 Band 工坊和插件",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -35,6 +35,7 @@
35
35
  "dist",
36
36
  "dev-host",
37
37
  "src/dev-managers.ts",
38
+ "src/inspector-default.ts",
38
39
  "src/inspector-plugins.ts",
39
40
  "src/load-plugins.ts",
40
41
  "bundled"
@@ -43,9 +44,9 @@
43
44
  "node": ">=22.19"
44
45
  },
45
46
  "dependencies": {
46
- "@kanyun-ai-infra/band-contracts": "^0.1.3",
47
- "@kanyun-ai-infra/band-plugin-react": "^0.2.0",
48
- "@kanyun-ai-infra/band-plugin-sdk": "^2.0.0",
47
+ "@kanyun-ai-infra/band-contracts": "^0.1.4",
48
+ "@kanyun-ai-infra/band-plugin-react": "^0.2.1",
49
+ "@kanyun-ai-infra/band-plugin-sdk": "^2.1.0",
49
50
  "es-module-lexer": "^2.3.2",
50
51
  "react": "^19.3.1",
51
52
  "react-dom": "^19.3.1",
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `band dev` 右边「夹具」栏默认展开的最小视口宽度(像素):不到这个宽度项目页的右栏会被夹具栏挤得显示不全,
3
+ * 默认收起,作者点「夹具」按钮展开。quickstart 写的「不到 1600 像素右栏显示不全」是同一个数。
4
+ */
5
+ export const INSPECTOR_OPEN_MIN_WIDTH = 1600;
6
+
7
+ export function inspectorOpenByDefault(viewportWidth: number): boolean {
8
+ return viewportWidth >= INSPECTOR_OPEN_MIN_WIDTH;
9
+ }