Releases: Cratis/Arc
Release v18.7.6
Fixed
- The model bound Commands and Queries were missing support for
internaltypes - both runtime and proxy generator now supports this.
Release v18.7.5
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
Fixed
- Fixing how we extract the metadata for
System.ComponentModel.DataAnnotationsbased attribute validators. We were using the wrong reflection method to extract this, causing it to crash in the context of theMetadataLoadContext.
Release v18.7.3
Fixed
- Fixing validation rule extraction for the proxy generator, it now supports both FluentValidation and
System.ComponentModel.DataAnnotationstypes 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
Fixed
- Removing the traces of the
GeneratedFIleIndexfrom 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
Fixed
- FIxing so that consumers of the
Cratispackage get theGlobalUsingsdefined 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
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
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 withruleFor()methodPropertyRulebase class and rule-specific implementations with default error messageswithMessage()support onRuleBuilderfor custom validation error messages
- Core rules:
QueryValidatorfor validating query parameters (extendsValidator<T>)ValidationRulesExtractorin 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 messagesOriginal 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.hbsand a similarQueryValidator.Commands & Queries
Before we execute commands or perform queries towards the server, we should run the associated validator. The result should still be a
CommandResultor aQueryResultand we would then fill in the validation result of these correctly.</issue_description>
Comments on the Issue (you are @copilot in this section)
- Fixes #427
✨ 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
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 underlyingIdentityProviderin the frontend. This works in conjunction with the@field()decorators from@cratis/fundamentalsand is also what the ProxyGenerator generates for typedIProvideIdentityDetails<>implementations. - Making the ProxyGenerator co-edit the
index.tsfile by understanding the exports and maintaining it properly. (#1533) - Adding a way to disable generation of the
index.tsfor 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 forisPerforming(#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
Changed
- Replaced
polly.corepackage dependency withMicrosoft.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)
- .NET 10: Version 10.1.0 (in
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)
- Fixes #294
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.