Skip to main content

Go Quick Start

This path takes one TeaQL model to a generated Go module and prepares a small SQLite-backed application. Keep handwritten application code outside the generated module so regeneration remains routine.

Current runtime: github.com/teaql/teaql-golang v0.1.0. The version is published as a GitHub tag and is available through the standard Go module proxy. Generated projects pin this version and no longer require a sibling runtime checkout or a local replace directive.

1. Prepare the workspace

Use this layout:

teaql-go-quick-start/
├── model/main.xml
├── generated/go-lib/
└── app/

Install Go 1.18 or newer, SQLite development headers, and the TeaQL generation client. Discover the exact Go target name from the live catalog rather than relying on an old document:

cargo teaql services
cargo teaql evaluate --input model/main.xml
# Generate with the Go library target returned by `services`.

The runtime can also be added directly to an existing Go module:

go get github.com/teaql/teaql-golang@v0.1.0
go list -m github.com/teaql/teaql-golang

Expected module version:

github.com/teaql/teaql-golang v0.1.0

Generated code imports subpackages such as core, runtime, and the selected provider/postgres, provider/mysql, or provider/sqlite package from this one module.

2. Create a small model

Create model/main.xml:

<?xml version="1.0" encoding="UTF-8"?>
<root name="order-review" org="example" data_service="sqlite" version="1.0.0">
<customer_order
order_number="WEB-10001"
_module_key="root" />
</root>

Evaluate before generation. If evaluation prints a Markdown report, fix the first model error and rerun it. Do not patch generated Go files.

3. Generate and inspect

Generate into generated/go-lib. Then inspect the actual package rather than translating names from another language:

find generated/go-lib -maxdepth 2 -type f | sort
rg 'func \(.*Request\)|func \(.*Entity\)' generated/go-lib
rg 'func \(.*Purpose|ExecuteForList|AuditAs|Save' generated/go-lib
go test ./...

The generated module normally contains q.go, e.go, runtime.go, lib.go, and one package per entity with request.go, entity.go, expression.go, behavior, and checker hooks. The generated go.mod is the authority for dependency versions; it should contain:

require github.com/teaql/teaql-golang v0.1.0

A generated production module must not contain a replace pointing at ../../teaql-golang. A local replace may be added temporarily by runtime developers, but it must not be committed as the normal installation path.

Never form plurals by adding s or es. Read q.go. Human predicates and non-human predicates are also different generated contracts; do not replace WhoAre/Whose with WhichAre/With, or the reverse.

4. Assemble trusted context

Provider, identity, tenant, permissions, request policy, and audit sinks belong in UserContext initialization. Application input must not supply them.

// Illustrative assembly: use the exact constructors emitted by the released
// generated module and runtime package.
ctx := runtime.NewUserContext()
ctx.InsertResource("dataService", dataService)
ctx.InsertResource("tenantId", trustedTenantID)
ctx.InsertResource("actorId", authenticatedActorID)

Read generated runtime.go and the released runtime documentation for the exact resource registration API. Do not add a second data-service argument to query execution: the only execution argument is *runtime.UserContext.

5. Write the first query

Once generated names have been inspected, application code follows this shape:

orders, err := lib.Q.CustomerOrders().
Comment("Find web orders").
WithOrderNumberContaining("WEB-").
OrderByIdAsc().
Limit(20).
Purpose("Display the authorized order list").
ExecuteForList(ctx)
if err != nil {
return err
}

Comment may appear anywhere before Purpose; it does not need to be adjacent. Purpose is the type-state transition that exposes execution. A non-executable Request must not expose ExecuteForList.

6. Make an audited mutation

Read the generated entity source for update method names:

order := lib.Q.CustomerOrders().
Comment("Create the first verified order").
Purpose("Persist an authorized order").
NewEntity(ctx)

order.UpdateOrderNumber("WEB-10002")
err = order.AuditAs("Create the first verified order").Save(ctx)

Saving without AuditAs must fail. Querying without purpose, comment, or initialized context must also fail rather than widening or silently degrading the operation.

7. Regenerate safely

Change the model, evaluate, regenerate the whole generated directory, and rerun the checks. Review q.go, Request, Entity, expression, go.mod, and provider wiring. Keep custom code in app/ or in documented behavior/checker extension files.

Continue with First Verification, then Go Customization.