Packages
ash_typescript
0.14.2
0.17.3
0.17.2
0.17.1
0.17.0
0.16.0
0.15.3
0.15.2
retired
0.15.1
retired
0.15.0
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
retired
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.6
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.2
0.10.1
0.10.0
0.9.1
0.9.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.1
0.7.0
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.0
0.4.0
0.3.3
0.3.2
0.3.1
0.2.0
0.1.2
0.1.0
Generate type-safe TypeScript clients directly from your Ash resources and actions, ensuring end-to-end type safety between your backend and frontend.
Current section
Files
Jump to
Current section
Files
documentation/features/developer-experience.md
<!--
SPDX-FileCopyrightText: 2025 Torkild G. Kjevik
SPDX-FileCopyrightText: 2025 ash_typescript contributors <https://github.com/ash-project/ash_typescript/graphs/contributors>
SPDX-License-Identifier: MIT
-->
# Developer Experience Features
AshTypescript provides features to improve developer experience: namespace organization, JSDoc generation, and API manifest documentation.
## Namespaces
Namespaces organize RPC actions into logical groups, improving discoverability in large codebases.
### Configuration Levels
Namespaces can be configured at three levels with cascading precedence:
**Domain Level** - Default namespace for all resources in a domain:
```elixir
defmodule MyApp.Domain do
use Ash.Domain, extensions: [AshTypescript.Rpc]
typescript_rpc do
namespace :api # All resources default to "api" namespace
resource MyApp.Todo do
rpc_action :list_todos, :read
end
end
end
```
**Resource Level** - Override for all actions on a specific resource:
```elixir
typescript_rpc do
namespace :api
resource MyApp.Todo do
namespace :todos # Overrides domain namespace
rpc_action :list_todos, :read
rpc_action :create_todo, :create
end
resource MyApp.User do
# Uses domain namespace "api"
rpc_action :list_users, :read
end
end
```
**Action Level** - Override for a specific action:
```elixir
typescript_rpc do
namespace :api
resource MyApp.Todo do
namespace :todos
rpc_action :list_todos, :read # Uses "todos"
rpc_action :admin_list, :read, namespace: :admin # Uses "admin"
end
end
```
### Precedence Order
Action namespace > Resource namespace > Domain namespace > nil
### Generated Output
With namespaces enabled, the generated JSDoc includes the namespace:
```typescript
/**
* List all todos
*
* @ashActionType :read
* @namespace todos
*/
export async function listTodos(...) { ... }
```
## JSDoc Generation
Generated TypeScript functions include JSDoc comments that provide IDE discoverability through hover documentation and autocomplete hints.
### Default Output
Every generated RPC function includes basic JSDoc:
```typescript
/**
* List all todos
*
* @ashActionType :read
*/
export async function listTodos(...) { ... }
```
### Exposing Ash Metadata
Enable detailed Ash metadata in JSDoc for development:
```elixir
config :ash_typescript,
add_ash_internals_to_jsdoc: true
```
This adds internal references:
```typescript
/**
* List all todos
*
* @ashActionType :read
* @ashResource MyApp.Todo
* @ashAction :list_todos
* @ashActionDef lib/my_app/resources/todo.ex
* @rpcActionDef lib/my_app/domain.ex
* @namespace todos
*/
export async function listTodos(...) { ... }
```
### JSDoc Tags Reference
| Tag | Description | When Shown |
|-----|-------------|------------|
| `@ashActionType` | Ash action type (`:read`, `:create`, etc.) | Always |
| `@ashResource` | Full Elixir module name | When `add_ash_internals_to_jsdoc: true` |
| `@ashAction` | Internal Ash action name | When `add_ash_internals_to_jsdoc: true` |
| `@ashActionDef` | Source file of Ash action definition | When `add_ash_internals_to_jsdoc: true` |
| `@rpcActionDef` | Source file of RPC action configuration | When `add_ash_internals_to_jsdoc: true` |
| `@namespace` | Action namespace | When namespace is configured |
| `@see` | Related actions | When `see:` option is configured |
| `@deprecated` | Deprecation notice | When `deprecated:` option is configured |
### Source Path Prefix (Monorepos)
For monorepo setups where Elixir code is in a subdirectory:
```elixir
config :ash_typescript,
source_path_prefix: "backend"
```
Output:
```typescript
/**
* @ashActionDef backend/lib/my_app/resources/todo.ex
* @rpcActionDef backend/lib/my_app/domain.ex
*/
```
### Custom Descriptions
Override default descriptions per action:
```elixir
typescript_rpc do
resource MyApp.Todo do
rpc_action :list_todos, :read,
description: "Fetch all todos for the current user"
end
end
```
When `add_ash_internals_to_jsdoc: true`, the Ash action's description is used as fallback if no RPC description is set.
### Related Actions
Link related actions in JSDoc using the `see` option:
```elixir
rpc_action :list_todos, :read,
see: [:create_todo, :update_todo]
```
Output:
```typescript
/**
* @see createTodo
* @see updateTodo
*/
```
### Deprecation Notices
Mark actions as deprecated:
```elixir
rpc_action :old_list, :read,
deprecated: true
rpc_action :legacy_list, :read,
deprecated: "Use listTodos instead"
```
Output:
```typescript
/**
* @deprecated
*/
/**
* @deprecated Use listTodos instead
*/
```
## Manifest Generation
Generate a Markdown manifest documenting all RPC actions for API documentation and developer onboarding.
### Configuration
```elixir
config :ash_typescript,
manifest_file: "./docs/RPC_MANIFEST.md",
add_ash_internals_to_manifest: true
```
### Sample Output
```markdown
# RPC Action Manifest
Generated: 2025-01-15
## Namespace: todos
### Todo
| Function | Action Type | Ash Action | Resource | Validation | Zod Schema | Channel |
|----------|-------------|------------|----------|------------|------------|---------|
| `listTodos` | read | `list` | `MyApp.Todo` | `validateListTodos` | `ListTodosInputSchema` | `listTodosChannel` |
| `createTodo` | create | `create` | `MyApp.Todo` | `validateCreateTodo` | `CreateTodoInputSchema` | `createTodoChannel` |
- **`listTodos`**: Fetch all todos for the current user
- **`createTodo`**: Create a new Todo | **See also:** `listTodos`
**Typed Queries:**
- `todoFields` -> `TodoFieldsResult`: Pre-defined field selection
```
### Grouping Behavior
- **With namespaces**: Actions grouped by namespace
- **Without namespaces**: Actions grouped by domain
### Controlling Manifest Content
The `add_ash_internals_to_manifest` config controls whether internal Ash details are shown:
| Setting | Columns Shown |
|---------|---------------|
| `false` | Function, Action Type |
| `true` | Function, Action Type, Ash Action, Resource |
## Configuration Reference
### All Developer Experience Options
```elixir
config :ash_typescript,
# JSDoc configuration
add_ash_internals_to_jsdoc: false, # Show Ash module/action details
source_path_prefix: nil, # Prefix for source paths (monorepos)
# Manifest configuration
manifest_file: nil, # Path to generate manifest (nil = disabled)
add_ash_internals_to_manifest: false # Show Ash details in manifest
```
### Development vs Production
**Development Configuration:**
```elixir
# config/dev.exs
config :ash_typescript,
add_ash_internals_to_jsdoc: true,
add_ash_internals_to_manifest: true,
manifest_file: "./docs/RPC_MANIFEST.md"
```
**Production Configuration:**
```elixir
# config/prod.exs
config :ash_typescript,
add_ash_internals_to_jsdoc: false,
add_ash_internals_to_manifest: false
```
## Common Patterns
### Namespace Organization by Feature
```elixir
typescript_rpc do
resource MyApp.Todo do
namespace :todos
rpc_action :list_todos, :read
rpc_action :create_todo, :create
end
resource MyApp.User do
namespace :users
rpc_action :list_users, :read
rpc_action :get_current_user, :get_current, namespace: :auth
end
resource MyApp.Session do
namespace :auth
rpc_action :login, :create
rpc_action :logout, :destroy
end
end
```
### Development-Only Metadata
```elixir
# config/config.exs
config :ash_typescript,
add_ash_internals_to_jsdoc: Mix.env() == :dev,
add_ash_internals_to_manifest: Mix.env() == :dev
```
### Monorepo Setup
```elixir
# backend/config/config.exs
config :ash_typescript,
source_path_prefix: "backend",
output_file: "../frontend/src/generated/ash_rpc.ts"
```
## Next Steps
- [RPC Action Options](rpc-action-options.md) - All action configuration options
- [Configuration Reference](../reference/configuration.md) - Complete configuration options
- [Lifecycle Hooks](lifecycle-hooks.md) - HTTP and channel lifecycle hooks