Code Generation#

Code generation utilities for extracting route metadata and generating type-safe route definitions.

Features#

  • Extract route metadata from Litestar applications

  • Generate Ziggy-compatible routes.json

  • Generate TypeScript route definitions with type safety

  • Support for path and query parameters with OpenAPI type enrichment

  • Inertia page props metadata extraction

Public code generation API.

This package provides code generation utilities for:

  • Unified asset export (export_integration_assets)

  • Route metadata export (routes.json + Ziggy-compatible TS)

  • Inertia page props metadata export

Internal implementation details (OpenAPI integration, TypeScript conversion) are kept in private submodules to keep the public API clean.

class litestar_vite.codegen.AsyncAPIChannel[source]#

Bases: object

AsyncAPI 3.0 Channel Object.

to_dict() → dict[str, Any][source]#

Convert the channel object to a dictionary.

Returns:

Dictionary representation of the channel object.

__init__(address: str, title: str | None = None, summary: str | None = None, description: str | None = None, parameters: dict[str, ~litestar_vite.codegen._asyncapi.AsyncAPIParameter]=<factory>, messages: dict[str, ~litestar_vite.codegen._asyncapi.AsyncAPIMessage]=<factory>, bindings: dict[str, ~typing.Any]=<factory>) → None#
class litestar_vite.codegen.AsyncAPIComponents[source]#

Bases: object

AsyncAPI 3.0 Components Object.

to_dict() → dict[str, Any][source]#

Convert the components object to a dictionary.

Returns:

Dictionary representation of the components object.

__init__(messages: dict[str, ~litestar_vite.codegen._asyncapi.AsyncAPIMessage]=<factory>, schemas: dict[str, ~typing.Any]=<factory>, parameters: dict[str, ~litestar_vite.codegen._asyncapi.AsyncAPIParameter]=<factory>) → None#
class litestar_vite.codegen.AsyncAPIDocument[source]#

Bases: object

Root AsyncAPI 3.0 Document.

to_dict() → dict[str, Any][source]#

Serialize the complete document to an AsyncAPI 3.0 specification dictionary.

Returns:

Deterministic dictionary representation of the AsyncAPI 3.0 specification.

__init__(info: AsyncAPIInfo, asyncapi: str = '3.0.0', id: str | None = None, servers: dict[str, ~litestar_vite.codegen._asyncapi.AsyncAPIServer]=<factory>, channels: dict[str, ~litestar_vite.codegen._asyncapi.AsyncAPIChannel]=<factory>, operations: dict[str, ~litestar_vite.codegen._asyncapi.AsyncAPIOperation]=<factory>, components: AsyncAPIComponents | None = None) → None#
class litestar_vite.codegen.AsyncAPIInfo[source]#

Bases: object

AsyncAPI 3.0 Info Object.

to_dict() → dict[str, Any][source]#

Convert the info object to a dictionary.

Returns:

Dictionary representation of the info object.

__init__(title: str, version: str, description: str | None = None) → None#
class litestar_vite.codegen.AsyncAPIMessage[source]#

Bases: object

AsyncAPI 3.0 Message Object.

to_dict() → dict[str, Any][source]#

Convert the message object to a dictionary.

Returns:

Dictionary representation of the message object.

__init__(name: str, title: str | None = None, summary: str | None = None, description: str | None = None, content_type: str = 'application/json', payload: dict[str, ~typing.Any]=<factory>) → None#
class litestar_vite.codegen.AsyncAPIOperation[source]#

Bases: object

AsyncAPI 3.0 Operation Object.

to_dict() → dict[str, Any][source]#

Convert the operation object to a dictionary.

Returns:

Dictionary representation of the operation object.

__init__(action: str, channel: dict[str, str], title: str | None = None, summary: str | None = None, description: str | None = None, messages: list[dict[str, str]] = <factory>) → None#
class litestar_vite.codegen.AsyncAPIParameter[source]#

Bases: object

AsyncAPI 3.0 Parameter Object.

to_dict() → dict[str, Any][source]#

Convert the parameter object to a dictionary.

Returns:

Dictionary representation of the parameter object.

__init__(description: str | None = None, enum: list[str] = <factory>, default: str | None = None) → None#
class litestar_vite.codegen.AsyncAPIServer[source]#

Bases: object

AsyncAPI 3.0 Server Object.

to_dict() → dict[str, Any][source]#

Convert the server object to a dictionary.

Returns:

Dictionary representation of the server object.

__init__(host: str, protocol: str, protocol_version: str | None = None, description: str | None = None) → None#
class litestar_vite.codegen.ExportResult[source]#

Bases: object

Result of the export operation.

exported_files: list[str]#

Files that were written (content changed).

unchanged_files: list[str]#

Files that were skipped (content unchanged).

openapi_schema: dict[str, Any] | None = None#

The OpenAPI schema dict (for downstream use).

asyncapi_schema: dict[str, Any] | None = None#

The AsyncAPI 3.0 schema dict (for downstream use).

asyncapi_source: str | None = None#

The authoritative source for the AsyncAPI schema (‘litestar-asyncapi’ or ‘builtin’).

__init__(exported_files: list[str] = <factory>, unchanged_files: list[str] = <factory>, openapi_schema: dict[str, ~typing.Any] | None=None, asyncapi_schema: dict[str, ~typing.Any] | None=None, asyncapi_source: str | None = None) → None#
class litestar_vite.codegen.InertiaPageMetadata[source]#

Bases: object

Metadata for a single Inertia page component.

__init__(component: str, route_path: str, props_type: str | None = None, schema_ref: str | None = None, handler_name: str | None = None, ts_type: str | None = None, custom_types: list[str] = <factory>, wrap_with_content: bool = False) → None#
class litestar_vite.codegen.RouteMetadata[source]#

Bases: object

Metadata for a single route.

__init__(name: str, path: str, methods: list[str], method: str, params: dict[str, str] = <factory>, query_params: dict[str, str] = <factory>, component: str | None = None) → None#
litestar_vite.codegen.app_has_realtime_surface(app: Litestar) → bool[source]#

Return whether the Litestar application defines any realtime surface.

A realtime surface includes: - Any plugin in app.plugins that provides AsyncAPI schemas. - Any route in app.routes that is a litestar.routes.WebSocketRoute. - Any plugin in app.plugins that is a litestar.channels.ChannelsPlugin. - Any HTTP route handler whose return annotation represents a Server-Sent Event (SSE).

Parameters:

app – The Litestar application instance.

Returns:

True if any realtime route, plugin, or SSE handler is detected, otherwise False.

litestar_vite.codegen.asyncapi_docs_paths(app: Litestar) → tuple[str, ...][source]#

Return reserved AsyncAPI documentation route prefixes.

When an AsyncAPI plugin is registered, returns a deduplicated tuple containing the default AsyncAPI documentation path (‘/asyncapi’) and any custom documentation path configured on the plugin. When no plugin is registered, returns an empty tuple.

Parameters:

app – The Litestar application instance.

Returns:

Tuple of reserved documentation path strings.

litestar_vite.codegen.create_asyncapi_document(app: Litestar, title: str = 'Litestar Realtime API', version: str = '1.0.0', description: str | None = None) → AsyncAPIDocument[source]#

Generate an AsyncAPI 3.0 document from a Litestar application.

Parameters:
  • app – The Litestar application instance.

  • title – Title for the AsyncAPI document.

  • version – Version of the API specification.

  • description – Optional description of the API.

Returns:

A populated AsyncAPIDocument instance.

litestar_vite.codegen.encode_deterministic_json(data: dict[str, Any], *, indent: int = 2, serializer: Callable[[Any], bytes] | None = None) → bytes[source]#

Encode JSON with sorted keys for deterministic output.

This is a wrapper that ensures all nested dict keys are sorted before serialization, producing byte-identical output for the same input data regardless of insertion order.

Parameters:
  • data – Dictionary to encode.

  • indent – Indentation level for formatting.

  • serializer – Optional custom serializer function. If not provided, uses litestar’s default encode_json.

Returns:

Formatted JSON bytes with sorted keys.

litestar_vite.codegen.export_asyncapi(*, app: Litestar, types_config: TypeGenConfig, serializer: Callable[[Any], bytes] | None = None, result: ExportResult) → None[source]#

Export AsyncAPI 3.0 schema to file.

Parameters:
  • app – The Litestar application instance.

  • types_config – The type generation configuration.

  • serializer – Optional custom serializer for JSON encoding.

  • result – ExportResult accumulator for exported or unchanged files.

litestar_vite.codegen.export_integration_assets(app: Litestar, config: ViteConfig, *, serializer: Callable[[Any], bytes] | None = None) → ExportResult[source]#

Export all integration artifacts with deterministic output.

This is the single source of truth for code generation. Both CLI commands and Plugin startup should call this function to ensure byte-identical output.

AsyncAPI export is independent of OpenAPI availability when channels are enabled and a realtime surface is present on the application (WebSocket routes, ChannelsPlugin, or SSE handlers). The configuration flag generate_channels=True is an opt-in ceiling rather than a mandate, so a REST-only application produces no AsyncAPI artifacts even when generate_channels is true. OpenAPI schema, route metadata, route definitions, and Inertia page prop artifacts require an active OpenAPI configuration.

The export order is critical: 1. Register Inertia page prop types in OpenAPI schema (mutates schema_dict) 2. Export openapi.json (now includes session prop types) 3. Export routes.json (uses schema for component refs) 4. Export routes.ts (if enabled) 5. Export inertia-pages.json (if enabled) 6. Export asyncapi.json (if enabled)

Parameters:
  • app – The Litestar application instance.

  • config – The ViteConfig instance.

  • serializer – Optional custom serializer for OpenAPI schema encoding.

Returns:

ExportResult with lists of exported and unchanged files.

litestar_vite.codegen.extract_channels_plugin_channels(app: Litestar, components_schemas: dict[str, Any] | None = None, *, context: AsyncAPISchemaContext | None = None, allocator: _ChannelKeyAllocator | None = None, operation_ids: set[str] | None = None) → tuple[dict[str, AsyncAPIChannel], dict[str, AsyncAPIOperation]][source]#

Extract channels and operations defined in Litestar ChannelsPlugin.

Fallback payload schema is unconstrained ({}) rather than {“type”: “object”} because a ChannelsPlugin topic may carry arrays, strings, numbers, or bytes.

Parameters:
  • app – The Litestar application instance.

  • components_schemas – Optional dictionary to collect named component schemas.

  • context – Optional schema context coordinating OpenAPI and DTO support.

  • allocator – Optional allocator to ensure unique channel keys across sources.

  • operation_ids – Optional set to ensure unique operation ids across sources.

Returns:

Tuple of (channels_mapping, operations_mapping). When ChannelsPlugin is not registered on the application, channel extraction returns an empty result.

litestar_vite.codegen.extract_inertia_pages(app: Litestar, *, openapi_schema: dict[str, Any] | None = None, fallback_type: str = 'unknown', openapi_support: OpenAPISupport | None = None) → list[InertiaPageMetadata][source]#

Extract Inertia page metadata from an application.

When multiple handlers map to the same component, GET handlers are preferred since Inertia pages are typically loaded via GET requests.

Parameters:
  • app – Litestar application instance.

  • openapi_schema – Optional OpenAPI schema dict.

  • fallback_type – TypeScript fallback type for unknown types.

  • openapi_support – Optional shared OpenAPISupport instance. If not provided, a new one will be created. Sharing improves determinism and performance.

Returns:

List of InertiaPageMetadata for each discovered page.

litestar_vite.codegen.extract_payload_schema(annotation: Any, components_schemas: dict[str, Any] | None = None) → dict[str, Any][source]#

Convert a Python type annotation to a JSON Schema for AsyncAPI message payloads.

Supports primitives, containers, unions, msgspec.Struct, dataclasses, Pydantic models, TypedDicts, and Enums. Registers complex schemas in components_schemas when provided.

Parameters:
  • annotation – The type annotation to convert.

  • components_schemas – Optional dictionary to collect named component schemas.

Returns:

JSON Schema representation or $ref dictionary for the payload.

litestar_vite.codegen.extract_realtime_channels(app: Litestar, components_schemas: dict[str, Any] | None = None, *, context: AsyncAPISchemaContext | None = None) → tuple[dict[str, AsyncAPIChannel], dict[str, AsyncAPIOperation]][source]#

Extract all real-time channels from WebSocket routes, ChannelsPlugin, and SSE routes.

Parameters:
  • app – The Litestar application instance.

  • components_schemas – Optional dictionary to collect named component schemas.

  • context – Optional schema context coordinating OpenAPI and DTO support.

Returns:

Tuple of (channels_mapping, operations_mapping).

litestar_vite.codegen.extract_route_metadata(app: Litestar, *, only: list[str] | None = None, exclude: list[str] | None = None, openapi_schema: dict[str, Any] | None = None) → list[RouteMetadata][source]#

Extract route metadata from a Litestar application.

Note

openapi_schema is used to resolve accurate type component references. If not provided, it will be generated from the application automatically.

Returns:

A list of RouteMetadata objects.

litestar_vite.codegen.extract_sse_routes(app: Litestar, components_schemas: dict[str, Any] | None = None, *, context: AsyncAPISchemaContext | None = None, allocator: _ChannelKeyAllocator | None = None, operation_ids: set[str] | None = None) → tuple[dict[str, AsyncAPIChannel], dict[str, AsyncAPIOperation]][source]#

Extract Server-Sent Event (SSE) routes from a Litestar application.

Parameters:
  • app – The Litestar application instance.

  • components_schemas – Optional dictionary to collect named component schemas.

  • context – Optional schema context coordinating OpenAPI and DTO support.

  • allocator – Optional allocator to ensure unique channel keys across sources.

  • operation_ids – Optional set to ensure unique operation ids across sources.

Returns:

Tuple of (channels_mapping, operations_mapping).

litestar_vite.codegen.extract_websocket_routes(app: Litestar, components_schemas: dict[str, Any] | None = None, *, context: AsyncAPISchemaContext | None = None, allocator: _ChannelKeyAllocator | None = None, operation_ids: set[str] | None = None) → tuple[dict[str, AsyncAPIChannel], dict[str, AsyncAPIOperation]][source]#

Extract WebSocket routes from a Litestar application into AsyncAPI channels and operations.

Parameters:
  • app – The Litestar application instance.

  • components_schemas – Optional dictionary to collect named component schemas.

  • context – Optional schema context coordinating OpenAPI and DTO support.

  • allocator – Optional allocator to ensure unique channel keys across sources.

  • operation_ids – Optional set to ensure unique operation ids across sources.

Returns:

Tuple of (channels_mapping, operations_mapping).

litestar_vite.codegen.find_asyncapi_plugin(app: Litestar) → Any | None[source]#

Find an AsyncAPI plugin registered on the Litestar application.

Queries Litestar’s plugin registry for a registered AsyncAPIPlugin, guarded by ASYNCAPI_INSTALLED.

Parameters:

app – The Litestar application instance.

Returns:

The registered AsyncAPI plugin instance if found, otherwise None.

litestar_vite.codegen.generate_inertia_pages_json(app: Litestar, *, openapi_schema: dict[str, Any] | None = None, include_default_auth: bool = True, include_default_flash: bool = True, inertia_config: InertiaConfig | None = None, types_config: TypeGenConfig | None = None) → dict[str, Any][source]#

Generate Inertia pages metadata JSON.

The output is deterministic: all dict keys are sorted alphabetically to produce byte-identical output for the same input data.

A single OpenAPISupport instance is shared across both page extraction and shared props building to ensure consistent schema registration and naming. This eliminates non-determinism from split schema registries.

Returns:

An Inertia pages metadata payload as a dictionary with sorted keys.

litestar_vite.codegen.generate_routes_json(app: Litestar, *, only: list[str] | None = None, exclude: list[str] | None = None, include_components: bool = False, openapi_schema: dict[str, Any] | None = None, routes_metadata: list[RouteMetadata] | None = None) → dict[str, Any][source]#

Generate Ziggy-compatible routes JSON.

The output is deterministic: routes are sorted by name to produce byte-identical output for the same input data.

Returns:

A Ziggy-compatible routes payload as a dictionary with sorted keys.

litestar_vite.codegen.generate_routes_ts(app: Litestar, *, only: list[str] | None = None, exclude: list[str] | None = None, openapi_schema: dict[str, Any] | None = None, global_route: bool = False, routes_metadata: list[RouteMetadata] | None = None) → str[source]#

Generate typed routes TypeScript file (Ziggy-style).

The output is deterministic: routes are sorted by name to produce byte-identical output for the same input data.

Returns:

The generated TypeScript source.

litestar_vite.codegen.normalize_asyncapi_document(document: dict[str, Any]) → dict[str, Any][source]#

Normalize an AsyncAPI document into a consistent internal shape.

Guarantees that:

  1. The asyncapi version string is present (‘3.0.0’ or ‘3.1.0’).

  2. Channels are re-keyed into collision-safe litestar-vite format using _ChannelKeyAllocator with protocol-aware source selection.

  3. Every channel has an explicit bindings dictionary with protocol markers.

  4. Operation channel and message $ref pointers match the allocated channel keys.

  5. Root document metadata, servers, and components are preserved intact.

Parameters:

document – Raw AsyncAPI document dictionary.

Returns:

A normalized AsyncAPI document dictionary.

litestar_vite.codegen.resolve_asyncapi_document(app: Litestar, title: str | None = None, version: str | None = None) → tuple[dict[str, Any], str][source]#

Resolve and normalize the AsyncAPI document for a Litestar application.

Probes for a registered AsyncAPI plugin via find_asyncapi_plugin. When found, attempts to retrieve the schema from the plugin via get_asyncapi_schema (or get_asyncapi_json if a non-dict is returned). On any exception or malformed return, or when no plugin is present, falls back seamlessly to create_asyncapi_document.

Both sources are passed through normalize_asyncapi_document to ensure identical internal channel keying and binding semantics for frontend code generation.

Parameters:
  • app – The Litestar application instance.

  • title – Optional title override for the AsyncAPI document.

  • version – Optional version override for the AsyncAPI document.

Returns:

Tuple of (normalized_document_dict, source_name) where source_name is either ‘litestar-asyncapi’ or ‘builtin’.

litestar_vite.codegen.strip_timestamp_for_comparison(content: bytes) → bytes[source]#

Remove generatedAt and other timestamp fields for content comparison.

This allows comparing file content while ignoring fields that change on every generation (like timestamps).

Parameters:

content – JSON content as bytes.

Returns:

JSON content with timestamp fields removed, sorted keys.

litestar_vite.codegen.typegen_outputs_requested(types_config: TypeGenConfig) → bool[source]#

Return whether the typegen config asks for any generated artifact.

litestar_vite.codegen.write_if_changed(path: Path, content: bytes | str, *, normalize_for_comparison: Callable[[bytes], bytes] | None = None, encoding: str = 'utf-8') → bool[source]#

Write content to file only if it differs from the existing content.

Uses hash comparison to avoid unnecessary writes that would trigger file watchers and unnecessary rebuilds. Optionally normalizes content before comparison (e.g., to strip timestamps).

Parameters:
  • path – The file path to write to.

  • content – The content to write (bytes or str).

  • normalize_for_comparison – Optional callback to normalize content before comparison (e.g., strip timestamps). The file is written with the original content, not the normalized version.

  • encoding – Encoding for string content.

Returns:

True if file was written (content changed), False if skipped (unchanged).