---
title: What the generator writes
editUrl: https://github.com/Cratis/Arc.TypeScript/edit/main/Documentation/proxy-generation/generated-code.md
description: The structure of generated command classes, query classes, parameters interfaces, models, and barrels, and the exact React hook signatures each query shape receives.
---


This page describes the generated files so you can read them, import from them, and predict what changes when the backend changes. Never edit them: the next run replaces any file that carries the `@generated by Cratis` header. The excerpts come from the Library and Tasks samples.

## Files and folders

| Backend artifact | Generated file |
| --- | --- |
| `@command()` class `RegisterAuthor` in `Features/Authors/Registration/Registration.ts` | `Features/Authors/Registration/RegisterAuthor.proxy.ts` |
| `@readModel()` class `Author` in `Features/Authors/Listing/Listing.ts` | `Features/Authors/Listing/Author.proxy.ts`, the model |
| `@query()` method `allAuthors` on `Author` | `Features/Authors/Listing/AllAuthors.proxy.ts`, named after the method in PascalCase |
| A `@field` model used by a command, query, or identity provider | A model file in its own namespace folder |
| Separate output folder only | `index.ts`, exporting generated files; no barrels are emitted in co-located mode |

Use `--artifacts Features --output Features --use-proxy-file-suffix` (absolute paths in a script) for the co-located layout. The suffix is required when the output is the artifacts folder or one of its ancestors, or a nested folder that contains backend artifacts (see [Configuration](/arc/backend/typescript/proxy-generation/configuration/)); with a dedicated output folder it is optional and files can end in `.ts`. Namespaces come from the discovery folder, or from an explicit `namespace` option, prefixed with `--root-namespace` when you set one. If the namespace or skipped segments change the generated path, check where it lands before importing it.

## Commands

For each command the file holds an interface, a validator when the command has client-safe rules, and the command class:

```typescript title="Authors/Registration/RegisterAuthor.proxy.ts (excerpt)"
export interface IRegisterAuthor {
    id?: Guid;
    name?: string;
}

export class RegisterAuthorValidator extends CommandValidator<IRegisterAuthor> {
    constructor() {
        super();
        this.ruleFor(c => c.name).notEmpty().withMessage('An author name is required');
        this.ruleFor(c => c.name).maxLength(100).withMessage('An author name cannot exceed 100 characters');
    }
}

export class RegisterAuthor extends Command<IRegisterAuthor> implements IRegisterAuthor {
    readonly route: string = '/api/authors/registration/register-author';
    readonly validation: CommandValidator = new RegisterAuthorValidator();
    readonly treatWarningsAsErrors: boolean = false;
    readonly roles: string[] = ['Librarian'];
```

| Member | Comes from |
| --- | --- |
| `I<Command>` interface | Every `@field` property, optional in the interface so you can fill it gradually |
| `<Command>Validator` | The literal, unconditional rules of the command's validators and of concept validators such as `AuthorNameValidator`; see [Validation rules](/arc/backend/typescript/proxy-generation/validation/) |
| Base class | `Command<IRegisterAuthor>` when `handle()` returns nothing for the client; `Command<IRegisterTask, Guid>` when it returns a value, here the Tasks sample's `TaskId` |
| `route` | The server's convention route, using the [route alignment](/arc/backend/typescript/proxy-generation/configuration/#route-alignment) options |
| `roles` | `@roles(...)` on the command, for display decisions only |
| `treatWarningsAsErrors` | `@command({ treatWarningsAsErrors: true })` |
| Properties | A getter and setter per field, with change tracking |
| `static use(initialValues?)` | Returns `[command, setValues, clearValues]` for React |

Values that `handle()` returns for the server, such as Chronicle events or [command operations](/arc/backend/typescript/commands/operations/), are not part of the client response. [Type mapping](/arc/backend/typescript/proxy-generation/type-mapping/#return-types) lists each return shape.

## Queries

Each query method becomes a class. A query with arguments also gets a parameters interface, named `<Query>Parameters` with no `I` prefix:

```typescript title="Books/Listing/BooksForAuthor.proxy.ts (excerpt)"
export interface BooksForAuthorParameters {
    authorId: Guid;
}

export class BooksForAuthor extends ObservableQueryFor<Book[], BooksForAuthorParameters> {
    readonly route: string = '/api/books/listing/books-for-author';
    readonly queryName: string = 'Books.Listing.Book.booksForAuthor';
    readonly treatWarningsAsErrors: boolean = false;
    readonly roles: string[] = [];
    readonly defaultValue: Book[] = [];
```

| Member | Meaning |
| --- | --- |
| Base class | `QueryFor<TResult, TParameters>` for a snapshot, `ObservableQueryFor<TResult, TParameters>` when the method returns an observable source |
| `queryName` | The fully qualified name the server uses for hub subscriptions |
| `defaultValue` | What `result.data` holds before the first answer: `[]` for a list, `{} as TModel` for a single model |
| `sortBy` | For list results, one sort helper per model field, as a static and an instance property; complex-field helpers are deprecated for removal in the next major release |
| `parameterDescriptors`, `requiredRequestParameters` | The arguments, so the client can wait until required ones are set |
| `validation` | A `QueryValidator` when the query's arguments have client-safe rules |

A query without arguments has no parameters interface, and its hooks take `sorting` as the first argument.

## Hook signatures

`result` is a `QueryResultWithState<TResult>` in every row. `args` appears only for queries with arguments.

| Query shape | Hook | Returns |
| --- | --- | --- |
| Snapshot, single result | `use(args?)`, `useSuspense(args?)` | `[result, perform, setSorting]` |
| Snapshot, list | `use(args?, sorting?)`, `useSuspense(args?, sorting?)` | `[result, perform, setSorting]` |
| Snapshot, list | `useWithPaging(pageSize, args?, sorting?)`, `useSuspenseWithPaging(...)` | `[result, perform, setSorting, setPage, setPageSize]` |
| Observable, single result | `use(args?)`, `useSuspense(args?)` | `[result]` |
| Observable, list | `use(args?, sorting?)`, `useSuspense(args?, sorting?)` | `[result, setSorting]` |
| Observable, list | `useWithPaging(pageSize, args?, sorting?)`, `useSuspenseWithPaging(...)` | `[result, setSorting, setPage, setPageSize]` |
| Observable, list | `useChangeStream(args?, getKey?, sorting?)` | `ChangeSet<TModel>` with `added`, `replaced`, and `removed` |
| Any | `when(condition)` | A builder with the same hooks, enabled only while `condition` is true |

Only list results get paging, sorting helpers, and change streams. That is a client API rule; the server decides how it pages. See [Paging](/arc/backend/typescript/queries/model-bound/paging/).

## Models

A read model or nested `@field` class becomes a class with the same `@field` declarations, so the client deserializes JSON into real types:

```typescript title="Authors/Listing/Author.proxy.ts (excerpt)"
export class Author {
    @field(Guid)
    id!: Guid;

    @field(String)
    name!: string;
}
```

The server declares `@field(AuthorId) id` and `@field(AuthorName) name`. Concepts arrive as their underlying types, here `Guid` and `string`, because the wire carries only the value. With `--emit-interfaces` the generator writes interfaces instead, which carry no runtime metadata. The identity provider's `detailsType` is generated the same way, for [`useIdentity`](/arc/backend/typescript/identity/frontend/).

## Related

- [Use generated proxies in React](/arc/backend/typescript/proxy-generation/frontend-usage/)
- [Type mapping](/arc/backend/typescript/proxy-generation/type-mapping/)
- [Validation rules](/arc/backend/typescript/proxy-generation/validation/)
- [File index tracking](/arc/backend/typescript/proxy-generation/file-index-tracking/)
