Skip to Content

gofasta g field

Adds a single column to an existing resource — patches the model struct, the DTOs (Create / Update / Response), and emits a paired .up.sql / .down.sql migration in one command. The DTO patches are opt-out via flags so you can keep a column out of CreateRequest (server-set) or out of the Response (write-only).

Uses dst  for AST patching, so comments, tag ordering, and import grouping are preserved.

Usage

gofasta g field <Resource> <name>:<type> [flags]

The resource must already exist (see gofasta g scaffold). The field is given in the same name:type shorthand the scaffold accepts.

Flags

FlagDefaultDescription
--no-dtofalseSkip every DTO patch — only the model + migration are updated.
--no-createfalseSkip the CreateRequest DTO patch (use for server-set fields like archived_at).
--no-updatefalseSkip the UpdateRequest DTO patch (use for immutable fields like created_by).
--no-responsefalseSkip the Response DTO patch (use for write-only fields like password_hash).
--dry-runfalsePreview the patches + migration without writing. Honors --json for a structured plan.

Supported types

Same set as g scaffold — see Field Types. The SQL type is driver-aware: string → VARCHAR(255) on Postgres / VARCHAR(255) on MySQL / TEXT on SQLite / NVARCHAR(255) on SQL Server / String on ClickHouse. Picked from database.driver in config.yaml.

Examples

Add an archive_reason text column with full DTO coverage:

gofasta g field Order archive_reason:string

Result:

  • app/models/order.model.go — appends ArchiveReason string \gorm:“not null”“
  • app/dtos/order.dtos.go — appends ArchiveReason string \json:“archive_reason”`toOrderCreateRequest, OrderUpdateRequest, OrderResponse`
  • db/migrations/NNNNNN_add_archive_reason_to_orders.up.sql — ALTER TABLE orders ADD COLUMN archive_reason VARCHAR(255);
  • db/migrations/NNNNNN_add_archive_reason_to_orders.down.sql — ALTER TABLE orders DROP COLUMN archive_reason;

Add a write-only password_hash field (omit from responses):

gofasta g field User password_hash:string --no-response

Add a server-set archived_at timestamp (omit from Create + Update):

gofasta g field Order archived_at:time --no-create --no-update

Model-only column (no DTO changes at all):

gofasta g field Order internal_notes:text --no-dto

Preview without writing:

gofasta g field Order shipped_at:time --dry-run

What it patches

FileChange
app/models/<snake>.model.goAppends the field to the <Resource> struct with the appropriate GORM tag. Adds time / github.com/google/uuid imports when the field type needs them.
app/dtos/<snake>.dtos.goAppends the field (with json:"..." tag, no GORM tag) to <Resource>CreateRequest, <Resource>UpdateRequest, and <Resource>Response — minus any opt-outs. Missing variants (e.g. you don’t have an UpdateRequest) are silently skipped.
db/migrations/NNNNNN_add_<field>_to_<plural>.up.sqlALTER TABLE <plural> ADD COLUMN <field> <sql-type>;
db/migrations/NNNNNN_add_<field>_to_<plural>.down.sqlALTER TABLE <plural> DROP COLUMN <field>;

NNNNNN is the next available 6-digit migration version.

Naming conventions

Field inputGo field nameJSON tagSQL column
archive_reason:stringArchiveReasonarchive_reasonarchive_reason
userID:uuidUserIDuserIDuser_id
is_active:boolIsActiveis_activeis_active

The PascalCase / camelCase / snake_case conversions are deterministic — same rules as the scaffold.

Idempotency

If the model struct already has the field, the command returns FIELD_ALREADY_EXISTS without touching anything. The DTOs and migrations are not checked the same way — but the migration filename includes a fresh version prefix, so re-running creates a duplicate migration rather than overwriting.

Error codes

CodeWhen
RESOURCE_NOT_FOUNDThe model file is missing. Run gofasta g scaffold <Resource> first.
FIELD_ALREADY_EXISTSThe model struct already has a field by that name. Pick a different name or remove the existing field first.
AST_PARSE_FAILEDThe model or DTO file has a syntax error.
Last updated on