Code generation (TypeScript types, GraphQL SDL, Gleam types + resolver stubs) and CLI for mochi GraphQL.
gleam add mochi_codegengleam run -m mochi_codegen/cli -- init # create mochi.config.yaml
gleam run -m mochi_codegen/cli -- generate # generate from configschema: "graphql/*.graphql"
# Optional: generate resolver boilerplate from .gql client operation files
operations_input: "src/graphql/**/*.gql"
output:
typescript: "src/generated/types.ts" # TypeScript type definitions
gleam_types: "src/api/domain/" # Gleam domain types (dir = one file per schema)
resolvers: "src/api/schema/" # Gleam resolver stubs (preserved on regen)
operations: "src/api/schema/" # Gleam operation resolvers (from .gql files)
sdl: null # Normalised SDL (omit to skip)
gleam:
types_module_prefix: "api/domain"
resolvers_module_prefix: "api/schema"
type_suffix: "_types"
resolver_suffix: "_resolvers"
generate_docs: trueOutput paths ending in / produce one file per schema file. Paths without / merge all schemas into a single file.
| Output | Policy |
|---|---|
typescript, sdl |
Always overwrite |
gleam_types |
Overwrite only when content changed |
resolvers, operations |
Never overwrite existing functions — only appends new stubs |
- Unknown operation fields fail the build. If an
operations_input.gqlfile references a root field that doesn't exist in the schema,generateexits withUnknownOperationFieldslisting the offending fields. The emitted Gleam (if you force generation some other way) contains a<MISSING:field_name>sentinel rather than a genericTODO, so it's greppable. - Argument defaults round-trip in SDL. Scalar defaults (
Bool,Int,Float,String) are rendered insdloutput. Complex defaults (lists, objects, enums) are omitted rather than emitted as broken syntax —mochi/schemastores them as type-erasedOption(Dynamic)which isn't reversible for non-scalars. - TypeScript enum values are identifier-checked. Values that don't match
[_A-Za-z][_0-9A-Za-z]*(which GraphQL itself forbids, but custom schema builders can bypass) are replaced with a// Skipped: ...comment rather than a brokenenummember. Grep the output for// Skipped:to find them. - Playground endpoints are escaped.
graphiql,playground,apollo_sandbox, andsimple_explorerall escape the endpoint URL before interpolating it into inline JS / HTML. Callers can pass any string without worrying about breaking the generated page. - Unmapped type-builder fields surface in the CLI output. Resolver generation emits
// TODO: register field "<name>"for types the generator can't map (uncommon custom scalars, unsupported non-null list shapes). The CLI success line is decorated with the count — e.g.Generated resolvers (3 unmapped fields — see TODO comments): src/generated/schema_resolvers.gleam— so these don't silently accumulate across regenerations.
import mochi_codegen
let ts = mochi_codegen.to_typescript(schema)
let sdl = mochi_codegen.to_sdl(schema)
let html = mochi_codegen.graphiql("/graphql")Apache-2.0