Skip to content

Releases: Cratis/Arc

Release v18.7.6

25 Dec 23:27
9ca3e3d

Choose a tag to compare

Fixed

  • The model bound Commands and Queries were missing support for internal types - both runtime and proxy generator now supports this.

Release v18.7.5

25 Dec 09:41
23301d9

Choose a tag to compare

Fixed

  • Improving deterministics regarding proxy generation of Commands and Queries by sorting all input data to the template generator.
  • Fixing a bug were the generator was generating all observable queries as regular queries first and then as observable queries, completely tripping up the hash algorithm for seeing if there were changes.

Release v18.7.4

25 Dec 08:34
aceef96

Choose a tag to compare

Fixed

  • Fixing how we extract the metadata for System.ComponentModel.DataAnnotations based attribute validators. We were using the wrong reflection method to extract this, causing it to crash in the context of the MetadataLoadContext.

Release v18.7.3

25 Dec 08:17
ddaa819

Choose a tag to compare

Fixed

  • Fixing validation rule extraction for the proxy generator, it now supports both FluentValidation and System.ComponentModel.DataAnnotations types properly.
  • Fixing missing JSDoc comments for types in general in the proxy generator
  • Adding a hash to the generated proxies of the content, used to not write new files unless they have actually changed.
  • Ensuring that validators for commands and queries are generated for all circumstances.

Release v18.7.2

23 Dec 11:37
60032fe

Choose a tag to compare

Fixed

  • Removing the traces of the GeneratedFIleIndex from the ProxyGenerator as we now maintain the index while building and do not need to generate a file to understand what is orphaned files for deletion.

Release v18.7.1

23 Dec 11:24
31ccca1

Choose a tag to compare

Fixed

  • FIxing so that consumers of the Cratis package get the GlobalUsings defined by the package injected into the build of their project.
  • Fixing a bug causing the proxy generator to classify some newly generated proxies as orphans and then just deleting them.

Release v18.7.0

23 Dec 07:35
6d3bac2

Choose a tag to compare

Added

  • Cratis package - Single-package dependency that bundles Arc, Chronicle, and Swagger with unified configuration API
    • builder.AddCratis() - Configures all services (Arc + Chronicle + Swagger)
    • app.UseCratis() - Registers middlewares and endpoints

Release v18.6.0

20 Dec 23:37
a2310c6

Choose a tag to compare

Summary

Implements client-side validation governed by backend FluentValidation rules. The ProxyGenerator extracts validation rules from AbstractValidator<> implementations using reflection and generates TypeScript validation code, enabling pre-flight validation before server calls without requiring version parity between ProxyGenerator and target assemblies.

Added

  • TypeScript validation rules engine with fluent API similar to FluentValidation
    • Core rules: notEmpty(), notNull(), minLength(), maxLength(), length(), emailAddress(), matches(), greaterThan(), lessThan(), etc.
    • Validator<T> class for programmatically building property validation rules with ruleFor() method
    • PropertyRule base class and rule-specific implementations with default error messages
    • withMessage() support on RuleBuilder for custom validation error messages
  • QueryValidator for validating query parameters (extends Validator<T>)
  • ValidationRulesExtractor in ProxyGenerator to extract rules from FluentValidation validators using pure reflection and string-based type checking
  • Validation descriptors (ValidationRuleDescriptor, PropertyValidationDescriptor) for template generation

Example

Backend validator:

public class CreateUserValidator : BaseValidator<CreateUserCommand>
{
    public CreateUserValidator()
    {
        RuleFor(x => x.Email).NotEmpty().WithMessage("Email address is required");
        RuleFor(x => x.Age).GreaterThanOrEqual(18);
    }
}

Generated TypeScript:

export class CreateUserCommandValidator extends CommandValidator<ICreateUserCommand> {
    constructor() {
        super();
        this.ruleFor(c => c.email).notEmpty().withMessage('Email address is required');
        this.ruleFor(c => c.age).greaterThanOrEqual(18); // Uses default: "'age' must be greater than or equal to 18."
    }
}

Client validation runs automatically:

const command = new CreateUserCommand();
command.email = ""; // Invalid
const result = await command.execute(); // Fails client-side validation
// result.isValid === false
// result.validationResults contains error details with appropriate messages
Original prompt

This section details on the original issue you should resolve

<issue_title>Support for client validation rules governed by the backend</issue_title>
<issue_description>The backend should govern all validation rules. But these should be automatically be picked up by the proxy generator and added to the proxy objects so that the client can perform validation.

We can only support out of the box validation rules and not type of .Must() rules. That means the out-of-the-box FluentValidation rules that look at input validation.

Frontend rules engine

We need a simple TypeScript based rules engine sitting in the Arc project under the validation folder. There is stuff there already, but feel free to expand on it, or replace whatever makes sense.
It should be possible to use the rule engine programmatically and should feel similar to how FluentValidation works with its fluent interface for building rules for a type and its properties. It can leverage the PropertyPath resolver proxy handler that we have in @cratis/fundamentals (https://github.com/Cratis/Fundamentals/blob/main/Source/JavaScript/PropertyPathResolverProxyHandler.ts) to create a nice fluent interface for being able o type safe specify which properties to add a rule to.

Make it extensible and follow the same pattern as FluentValidation where the rules are extension methods. Leverage abstract classes for interfaces if needed.

ProxyGenerator

The Proxy generator needs to then understand anything that implements an AbstractValidator<> for the type and use reflection to understand what rules to apply.

The TypeScript code has the concept of a CommandValidator that implements the Validator, this is already present in the command.hbs. This is the thing that needs to contain the generated rules.

We need a similar thing for the query.hbs and a similar QueryValidator.

Commands & Queries

Before we execute commands or perform queries towards the server, we should run the associated validator. The result should still be a CommandResult or a QueryResult and we would then fill in the validation result of these correctly.

</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Release v18.5.0

19 Dec 12:59
7b341da

Choose a tag to compare

Added

  • Add support for add column extensions for EFCore migrations that are multi-database type friendly (#1527).
  • JSDoc generation of XML documentation in the ProxyGenerator for commands and queries (#59).
  • Adding ping/pong for WebSockets - introducing a protocol that server and client understands. Implemented for both backend and frontend (#19).
  • Type safe deserialization support for identity details objects when using the useIdentity() or underlying IdentityProvider in the frontend. This works in conjunction with the @field() decorators from @cratis/fundamentals and is also what the ProxyGenerator generates for typed IProvideIdentityDetails<> implementations.
  • Making the ProxyGenerator co-edit the index.ts file by understanding the exports and maintaining it properly. (#1533)
  • Adding a way to disable generation of the index.ts for the ProxyGenerator.
  • Adding support for observing EntityFramework DbSet<>, similar to what we have for MongoDB with .Observe() extension methods (#1524).

Fixed

  • React useObservableQuery() now gets the correct initial state for isPerforming (#1483).
  • Bringing back suppport for the [Authorize] attribute for ASP.NET controller based commands and queries. This was an oversight when we split Arc into Arc.Core without the dependency to ASP.NET Core (#1567).
  • Improve file tracking to be more source control friendly by dropping the generated file index. (#1533)
  • Fixing so that the order in a tuple returned from a model-bound command does not matter with regards to value resolution (#1535).

Release v18.4.3

18 Dec 10:25
cd9b455

Choose a tag to compare

Changed

  • Replaced polly.core package dependency with Microsoft.Extensions.Resilience, Microsoft's recommended resilience library for .NET 8+ applications
  • Updated retry predicate from PredicateBuilder().Handle<Exception>() to lambda-based predicate: args => args.Outcome.Exception is not null ? PredicateResult.True() : PredicateResult.False()
  • Configured framework-specific package versions:
    • .NET 10: Version 10.1.0 (in Directory.Packages.props)
    • .NET 8-9: Version 9.10.0 (in Directory.Packages.NET8-9.props)

Technical note: Microsoft.Extensions.Resilience is built on Polly v8, so core types (ResiliencePipeline, ResiliencePipelineBuilder) remain in the Polly namespace. No changes required to interceptors or test code beyond package references.

Original prompt

This section details on the original issue you should resolve

<issue_title>Switch to Microsoft.Extensions.Resilience</issue_title>
<issue_description>We’re using Polly for resilience in the MongoDB project in interceptors.
Goal is to get rid of Polly and use the new Microsoft Extensions.

You can read more in details about how it works here</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.