Sign in

    smithy-codegen-moonbit

    A Smithy code generator for MoonBit JSON-RPC peers

    Download zip
    Author
    Version
    0.7.0
    License
    Apache-2.0
    Last updated
    5 hours ago
    Downloads
    5

    #MoonBit JSON-RPC code generator

    moonrockz/smithy-codegen-moonbit generates a MoonBit JSON-RPC 2.0 peer from a Smithy model with smithy.rpc traits. The Smithy CLI registers it as the build plugin moonbit-jsonrpc-codegen. The generator has no file access; the build runner writes its files.

    The generator reads the prepared contracts of moonrockz/smithy-codegen-jsonrpc: methods, parameter modes, result selection, modeled errors, structure member names, unknown member policies and session rules. It does not read the RPC traits a second time, so the generated peer and smithy validate rpc use the same rules.

    #Settings

    SettingRequiredMeaning
    serviceyesThe service shape ID. With protocol, a service of the protocol.
    protocolnoA jsonRpcProtocol structure. Without it, the service has the peers client and server.
    peeryesThe peer to generate.
    transportsnostdio, http and websocket. All by default.
    moduleyesThe MoonBit module name of the output, such as example/terminal.

    { "version": "1.0", "sources": ["model.smithy"], "plugins": { "moonbit-jsonrpc-codegen::moonbit-terminal": { "service": "example.payments#PaymentTerminal", "protocol": "example.payments#TerminalProtocol", "peer": "terminal", "module": "example/terminal" } } }

    #Output

    The output is one MoonBit module. The root package holds the generated code. The package rpc is a copy of the runtime in runtimes/moonbit/rpc, which is real MoonBit code with its own tests. mise run runtime:embed copies the runtime into runtime_files.mbt, and mise run validate fails when the copy differs.

    FileContent
    moon.modThe module name and moonbitlang/async@0.22.5.
    moon.pkgThe import of the runtime package as @rpc.
    types.mbtA struct for each structure, an enum for each union and enum, each with to_json and from_json.
    errors.mbtA struct for each modeled error, the error type ServiceError, and the conversions to and from @rpc.RpcError.
    handler.mbtThe trait <Service>Handler of the service that the peer accepts, and register_<service>(peer, handler).
    client.mbtThe typed client <Service>Client of the service that the peer calls.
    session.mbtsession_rules() from the prepared session contract, and new_peer(log?).
    session_test.mbtA test that builds the rules and a peer.
    rpc/The runtime.

    Type mapping: String, Bool, Int (byte, short, integer), Int64 (long), Double (float, double), @rpc.Decimal (bigDecimal), @rpc.BigInteger (bigInteger), Bytes (blob, base64 text), Json (document), @rpc.Timestamp, Array[T], Map[String, T], and T? for a member that is not required. A decimal or a big integer keeps the exact text of its JSON number; no value goes through a Double. Enums are closed: an unknown value is a decode error.

    Names: fields and methods are snake_case, types are PascalCase, and enum and union variants are PascalCase (INSERT_CARD is InsertCard). A MoonBit keyword gets a _ suffix. The service rename map applies through ServiceNames. Two members or shapes with one MoonBit name are an error that names both.

    The modeled cancel method of the peer is not in its handler trait: the runtime cancels the call and answers with the modeled code. A method with a jsonRpcRefersToCall member is registered with Peer::call_reference.

    #Example

    ///|
    test {
    let loaded = @rpc.loader()
    .add_idl(
    "echo.smithy",
    (
    #|$version: "2"
    #|namespace example
    #|use smithy.rpc#jsonRpc
    #|use smithy.rpc#method
    #|@jsonRpc(versions: ["2.0"])
    #|service Echo { version: "1", operations: [Say] }
    #|@method(name: "say", params: "named", resultMember: "text")
    #|operation Say { input: SayInput, output: SayInput }
    #|structure SayInput { @required text: String }
    ),
    )
    .assemble()
    let files = @moonbit.run(
    @codegen.PluginContext::from_build(loaded.model.unwrap(), {
    "service": "example#Echo",
    "peer": "server",
    "module": "example/echo",
    }),
    )
    assert_true(
    files["handler.mbt"].contains(
    "async say(Self, SayInput, @rpc.CallContext) -> String raise",
    ),
    )
    }

    The sample in examples/payment-terminal/ has golden output in generated/moonbit/. mise run codegen:payment-terminal writes it, and mise run codegen:payment-terminal -- --check fails when it is not current.

    plugin

    fn plugin(model :
    Model
    , settings : Json) -> Map[String, String] raise
    BuildError

    The plugin for the build runner. Register it as moonbit-jsonrpc-codegen.

    run

    Generate a MoonBit JSON-RPC peer. Settings: service, protocol, peer, transports (see PeerSettings) and module, the MoonBit module name of the output, such as example/terminal.

    snake_name

    fn snake_name(name : String) -> String

    A snake_case name for a field, a function or a method. A keyword gets a _ suffix. A name that starts with a digit gets an n prefix.

    type_name

    fn type_name(name : String) -> String

    The name of a generated type: the contextual name with an upper-case first letter. A name that the core library uses gets a _ suffix.

    variant_name

    fn variant_name(name : String) -> String

    A PascalCase name for an enum or a union variant. INSERT_CARD is InsertCard, manualEntry is ManualEntry and USD is Usd.

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io