Skip to content

Decorator reference

Arc for TypeScript discovers what your application exposes from decorators on your classes, the way Arc on .NET uses attributes. This is the whole set, grouped by concern. Decorators come from @cratis/arc.core unless the table says otherwise. Both standard decorators and legacy experimentalDecorators are supported.

DecoratorValid onEffect.NET
@command({ namespace?, treatWarningsAsErrors? })classMarks a command; Arc exposes it and calls its instance handle(). treatWarningsAsErrors sets the generated client’s flag[Command]
@readModel({ namespace? })classMarks a read model; its @query() static methods become queries[ReadModel]
@query(options?, ...descriptors)public static method of a read modelMarks a query; options is { observable?, argumentsModel?, httpMethod?, treatWarningsAsErrors? }. httpMethod takes a QueryHttpMethod member and, like treatWarningsAsErrors, sets a generated client preferenceStatic method on a [ReadModel]
@validator(Target)class extending CommandValidator, QueryValidator, ConceptValidator, or ModelValidatorAssociates the validator with its exact target typeDiscovered AbstractValidator<T>
DecoratorValid onEffect.NET
@field(Type, ...) from @cratis/fundamentalspublic instance fieldDeclares the field and its wire typeThe property’s CLR type
@key()fieldThe command key, and the storage identity of a read model[Key]
@optional()fieldThe field may be omitted on inputNullable reference type
@nullable()fieldThe field may be nullNullable type
@defaultValue(value)fieldOmitted input takes this valueDefault parameter value
@enumeration(EnumObject)scalar fieldRestricts the value to the members of an enum objectEnum-typed property
@derivedType('id') from @cratis/fundamentalsclassRegisters a polymorphic subtype, written as _derivedTypeIdFundamentals derived types
DecoratorValid onEffect.NET
@path('/api/...')command or read-model class, @query() methodOverrides the derived route[Path]

The counterpart of [QueryHttpMethod] is the httpMethod option: @query({ httpMethod: QueryHttpMethod.Query }), with QueryHttpMethod from @cratis/arc.core, makes the generated client send QUERY. Get and Auto are the other members. The option does not change the server, which accepts GET and QUERY unless generatedApis.enableQueryHttpMethod is false. There is no equivalent of [FromRequest]: arguments bind from the query string or QUERY body.

DecoratorValid onEffect.NET
@authorize()class, @query() methodRequires an authenticated caller[Authorize]
@authorize('Policy') or @authorize({ policy?, roles?, schemes? })class, @query() methodRequires a policy, any listed role, and/or a named scheme[Authorize(Policy = ...)]
@roles('A', 'B')class, @query() methodRequires at least one of the roles[Roles]
@allowAnonymous()class, @query() methodAllows everyone[AllowAnonymous]

Stacked declarations on the same target must all pass; an explicit query method declaration replaces its read-model class declaration. Without method decorators, the class declaration applies. Command authorization belongs on its class: decorators on handle(), provide(), any other command method, or a non-query static method fail at build.

DecoratorValid onEffect.NET
@inject(...tokens)command handle() or provide()One token or marker per parameter, in orderMethod parameter injection
@injectable(...tokens)classConstructor dependencies; static inject = [...] as const is equivalentConstructor injection
@singleton(), @scoped(), @transient()classRegisters a discovered service with that lifetimeService lifetime conventions
DecoratorValid onEffect
@commandResponseValueHandler()class implementing CommandResponseValueHandlerRegisters a scoped response value handler
@queryRenderer()class implementing QueryRendererRegisters a scoped query renderer
@readModelInterceptor()class implementing ReadModelInterceptorRegisters a scoped read-model interceptor
@identityDetailsProvider()class implementing IdentityDetailsProviderRegisters the identity details provider

These are not decorators, but you pass them to @query(...) and @inject(...):

DescriptorUsed inBinds
argument(name, Type, { optional?, elementType? })@queryA named query argument
service(Token)@queryA service
queryOptions()@queryThe request’s paging and sorting
abortSignal()@injectThe request’s AbortSignal
commandContext()@injectThe CommandContext
provided(Type)@inject on handle()A value from provide(), by runtime type
commandReadModel(Type, { optional? })@injectA read model loaded by the command key
mongoCollection(Model) from @cratis/arc.mongodbservice(...) or @injectThe tenant’s MongoDB collection
drizzleReadModel(Model), drizzleDatabase() from @cratis/arc.drizzleservice(...) or @injectThe tenant’s read-only SQL handle or writable database

From @cratis/arc.chronicle (experimental):

DecoratorValid onEffect.NET
@eventSourceType('Type', { concurrency? })command classDefault event source type for returned eventsCommand event metadata
@eventStreamType('Type', { concurrency? })command classDefault event stream typeCommand event metadata
@eventStreamId('id', { concurrency? })command classDefault event stream IDCommand event metadata
@eventSourceDefinition(Source, 'Stream'?)command or aggregate classRoute events through a Chronicle event source definition and streamEvent source definitions
@eventSubject('subject')command classDefault compliance subjectCommand event metadata
@notAudited()command fieldKeeps the value out of the causation chain[NotAudited]

Event types, projections, and Chronicle read models use the SDK’s own decorators, such as @eventType() from @cratis/chronicle/events.