You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 602045b
Browse filesBrowse the repository at this point in the historyBrowse files
-`src/context.ts` — `getContext` builds the per-action HTTP/output context; call it only inside actions so `--help` never requires a token.
26
+
-`src/errors.ts` — sole definition of CLI error classes, API status hints, and the stable exit-code contract.
27
+
-`src/output.ts` — `printJson`/`printOk`/`printTable`/`printRecord`, TTY color honoring `NO_COLOR`, and CJK/emoji display-width alignment.
28
+
-`src/confirm.ts` — `confirmDestructive` enforces the interactive confirmation or `--yes` gate for destructive actions.
29
+
-`src/commands/` — Commander-facing domain modules; each exports one `register<Domain>Commands` function and owns flags, action orchestration, and rendering.
30
+
-`src/commands/auth.ts` — `registerAuthCommands` registers connectivity and authenticated-account status commands.
31
+
-`src/commands/book.ts` — `registerBookCommands` registers book list/get/create/update/delete, pagination, validation, and delete confirmation.
32
+
-`src/commands/doc.ts` — `registerDocCommands` registers document CRUD, body/file handling, pagination, and version reads.
-`src/commands/toc.ts` — `registerTocCommands` registers TOC tree reads and cross-field-validated node updates.
37
+
-`src/commands/user.ts` — `registerUserCommands` registers current-user and user-group reads with role filtering and pagination.
38
+
-`src/client/http.ts` — the only HTTP exit; adds auth/base URL/timeout, normalizes errors, retries 429 for every method, and retries 502/503/504 or network failures only for GET.
39
+
-`src/client/api/` — thin domain wrappers: `YuqueHttp` is the first argument, typed `ApiEnvelope` responses are awaited, and `res.data` is returned.
40
+
-`src/client/api/book.ts` — book owner collection and id-or-namespace item API wrappers.
41
+
-`src/client/api/doc.ts` — document CRUD, global-id lookup, and published-version API wrappers.
42
+
-`src/client/api/group.ts` — group-member list/update/remove API wrappers.
43
+
-`src/client/api/search.ts` — doc/repo search API wrapper.
44
+
-`src/client/api/stats.ts` — group aggregate and paged member/book/doc statistics API wrappers, including the live-array correction to the spec types.
45
+
-`src/client/api/toc.ts` — book TOC read/update API wrappers and update-body shape.
46
+
-`src/client/api/user.ts` — heartbeat, current-user, and user-groups API wrappers.
47
+
-`src/client/book-ref.ts` — parses a book reference as a numeric id or `group/slug` and produces the encoded `/repos/...` base path.
48
+
-`src/client/paginate.ts` — drains offset-paged endpoints for `--all` until the first short page.
49
+
-`src/client/types.gen.ts` — generated from `spec/yuque-openapi.yaml`; edit the spec and run `npm run gen:types`, never edit this file directly.
50
+
-`src/client/types.ts` — thin compatibility adapter over the generated schemas; preserves public type names, live-API extensions, and index signatures for `--json` pass-through.
51
+
-`spec/yuque-openapi.yaml` — vendored upstream OpenAPI contract and source of truth for the supported operation surface.
52
+
-`scripts/smoke-dist-cli.js` — spawns `dist/bin.js` as an installed CLI would and checks version/help plus representative usage/auth exit codes.
53
+
-`tests/commands/` — mocked command-action unit tests for exact requests, rendering, validation, confirmation, and exit behavior.
54
+
-`tests/client/` — transport retry/error and book-reference unit contracts.
55
+
-`tests/docs/` — programmatic drift locks for README command coverage and this repository guide.
-`tests/spec-coverage.test.ts` — pins every operationId + method + path to registered leaf commands and locks the expected command list.
58
+
59
+
## Contracts & locks
60
+
61
+
- Command surface is **locked 1:1 against `spec/yuque-openapi.yaml`** by `tests/spec-coverage.test.ts`; adding/renaming a command or refreshing the spec requires a deliberate mapping update.
62
+
- Both READMEs are locked by `tests/docs/command-surface-docs.test.ts` for the exact heading count and exact registered leaf-command set; keep README.md and README.zh-CN.md strictly isomorphic.
63
+
- Exit codes are stable and scripts may rely on them: `0 success · 1 API/unknown error · 2 usage error · 3 auth error · 4 not found · 5 rate limited` (`src/errors.ts`).
64
+
- All HTTP goes through `src/client/http.ts`; command handlers never call axios directly.
65
+
- Human output goes through `src/output.ts`; `--json` prints the complete unprojected payload returned by the API wrapper.
66
+
-`npm run check` is the merge gate and matches CI: lint, format check, generated-type drift check, typecheck, coverage-enforced unit tests, one build, dist smoke, then functional e2e.
67
+
- New or changed commands need always-on mock-server coverage in `tests/e2e/`, not only unit coverage; see `tests/e2e/README.md` for the optional real-API gates.
68
+
69
+
## Adding a command
70
+
71
+
1. Add the typed wrapper in `src/client/api/<domain>.ts`; take `http` first and `return res.data` to unwrap `ApiEnvelope`.
72
+
2. Register the subcommand in `src/commands/<domain>.ts`; action order is local flag validation (`UsageError`) → `confirmDestructive` for destructive work, before `getContext` → `getContext(cmd)` → API call → `if (ctx.json) { printJson(raw); return; }` with the complete wrapper result → `printOk`/`printTable`/`printRecord`.
73
+
3. For a new domain, add the import at the top of `src/cli.ts` and call its register function inside `buildProgram`.
74
+
4. Update the `OPERATION_TO_COMMANDS` operationId + method + path tuples and `EXPECTED_LEAF_COMMANDS` in `tests/spec-coverage.test.ts`.
75
+
5. Update `README.md` and `README.zh-CN.md`: increment each commands-section heading count and add an isomorphic command-table row; `tests/docs/command-surface-docs.test.ts` locks both.
76
+
6. Regenerate the pinned help surface — `UPDATE_HELP_GOLDEN=1 npx vitest run tests/docs/help-surface.test.ts` — and review the `tests/docs/help-surface.golden.json` diff; any new or changed flag must appear there deliberately.
77
+
7. Add `tests/commands/` unit coverage with exact request assertions and the expected process exit code.
78
+
8. Add a `tests/e2e/` mock-suite case with wire-level request assertions against the built binary.
79
+
9. Run `npm run check` and require the complete gate to pass.
80
+
81
+
## Conventions & gotchas
82
+
83
+
- ESM is mandatory (`package.json` has `"type": "module"`); relative TypeScript imports use `.js` suffixes because those are the emitted runtime paths.
84
+
- Runtime support is Node >= 20, as pinned by `package.json#engines`.
85
+
- For new flag validation, use `Option.choices` for enums or an argument parser that throws `UsageError`; both map to exit 2 because `buildProgram` calls `exitOverride` before registration and Commander copies that callback into subcommands (`tests/commands/flag-validation.test.ts` locks this). Put cross-field and semantic-required checks inside the action and throw `UsageError`; do not introduce new `InvalidArgumentError` parsers.
86
+
- Destructive actions call `confirmDestructive` before `getContext`, so confirmation precedes auth/client setup; every such command supports `--yes`.
87
+
- Convenience scripts: `npm run lint:fix` fixes lint, `npm run format` writes formatting, `npm run test:watch` watches unit tests, `npm run test:coverage` runs coverage, and `npm run dev` runs `src/bin.ts` directly through tsx.
88
+
- Smoke and e2e exercise built `dist` output: `npm run smoke:dist` and `npm run test:e2e` build first, while `npm run check` builds once then calls their `:built` variants.
89
+
- Release work includes updating `CHANGELOG.md`; npm's `prepublishOnly` lifecycle runs the build before publication.
Copy file name to clipboardExpand all lines: README.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -87,7 +87,7 @@ Each command maps to the [Yuque OpenAPI](https://www.yuque.com/yuque/developer/a
87
87
||`stats books <login>`| Per-book statistics |
88
88
||`stats docs <login>`| Per-doc statistics |
89
89
90
-
Books (知识库) accept either a numeric id or an `owner/slug` namespace everywhere. Run `yuque <command> --help` for all flags.
90
+
Books (知识库) accept either a numeric id or an `owner/slug` namespace everywhere. For data-table docs, `doc get` accepts `--page` and `--page-size` to page the content. Run `yuque <command> --help` for all flags.
91
91
92
92
## Output & scripting
93
93
@@ -132,11 +132,11 @@ cd yuque-open-cli
132
132
npm install
133
133
npm test# unit tests
134
134
npm run build # compile TypeScript
135
-
npm run test:e2e #functional tests: the built binary vs a mock Yuque API
135
+
npm run test:e2e #build, then run the binary against a mock Yuque API
136
136
npm run dev -- --help # run from source
137
137
```
138
138
139
-
The command surface is pinned to [spec/yuque-openapi.yaml](./spec/yuque-openapi.yaml) by [tests/spec-coverage.test.ts](./tests/spec-coverage.test.ts); `npm run check` is the merge gate.
139
+
The command surface is pinned to [spec/yuque-openapi.yaml](./spec/yuque-openapi.yaml) by [tests/spec-coverage.test.ts](./tests/spec-coverage.test.ts); `npm run check` is the merge gate (lint, formatting, type checking, coverage-enforced unit tests, one build, dist smoke, and functional e2e).
140
140
141
141
## Links
142
142
@@ -148,7 +148,7 @@ The command surface is pinned to [spec/yuque-openapi.yaml](./spec/yuque-openapi.
0 commit comments