# anetos generate reference

Source: https://docs.anetos.dev/reference/anetos-generate/

`anetos generate` writes the typed columns of your models. It is part of the
`anetos` developer tool (module `anetos.dev/anetos/cli`). See
[Generate typed columns](https://docs.anetos.dev/guides/code-generation/index.md) for a walkthrough.

## Installing and running

| Command | Does |
|---|---|
| `go get -tool anetos.dev/anetos/cli/cmd/anetos@latest` | Adds the tool to your module's `go.mod` |
| `go tool anetos generate [packages]` | Generates for the packages (default `./...`, relative to the current directory) |
| `go tool anetos generate --check [packages]` | Writes nothing; exits with status 1 and lists the out-of-date files |
| `go tool anetos version` | Prints the tool's version |
| `//go:generate go tool anetos generate` | Runs it from `go generate ./...` |

Package patterns are the ones `go build` takes. Exit status: 0 on
success, 1 on errors (or out-of-date files with `--check`), 2 for bad
usage.

## Which structs are models

A named, non-generic struct type declared at package level (in a non-test
file) is a model when it:

| Rule | Example |
|---|---|
| Embeds `db.Model`, `db.Timestamps` or `db.SoftDeletes`, directly or through embedded structs | `type Post struct { db.Model; … }` |
| Has a `TableName() string` method (value or pointer receiver) | `func (Setting) TableName() string` |
| Has `//anetos:model` in its doc comment | a plain struct |

Models, and the structs of their package they embed, must be in files
without build constraints (no `//go:build` line, no `_linux.go`-style
name), so the generated file is the same on every platform. `//anetos:skip` in the doc comment excludes a struct. Any other
`//anetos:` directive is an error. Structs that scan themselves
(`sql.Scanner`, `driver.Valuer`, `time.Time`) are values, not models.

## What is generated

One file per package, `models_gen.go`, starting with
`// Code generated by anetos generate. DO NOT EDIT.` For each model `Name` in
source order:

```go
// illustrative
// NameCols are the columns of [Name].
var NameCols = struct {
	Field db.Column[FieldType]
	…
}{
	Field: db.Col[FieldType]("column"),
	…
}
```

| Field | Generated |
|---|---|
| `Title string` | `Title db.Column[string]`, column `title` |
| `AuthorID int64 \`db:"author"\`` | `AuthorID db.Column[int64]`, column `author` |
| `PublishedAt *time.Time` | `db.Column[*time.Time]` (compare with `new(t)`, set `NULL` with `nil`) |
| `Tags []string \`db:"tags,json"\`` | `db.Column[[]string]` made with `db.JSONCol` |
| Fields of embedded structs (`db.Model`: `ID`, `CreatedAt`, `UpdatedAt`) | Flattened in place, like the runtime |
| `Author *User \`rel:"belongs_to"\``, `Comments []Comment \`rel:"has_many"\`` | A relation handle in `PostRels`: `Author db.Rel[Post, User]`, made with `db.RelOf[Post, User]("Author")` |
| Untagged struct, pointer-to-struct and slice-of-struct fields | Nothing |
| `db:"-"` and unexported fields | Nothing |

The column rules are the `db` package's
([models reference](https://docs.anetos.dev/reference/models/index.md)). The generated names are the struct
field names; an unexported model `post` gets `postCols`. Imports get
another name (`time2`) when the package already declares that name in
any of its files (in-package tests and other platforms' files included).

## Files it manages

- It only overwrites or removes a `models_gen.go` that starts with its
  header (Unix or Windows line endings); any other file with that name is
  an error, even one excluded from the build.
- It removes `models_gen.go` from a package with no models left.
- It ignores the current `models_gen.go` while reading the package, and
  compile errors outside model fields (such as code using a column not
  generated yet). Syntax errors, and type errors in a model's fields,
  stop it.
- Packages are only type-checked when they import the `db` package
  (directly or not), mention `TableName` or a `//anetos:` directive, or
  already have a `models_gen.go`.

## Errors

| Message | Meaning |
|---|---|
| `two fields map to column "x"` | Two fields have the same column name |
| `unknown db tag option "x" (known: pk, json, readonly)` | A typo in a `db` tag |
| `more than one pk field` | Composite keys aren't supported by models |
| `columns "a" and "b" both come from fields named X` | Two fields (one embedded) share a Go name; rename one |
| `XCols is already declared`, `XRels is already declared` | The package declares a name anetos generate needs |
| `unknown relation "x"`, `bad has_many option "x"` | A typo in a `rel` tag |
| `a has_many relation is a slice of models`, `… a pointer to a model` | The field's type doesn't fit the relation kind |
| `field X has a db tag and a rel tag` | A field is a column or a relation, not both |
| `field X has …, which package … can't name` | An embedded struct from another package has a field of an unexported type, a type from an `internal` package yours can't import, or an anonymous struct with unexported fields; tag it `db:"-"` or change the embedded struct |
| `models in files with build constraints aren't supported`, `embeds X, declared in a file with build constraints` | The model, or a struct of the package it embeds, is in a `_linux.go`-style file or one with a `//go:build` line: the generated file would differ per platform |
| `embeds itself` | A struct embeds itself through a pointer |
| `generic types and aliases can't be models` | `//anetos:model` on a generic type or alias |
| `is marked //anetos:model but is not a model struct` | The type isn't a struct, or scans itself |
| `models_gen.go was not written by anetos generate` | Rename your file |
