Skip to content

Commit f678387

Browse files
authored
Merge branch 'main' into redis-topic-prefix
2 parents f423be8 + 0d38466 commit f678387

File tree

1,009 files changed

+41618
-7374
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,009 files changed

+41618
-7374
lines changed

.editorconfig

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ rulers = 120
1212
# ReSharper properties
1313
resharper_align_multiline_statement_conditions = false
1414
resharper_braces_for_ifelse = not_required
15-
resharper_wrap_object_and_collection_initializer_style = chop_always
15+
resharper_keep_existing_initializer_arrangement = false
16+
resharper_trailing_comma_in_multiline_lists = false
17+
resharper_wrap_object_and_collection_initializer_style = wrap_if_long
1618

1719
# Microsoft .NET properties
18-
csharp_new_line_before_members_in_object_initializers = true
20+
csharp_new_line_before_members_in_object_initializers = false
1921

2022
[*.md]
2123
trim_trailing_whitespace = false

.github/workflows/release.yml

Lines changed: 124 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Release
1+
name: 🚀 Release
22

33
on:
44
push:
@@ -7,51 +7,130 @@ on:
77

88
jobs:
99
release:
10+
name: 📦 Build & Publish NuGet Packages
1011
runs-on: ubuntu-22.04
1112
permissions:
1213
contents: write
1314
steps:
14-
- name: Checkout
15-
uses: actions/checkout@v4
16-
with:
17-
show-progress: false
18-
19-
- name: Install .NET
20-
uses: actions/setup-dotnet@v4
21-
with:
22-
dotnet-version: |
23-
8.x
24-
9.x
25-
26-
- name: Get the version
27-
id: get_version
28-
run: echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
29-
30-
- name: Build Packages
31-
run: |
32-
./build.sh pack --SemVersion ${{ env.GIT_TAG }} --Configuration Release
33-
34-
- name: Push Packages
35-
run: |
36-
./build.cmd publish --skip
37-
env:
38-
NuGetApiKey: ${{ secrets.NUGETAPIKEY }}
39-
40-
- name: Get release
41-
id: get_release
42-
run: |
43-
RELEASE_ID=$(gh api repos/ChilliCream/graphql-platform/releases/tags/${{ env.GIT_TAG }} --jq '.id')
44-
UPLOAD_URL=$(gh api repos/ChilliCream/graphql-platform/releases/$RELEASE_ID --jq '.upload_url')
45-
echo "RELEASE_ID=$RELEASE_ID" >> $GITHUB_ENV
46-
echo "UPLOAD_URL=${UPLOAD_URL}" >> $GITHUB_ENV
47-
env:
48-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
49-
50-
- name: Upload Release Assets
51-
run: |
52-
for file in ./output/packages/*.nupkg; do
53-
echo "Uploading $file"
54-
gh release upload ${{ env.GIT_TAG }} "$file" --repo ChilliCream/graphql-platform
55-
done
56-
env:
57-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
15+
- name: 📦 Checkout
16+
uses: actions/checkout@v4
17+
with:
18+
show-progress: false
19+
20+
- name: 🛠 Install .NET
21+
uses: actions/setup-dotnet@v4
22+
with:
23+
dotnet-version: |
24+
8.x
25+
9.x
26+
27+
- name: 🏷 Get the version from tag
28+
id: get_version
29+
run: echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
30+
31+
- name: 📦 Build NuGet Packages
32+
run: |
33+
./build.sh pack --SemVersion ${{ env.GIT_TAG }} --Configuration Release
34+
35+
- name: 🚀 Push Packages to NuGet
36+
run: |
37+
./build.cmd publish --skip
38+
env:
39+
NuGetApiKey: ${{ secrets.NUGETAPIKEY }}
40+
41+
- name: 🔎 Get GitHub Release Info
42+
id: get_release
43+
run: |
44+
RELEASE_ID=$(gh api repos/ChilliCream/graphql-platform/releases/tags/${{ env.GIT_TAG }} --jq '.id')
45+
UPLOAD_URL=$(gh api repos/ChilliCream/graphql-platform/releases/$RELEASE_ID --jq '.upload_url')
46+
echo "RELEASE_ID=$RELEASE_ID" >> $GITHUB_ENV
47+
echo "UPLOAD_URL=${UPLOAD_URL}" >> $GITHUB_ENV
48+
env:
49+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
50+
51+
- name: 📤 Upload .nupkg Release Assets
52+
run: |
53+
for file in ./output/packages/*.nupkg; do
54+
echo "📤 Uploading $file"
55+
gh release upload ${{ env.GIT_TAG }} "$file" --repo ChilliCream/graphql-platform
56+
done
57+
env:
58+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
59+
60+
build-aot:
61+
name: 🧱 Build and Publish Fusion Tooling
62+
runs-on: ${{ matrix.os }}
63+
permissions:
64+
contents: write
65+
strategy:
66+
matrix:
67+
include:
68+
# Linux (x64)
69+
- os: ubuntu-22.04
70+
rid: linux-x64
71+
ext: ""
72+
- os: ubuntu-22.04
73+
rid: linux-musl-x64
74+
ext: ""
75+
# Linux (arm64 on ARM runner!)
76+
- os: ubuntu-24.04-arm
77+
rid: linux-arm64
78+
ext: ""
79+
# macOS
80+
- os: macos-15
81+
rid: osx-x64
82+
ext: ""
83+
- os: macos-15
84+
rid: osx-arm64
85+
ext: ""
86+
# Windows
87+
- os: windows-2025
88+
rid: win-x64
89+
ext: ".exe"
90+
- os: windows-2025
91+
rid: win-x86
92+
ext: ".exe"
93+
# Windows (arm64 on ARM runner!)
94+
- os: windows-11-arm
95+
rid: win-arm64
96+
ext: ".exe"
97+
98+
steps:
99+
- name: 📦 Checkout
100+
uses: actions/checkout@v4
101+
102+
- name: 🛠 Install .NET
103+
uses: actions/setup-dotnet@v4
104+
with:
105+
dotnet-version: 9.x
106+
107+
- name: 🧩 Publish AOT Binary for ${{ matrix.rid }}
108+
shell: bash
109+
run: |
110+
dotnet publish ./src/HotChocolate/Fusion-vnext/src/Fusion.CommandLine \
111+
-c Release \
112+
-r ${{ matrix.rid }} \
113+
-f net9.0 \
114+
--self-contained true \
115+
-p:PublishAot=true \
116+
-p:TargetFrameworks=NET9.0 \
117+
-o ./publish
118+
119+
- name: 📦 Zip Binary (Windows)
120+
if: runner.os == 'Windows'
121+
run: Compress-Archive -Path publish/fusion.exe -DestinationPath fusion-${{ matrix.rid }}.zip
122+
shell: pwsh
123+
124+
- name: 📦 Zip Binary (Unix)
125+
if: runner.os != 'Windows'
126+
run: |
127+
cd publish
128+
zip ../fusion-${{ matrix.rid }}.zip fusion${{ matrix.ext }}
129+
shell: bash
130+
131+
- name: 📤 Upload Zipped AOT Binary
132+
shell: bash
133+
run: |
134+
gh release upload ${{ github.ref_name }} fusion-${{ matrix.rid }}.zip --repo ${{ github.repository }}
135+
env:
136+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.markdownlint.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ MD033:
2727
- u
2828
- Video
2929
MD036: false # Rationale: Possibly too strict, used frequently in documentation.
30+
MD059: false # Rationale: Already used in many places in the documentation.

src/All.slnx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,11 @@
6767
<Folder Name="/HotChocolate/Caching/" />
6868
<Folder Name="/HotChocolate/Caching/src/">
6969
<Project Path="HotChocolate/Caching/src/Caching/HotChocolate.Caching.csproj" />
70+
<Project Path="HotChocolate/Caching/src/Caching.Memory/HotChocolate.Caching.Memory.csproj" />
7071
</Folder>
7172
<Folder Name="/HotChocolate/Caching/test/">
7273
<Project Path="HotChocolate/Caching/test/Caching.Tests/HotChocolate.Caching.Tests.csproj" />
74+
<Project Path="HotChocolate/Caching/test/Caching.Memory.Tests/HotChocolate.Caching.Memory.Tests.csproj" />
7375
</Folder>
7476
<Folder Name="/HotChocolate/Core/" />
7577
<Folder Name="/HotChocolate/Core/src/">
@@ -143,12 +145,10 @@
143145
</Folder>
144146
<Folder Name="/HotChocolate/Data/" />
145147
<Folder Name="/HotChocolate/Data/src/">
146-
<Project Path="HotChocolate/Data/src/AutoMapper/HotChocolate.Data.AutoMapper.csproj" />
147148
<Project Path="HotChocolate/Data/src/Data/HotChocolate.Data.csproj" />
148149
<Project Path="HotChocolate/Data/src/EntityFramework/HotChocolate.Data.EntityFramework.csproj" />
149150
</Folder>
150151
<Folder Name="/HotChocolate/Data/test/">
151-
<Project Path="HotChocolate/Data/test/Data.AutoMapper.Tests/HotChocolate.Data.AutoMapper.Tests.csproj" />
152152
<Project Path="HotChocolate/Data/test/Data.EntityFramework.Pagination.Tests/HotChocolate.Data.EntityFramework.Pagination.Tests.csproj" />
153153
<Project Path="HotChocolate/Data/test/Data.EntityFramework.Tests/HotChocolate.Data.EntityFramework.Tests.csproj" />
154154
<Project Path="HotChocolate/Data/test/Data.Filters.InMemory.Tests/HotChocolate.Data.Filters.InMemory.Tests.csproj" />

src/Directory.Packages.props

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
<PackageVersion Include="Aspire.Hosting.PostgreSQL" Version="8.0.0" />
1010
<PackageVersion Include="Aspire.Hosting.RabbitMQ" Version="8.0.0" />
1111
<PackageVersion Include="Aspire.Hosting.Redis" Version="8.0.0" />
12-
<PackageVersion Include="AutoMapper" Version="10.1.1" />
1312
<PackageVersion Include="Azure.Storage.Blobs" Version="12.23.0" />
1413
<PackageVersion Include="Basic.Reference.Assemblies.Net80" Version="1.7.8" />
1514
<PackageVersion Include="Basic.Reference.Assemblies.Net90" Version="1.7.8" />

src/GreenDonut/src/GreenDonut.Data.EntityFramework/Expressions/ExtractSelectExpressionVisitor.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
1212
{
1313
if (node.Method.Name == _selectMethod && node.Arguments.Count == 2)
1414
{
15-
var lambda = StripQuotes(node.Arguments[1]);
15+
var lambda = ConvertToLambda(node.Arguments[1]);
1616
if (lambda.Type.IsGenericType
1717
&& lambda.Type.GetGenericTypeDefinition() == typeof(Func<,>))
1818
{
@@ -29,13 +29,20 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
2929
return base.VisitMethodCall(node);
3030
}
3131

32-
private static LambdaExpression StripQuotes(Expression e)
32+
private static LambdaExpression ConvertToLambda(Expression e)
3333
{
3434
while (e.NodeType == ExpressionType.Quote)
3535
{
3636
e = ((UnaryExpression)e).Operand;
3737
}
3838

39-
return (LambdaExpression)e;
39+
if (e.NodeType != ExpressionType.MemberAccess)
40+
{
41+
return (LambdaExpression)e;
42+
}
43+
44+
// Convert the property expression into a lambda expression
45+
var typeArguments = e.Type.GetGenericArguments()[0].GetGenericArguments();
46+
return Expression.Lambda(e, Expression.Parameter(typeArguments[0]));
4047
}
4148
}

src/GreenDonut/src/GreenDonut.Data/Extensions/GreenDonutPageExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public static ImmutableArray<PageCursor> CreateRelativeForwardCursors<T>(this Pa
112112
return [];
113113
}
114114

115-
var totalPages = (page.TotalCount ?? 0) / (page.RequestedSize ?? 10);
115+
var totalPages = Math.Ceiling((double)(page.TotalCount ?? 0) / (page.RequestedSize ?? 10));
116116

117117
if (page.Index >= totalPages)
118118
{

src/GreenDonut/test/GreenDonut.Data.EntityFramework.Tests/PagingHelperIntegrationTests.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Linq.Expressions;
12
using GreenDonut.Data.TestContext;
23
using Microsoft.EntityFrameworkCore;
34
using Microsoft.Extensions.DependencyInjection;
@@ -178,6 +179,45 @@ await CreateSnapshot()
178179
.MatchMarkdownAsync();
179180
}
180181

182+
[Fact]
183+
public async Task Paging_WithChildCollectionProjectionExpression_First_5()
184+
{
185+
// Arrange
186+
var connectionString = CreateConnectionString();
187+
await SeedAsync(connectionString);
188+
using var capture = new CapturePagingQueryInterceptor();
189+
190+
// Act
191+
await using var context = new CatalogContext(connectionString);
192+
193+
var pagingArgs = new PagingArguments
194+
{
195+
First = 5
196+
};
197+
198+
var result = await context.Brands
199+
.Select(BrandWithProductsDto.Projection)
200+
.OrderBy(t => t.Name)
201+
.ThenBy(t => t.Id)
202+
.ToPageAsync(pagingArgs);
203+
204+
// Assert
205+
await CreateSnapshot()
206+
.AddQueries(capture.Queries)
207+
.Add(
208+
new
209+
{
210+
result.HasNextPage,
211+
result.HasPreviousPage,
212+
First = result.First?.Id,
213+
FirstCursor = result.First is not null ? result.CreateCursor(result.First) : null,
214+
Last = result.Last?.Id,
215+
LastCursor = result.Last is not null ? result.CreateCursor(result.Last) : null
216+
})
217+
.Add(result.Items)
218+
.MatchMarkdownAsync();
219+
}
220+
181221
[Fact]
182222
public async Task BatchPaging_First_5()
183223
{
@@ -351,6 +391,37 @@ public BrandDto(int id, string name)
351391
public string Name { get; }
352392
}
353393

394+
public class BrandWithProductsDto
395+
{
396+
public required int Id { get; init; }
397+
398+
public required string Name { get; init; }
399+
400+
public required IReadOnlyCollection<ProductDto> Products { get; init; }
401+
402+
public static Expression<Func<Brand, BrandWithProductsDto>> Projection
403+
=> brand => new BrandWithProductsDto
404+
{
405+
Id = brand.Id,
406+
Name = brand.Name,
407+
Products = brand.Products.AsQueryable().Select(ProductDto.Projection).ToList()
408+
};
409+
}
410+
411+
public class ProductDto
412+
{
413+
public required int Id { get; init; }
414+
415+
public required string Name { get; init; }
416+
417+
public static Expression<Func<Product, ProductDto>> Projection
418+
=> product => new ProductDto
419+
{
420+
Id = product.Id,
421+
Name = product.Name
422+
};
423+
}
424+
354425
public class ProductsByBrandDataLoader : StatefulBatchDataLoader<int, Page<Product>>
355426
{
356427
private readonly IServiceProvider _services;

src/GreenDonut/test/GreenDonut.Data.EntityFramework.Tests/RelativeCursorTests.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,23 @@ await ctx.Brands.Where(t => t.GroupId == 2).OrderBy(t => t.Name).ThenBy(t => t.I
12221222
await Assert.ThrowsAsync<ArgumentException>(Error);
12231223
}
12241224

1225+
[Fact]
1226+
public async Task RequestedSize_Not_Evenly_Divisible_By_TotalCount()
1227+
{
1228+
// Arrange
1229+
var connectionString = CreateConnectionString();
1230+
await SeedAsync(connectionString);
1231+
await using var context = new TestContext(connectionString);
1232+
var arguments = new PagingArguments(12) { EnableRelativeCursors = true };
1233+
1234+
// Act
1235+
var first = await context.Brands.OrderBy(t => t.Name).ThenBy(t => t.Id).ToPageAsync(arguments);
1236+
1237+
// Assert
1238+
Assert.Equal(20, first.TotalCount);
1239+
Assert.Single(first.CreateRelativeForwardCursors());
1240+
}
1241+
12251242
private static async Task SeedAsync(string connectionString)
12261243
{
12271244
await using var context = new TestContext(connectionString);

0 commit comments

Comments
 (0)