Skip to content

Extract generic CRUD runners (~2,000 lines of boilerplate) #141

Description

@yorkable

The same 5-verb CRUD pattern is hand-copied across ~20 resources. Measured across cmd/*.go (tests excluded):

  • {Items, TotalCount} list unmarshal: 20×; search-query builder: 20×; page/limit flag block: 25×; Total: %d footer: 25×.
  • Get []string{"FIELD","VALUE"} table: 20×.
  • Create/update file-read block ("reading file"/"parsing JSON file"): 58×.
  • "use --file to provide update body": 21×; delete pattern: 20×; getOutputFmt()=="json" guard: 50×.

cmd/services.go, cmd/data_sources.go, cmd/voice_groups.go are ≥90% identical modulo path/columns. A plain CRUD resource costs ~220 lines today.

Proposal — small shared runner file (cmd/runners.go, ~120-150 lines), NOT codegen. Go 1.21 generics keep typed structs at the call site:

func readJSONBody(file string) (interface{}, error)
func runList[T any](path string, page, limit int, search, searchField string, headers []string, row func(T) []string) error
func runGet[T any](path string, rows func(T) [][]string) error
func runDelete(path, label, id string) error
func runUpdateByBody(path, idKey, id string, numeric bool, file string) error
func runUpdateByURL(path, file string) error

What varies (columns, json.Number handling, truncation widths, key type id/name/email, two update-routing styles) lives in the closures/params. Special verbs (tools get ID-fallback, voice-groups sample, outbound upload, sessions audio, insights activate) stay hand-written.

Saves ~1,700-2,000 net lines (15-20% of non-test cmd/). Risk low-medium: behavior is pinned by the 2.7k-line stub suite (method/path/body per command); migrate 2-3 files per PR, old/new coexist. Important: the spec-sync skill templates new resources by copying an existing cmd file — update .claude/skills/syllable-sync/SKILL.md and AGENTS.md in the same PR that converts the first file. Effort: M (spread over PRs).

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Latent bug or notable frictionepic:architectureEpic — maintainability, duplication, dependencies

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions