libero/scanner

Scanning and convention validation for message modules.

Discovers modules in the shared package that export MsgFromClient or MsgFromServer custom types, and validates that the server package follows the required conventions (handler modules, shared state, etc.). Handlers are discovered by scanning server source for modules that export pub fn update_from_client and matching via the first parameter’s type.

Types

A message module discovered in the shared package.

pub type MessageModule {
  MessageModule(
    module_path: String,
    file_path: String,
    has_msg_from_client: Bool,
    has_msg_from_server: Bool,
    handler_modules: List(String),
  )
}

Constructors

  • MessageModule(
      module_path: String,
      file_path: String,
      has_msg_from_client: Bool,
      has_msg_from_server: Bool,
      handler_modules: List(String),
    )

    Arguments

    module_path

    Module path relative to shared/src/, e.g. “shared/todos”

    file_path

    Absolute file path

    has_msg_from_client

    Whether this module exports a MsgFromClient type

    has_msg_from_server

    Whether this module exports a MsgFromServer type

    handler_modules

    The server modules that handle MsgFromClient for this message module, e.g. [“server/store”]. Empty if no handler found or not applicable.

Values

pub fn derive_module_path(file_path file_path: String) -> String

Derive the Gleam module path from a file path by finding /src/ and taking everything after it, then stripping the .gleam extension. E.g. examples/todos/shared/src/shared/todos.gleam -> shared/todos.

pub fn last_module_segment(
  module_path module_path: String,
) -> String

Extract the last path segment from a module path. E.g. shared/todos -> todos, todos -> todos.

pub fn scan_message_modules(
  shared_src shared_src: String,
) -> Result(
  #(List(MessageModule), dict.Dict(String, String)),
  List(gen_error.GenError),
)

Scan the shared package source directory for modules that export MsgFromClient or MsgFromServer types. These define the wire contract for the message-type convention.

Returns Ok(modules) with the list of matching modules, or Error([NoMessageModules(...)]) if no message modules are found.

pub fn validate_conventions(
  message_modules message_modules: List(MessageModule),
  server_src server_src: String,
  shared_state_path shared_state_path: String,
  app_error_path app_error_path: String,
) -> Result(List(MessageModule), List(gen_error.GenError))

Validate that the server package follows the conventions required for code generation:

  1. server/shared_state.gleam exists
  2. server/app_error.gleam exists
  3. For each message module with has_msg_from_client, a server module exports pub fn update_from_client with the correct msg type

Returns Ok(#(updated_modules, errors)) where updated_modules have handler_module populated from discovered handlers. Errors are fatal only if non-empty.

pub fn validate_msg_from_server_fields(
  message_modules message_modules: List(MessageModule),
) -> Result(Nil, List(gen_error.GenError))

Validate that every MsgFromServer variant has at most one field. Dispatch unwraps the envelope with element(2, Tuple) in Erlang, which silently drops extra fields. Zero-field variants (bare atoms) are fine, they unwrap to Nil.

Search Document