Files
go-onlyoffice/AGENTS.md
T
eSlider 4eb14c082c feat(cli)!: subject-based command tree (tea-style) + global --output flag
BREAKING:
- Flat oo verb-noun layout replaced with subject → verb, mirroring the
  gitea `tea` CLI. Every subject is one file in cmd/oo/:

    oo calendar       list | events | add | delete
    oo projects       list | get | milestones | create | update | delete
    oo tasks          list | get | create | update | delete | subtask add
    oo users          list | self                  (alias: oo whoami)
    oo contacts       list | get | delete | info-add
    oo persons        list | create | delete
    oo companies      list | create | delete
    oo opportunities  list | get | create | delete | stages | member-add
    oo cases          list | create | delete | member-add
    oo crm-tasks      list | create | delete | categories
    oo applications   sync

- Global `--output/-o table|json` flag on the root command; every list uses
  a single printTable helper that flattens nested bidCurrency → abbreviation
  for readability, truncates long cells, and dumps verbatim in JSON mode.

Library additions surfaced in the CLI:
- oo users / oo whoami via SelfUserID + GetUsers.
- oo projects full CRUD via Create/Update/Delete/GetProjectByID/Milestones.
- oo crm-tasks and oo cases via ListCRMTasks/CreateCRMTask/DeleteCRMTask/
  ListTaskCategories/ListCases/CreateCase/DeleteCase/AddCaseMember.
- oo contacts info-add via AddContactInfo.
- oo opportunities stages/member-add via ListDealStages/AddOpportunityMember.

Internal:
- cmd/oo/common.go — rootCmd, newOO (uses AuthenticateContext), printTable,
  printObject, fmtCell, deref* helpers.
- cmd/oo/crm.go deleted; content split into contacts.go, opportunities.go,
  cases.go, crm_tasks.go for locality.

Docs:
- README: new subject→verb table + migration note.
- AGENTS.md: CLI section rewritten; new rule enforcing subject→verb and
  printTable/printObject routing.
- CHANGELOG: 0.5.0 entry with full old→new mapping.

Made-with: Cursor
2026-04-24 14:55:43 +01:00

4.3 KiB

AGENTS — go-onlyoffice

Canonical Go client for OnlyOffice Workspace (Projects + Calendar + CRM) and the oo command.

Topology

  • Library — flat package onlyoffice at repo root. Split by domain file, not by subpackage, so every call site reads c.XxxYyy() against a single *Client. Files:
    • client.go — Client, Credentials, Defaults, env helpers, NewClient.
    • request.go — Request, Query, Time, Token, MetaResponse, Permissions.
    • auth.go — Authenticate, AuthenticateContext, InvalidateToken, Auth, token lifecycle.
    • http.go — transport + DRY response decoders (ResponseArray/ResponseObject/postFormObject/putFormObject/deleteObject).
    • projects.go, tasks.go, users.go, calendar.go, crm.go, files.go — typed / untyped domain methods.
    • Pure stdlib + google/go-querystring; no UI, no dotenv.
  • CLI — cmd/oo/ as package main. Cobra wrapper that loads .env via godotenv at startup. Subject-based command tree mirroring tea:
    • main.go — entry point (docstring lists the command tree).
    • common.go — rootCmd, newOO, printTable/printObject, --output table|json flag.
    • calendar.go, projects.go, tasks.go, users.go, contacts.go, opportunities.go, cases.go, crm_tasks.go, apps.go — one file per subject, each registers its subject cobra.Command in init() and attaches verb subcommands (list/get/create/update/delete/…).
    • CLI-only deps (spf13/cobra, joho/godotenv) stay out of the library.
  • Applications sync — cmd/oo/applications/. README→CRM bridge, CV-specific; kept under cmd/oo/ so it's clear it's internal to the binary, not a library feature.

Rules

  • Library must never call godotenv.Load() — the CLI does that.
  • New endpoints go into the library first; CLI commands are thin wrappers.
  • Prefer ResponseObject / postFormObject / putFormObject / deleteObject over hand-rolled json.Unmarshal(responseField(...)) blocks — they exist for DRY, use them.
  • Domain split is by file, not by subpackage. Don't introduce internal/ or pkg/* subpackages inside the library — it flattens the *Client call surface for a reason.
  • CLI commands follow subject → verb structure (oo <subject> <verb>), never oo <verb>-<subject>. Add new commands to the existing subject file if one fits; create a new cmd/oo/<subject>.go for a genuinely new domain.
  • Every table output goes through printTable(headers, rows); every single-object through printObject(v). Do not fmt.Println rows ad-hoc or the --output json flag breaks for that command.
  • No secrets in the repo; use .env (gitignored). Commit .env.example only.
  • Follow SemVer on tags; this repo is tagged at GitHub under git@github.com:eSlider/go-onlyoffice.git.

Testing policy (2026-04-24)

No synthetic OnlyOffice mockups. Protocol-level behaviour must be verified against a real OnlyOffice instance. httptest.NewServer is only acceptable for testing the caller's logic that the library can't reach (for example, the user's own HTTP handler). Anywhere we would otherwise write mux.HandleFunc("/api/2.0/...") to emulate OnlyOffice, we write an integration test instead.

  • Unit tests (*_test.go, no build tag) — pure Go: parsers, encoders, struct conversions. No network. No fake servers that emulate the vendor.
  • Integration tests (//go:build integration tag in *_integration_test.go) — hit a live OnlyOffice instance. Credentials come from ONLYOFFICE_URL, ONLYOFFICE_USER, ONLYOFFICE_PASS (aliases _HOST/_NAME/_PASSWORD also accepted). Tests skip cleanly when credentials are missing so go test ./... remains green in CI.
  • Run integration with: go test -tags=integration ./....
  • New endpoints must ship with an integration test before merge.