Go Helper Conventions

Helper vs. Generated Files

Every construct’s Go package has two kinds of files:

File Editable? Purpose
<construct>.go No — auto-generated Struct definitions from schema
<construct>_helper.go Yes — manual SQL drivers, interfaces, table names

Helper files must include this comment at the top:

// This is not autogenerated.

What Goes in a Helper File

1. TableName() Method

Returns the database table name for GORM/Pop:

func (c *Connection) TableName() string {
    return "connections"
}

2. SQL Driver Methods (Scan/Value)

For types stored as JSON blobs in a single DB column, implement sql.Scanner and driver.Valuer.

Value() — always marshal, never return SQL NULL:

// CORRECT — matches core.Map pattern
func (m MetadataMap) Value() (driver.Value, error) {
    b, err := json.Marshal(m)
    if err != nil {
        return nil, err
    }
    return string(b), nil
}
Do not return (nil, nil) from Value() This writes SQL NULL, which is inconsistent with core.Map behavior. Always marshal — even a nil value produces the JSON string "null".

Scan() — zero the receiver on nil src:

func (m *MetadataMap) Scan(src interface{}) error {
    switch v := src.(type) {
    case []byte:
        return json.Unmarshal(v, m)
    case string:
        return json.Unmarshal([]byte(v), m)
    case nil:
        *m = nil    // ← Zero the receiver to avoid stale data
        return nil
    default:
        return fmt.Errorf("unsupported type: %T", src)
    }
}

3. Entity Interface Implementation

If the construct participates in Meshery’s entity system:

func (c *Connection) GetID() core.Uuid {
    return c.Id
}

func (c *Connection) GetEntityType() string {
    return "connection"
}

x-generate-db-helpers: true

For types stored as JSON blobs that have a dedicated schema definition, use the x-generate-db-helpers annotation at the schema component level (not per-property):

# In api.yml
components:
  schemas:
    ConnectionMetadata:
      x-generate-db-helpers: true
      type: object
      properties:
        version:
          type: string

This auto-generates Scan()/Value() methods, so you don’t need to write them manually.

When NOT to use x-generate-db-helpers
  • Types mapped to full DB tables (they use ORM, not JSON blob storage)
  • Amorphous types without a fixed schema — use x-go-type: "core.Map" instead
  • On individual properties — annotation must be at the component level

x-go-type and x-go-type-import

Override the generated Go type for a schema property:

metadata:
  x-go-type: "core.Map"
  x-go-type-import:
    path: "github.com/meshery/schemas/models/core"
    alias: core

All core type imports must use models/core with alias core. Do not reference models/v1alpha1/core.

Checklist for New Helpers

  • File starts with // This is not autogenerated.
  • TableName() returns the correct plural snake_case table name
  • Value() always marshals — never returns (nil, nil)
  • Scan() zeros the receiver (*m = nil) when src is nil
  • No hand-editing of the companion generated .go file