Skip to content

Analyze Arc server artifacts

Use @cratis/eslint-plugin-arc-core to find model-bound binding mistakes before you build or start an Arc server. This is a publishable 0.x source preview (not yet published); it does not lint the existing Arc frontend packages. The existing @cratis/eslint-plugin-arc name belongs to the frontend repository.

Configure ESLint 10 with typescript-eslint (which installs @typescript-eslint/parser) and type information for the binding rules:

import arc from '@cratis/eslint-plugin-arc-core';
import tseslint from 'typescript-eslint';
export default tseslint.config(
...tseslint.configs.recommended,
arc.configs['recommended-type-checked']
);

Run eslint src. Both presets enable the mapped ARC diagnostics, three Chronicle rules, and TypeScript-only rules below, except the opt-in name rule. recommended works without type information: type-dependent comparisons are skipped, while syntax checks still run. recommended-type-checked enables parserOptions.projectService to check parameter and token types and adds arcchr0006 and arcchr0010; files without an applicable tsconfig must be excluded or added to the project service. Both presets require a TypeScript parser. Arc decorators must resolve to imports from @cratis/arc.core, and @field must come from @cratis/fundamentals (including aliases and namespace imports); custom wrappers are not recognized. Runtime and proxy-generator checks remain authoritative.

The .NET IDs are retained only when the same mistake can happen in the TypeScript API. The columns distinguish a behavior analog from a verbatim Roslyn rule.

.NET diagnosticTypeScript statusReason
ARC0001N/ATypeScript queries intentionally permit arbitrary result shapes; they do not enforce a read-model return type.
ARC0002AnalogA class with public fields and an instance handle() may be an undecorated command.
ARC0003AnalogExternal handle(command: DecoratedCommand) methods do not run as command handlers.
ARC0004AnalogA command needs an instance handle() (including inherited handlers); TypeScript private is runtime-callable.
ARC0005AnalogA direct provide() value with no handler parameters is discarded; this rule does not infer control outcomes or nested returns.
ARC0006N/AcommandReadModel(Type) rejects a missing model unless you pass { optional: true }, so the choice is already explicit in the declaration.
ARC0007–ARC0009N/ATypeScript has classes, not C# records; Concepts are classes extending ConceptAs.
ARC0010AnalogAsync handle() without await, for-await, or a returned value wraps a synchronous result.
ARC0011N/ATypeScript does not have nameof; roles are strings.
ARC0012AnalogBuilt-in errors from decorated artifacts obscure domain failures.
ARC0013N/AArc captures ruleFor paths using a Proxy, does not invoke selectors on input, walks paths null-safely, and unwraps concepts automatically.
ARC0014AnalogHTTP cannot supply generic type arguments to @query.
ARC0015AnalogPrimitive query parameter converted to ConceptAs inside a query skips concept validation; command handler parameters are service or provided values, not wire inputs.
ARC0016–ARC0018N/ATypeScript operations are explicit returned CommandOperation objects, not C# annotated methods or generated invokers.
ARC0019Analog@allowAnonymous() conflicts with @authorize() or @roles() on one declaration.
ARC0020–ARC0021N/AASP.NET Core attributes and authentication schemes do not exist in this Node host.

Chronicle analogs: ARCCHR0003, type-checked ARCCHR0006, ARCCHR0007, ARCCHR0009, and type-checked ARCCHR0010. See Chronicle code analysis for the complete .NET ARCCHR mapping, including diagnostics without TypeScript equivalents.

TypeScript-only rules: missing-field, declared-field, inject-binding, query-binding, query-argument-name (opt-in), misplaced-decorator, unexported-artifact, and validator-target. No automatic fix is offered: .NET’s Task unwrap fix changes async rejection semantics in JavaScript; its nameof fix has no TypeScript equivalent. Manual fixes are shown on each page.