Hof Schemas are CUE definitions and serve as the contract between
you, the generator writer, and your users.
Your schemas capture the essence of the problem,
set the constraints for users designing with your generator,
and are the input to your code generation templates.
A minimal schema
packageschema#MySchema: {// anything you want}
A Minimal REST Schema
Let’s start by sketching out the minimal definition for a server.
We put this in the schema/ directory and thus CUE package.
schema/server.cue
packageschema#Server: {// Most schemas have a name field Name: string// Some more common "optional" fields// we use defaults rather than CUE optional syntax Description: string|*"" Help: string|*""}
Note how we use default values for “optional” fields in our generator UX,
rather than CUE optional syntax.
This avoids some nil-ness checks and conversions
and make template writing easier.
Routes and Handlers
Routes are a main focal point of REST servers.
When we generate the code, we will need handlers for each.
Here is the schema for a Route that will have a handler generated.
schema/server.cue
#HttpMethod: "OPTIONS"|"HEAD"|"GET"|"POST"|"PATCH"|"PUT"|"DELETE"|"CONNECT"|"TRACE"#Server: {// ... Routes: #Routes}#Routes: [...#Route] |*[]#Route: { Name: string Path: string Method: #HttpMethod// Route and Query params Params: [...string] |*[] Query: [...string] |*[]// Fields which allow the user to write// handler bodies directly in CUE Body?: string Imports: [...string] |*[]// Allows subroutes for routes Routes: [...#Route]}
Extra Features
These are features you may want to provide to your server users.
While the user only has to set a boolean or flag,
they can get advanced capabilities which are the consistent
for every generated server.
schema/server.cue
#Server: {// ...// list of file globs to be embedded into the server when built EmbedGlobs: [...string]// enable prometheus metrics Prometheus: bool}
Calculated Fields
These are fields and values you can infer from a user’s input that they do not need to set.
They are often for making template writing easier
by formatting or collecting values.
schema/server.cue
import"strings"#Server: {// ...// various casings of the resource Name serverName: strings.ToCamel(Name) ServerName: strings.ToTitle(Name) SERVER_NAME: strings.ToUpper(Name)}
Language Fields
There are typically language specifics which may need to be configured.
You will likely need to make some accessible to your users.
schema/server.cue
#Server: {// ...// We need to know the module name for Go GoModule: string}
Final Schema
Final Schema
schema/server.cue
packageschemaimport"strings"#HttpMethod: "OPTIONS"|"HEAD"|"GET"|"POST"|"PATCH"|"PUT"|"DELETE"|"CONNECT"|"TRACE"#Server: {// Most schemas have a name field Name: string// Some more common "optional" fields// we use defaults rather than CUE optional syntax Description: string|*"" Help: string|*""// language fields GoModule: string// The server routes Routes: #Routes// list of file globs to be embedded into the server when built EmbedGlobs: [...string]// enable prometheus metrics Prometheus: bool// various casings of the server Name serverName: strings.ToCamel(Name) ServerName: strings.ToTitle(Name) SERVER_NAME: strings.ToUpper(Name)}#Routes: [...#Route] |*[]#Route: { Name: string Path: string Method: #HttpMethod// Route and Query params Params: [...string] |*[] Query: [...string] |*[]// Fields which allow the user to write// handler bodies directly in CUE Body?: string Imports: [...string] |*[]// Allows subroutes for routes Routes: [...#Route]}