moonbitstack/moonctl/scaffold does not have a README file

    Regen

    pub(all) enum Regen {
    Always
    Once
    } derive(Eq)

    Whether a regeneration may replace a file that is already on disk. Always is for what moonctl owns — the routes and the types, which must follow the spec — and Once for what it only seeds: handlers, logic, configuration, manifests.

    Regen::equal

    fn Regen::equal(Regen, Regen) -> Bool

    Regen::not_equal

    fn Regen::not_equal(x : Regen, y : Regen) -> Bool

    TreeFile

    pub(all) struct TreeFile {
    path : String
    content : String
    regen : Regen
    }

    One file of a generated project tree: where it goes, what is in it, and whether regenerating the tree is allowed to overwrite it.

    generate_gql_tree

    fn generate_gql_tree(spec :
    Spec
    , style? :
    Style
    , dir? : String) -> Array[TreeFile]

    The layered GraphQL tree for spec under dir: internal/schema with the annotated types and root fields (seeded once — the resolvers are yours to write), the rule that regenerates the schema from them, internal/config and the entry point serving it on 12000.

    Hand the result to tree_plan to keep what the author has filled in.

    generate_mcp_from_spec

    fn generate_mcp_from_spec(spec :
    Spec
    , style? :
    Style
    , dir? : String) -> Array[TreeFile]

    The MCP server tree for the service spec describes: the same module, packages and build rule as generate_mcp_tree, with the spec's routes as its tools.

    generate_mcp_tree

    fn generate_mcp_tree(module_ : String, style? :
    Style
    , dir? : String, tools? : String, registration? : String, checks? : String) -> Array[TreeFile]

    The MCP server tree for module module_ under dir: the shared module, configuration and context, internal/tools with the annotated functions, their generated registration and a test, and the build rule that keeps the registration in step with the functions.

    generate_orm_tree

    fn generate_orm_tree(spec :
    Spec
    , style? :
    Style
    , dir? : String) -> Array[TreeFile]

    The annotated models and migrations for spec: every type block is a table, its id field (when it has one) the primary key, and a field with no single column — a slice, a map, a nested type — is skipped rather than stored.

    generate_orm_tree_from_ddl

    fn generate_orm_tree_from_ddl(tables : Array[
    DdlTable
    ], module_ : String, style? :
    Style
    , dir? : String) -> Array[TreeFile]

    The annotated models, migrations and CRUD helpers for a SQL schema. The table and column names are the schema's; a nullable column is declared optional, so #orm reads it as one.

    generate_rpc_tree

    fn generate_rpc_tree(proto :
    Proto
    , style? :
    Style
    , dir? : String) -> Array[TreeFile]

    The layered gRPC tree goctl writes for a .proto, in MoonBit, under dir: pb/ with the messages, codecs and handler tables (rewritten on every run), internal/logic with one function per RPC and internal/config/internal/svc (seeded once), internal/server wiring the logic into each service, client/ with a typed client per service, and the entry point serving it all on 12000.

    Hand the result to tree_plan to keep what the author has filled in.

    generate_tree

    fn generate_tree(spec :
    Spec
    , style? :
    Style
    , dir? : String) -> Array[TreeFile]

    Generate the layered project tree goctl writes, in MoonBit: the service entry point and its moon.mod, etc/<service>.yaml, internal/config, internal/svc, internal/types, internal/handler (the generated routes plus a stub per handler, under internal/handler/<group>/ for a grouped route), internal/logic, internal/middleware for every middleware an @server block named, and a moon.pkg for each of those packages.

    style (default gozero) names the files and the handler, logic and middleware entry points inside them. Names the spec itself chose — the type blocks and their fields — are left as written, since a MoonBit type name has to keep its capital. dir puts the whole tree under a directory.

    Each file says whether a regeneration may overwrite it; hand the result to tree_plan to apply that.

    generator_command

    fn generator_command(library : String, cmd : String) -> String

    The moonx command that runs one of a library's generators, for the rule(...) that wires it into moon.mod.

    gql_dropped_fields

    fn gql_dropped_fields(spec :
    Spec
    ) -> Array[String]

    The fields of a type block that GraphQL has no type for, as <type>.<field> (<type>), for the command to report.

    gql_expressible

    fn gql_expressible(ty : String) -> Bool

    Whether moongql has a GraphQL type for ty. A slice or an optional is that of its element; Bytes and Map have none, and a field of one of those keeps the generated ToGql impl from compiling, so it is dropped from the schema and reported instead.

    gql_schema_for

    fn gql_schema_for(spec :
    Spec
    ) -> String

    The seeded schema for spec: one annotated struct per type block, one root field per route.

    mcp_checks_for

    fn mcp_checks_for(spec :
    Spec
    ) -> String

    The test a spec-derived server is seeded with: every offered route registered as a tool, counted through tools/list.

    mcp_registration_for

    fn mcp_registration_for(spec :
    Spec
    ) -> String

    internal/tools/tools.g.mbt: what moonmcp regenerates from those functions, so a fresh project compiles before its first build.

    mcp_skipped

    fn mcp_skipped(spec :
    Spec
    ) -> Array[String]

    The routes a generated server does not offer, each as <verb> <path>: they declare no request type, so there is nothing for a tool to take.

    mcp_tools_for

    fn mcp_tools_for(spec :
    Spec
    ) -> String

    internal/tools/tools.mbt for spec: one annotated function per offered route.

    pins

    let pins : Map[String, String]

    The version of each library generated code imports.

    These are the versions this repository's CI scaffolds a project against and builds, so a generated project is promised to compile with them. A project that wants a later release edits its own moon.mod.

    port

    let port : Int

    The port a scaffolded service listens on.

    12000, the one every server in this family defaults to: HTTP, WebSocket and h2c share it because one listener tells them apart, so a generated manifest and a generated configuration name the same number without anyone saying which they meant.

    rule_line

    fn rule_line(name : String, command : String) -> String

    The rule(...) entry that wires a moonx generator into moon.mod, on one line when it fits in the width moon fmt breaks at and one argument per line when it does not — the two shapes the formatter leaves it in, so a generated moon.mod never changes on the first format.

    scaffold_api

    fn scaffold_api(name : String) -> Array[
    GenFile
    ]

    Scaffold a moonapi service under <name>/: goctl's api new. The layered tree of generate_tree for a sample spec with GET /ping, a test calling it, and an entry point serving it on mooncat.

    scaffold_docker

    fn scaffold_docker(name : String, port? : Int) -> Array[
    GenFile
    ]

    Scaffold container files for a native mctl-generated service: a Dockerfile (a MoonBit build stage that produces the native binary, then a slim runtime stage that runs it) and a .dockerignore. name is the binary/image name, port the port the service listens on. goctl's goctl docker.

    scaffold_gql

    fn scaffold_gql(name : String) -> Array[
    GenFile
    ]

    Scaffold a moongql service under <name>/: the annotated tree of generate_gql_tree for a sample spec — the types as #gql.type, the routes as root fields — and a test that asks the schema what it is.

    scaffold_kube

    fn scaffold_kube(name : String, port? : Int, replicas? : Int) -> Array[
    GenFile
    ]

    Scaffold a Kubernetes deployment for the service under deploy/: a Deployment (replicas pods of the <name> image, a container port, and a liveness probe on /ping) and a Service exposing it. goctl's goctl kube deploy.

    The manifests are built as values and written by moonyaml, not joined out of string fragments. A generator that joins fragments has the indentation in its string literals, where a missed space is invisible, and quotes nothing — so the first service name with a colon in it emits a file Kubernetes reads as something else.

    scaffold_mcp

    fn scaffold_mcp(name : String) -> Array[
    GenFile
    ]

    Scaffold an MCP server under <name>/: annotated tools, a resource and a prompt, a test calling the tool, and an entry point serving them over Streamable HTTP or, with --stdio, over stdio.

    scaffold_model

    fn scaffold_model(name : String) -> Array[
    GenFile
    ]

    Scaffold a moonorm data-layer project under <name>/: a moon.mod carrying the orm rule, a sample schema.sql, the tables as #orm annotations under internal/model (through the same generate_orm_tree_from_ddl as gen crud), and a README. goctl's goctl model … new.

    scaffold_rpc

    fn scaffold_rpc(name : String) -> Array[
    GenFile
    ]

    Scaffold a moonrpc service under <name>/: goctl's rpc new. The layered tree of generate_rpc_tree for a sample proto with a Ping that answers pong, and a test serving it and calling it through the typed client.

    tree_plan

    fn tree_plan(tree : Array[TreeFile], exists : (String) -> Bool) -> Array[
    GenFile
    ]

    The files of tree a run should actually write, given a way to ask whether a path is already on disk. A file moonctl owns (Always — the routes and the types) is always written; anything else is written only when it is not there yet, so a second run refreshes what follows the spec and leaves every handler and logic body the author has since filled in exactly as it is.