Skip to content

Commit 2f8e29c

Browse files
committed
refactor: simplify example commands
1 parent 63285e9 commit 2f8e29c

18 files changed

Lines changed: 127 additions & 115 deletions

File tree

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ so it can be copied and run independently.
1919
cd examples/01-content-operations
2020
pnpm install
2121
pnpm build
22-
pnpm server
22+
pnpm link-cli
23+
pnpm start-server
2324
```
2425

2526
After the Server starts, install the skill from another terminal in the same directory:
@@ -40,14 +41,15 @@ Use univer-content to create a sales spreadsheet with 10 sample records.
4041
cd examples/02-visual-inspection
4142
pnpm install
4243
pnpm build
43-
pnpm server
44+
pnpm link-cli
45+
pnpm start-server
4446
```
4547

4648
Use another terminal in the same `02-visual-inspection` directory:
4749

4850
```bash
49-
pnpm start create sheet --name "Visual Demo"
50-
pnpm start screenshot --unit <unit-id> --sheet Data --range A1:B2 --out output
51+
UNIT_ID=$(univer-example-cli create sheet --name "Visual Demo")
52+
univer-example-cli screenshot --unit "$UNIT_ID" --sheet Data --range A1:B2 --out output
5153
```
5254

5355
See each example README for its complete command sequence and verification steps.

README.zh-CN.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
cd examples/01-content-operations
1919
pnpm install
2020
pnpm build
21-
pnpm server
21+
pnpm link-cli
22+
pnpm start-server
2223
```
2324

2425
Server 启动后,在同一个目录的另一个终端安装 skill:
@@ -39,14 +40,15 @@ pnpm skill:install
3940
cd examples/02-visual-inspection
4041
pnpm install
4142
pnpm build
42-
pnpm server
43+
pnpm link-cli
44+
pnpm start-server
4345
```
4446

4547
另开终端,仍在 `02-visual-inspection` 目录:
4648

4749
```bash
48-
pnpm start create sheet --name "Visual Demo"
49-
pnpm start screenshot --unit <unit-id> --sheet Data --range A1:B2 --out output
50+
UNIT_ID=$(univer-example-cli create sheet --name "Visual Demo")
51+
univer-example-cli screenshot --unit "$UNIT_ID" --sheet Data --range A1:B2 --out output
5052
```
5153

5254
完整命令和验证方式见各 example 的 README。

examples/01-content-operations/README.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,27 @@ After entering this example, run every command from the current directory:
2222
```bash
2323
pnpm install
2424
pnpm build
25-
pnpm server
25+
pnpm link-cli
26+
pnpm start-server
2627
```
2728

28-
Use another terminal in the same directory:
29+
Use another terminal in the same directory. `create` prints the new short Unit ID, so the remaining
30+
commands can capture and reuse it directly:
2931

3032
```bash
31-
pnpm start create sheet --name "Demo"
33+
UNIT_ID=$(univer-example-cli create sheet --name "Demo")
3234

33-
pnpm start inspect range A1:B2 --worksheet index:1 \
34-
--unit <unit-id> --json
35+
univer-example-cli inspect range A1:B2 --worksheet index:1 \
36+
--unit "$UNIT_ID" --json
3537

36-
pnpm start execute --unit <unit-id> \
38+
univer-example-cli execute --unit "$UNIT_ID" \
3739
--code 'workbook.getActiveSheet().getRange("A2:B2").setValues([["Updated", 2]])'
3840

39-
pnpm start open --unit <unit-id>
41+
univer-example-cli open --unit "$UNIT_ID"
4042

41-
# An Agent queries the Facade API before generating execution code
42-
pnpm start api find setValues --unit sheet
43-
pnpm start api show FRange.setValues
43+
# Simulate an Agent querying the Facade API before generating execution code
44+
univer-example-cli api find setValues --unit sheet
45+
univer-example-cli api show FRange.setValues
4446
```
4547

4648
## Use it with an Agent
@@ -63,6 +65,7 @@ finished, run:
6365

6466
```bash
6567
pnpm skill:uninstall
68+
pnpm unlink-cli
6669
```
6770

6871
## Source order

examples/01-content-operations/README.zh-CN.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,26 @@ Web ──┘
2020
```bash
2121
pnpm install
2222
pnpm build
23-
pnpm server
23+
pnpm link-cli
24+
pnpm start-server
2425
```
2526

26-
另开终端,仍在当前目录操作:
27+
另开终端,仍在当前目录操作`create` 会输出新建 Unit 的短 ID,后续命令可以直接保存并复用
2728

2829
```bash
29-
pnpm start create sheet --name "Demo"
30+
UNIT_ID=$(univer-example-cli create sheet --name "Demo")
3031

31-
pnpm start inspect range A1:B2 --worksheet index:1 \
32-
--unit <unit-id> --json
32+
univer-example-cli inspect range A1:B2 --worksheet index:1 \
33+
--unit "$UNIT_ID" --json
3334

34-
pnpm start execute --unit <unit-id> \
35+
univer-example-cli execute --unit "$UNIT_ID" \
3536
--code 'workbook.getActiveSheet().getRange("A2:B2").setValues([["Updated", 2]])'
3637

37-
pnpm start open --unit <unit-id>
38+
univer-example-cli open --unit "$UNIT_ID"
3839

39-
# Agent 在生成执行代码前查询 Facade API
40-
pnpm start api find setValues --unit sheet
41-
pnpm start api show FRange.setValues
40+
# 模拟 Agent 在生成执行代码前查询 Facade API
41+
univer-example-cli api find setValues --unit sheet
42+
univer-example-cli api show FRange.setValues
4243
```
4344

4445
## 交给 Agent 使用
@@ -60,6 +61,7 @@ Agent 会创建、填充、提交和校验 Unit,并返回 Web 地址。Skill
6061

6162
```bash
6263
pnpm skill:uninstall
64+
pnpm unlink-cli
6365
```
6466

6567
## 源码顺序

examples/01-content-operations/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,22 @@
33
"version": "0.0.0",
44
"private": true,
55
"bin": {
6-
"content-operations": "./dist/cli/main.js"
6+
"univer-example-cli": "./dist/cli/main.js"
77
},
88
"type": "module",
99
"scripts": {
1010
"build": "vite build && tsc -p tsconfig.node.json",
1111
"check": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm test",
1212
"format": "oxfmt .",
1313
"format:check": "oxfmt --check .",
14+
"link-cli": "pnpm link --global",
1415
"lint": "oxlint .",
1516
"skill:install": "node scripts/skill.mjs install",
1617
"skill:uninstall": "node scripts/skill.mjs uninstall",
17-
"server": "node dist/server/main.js",
18-
"start": "node dist/cli/main.js",
18+
"start-server": "node dist/server/main.js",
1919
"test": "pnpm build && vitest run --root . test",
20-
"typecheck": "tsc -p tsconfig.node.json --noEmit && tsc -p tsconfig.web.json --noEmit"
20+
"typecheck": "tsc -p tsconfig.node.json --noEmit && tsc -p tsconfig.web.json --noEmit",
21+
"unlink-cli": "pnpm remove --global @univer-cli-example/content-operations"
2122
},
2223
"dependencies": {
2324
"@univer-cli/api-reference": "1.0.0-insiders.20260822-0c0c0dd",

examples/01-content-operations/skills/univer-content/SKILL.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,20 @@ description: Create and edit a collaborative Univer Sheet, Doc, or Slide when th
55

66
# Work with Univer Content
77

8-
Use `pnpm start <command>` from the current `01-content-operations` directory. The user starts the
9-
Server separately with `pnpm server`.
8+
Use `univer-example-cli <command>`. The user starts the Server separately with
9+
`pnpm start-server` from the current `01-content-operations` directory.
1010

1111
## Workflow
1212

1313
1. Choose `sheet`, `doc`, or `slide` from the request. Run
14-
`pnpm start create <type> --name <name>` and retain the returned `unitId`.
14+
`univer-example-cli create <type> --name <name>` and retain the returned `unitId`.
1515
2. Inspect the new Unit with the matching overview target: `workbook`, `document`, or
1616
`presentation`.
17-
3. Before using an unfamiliar Facade API, query it with `api find` and `api show`. Execution code
18-
receives `workbook` for a Sheet, `doc` for a Doc, and `presentation` for a Slide.
19-
4. Run `pnpm start execute` once with the complete trusted Facade JavaScript change.
17+
3. Before using an unfamiliar Facade API, query it with `univer-example-cli api find` and
18+
`univer-example-cli api show`. Execution code receives `workbook` for a Sheet, `doc` for a Doc,
19+
and `presentation` for a Slide.
20+
4. Run `univer-example-cli execute` once with the complete trusted Facade JavaScript change.
2021
5. Require `commit: "confirmed"`, retain the returned revision, and do not retry a failed commit.
2122
6. Inspect the changed range, paragraph, or slide with `--json` and verify the requested content.
22-
7. Run `pnpm start open --no-launch` and return the Unit type, name, `unitId`, revision, and URL.
23-
Open the browser only when the user asks.
23+
7. Run `univer-example-cli open --no-launch` and return the Unit type, name, `unitId`, revision, and
24+
URL. Open the browser only when the user asks.

examples/01-content-operations/src/cli/features/unit.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export function createUnitCommand(): Command {
2323
headers: { "content-type": "application/json" },
2424
body: JSON.stringify({ name: options.name, type }),
2525
});
26-
process.stdout.write(`${JSON.stringify(await response.json(), undefined, 2)}\n`);
26+
const { unitId } = (await response.json()) as { readonly unitId: string };
27+
process.stdout.write(`${unitId}\n`);
2728
});
2829
return command;
2930
}

examples/01-content-operations/src/cli/program.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { executeCommand, inspectCommand } from "./features/unit-content.js";
44
import { createUnitCommand, openUnitCommand } from "./features/unit.js";
55

66
export function createProgram(): Command {
7-
const program = new Command("content-operations").description(
7+
const program = new Command("univer-example-cli").description(
88
"Create, inspect, edit, and view collaborative Univer content",
99
);
1010
program.addCommand(createUnitCommand());

examples/01-content-operations/src/server/server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export async function startServer(
4646

4747
const app = express();
4848
app.post("/api/units", express.json(), async (request, response) => {
49-
const unitId = randomUUID();
49+
const unitId = randomUUID().slice(0, 8);
5050
const unitType = parseUnitType(request.body.type);
5151
const name = String(request.body.name ?? `Untitled ${unitTypeLabel(unitType)}`);
5252
const result = await service.createUnitFromData(createUnitInput(unitType, unitId, name), {

examples/01-content-operations/test/smoke.test.ts

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@ afterEach(async () => await server?.close());
1616

1717
it("creates, inspects, executes, and opens Sheet, Doc, and Slide units", async () => {
1818
server = await startServer(":memory:");
19-
const created = JSON.parse(await run("create", "sheet", "--name", "Demo Sheet")) as {
20-
readonly unitId: string;
21-
};
22-
const sheetId = created.unitId;
19+
const sheetId = (await run("create", "sheet", "--name", "Demo Sheet")).trim();
2320

2421
const before = await run(
2522
"inspect",
@@ -53,55 +50,51 @@ it("creates, inspects, executes, and opens Sheet, Doc, and Slide units", async (
5350
) as Record<string, unknown>;
5451
expect(execution).toMatchObject({ commit: "confirmed", revision: 2, value: "done" });
5552

56-
const document = JSON.parse(await run("create", "doc", "--name", "Demo Doc")) as {
57-
readonly unitId: string;
58-
};
53+
const documentId = (await run("create", "doc", "--name", "Demo Doc")).trim();
5954
expect(
60-
JSON.parse(await run("inspect", "document", "--unit", document.unitId, "--json")),
55+
JSON.parse(await run("inspect", "document", "--unit", documentId, "--json")),
6156
).toMatchObject({ kind: "document", title: "Demo Doc" });
6257
expect(
6358
JSON.parse(
6459
await run(
6560
"execute",
6661
"--unit",
67-
document.unitId,
62+
documentId,
6863
"--code",
6964
'await api.executeCommand("doc.mutation.rename-doc", { unitId: doc.getId(), name: "Updated Doc" }); return doc.getName();',
7065
),
7166
),
7267
).toMatchObject({ commit: "confirmed", revision: 2, value: "Updated Doc" });
7368
expect(
74-
JSON.parse(await run("inspect", "document", "--unit", document.unitId, "--json")),
69+
JSON.parse(await run("inspect", "document", "--unit", documentId, "--json")),
7570
).toMatchObject({ title: "Updated Doc" });
7671

77-
const presentation = JSON.parse(await run("create", "slide", "--name", "Demo Slide")) as {
78-
readonly unitId: string;
79-
};
72+
const presentationId = (await run("create", "slide", "--name", "Demo Slide")).trim();
8073
expect(
81-
JSON.parse(await run("inspect", "presentation", "--unit", presentation.unitId, "--json")),
74+
JSON.parse(await run("inspect", "presentation", "--unit", presentationId, "--json")),
8275
).toMatchObject({ kind: "presentation", name: "Demo Slide" });
8376
expect(
8477
JSON.parse(
8578
await run(
8679
"execute",
8780
"--unit",
88-
presentation.unitId,
81+
presentationId,
8982
"--code",
9083
'presentation.setName("Updated Slide"); return presentation.getName();',
9184
),
9285
),
9386
).toMatchObject({ commit: "confirmed", revision: 2, value: "Updated Slide" });
9487

95-
for (const unitId of [sheetId, document.unitId, presentation.unitId]) {
88+
for (const unitId of [sheetId, documentId, presentationId]) {
9689
const url = await run("open", "--unit", unitId, "--no-launch");
9790
const page = await (await fetch(url.trim())).text();
9891
expect(page).toContain('id="sidebar"');
9992
expect(page).toContain('id="app"');
10093
}
10194
expect(await (await fetch(`${server.origin}/api/units`)).json()).toMatchObject([
10295
{ name: "Demo Sheet", unitId: sheetId, unitType: "sheet" },
103-
{ name: "Demo Doc", unitId: document.unitId, unitType: "doc" },
104-
{ name: "Demo Slide", unitId: presentation.unitId, unitType: "slide" },
96+
{ name: "Demo Doc", unitId: documentId, unitType: "doc" },
97+
{ name: "Demo Slide", unitId: presentationId, unitType: "slide" },
10598
]);
10699
expect(await run("api", "find", "setValues", "--unit", "sheet")).toContain("FRange.setValues");
107100
expect(await run("api", "show", "FRange.setValues")).toContain("setValues");
@@ -112,19 +105,18 @@ it("restores the file list and Unit from SQLite", async () => {
112105
const databaseFile = join(directory, "content.sqlite");
113106
try {
114107
server = await startServer(databaseFile);
115-
const created = JSON.parse(await run("create", "sheet", "--name", "Persistent")) as {
116-
readonly unitId: string;
117-
};
108+
const unitId = (await run("create", "sheet", "--name", "Persistent")).trim();
118109
await server.close();
119110
server = undefined;
120111

121112
server = await startServer(databaseFile);
122113
expect(await (await fetch(`${server.origin}/api/units`)).json()).toMatchObject([
123-
{ name: "Persistent", unitId: created.unitId, unitType: "sheet" },
114+
{ name: "Persistent", unitId, unitType: "sheet" },
124115
]);
125-
expect(
126-
JSON.parse(await run("inspect", "workbook", "--unit", created.unitId, "--json")),
127-
).toMatchObject({ name: "Persistent", unitId: created.unitId });
116+
expect(JSON.parse(await run("inspect", "workbook", "--unit", unitId, "--json"))).toMatchObject({
117+
name: "Persistent",
118+
unitId,
119+
});
128120
} finally {
129121
await server?.close();
130122
server = undefined;

0 commit comments

Comments
 (0)