Generators specify the mapping from inputs to templates.
They will have input schema(s) and some configuration options for users,
and map the In field to the Out field for hof to process.
Generator Schema
HofGenerators and Files have their own schemas.
Only the core fields are shown here.
You can find the real schemas in the hof repository.
Generator Schemas
// Definition for a generator#Generator: {// Base directory for the output Outdir: string|*"./"// "Global" input, merged with In per file before generating output In: {...} |*{...}// you may also supply additional user config// often you will construct "In" from// more meaningful fields presented to the user// The list fo files for hof to generate// Out: [...#File] | *[...] Out: [...#File] |*[]// Template (top-level) TemplateConfig (globs+config) Templates: [...#Templates] |*[#Templates & {Globs: ["./templates/**/*"], TrimPrefix: "./templates/"}]// Partial (nested) TemplateConfig (globs+config) Partials: [...#Templates] |*[#Templates & {Globs: ["./partials/**/*"], TrimPrefix: "./partials/"}]// Statics are copied directly into the output, bypassing the rendering Statics: [...#Statics] |*[#Statics & {Globs: ["./static/**/*"], TrimPrefix: "./static/"}]// ... other fields for generator writers}// A file which should be generated by hof#File: {// The local input data, defaults to the generator In fields In: {...}// The full path under the output location// empty implies don't generate, even though it may endup in the list Filepath: string|*""// One of the following should be set// The template contents TemplateContent: string|*""// Path for the loaded templates TemplatePath: string|*""// ... advanced template configuration}
Mapping In to Out
Your goal as a generator writer is to fill in the Out field from the In field.
The In field will be passed through the templates and partials
if they are defined in the Out list.
In represents the data presented to the templates.
You can have your users set values in meaningful fields and collect them
You can add any other separate or calculated data
The top-level In is passed to all templates and can be extended with the per-template field
Out holds the files to be rendered by hof
Is a list of HofGeneratorFiles, where each…
Has a filepath for where it will be written under Outdir
Has an In value which will be unified with the top-level
There are typically two types of files (templates)
Files which are generated once per application. Think of a main.go or index.js. We often call these “once” files or templates.
Files which are generated for each sub-resource. These might be routes in a server or commands in a CLI. We often call these “repeated” files or templates.
You can use as many helper fields or calculations as you want
Calculate commonly used fields or values for In
Interpolate common base paths for filepaths
Create file lists for repeated templates.
Server Generator
gen/server.cue
packagegenimport ("github.com/hofstadter-io/hof/schema/gen""hof.io/docs/example/schema")// Generator definition#Generator: gen.#Generator & {// User inputs to this generator// -----------------------------// The server design conforming to the server schema Server: schema.#Server// Base output directory, defaults to current Outdir: string|*"./"// Required fields for hof// ------------------------// In is passed to every template In: { SERVER: Server }// Actual files generated by hof, combined into a single list Out: [...gen.#File] & _All _All: [ for _, F in _OnceFiles {F}, for _, F in _RouteFiles {F}, ]// Note, we can omit Templates, Partials, and Statics// since the default values are sufficient for us// Internal fields for mapping Input to templates// ----------------------------------------------// Files that are generated once per server _OnceFiles: [...gen.#File] & [ { TemplatePath: "go.mod" Filepath: "go.mod" }, { TemplatePath: "server.go" Filepath: "server.go" }, { TemplatePath: "router.go" Filepath: "router.go" }, { TemplatePath: "middleware.go" Filepath: "middleware.go" }, ]// Routes, we create a file per route in the Server _RouteFiles: [...gen.#File] & [ for _, R in Server.Routes { In: { ROUTE: { R } } TemplatePath: "route.go" Filepath: "routes/\(In.ROUTE.Name).go" }, ]// We'll see how to handle nested or sub-routes in the "full-example" section ...}