Arc.ProxyGenerator (cratis_arc v0.1.0)

Copy Markdown View Source

Generates TypeScript proxies for the React frontend packages (@cratis/arc, @cratis/arc.react) from the commands and read models of an Arc.Application.

Proxy generation is opt-in. Nothing is generated unless you run mix arc.gen.proxies or configure the :arc compiler. A backend serving LiveView or an API to another client never generates TypeScript.

# mix.exs
def project do
  [
    # ...
    compilers: Mix.compilers() ++ [:arc],
    arc: [application: MyApp.Arc, output: "assets/src/arc"]
  ]
end

What is generated

One file per artifact, in a folder that mirrors the module namespace after the leading segments_to_skip segments:

  • a command module becomes a Command class with its interface, route, roles, property descriptors, client-side validator and a use hook
  • each query of a read model becomes a QueryFor (or ObservableQueryFor) class with parameters, sorting helpers and the use, useWithPaging, useSuspense and when hooks
  • each model and nested schema becomes a class with @field decorators
  • the identity provider's details type becomes a class too, to pass to IdentityProvider.getCurrent or useIdentity
  • an index.ts per folder re-exports the generated files

The output follows the C# proxy generator's templates, so the frontend packages consume it unchanged.

Safety

Every generated file starts with // @generated by Cratis. Source: <module>. Hash: <sha256>. A file without that marker is never overwritten, and stale cleanup deletes only files that carry it. Output is deterministic: generating twice produces identical bytes, and an unchanged file is not rewritten.

Options

Read from arc: in mix.exs, or given as flags to mix arc.gen.proxies.

  • :application - the Arc.Application module (required)
  • :output - the directory to generate into (required)
  • :layout - :namespace (default) mirrors the module namespace under :output; :colocated writes each proxy beside the source file of its module, so :output is the root that holds your Elixir and your React code, for example "lib". See Vertical slices
  • :remove_stale - delete generated files for artifacts that no longer exist; default true

Summary

Functions

Generates proxies into output.

Renders every proxy without touching the file system. Returns files with a path relative to the output directory, the source module, and the TypeScript body.

Types

result()

@type result() :: %{
  written: [String.t()],
  unchanged: [String.t()],
  removed: [String.t()]
}

Functions

generate(application, opts)

@spec generate(module(), keyword()) :: {:ok, result()} | {:error, [String.t()]}

Generates proxies into output.

Options

  • :output - the directory (required)
  • :layout - :namespace (default) or :colocated
  • :root - for :colocated, the directory source folders are relative to; defaults to :output
  • :remove_stale - default true
  • :dry_run - report what would change without writing

render(application, options \\ [])

@spec render(module(), keyword()) :: [Arc.ProxyGenerator.Artifact.t()]

Renders every proxy without touching the file system. Returns files with a path relative to the output directory, the source module, and the TypeScript body.