with one click
refactoring
Refactor existing packages toward the standard service/adapter pattern. Use when restructuring a domain package, splitting a monolithic package, or removing anti-patterns.
Menu
Refactor existing packages toward the standard service/adapter pattern. Use when restructuring a domain package, splitting a monolithic package, or removing anti-patterns.
Work with Ent ORM schemas and generated code. Use when modifying ent schemas, debugging ent query issues, or dealing with Postgres type mappings.
Write tests for OpenMeter services following project conventions. Use when creating unit tests, integration tests, or service tests.
Work with the subscription sync bridge in `openmeter/billing/worker/subscriptionsync/...`. Use when modifying how subscription target state is reconciled into billing artifacts such as invoice lines, split-line groups, or charges; when changing persisted-state loading, reconciler patch routing, or subscription sync tests; and when reasoning about the bridge between subscription views and billing state.
Use when writing or refactoring Go code in OpenMeter that can use github.com/samber/lo helpers, especially trivial slice-to-map, map keys/values, mapping, filtering, grouping, uniqueness, set-like conversions, and map entry transformations.
Work with OpenMeter billing charges, including the root charges facade, charge meta queries, charge creation and advancement, usage-based lifecycle state machines, realization runs, and charges test setup. Use when modifying `openmeter/billing/charges/...` or charge-related tests.
Work with the OpenMeter ledger package. Use when modifying ledger code, writing ledger tests, or debugging ledger issues.
| name | refactoring |
| description | Refactor existing packages toward the standard service/adapter pattern. Use when restructuring a domain package, splitting a monolithic package, or removing anti-patterns. |
| user-invocable | true |
| argument-hint | [package to refactor or description of refactoring] |
| allowed-tools | Read, Edit, Write, Bash, Grep, Glob, Agent |
You are helping the user refactor existing openmeter/ packages toward the standard service/adapter pattern described in the /service skill.
See the /service skill for the full target pattern. In summary, every feature package should have:
openmeter/<domain>/
├── service.go # Service interface definition
├── adapter.go # Adapter interface definition
├── <domain>.go # Domain types and models
├── errors.go # Custom errors (optional, only when needed)
├── event.go # Domain events (optional, for packages that modify DB entities)
├── adapter/ # Adapter layer implementation (data access)
│ ├── adapter.go # Config, New(), transaction boilerplate
│ ├── <operation>.go # One file per operation (list.go, get.go, create.go, etc.)
│ └── mapping.go # Entity ↔ domain type mapping functions
├── service/ # Service layer implementation (business logic + orchestration)
│ └── service.go
├── driver/ # v1 API, do not implement for new services (also called: httpdriver, driver)
│ └── <operation>.go
Key rules:
Complex domain packages with non-standard structure:
| Package | Issues |
|---|---|
subscription | 30+ files in root, logic spread across root (apply, billing, context, locks, patch), specialized subdirs (addon/, entitlement/, hooks/, patch/) |
productcatalog | 20+ files in root, multiple entity types mixed together (addon, plan, feature, discount, entitlement), inconsistent subdir naming (driver/ vs adapter/) |
billing | 20+ files in root (invoice, customer, discount, app), complex domain mixed into single package |
app | Heavy root (app, appbase, customer, marketplace, webhook, registry, input), multiple impl subdirs (stripe/, sandbox/, custominvoicing/) |
credit | Domain split across balance/, grant/, engine/ subdirs with connector pattern in root |
entitlement | Has adapter/service but also boolean/, metered/, static/, snapshot/, balanceworker/, hooks/ — uses connector pattern |
notification | Has adapter/service but also consumer/, eventhandler/, internal/ — non-standard extensions |
Partially compliant or minor structural issues:
| Package | Issues |
|---|---|
ingest | Non-standard adapter naming (ingestadapter/), mixed patterns (kafkaingest/, inmemory in root) |
streaming | Uses connector pattern, clickhouse/ impl dir, no service/adapter split |
sink | No service/adapter pattern, utility-focused with flushhandler/, models/ |
These are infrastructure, utility, or minimal packages where the pattern may not apply:
ent, watermill, dedupe, server, namespace, registry, event, apiconverter, testutils, debug, session, info
When refactoring a package toward the standard pattern:
Analyze current structure: Read the package to understand all files, types, and dependencies. Map out which code is domain types, which is business logic, and which is data access.
Identify entity boundaries: If the package mixes multiple independent entities (e.g., productcatalog has plan, addon, feature), consider splitting into separate packages first.
Extract root interfaces: Move all types, interfaces, input DTOs, and errors to the root package. Remove any implementation code from root.
Create adapter/: Move all database queries, entity mapping, and Ent ORM code into adapter/. Ensure it only does data access — no business decisions.
Create service/: Move all business logic, orchestration, and transaction wrapping into service/. This includes validation beyond simple input checks, precondition enforcement, multi-step operations, and event publishing.
Remove anti-patterns: Eliminate connectors, deep nesting, scattered types. Replace global state with constructor injection.
Update wiring: Update app/common/<domain>.go and cmd/*/wire.go to match new constructor signatures. Run make generate.
Update imports: Fix all imports across the codebase that reference moved types or functions.
Run tests: make test to verify nothing is broken.
grep to find all import paths.make generate to update wire_gen.go files.