feat!: 基于 OpenAPI 规格重写为 TypeScript CLI(覆盖全部 38 个官方操作)#2
Conversation
…leton, spec contract Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Domains: auth/ping, user, search, repo, doc (incl. versions), toc, group members, team statistics. Bilingual READMEs, docs lock test, exit-code contract fix (exitOverride before subcommand registration). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…fy help style - drop repo create --type (not in spec requestBody); add --enhanced-privacy - add repo list --filter-by-ability; cap --limit/--page/--role per spec bounds - capitalize all command descriptions consistently Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- http: method-aware retry — never silently replay non-idempotent writes on timeout/5xx; flag ambiguity in the error message; pin backoff schedule in tests - docs lock: boundary-aware command matching (no prefix false-positives) plus a reverse lock against phantom README rows; spec table now pins method+path per op - doc/user: validate --offset/--limit regardless of --all; document precedence - output: EastAsianWidth-based display width (Hangul/emoji/CJK ext); EPIPE exits 0 - stats: --json always prints the bare rows array in both paging modes - help/READMEs: mark required flags, fix toc verbs, rekey troubleshooting on real error strings, document YUQUE_PERSONAL_TOKEN fallback Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e OpenAPI Replaces the previous interactive JS CLI entirely: 26 noun-verb commands locked 1:1 against the vendored OpenAPI spec (38 operations), stable exit codes, --json/--all scripting support, method-aware retry, and bilingual READMEs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e9dee74af4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ) | ||
| : await fetchPage(ctx.http, { ...filters, page: opts.page, limit: opts.limit }); | ||
| if (ctx.json) { | ||
| printJson(rows); |
There was a problem hiding this comment.
Preserve stats pagination metadata in JSON
When a stats list command runs with --json but without --all, the API client's page object includes total, yet the callbacks extract only .members, .books, or .docs and this line prints that reduced array. Scripts therefore cannot retrieve the result count despite --json promising the full payload; preserve the page object for non---all JSON output.
AGENTS.md reference: AGENTS.md:L34-L34
Useful? React with 👍 / 👎.
| .requiredOption('--slug <slug>', 'repo path (slug) (required)') | ||
| .option('--group', 'create under a group instead of a user') | ||
| .option('--description <description>', 'repo description') | ||
| .option('--public <n>', 'visibility: 0 private, 1 public, 2 org-only', parseNonNegativeInt) |
There was a problem hiding this comment.
Reject unsupported repo visibility values
For repo create and repo update, --public is documented and specified as the enum 0|1|2, but parseNonNegativeInt also accepts values such as 3. Those invalid invocations reach the API and become API failures with exit code 1 instead of being rejected locally as usage errors with exit code 2; use an enum-aware parser for these options.
AGENTS.md reference: AGENTS.md:L26-L27
Useful? React with 👍 / 👎.
| printRecord(detail, DOC_META_FIELDS); | ||
| return; | ||
| } | ||
| writeBody(detail.body); |
There was a problem hiding this comment.
Render spreadsheet document bodies
When doc get receives a Sheet document, the OpenAPI response carries its content in body_sheet and may omit body; reading only detail.body therefore prints nothing and exits successfully for that supported document type. Select the appropriate content field based on the response type, or report that the format cannot be rendered.
Useful? React with 👍 / 👎.
| this.sleep = options.sleep ?? defaultSleep; | ||
| this.axios = axios.create({ | ||
| baseURL: `${options.host}/api/v2`, | ||
| timeout: options.timeoutMs ?? 30000, |
There was a problem hiding this comment.
和yuque-mcp-server 客户端保持一致正常都够用;加了一个配置项也可以调大。
| coverage/ | ||
| *.tgz | ||
|
|
||
| # Env files |
| action: opts.action, | ||
| ...(opts.actionMode !== undefined && { action_mode: opts.actionMode }), | ||
| ...(opts.targetUuid !== undefined && { target_uuid: opts.targetUuid }), | ||
| ...(opts.nodeUuid !== undefined && { node_uuid: opts.nodeUuid }), |
There was a problem hiding this comment.
target_uuid 不填默认为根节点,node_uuid 是移动/更新/删除场景才需要
| const opts = update.opts<TocUpdateOptions>(); | ||
| const body: TocUpdateBody = { | ||
| action: opts.action, | ||
| ...(opts.actionMode !== undefined && { action_mode: opts.actionMode }), |
- stats --json keeps the page object ({rows-key, total}) in both paging modes
- repo --public validates the 0|1|2 enum locally (exit 2, no wire call)
- doc get renders sheet/table docs via body_sheet/body_table fallback, warns
on stderr when nothing is renderable
- toc update enforces spec cross-field rules: edit/remove need --node-uuid,
creating needs --type plus per-type fields; --target-uuid stays optional
(defaults to root)
- request timeout configurable via --timeout / YUQUE_TIMEOUT_MS (default 30s,
same as yuque-mcp-server)
- restore log/env/editor entries dropped from .gitignore in the rewrite
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ated real-API suite - tests/e2e mock suite: FixtureServer + async runner spawn the real dist/bin.js and assert wire traffic, rendering, exit codes, retry semantics (31 cases) - keep the env-gated real-API suite (cli.e2e.test.ts) and document both layers in tests/e2e/README.md - npm run check now ends with test:e2e; CI gate unchanged (single check) - .github/workflows/real-api-e2e.yml: weekly + manual read-only run, enabled only when the YUQUE_E2E_TOKEN secret exists Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
npm run check's e2e step now enables the gated real-API read paths whenever the YUQUE_E2E_TOKEN secret is configured (Node 22 leg only, weekly schedule added for drift detection); the separate real-api workflow is removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The account's first repo can be a Design board, whose /docs and /toc endpoints 404; filter with repo list --type Book (and point at YUQUE_E2E_REPO in the failure hint). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
/users/{login}/repos 404s for some accounts (private profiles) while the
numeric id works; probe both and reuse the working ref for user-groups and
repo-list assertions. YUQUE_E2E_LOGIN still pins it explicitly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… empty CI's YUQUE_E2E_TOKEN belongs to a dedicated empty test account; first run creates cli-e2e-sandbox with one fixture doc via the CLI itself, later runs discover it through the Book listing. No manual setup or repo variables needed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reuses the org-owned npm name (superseding the 0.1.x interactive CLI) with a major bump for the breaking rewrite; bin stays `yuque`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ional deps Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…bindings breaks npm ci Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
改为独立仓库开发,本 PR 不再需要:新实现已迁移至 https://github.com/yuque/cli(npm 包名 @yuque/cli)。原仓库保持不变。 |
概要
将本仓库整体替换为一套规格驱动的语雀命令行工具(与 yuque-mcp-server 同一套工程约定),完全覆盖原有的交互式 JS 实现。命令面以 vendored 的官方 OpenAPI 3.1 规格(
spec/yuque-openapi.yaml,38 个 operation)为唯一事实源,由契约测试逐行钉死。内容
owner/slug(id/namespace 两组路径变体折叠为同一命令)YUQUE_TOKEN/--token(flag 优先,兼容YUQUE_PERSONAL_TOKEN);YUQUE_HOST支持空间与私有化部署--json全量输出、--all自动翻页、429 自动退避;破坏性命令需交互确认或--yestests/spec-coverage.test.ts钉死 operationId→method+path→命令 映射;双语 README 由tests/docs/command-surface-docs.test.ts锁定(数量标题 + 边界匹配 + 反向锁)npm run check(lint+format+typecheck+test+build+dist smoke)为合并门槛,CI 已配置(Node 20/22)兼容性说明
@yuque/cli、版本 0.1.0。npm 上yuque-cli(0.1.1,binyuque)即本仓库旧实现发布的包——若沿用该包名发布可改回yuque-cli并升 major,建议合并后另行决策🤖 Generated with Claude Code