documentation/dsls/DSL-AshTypescript.TypedController.md

<!--
This file was generated by Spark. Do not edit it by hand.
-->
# AshTypescript.TypedController

Spark DSL extension for defining typed controller routes.

This extension generates TypeScript path helper functions and a thin Phoenix
controller from routes configured in the DSL. Unlike `AshTypescript.ControllerResource`,
this is a standalone Spark DSL — not attached to `Ash.Resource`.

Routes contain colocated arguments and handler functions (inline closures or
handler modules implementing `AshTypescript.TypedController.Route`).

## Usage

Three syntaxes are supported for defining routes:

    defmodule MyApp.Session do
      use AshTypescript.TypedController

      typed_controller do
        module_name MyAppWeb.SessionController

        # Verb shortcut (preferred)
        post :login do
          run fn conn, params -> Plug.Conn.send_resp(conn, 200, "OK") end
          argument :code, :string, allow_nil?: false
          argument :remember_me, :boolean
        end

        # Positional method arg
        route :auth, :get do
          run fn conn, _params -> Plug.Conn.send_resp(conn, 200, "Auth") end
        end

        # Method defaults to :get when omitted
        route :home do
          run fn conn, _params -> Plug.Conn.send_resp(conn, 200, "Home") end
        end
      end
    end


## typed_controller
Define typed controller routes

### Nested DSLs
 * [route](#typed_controller-route)
   * argument
 * [get](#typed_controller-get)
   * argument
 * [post](#typed_controller-post)
   * argument
 * [patch](#typed_controller-patch)
   * argument
 * [put](#typed_controller-put)
   * argument
 * [delete](#typed_controller-delete)
   * argument





### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`module_name`](#typed_controller-module_name){: #typed_controller-module_name .spark-required} | `atom` |  | The module name for the generated Phoenix controller (e.g. MyAppWeb.SessionController) |
| [`namespace`](#typed_controller-namespace){: #typed_controller-namespace } | `String.t` |  | Default namespace (filename) for all routes in this controller. Can be overridden per-route. |



### typed_controller.route
```elixir
route name, method \\ nil
```


Define a route that maps a controller action to a handler.

Supports three syntaxes:
- `route :name, :post do ... end` (positional method arg)
- `route :name do ... end` (defaults to GET)
- `post :name do ... end` (verb shortcut)

The handler can be an inline function (fn/2) or a module implementing
the `AshTypescript.TypedController.Route` behaviour. Handlers receive
`(conn, params)` and must return a `%Plug.Conn{}`.


### Nested DSLs
 * [argument](#typed_controller-route-argument)




### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#typed_controller-route-name){: #typed_controller-route-name .spark-required} | `atom` |  | The controller action name (e.g. :login, :auth) |
| [`method`](#typed_controller-route-method){: #typed_controller-route-method } | `:get \| :post \| :patch \| :put \| :delete` | `:get` | The HTTP method. Defaults to :get. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`run`](#typed_controller-route-run){: #typed_controller-route-run .spark-required} | `(any, any -> any) \| atom` |  | The handler — an fn/2 closure or a module implementing AshTypescript.TypedController.Route |
| [`description`](#typed_controller-route-description){: #typed_controller-route-description } | `String.t` |  | JSDoc description for the generated TypeScript path helper |
| [`deprecated`](#typed_controller-route-deprecated){: #typed_controller-route-deprecated } | `boolean \| String.t` |  | Mark this route as deprecated. Set to true for a default message, or provide a custom deprecation notice. |
| [`see`](#typed_controller-route-see){: #typed_controller-route-see } | `list(atom)` | `[]` | List of related route names to reference in JSDoc @see tags. |
| [`zod_schema_name`](#typed_controller-route-zod_schema_name){: #typed_controller-route-zod_schema_name } | `String.t` |  | Override the generated Zod schema name (used as-is for the exported const). Use when the default name collides with an RPC action's Zod schema. |
| [`namespace`](#typed_controller-route-namespace){: #typed_controller-route-namespace } | `String.t` |  | Namespace for organizing this route into a separate file (becomes the filename). Overrides controller-level namespace. |


### typed_controller.route.argument
```elixir
argument name, type
```


Define an argument for this route.





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#typed_controller-route-argument-name){: #typed_controller-route-argument-name .spark-required} | `atom` |  | The argument name |
| [`type`](#typed_controller-route-argument-type){: #typed_controller-route-argument-type .spark-required} | `atom \| {atom, keyword}` |  | The Ash type (e.g. :string, :boolean, :integer) |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`constraints`](#typed_controller-route-argument-constraints){: #typed_controller-route-argument-constraints } | `keyword` | `[]` | Type constraints |
| [`allow_nil?`](#typed_controller-route-argument-allow_nil?){: #typed_controller-route-argument-allow_nil? } | `boolean` | `true` | Whether this argument can be nil. Set to false to make it required. |
| [`default`](#typed_controller-route-argument-default){: #typed_controller-route-argument-default } | `any` |  | Default value for this argument |





### Introspection

Target: `AshTypescript.TypedController.Dsl.RouteArgument`




### Introspection

Target: `AshTypescript.TypedController.Dsl.Route`

### typed_controller.get
```elixir
get name
```


Define a GET route. Shorthand for `route :name, :get`.

### Nested DSLs
 * [argument](#typed_controller-get-argument)




### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#typed_controller-get-name){: #typed_controller-get-name .spark-required} | `atom` |  | The controller action name (e.g. :login, :auth) |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`run`](#typed_controller-get-run){: #typed_controller-get-run .spark-required} | `(any, any -> any) \| atom` |  | The handler — an fn/2 closure or a module implementing AshTypescript.TypedController.Route |
| [`description`](#typed_controller-get-description){: #typed_controller-get-description } | `String.t` |  | JSDoc description for the generated TypeScript path helper |
| [`deprecated`](#typed_controller-get-deprecated){: #typed_controller-get-deprecated } | `boolean \| String.t` |  | Mark this route as deprecated. Set to true for a default message, or provide a custom deprecation notice. |
| [`see`](#typed_controller-get-see){: #typed_controller-get-see } | `list(atom)` | `[]` | List of related route names to reference in JSDoc @see tags. |
| [`zod_schema_name`](#typed_controller-get-zod_schema_name){: #typed_controller-get-zod_schema_name } | `String.t` |  | Override the generated Zod schema name (used as-is for the exported const). Use when the default name collides with an RPC action's Zod schema. |
| [`namespace`](#typed_controller-get-namespace){: #typed_controller-get-namespace } | `String.t` |  | Namespace for organizing this route into a separate file (becomes the filename). Overrides controller-level namespace. |


### typed_controller.get.argument
```elixir
argument name, type
```


Define an argument for this route.





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#typed_controller-get-argument-name){: #typed_controller-get-argument-name .spark-required} | `atom` |  | The argument name |
| [`type`](#typed_controller-get-argument-type){: #typed_controller-get-argument-type .spark-required} | `atom \| {atom, keyword}` |  | The Ash type (e.g. :string, :boolean, :integer) |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`constraints`](#typed_controller-get-argument-constraints){: #typed_controller-get-argument-constraints } | `keyword` | `[]` | Type constraints |
| [`allow_nil?`](#typed_controller-get-argument-allow_nil?){: #typed_controller-get-argument-allow_nil? } | `boolean` | `true` | Whether this argument can be nil. Set to false to make it required. |
| [`default`](#typed_controller-get-argument-default){: #typed_controller-get-argument-default } | `any` |  | Default value for this argument |





### Introspection

Target: `AshTypescript.TypedController.Dsl.RouteArgument`




### Introspection

Target: `AshTypescript.TypedController.Dsl.Route`

### typed_controller.post
```elixir
post name
```


Define a POST route. Shorthand for `route :name, :post`.

### Nested DSLs
 * [argument](#typed_controller-post-argument)




### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#typed_controller-post-name){: #typed_controller-post-name .spark-required} | `atom` |  | The controller action name (e.g. :login, :auth) |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`run`](#typed_controller-post-run){: #typed_controller-post-run .spark-required} | `(any, any -> any) \| atom` |  | The handler — an fn/2 closure or a module implementing AshTypescript.TypedController.Route |
| [`description`](#typed_controller-post-description){: #typed_controller-post-description } | `String.t` |  | JSDoc description for the generated TypeScript path helper |
| [`deprecated`](#typed_controller-post-deprecated){: #typed_controller-post-deprecated } | `boolean \| String.t` |  | Mark this route as deprecated. Set to true for a default message, or provide a custom deprecation notice. |
| [`see`](#typed_controller-post-see){: #typed_controller-post-see } | `list(atom)` | `[]` | List of related route names to reference in JSDoc @see tags. |
| [`zod_schema_name`](#typed_controller-post-zod_schema_name){: #typed_controller-post-zod_schema_name } | `String.t` |  | Override the generated Zod schema name (used as-is for the exported const). Use when the default name collides with an RPC action's Zod schema. |
| [`namespace`](#typed_controller-post-namespace){: #typed_controller-post-namespace } | `String.t` |  | Namespace for organizing this route into a separate file (becomes the filename). Overrides controller-level namespace. |


### typed_controller.post.argument
```elixir
argument name, type
```


Define an argument for this route.





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#typed_controller-post-argument-name){: #typed_controller-post-argument-name .spark-required} | `atom` |  | The argument name |
| [`type`](#typed_controller-post-argument-type){: #typed_controller-post-argument-type .spark-required} | `atom \| {atom, keyword}` |  | The Ash type (e.g. :string, :boolean, :integer) |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`constraints`](#typed_controller-post-argument-constraints){: #typed_controller-post-argument-constraints } | `keyword` | `[]` | Type constraints |
| [`allow_nil?`](#typed_controller-post-argument-allow_nil?){: #typed_controller-post-argument-allow_nil? } | `boolean` | `true` | Whether this argument can be nil. Set to false to make it required. |
| [`default`](#typed_controller-post-argument-default){: #typed_controller-post-argument-default } | `any` |  | Default value for this argument |





### Introspection

Target: `AshTypescript.TypedController.Dsl.RouteArgument`




### Introspection

Target: `AshTypescript.TypedController.Dsl.Route`

### typed_controller.patch
```elixir
patch name
```


Define a PATCH route. Shorthand for `route :name, :patch`.

### Nested DSLs
 * [argument](#typed_controller-patch-argument)




### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#typed_controller-patch-name){: #typed_controller-patch-name .spark-required} | `atom` |  | The controller action name (e.g. :login, :auth) |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`run`](#typed_controller-patch-run){: #typed_controller-patch-run .spark-required} | `(any, any -> any) \| atom` |  | The handler — an fn/2 closure or a module implementing AshTypescript.TypedController.Route |
| [`description`](#typed_controller-patch-description){: #typed_controller-patch-description } | `String.t` |  | JSDoc description for the generated TypeScript path helper |
| [`deprecated`](#typed_controller-patch-deprecated){: #typed_controller-patch-deprecated } | `boolean \| String.t` |  | Mark this route as deprecated. Set to true for a default message, or provide a custom deprecation notice. |
| [`see`](#typed_controller-patch-see){: #typed_controller-patch-see } | `list(atom)` | `[]` | List of related route names to reference in JSDoc @see tags. |
| [`zod_schema_name`](#typed_controller-patch-zod_schema_name){: #typed_controller-patch-zod_schema_name } | `String.t` |  | Override the generated Zod schema name (used as-is for the exported const). Use when the default name collides with an RPC action's Zod schema. |
| [`namespace`](#typed_controller-patch-namespace){: #typed_controller-patch-namespace } | `String.t` |  | Namespace for organizing this route into a separate file (becomes the filename). Overrides controller-level namespace. |


### typed_controller.patch.argument
```elixir
argument name, type
```


Define an argument for this route.





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#typed_controller-patch-argument-name){: #typed_controller-patch-argument-name .spark-required} | `atom` |  | The argument name |
| [`type`](#typed_controller-patch-argument-type){: #typed_controller-patch-argument-type .spark-required} | `atom \| {atom, keyword}` |  | The Ash type (e.g. :string, :boolean, :integer) |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`constraints`](#typed_controller-patch-argument-constraints){: #typed_controller-patch-argument-constraints } | `keyword` | `[]` | Type constraints |
| [`allow_nil?`](#typed_controller-patch-argument-allow_nil?){: #typed_controller-patch-argument-allow_nil? } | `boolean` | `true` | Whether this argument can be nil. Set to false to make it required. |
| [`default`](#typed_controller-patch-argument-default){: #typed_controller-patch-argument-default } | `any` |  | Default value for this argument |





### Introspection

Target: `AshTypescript.TypedController.Dsl.RouteArgument`




### Introspection

Target: `AshTypescript.TypedController.Dsl.Route`

### typed_controller.put
```elixir
put name
```


Define a PUT route. Shorthand for `route :name, :put`.

### Nested DSLs
 * [argument](#typed_controller-put-argument)




### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#typed_controller-put-name){: #typed_controller-put-name .spark-required} | `atom` |  | The controller action name (e.g. :login, :auth) |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`run`](#typed_controller-put-run){: #typed_controller-put-run .spark-required} | `(any, any -> any) \| atom` |  | The handler — an fn/2 closure or a module implementing AshTypescript.TypedController.Route |
| [`description`](#typed_controller-put-description){: #typed_controller-put-description } | `String.t` |  | JSDoc description for the generated TypeScript path helper |
| [`deprecated`](#typed_controller-put-deprecated){: #typed_controller-put-deprecated } | `boolean \| String.t` |  | Mark this route as deprecated. Set to true for a default message, or provide a custom deprecation notice. |
| [`see`](#typed_controller-put-see){: #typed_controller-put-see } | `list(atom)` | `[]` | List of related route names to reference in JSDoc @see tags. |
| [`zod_schema_name`](#typed_controller-put-zod_schema_name){: #typed_controller-put-zod_schema_name } | `String.t` |  | Override the generated Zod schema name (used as-is for the exported const). Use when the default name collides with an RPC action's Zod schema. |
| [`namespace`](#typed_controller-put-namespace){: #typed_controller-put-namespace } | `String.t` |  | Namespace for organizing this route into a separate file (becomes the filename). Overrides controller-level namespace. |


### typed_controller.put.argument
```elixir
argument name, type
```


Define an argument for this route.





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#typed_controller-put-argument-name){: #typed_controller-put-argument-name .spark-required} | `atom` |  | The argument name |
| [`type`](#typed_controller-put-argument-type){: #typed_controller-put-argument-type .spark-required} | `atom \| {atom, keyword}` |  | The Ash type (e.g. :string, :boolean, :integer) |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`constraints`](#typed_controller-put-argument-constraints){: #typed_controller-put-argument-constraints } | `keyword` | `[]` | Type constraints |
| [`allow_nil?`](#typed_controller-put-argument-allow_nil?){: #typed_controller-put-argument-allow_nil? } | `boolean` | `true` | Whether this argument can be nil. Set to false to make it required. |
| [`default`](#typed_controller-put-argument-default){: #typed_controller-put-argument-default } | `any` |  | Default value for this argument |





### Introspection

Target: `AshTypescript.TypedController.Dsl.RouteArgument`




### Introspection

Target: `AshTypescript.TypedController.Dsl.Route`

### typed_controller.delete
```elixir
delete name
```


Define a DELETE route. Shorthand for `route :name, :delete`.

### Nested DSLs
 * [argument](#typed_controller-delete-argument)




### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#typed_controller-delete-name){: #typed_controller-delete-name .spark-required} | `atom` |  | The controller action name (e.g. :login, :auth) |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`run`](#typed_controller-delete-run){: #typed_controller-delete-run .spark-required} | `(any, any -> any) \| atom` |  | The handler — an fn/2 closure or a module implementing AshTypescript.TypedController.Route |
| [`description`](#typed_controller-delete-description){: #typed_controller-delete-description } | `String.t` |  | JSDoc description for the generated TypeScript path helper |
| [`deprecated`](#typed_controller-delete-deprecated){: #typed_controller-delete-deprecated } | `boolean \| String.t` |  | Mark this route as deprecated. Set to true for a default message, or provide a custom deprecation notice. |
| [`see`](#typed_controller-delete-see){: #typed_controller-delete-see } | `list(atom)` | `[]` | List of related route names to reference in JSDoc @see tags. |
| [`zod_schema_name`](#typed_controller-delete-zod_schema_name){: #typed_controller-delete-zod_schema_name } | `String.t` |  | Override the generated Zod schema name (used as-is for the exported const). Use when the default name collides with an RPC action's Zod schema. |
| [`namespace`](#typed_controller-delete-namespace){: #typed_controller-delete-namespace } | `String.t` |  | Namespace for organizing this route into a separate file (becomes the filename). Overrides controller-level namespace. |


### typed_controller.delete.argument
```elixir
argument name, type
```


Define an argument for this route.





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#typed_controller-delete-argument-name){: #typed_controller-delete-argument-name .spark-required} | `atom` |  | The argument name |
| [`type`](#typed_controller-delete-argument-type){: #typed_controller-delete-argument-type .spark-required} | `atom \| {atom, keyword}` |  | The Ash type (e.g. :string, :boolean, :integer) |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`constraints`](#typed_controller-delete-argument-constraints){: #typed_controller-delete-argument-constraints } | `keyword` | `[]` | Type constraints |
| [`allow_nil?`](#typed_controller-delete-argument-allow_nil?){: #typed_controller-delete-argument-allow_nil? } | `boolean` | `true` | Whether this argument can be nil. Set to false to make it required. |
| [`default`](#typed_controller-delete-argument-default){: #typed_controller-delete-argument-default } | `any` |  | Default value for this argument |





### Introspection

Target: `AshTypescript.TypedController.Dsl.RouteArgument`




### Introspection

Target: `AshTypescript.TypedController.Dsl.Route`





<style type="text/css">.spark-required::after { content: "*"; color: red !important; }</style>