Skip to content

Commit e634614

Browse files
authored
Merge pull request #11 from Alos-no/develop
Develop
2 parents 092710e + b197a55 commit e634614

File tree

18 files changed

+197
-172
lines changed

18 files changed

+197
-172
lines changed

docs/docfx.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@
7373
"apiSpecFolder": "docs/api"
7474
},
7575
"_gitUrlPattern": "github",
76-
"_appFooter": "Built and maintained by <a href=\"https://alos.no\" target=\"_blank\" rel=\"noopener\">Alos Engineering</a> · Licensed under <a href=\"https://github.com/Alos-no/Cloudflare.NET/blob/main/LICENSE.txt\" target=\"_blank\" rel=\"noopener\">Apache 2.0</a>"
76+
"_appFooter": "Built and maintained by <a href=\"https://alos.no\" target=\"_blank\" rel=\"noopener\">Alos Engineering</a> · Licensed under <a href=\"https://github.com/Alos-no/Cloudflare.NET/blob/main/LICENSE.txt\" target=\"_blank\" rel=\"noopener\">Apache 2.0</a>",
77+
"_googleAnalyticsTagId": "G-J3X1J125E2"
7778
},
7879

7980
"sitemap": {

samples/Cloudflare.NET.Sample.csproj/Samples/AccountSamples.cs

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -87,24 +87,24 @@ private async Task RunCorsConfigurationAsync(string bucketName)
8787
// Rule for local development
8888
new CorsRule(
8989
new CorsAllowed(
90-
Methods: new[] { "GET", "PUT", "POST", "DELETE" },
91-
Origins: new[] { "http://localhost:3000", "http://localhost:5173" },
92-
Headers: new[] { "Content-Type", "Authorization" }
90+
new[] { "GET", "PUT", "POST", "DELETE" },
91+
new[] { "http://localhost:3000", "http://localhost:5173" },
92+
new[] { "Content-Type", "Authorization" }
9393
),
94-
Id: "Local Development",
95-
ExposeHeaders: new[] { "ETag", "Content-Length" },
96-
MaxAgeSeconds: 3600
94+
"Local Development",
95+
new[] { "ETag", "Content-Length" },
96+
3600
9797
),
9898
// Rule for production
9999
new CorsRule(
100100
new CorsAllowed(
101-
Methods: new[] { "GET", "HEAD" },
102-
Origins: new[] { "https://example.com" },
103-
Headers: new[] { "Content-Type" }
101+
new[] { "GET", "HEAD" },
102+
new[] { "https://example.com" },
103+
new[] { "Content-Type" }
104104
),
105-
Id: "Production",
106-
ExposeHeaders: new[] { "ETag" },
107-
MaxAgeSeconds: 7200
105+
"Production",
106+
new[] { "ETag" },
107+
7200
108108
)
109109
}
110110
);
@@ -132,11 +132,11 @@ private async Task RunCorsConfigurationAsync(string bucketName)
132132
{
133133
new CorsRule(
134134
new CorsAllowed(
135-
Methods: new[] { "GET" },
136-
Origins: new[] { "*" },
137-
Headers: new[] { "Content-Type" }
135+
new[] { "GET" },
136+
new[] { "*" },
137+
new[] { "Content-Type" }
138138
),
139-
Id: "Public Read",
139+
"Public Read",
140140
MaxAgeSeconds: 86400
141141
)
142142
}
@@ -162,32 +162,32 @@ private async Task RunLifecycleConfigurationAsync(string bucketName)
162162
{
163163
// Rule to delete old log files after 90 days
164164
new LifecycleRule(
165-
Id: "Delete old logs",
166-
Enabled: true,
167-
Conditions: new LifecycleRuleConditions("logs/"),
165+
"Delete old logs",
166+
true,
167+
new LifecycleRuleConditions("logs/"),
168168
DeleteObjectsTransition: new DeleteObjectsTransition(LifecycleCondition.AfterDays(90))
169169
),
170170
// Rule to abort incomplete multipart uploads after 7 days
171171
new LifecycleRule(
172-
Id: "Cleanup incomplete uploads",
173-
Enabled: true,
172+
"Cleanup incomplete uploads",
173+
true,
174174
AbortMultipartUploadsTransition: new AbortMultipartUploadsTransition(LifecycleCondition.AfterDays(7))
175175
),
176176
// Rule to transition archived data to Infrequent Access storage class after 30 days
177177
new LifecycleRule(
178-
Id: "Archive to Infrequent Access",
179-
Enabled: true,
180-
Conditions: new LifecycleRuleConditions("archive/"),
178+
"Archive to Infrequent Access",
179+
true,
180+
new LifecycleRuleConditions("archive/"),
181181
StorageClassTransitions: new[]
182182
{
183183
new StorageClassTransition(LifecycleCondition.AfterDays(30), R2StorageClass.InfrequentAccess)
184184
}
185185
),
186186
// Combined rule: transition to IA then delete (for temp files)
187187
new LifecycleRule(
188-
Id: "Temp file lifecycle",
189-
Enabled: true,
190-
Conditions: new LifecycleRuleConditions("temp/"),
188+
"Temp file lifecycle",
189+
true,
190+
new LifecycleRuleConditions("temp/"),
191191
StorageClassTransitions: new[]
192192
{
193193
new StorageClassTransition(LifecycleCondition.AfterDays(14), R2StorageClass.InfrequentAccess)
@@ -220,7 +220,8 @@ private async Task RunLifecycleConfigurationAsync(string bucketName)
220220

221221
if (rule.StorageClassTransitions != null)
222222
foreach (var transition in rule.StorageClassTransitions)
223-
logger.LogInformation(" Transition to {StorageClass} after: {Days} days", transition.StorageClass, transition.Condition.MaxAge);
223+
logger.LogInformation(" Transition to {StorageClass} after: {Days} days", transition.StorageClass,
224+
transition.Condition.MaxAge);
224225
}
225226

226227
// 3. Update Lifecycle Policy (simpler configuration)
@@ -230,8 +231,8 @@ private async Task RunLifecycleConfigurationAsync(string bucketName)
230231
{
231232
// Single rule: delete all objects after 365 days
232233
new LifecycleRule(
233-
Id: "Annual cleanup",
234-
Enabled: true,
234+
"Annual cleanup",
235+
true,
235236
DeleteObjectsTransition: new DeleteObjectsTransition(LifecycleCondition.AfterDays(365))
236237
)
237238
}

src/Cloudflare.NET/Accounts/IAccountsApi.cs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,16 @@ Task<CustomDomainResponse> AttachCustomDomainAsync(string bucketName,
104104
/// <param name="corsPolicy">The CORS policy to apply to the bucket.</param>
105105
/// <param name="cancellationToken">A cancellation token.</param>
106106
/// <returns>A task that represents the asynchronous operation.</returns>
107-
/// <seealso href="https://developers.cloudflare.com/api/resources/r2/subresources/buckets/subresources/cors/methods/update/" />
107+
/// <seealso
108+
/// href="https://developers.cloudflare.com/api/resources/r2/subresources/buckets/subresources/cors/methods/update/" />
108109
Task SetBucketCorsAsync(string bucketName, BucketCorsPolicy corsPolicy, CancellationToken cancellationToken = default);
109110

110111
/// <summary>Deletes the CORS policy for an R2 bucket, removing all CORS rules.</summary>
111112
/// <param name="bucketName">The name of the bucket.</param>
112113
/// <param name="cancellationToken">A cancellation token.</param>
113114
/// <returns>A task that represents the asynchronous operation.</returns>
114-
/// <seealso href="https://developers.cloudflare.com/api/resources/r2/subresources/buckets/subresources/cors/methods/delete/" />
115+
/// <seealso
116+
/// href="https://developers.cloudflare.com/api/resources/r2/subresources/buckets/subresources/cors/methods/delete/" />
115117
Task DeleteBucketCorsAsync(string bucketName, CancellationToken cancellationToken = default);
116118

117119
/// <summary>Gets the lifecycle policy for an R2 bucket.</summary>
@@ -122,10 +124,11 @@ Task<CustomDomainResponse> AttachCustomDomainAsync(string bucketName,
122124
/// <see cref="BucketLifecyclePolicy" /> with the current lifecycle rules.
123125
/// </returns>
124126
/// <remarks>
125-
/// Lifecycle rules determine object retention, automatic deletion, storage class transitions,
126-
/// and cleanup of incomplete multipart uploads. A bucket can have up to 1000 lifecycle rules.
127+
/// Lifecycle rules determine object retention, automatic deletion, storage class transitions, and cleanup of
128+
/// incomplete multipart uploads. A bucket can have up to 1000 lifecycle rules.
127129
/// </remarks>
128-
/// <seealso href="https://developers.cloudflare.com/api/resources/r2/subresources/buckets/subresources/lifecycle/methods/get/" />
130+
/// <seealso
131+
/// href="https://developers.cloudflare.com/api/resources/r2/subresources/buckets/subresources/lifecycle/methods/get/" />
129132
Task<BucketLifecyclePolicy> GetBucketLifecycleAsync(string bucketName, CancellationToken cancellationToken = default);
130133

131134
/// <summary>Sets or updates the lifecycle policy for an R2 bucket.</summary>
@@ -136,22 +139,29 @@ Task<CustomDomainResponse> AttachCustomDomainAsync(string bucketName,
136139
/// <remarks>
137140
/// <para>Lifecycle rules can perform the following actions:</para>
138141
/// <list type="bullet">
139-
/// <item><description>Delete objects after a specified age or on a specific date</description></item>
140-
/// <item><description>Abort incomplete multipart uploads after a specified age</description></item>
141-
/// <item><description>Transition objects to Infrequent Access storage class</description></item>
142+
/// <item>
143+
/// <description>Delete objects after a specified age or on a specific date</description>
144+
/// </item>
145+
/// <item>
146+
/// <description>Abort incomplete multipart uploads after a specified age</description>
147+
/// </item>
148+
/// <item>
149+
/// <description>Transition objects to Infrequent Access storage class</description>
150+
/// </item>
142151
/// </list>
143152
/// <para>Rules are processed within 24 hours of being set. Maximum of 1000 rules per bucket.</para>
144153
/// </remarks>
145-
/// <seealso href="https://developers.cloudflare.com/api/resources/r2/subresources/buckets/subresources/lifecycle/methods/update/" />
154+
/// <seealso
155+
/// href="https://developers.cloudflare.com/api/resources/r2/subresources/buckets/subresources/lifecycle/methods/update/" />
146156
Task SetBucketLifecycleAsync(string bucketName, BucketLifecyclePolicy lifecyclePolicy, CancellationToken cancellationToken = default);
147157

148158
/// <summary>Deletes the lifecycle policy for an R2 bucket, removing all lifecycle rules.</summary>
149159
/// <param name="bucketName">The name of the bucket.</param>
150160
/// <param name="cancellationToken">A cancellation token.</param>
151161
/// <returns>A task that represents the asynchronous operation.</returns>
152162
/// <remarks>
153-
/// Cloudflare R2 does not have a dedicated DELETE endpoint for lifecycle policies.
154-
/// This method removes the policy by setting an empty rules array.
163+
/// Cloudflare R2 does not have a dedicated DELETE endpoint for lifecycle policies. This method removes the policy
164+
/// by setting an empty rules array.
155165
/// </remarks>
156166
/// <seealso href="https://developers.cloudflare.com/r2/buckets/object-lifecycles/" />
157167
Task DeleteBucketLifecycleAsync(string bucketName, CancellationToken cancellationToken = default);

src/Cloudflare.NET/Accounts/Models/R2BucketModels.cs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ namespace Cloudflare.NET.Accounts.Models;
44
using System.Text.Json.Serialization;
55
using Core.Json;
66

7-
87
#region Bucket Models
98

109
/// <summary>Defines the request payload for creating an R2 bucket.</summary>
@@ -52,7 +51,6 @@ IReadOnlyList<R2Bucket> Buckets
5251

5352
#endregion
5453

55-
5654
#region CORS Models
5755

5856
/// <summary>Defines the allowed HTTP methods, origins, and headers for a CORS rule.</summary>
@@ -93,20 +91,17 @@ IReadOnlyList<CorsRule> Rules
9391

9492
#endregion
9593

96-
9794
#region Lifecycle Models
9895

9996
/// <summary>Defines the condition type for lifecycle rule transitions.</summary>
10097
[JsonConverter(typeof(JsonStringEnumMemberConverter))]
10198
public enum LifecycleConditionType
10299
{
103100
/// <summary>Condition based on object age in days.</summary>
104-
[EnumMember(Value = "Age")]
105-
Age,
101+
[EnumMember(Value = "Age")] Age,
106102

107103
/// <summary>Condition based on a specific date.</summary>
108-
[EnumMember(Value = "Date")]
109-
Date
104+
[EnumMember(Value = "Date")] Date
110105
}
111106

112107
/// <summary>Represents a condition that triggers a lifecycle transition.</summary>
@@ -129,13 +124,13 @@ public record LifecycleCondition(
129124
/// <param name="days">The number of days after object creation.</param>
130125
/// <returns>A new <see cref="LifecycleCondition" /> with Age type and MaxAge in seconds.</returns>
131126
public static LifecycleCondition AfterDays(int days) =>
132-
new(LifecycleConditionType.Age, MaxAge: days * SecondsPerDay);
127+
new(LifecycleConditionType.Age, days * SecondsPerDay);
133128

134129
/// <summary>Creates an age-based lifecycle condition using seconds.</summary>
135130
/// <param name="seconds">The number of seconds after object creation.</param>
136131
/// <returns>A new <see cref="LifecycleCondition" /> with Age type and MaxAge in seconds.</returns>
137132
public static LifecycleCondition AfterSeconds(int seconds) =>
138-
new(LifecycleConditionType.Age, MaxAge: seconds);
133+
new(LifecycleConditionType.Age, seconds);
139134

140135
/// <summary>Creates a date-based lifecycle condition.</summary>
141136
/// <param name="date">The date on which the transition should occur.</param>
@@ -145,7 +140,10 @@ public static LifecycleCondition OnDate(DateTime date) =>
145140
}
146141

147142
/// <summary>Represents the filtering conditions for which objects a lifecycle rule applies to.</summary>
148-
/// <param name="Prefix">The object key prefix to filter objects. Only objects with keys starting with this prefix are affected.</param>
143+
/// <param name="Prefix">
144+
/// The object key prefix to filter objects. Only objects with keys starting with this prefix are
145+
/// affected.
146+
/// </param>
149147
public record LifecycleRuleConditions(
150148
[property: JsonPropertyName("prefix")]
151149
string? Prefix = null
@@ -168,11 +166,15 @@ LifecycleCondition Condition
168166
/// <summary>Defines the available R2 storage classes for lifecycle transitions.</summary>
169167
public static class R2StorageClass
170168
{
169+
#region Constants & Statics
170+
171171
/// <summary>Standard storage class for frequently accessed data.</summary>
172172
public const string Standard = "Standard";
173173

174174
/// <summary>Infrequent Access storage class for less frequently accessed data with lower storage costs.</summary>
175175
public const string InfrequentAccess = "InfrequentAccess";
176+
177+
#endregion
176178
}
177179

178180
/// <summary>Represents a transition to change the storage class of objects.</summary>

src/Cloudflare.NET/Core/ApiResource.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ protected async Task<TResult> PutAsync<TResult>(string requestUri, object? paylo
9696

9797
/// <summary>Sends a POST request with a pre-serialized JSON string to the specified URI.</summary>
9898
/// <remarks>
99-
/// Use this method when you need custom JSON serialization (e.g., camelCase instead of snake_case).
100-
/// The caller is responsible for serializing the payload to JSON.
99+
/// Use this method when you need custom JSON serialization (e.g., camelCase instead of snake_case). The caller is
100+
/// responsible for serializing the payload to JSON.
101101
/// </remarks>
102102
/// <typeparam name="TResult">The expected type of the "result" object in the JSON response.</typeparam>
103103
/// <param name="requestUri">The URI to send the request to.</param>
@@ -108,7 +108,7 @@ protected async Task<TResult> PostJsonAsync<TResult>(string requestUr
108108
string jsonContent,
109109
CancellationToken cancellationToken = default)
110110
{
111-
using var scope = Logger.BeginScope("RequestUri: {RequestUri}", requestUri);
111+
using var scope = Logger.BeginScope("RequestUri: {RequestUri}", requestUri);
112112
Logger.SendingRequest("POST", requestUri);
113113
var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
114114
var response = await HttpClient.PostAsync(requestUri, content, cancellationToken);
@@ -117,8 +117,8 @@ protected async Task<TResult> PostJsonAsync<TResult>(string requestUr
117117

118118
/// <summary>Sends a PUT request with a pre-serialized JSON string to the specified URI.</summary>
119119
/// <remarks>
120-
/// Use this method when you need custom JSON serialization (e.g., camelCase instead of snake_case).
121-
/// The caller is responsible for serializing the payload to JSON.
120+
/// Use this method when you need custom JSON serialization (e.g., camelCase instead of snake_case). The caller is
121+
/// responsible for serializing the payload to JSON.
122122
/// </remarks>
123123
/// <typeparam name="TResult">The expected type of the "result" object in the JSON response.</typeparam>
124124
/// <param name="requestUri">The URI to send the request to.</param>
@@ -129,7 +129,7 @@ protected async Task<TResult> PutJsonAsync<TResult>(string requestUri
129129
string jsonContent,
130130
CancellationToken cancellationToken = default)
131131
{
132-
using var scope = Logger.BeginScope("RequestUri: {RequestUri}", requestUri);
132+
using var scope = Logger.BeginScope("RequestUri: {RequestUri}", requestUri);
133133
Logger.SendingRequest("PUT", requestUri);
134134
var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
135135
var response = await HttpClient.PutAsync(requestUri, content, cancellationToken);

src/Cloudflare.NET/Core/Auth/AuthLogs.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace Cloudflare.NET.Core.Auth;
99
internal static partial class AuthLogs
1010
{
1111
#if NET6_0_OR_GREATER
12+
1213
#region Source-Generated Logging (NET6+)
1314

1415
[LoggerMessage(
@@ -20,7 +21,6 @@ internal static partial class AuthLogs
2021
#endregion
2122

2223
#else
23-
2424
#region Manual Logging (NetStandard2.1)
2525

2626
public static void AddingAuthHeader(this ILogger logger, Uri? requestUri)

src/Cloudflare.NET/Core/Internal/CallerArgumentExpressionAttribute.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#if !NET5_0_OR_GREATER
2-
32
// ReSharper disable once CheckNamespace
43
namespace System.Runtime.CompilerServices;
54

src/Cloudflare.NET/Core/Internal/IsExternalInit.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#if !NET5_0_OR_GREATER
2-
32
// ReSharper disable once CheckNamespace
43
namespace System.Runtime.CompilerServices;
54

src/Cloudflare.NET/Core/Json/SnakeCaseNamingPolicy.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#if !NET8_0_OR_GREATER
2-
32
namespace Cloudflare.NET.Core.Json;
43

54
using System.Buffers;
@@ -57,12 +56,12 @@ public override string ConvertName(string name)
5756

5857
try
5958
{
60-
var bufferIndex = 0;
59+
var bufferIndex = 0;
6160
var previousCategory = CharCategory.Boundary;
6261

6362
for (var i = 0; i < name.Length; i++)
6463
{
65-
var current = name[i];
64+
var current = name[i];
6665
var currentCategory = GetCharCategory(current);
6766

6867
// Determine if we need to insert an underscore before this character.
@@ -104,7 +103,7 @@ public override string ConvertName(string name)
104103
}
105104

106105
buffer[bufferIndex++] = char.ToLowerInvariant(current);
107-
previousCategory = currentCategory;
106+
previousCategory = currentCategory;
108107
}
109108

110109
return new string(buffer, 0, bufferIndex);

src/Cloudflare.NET/Core/Models/ApiResourceLogs.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace Cloudflare.NET.Core.Models;
99
internal static partial class ApiResourceLogs
1010
{
1111
#if NET6_0_OR_GREATER
12+
1213
#region Source-Generated Logging (NET6+)
1314

1415
[LoggerMessage(
@@ -67,7 +68,6 @@ public static partial void ApiReturnedFailure(
6768
#endregion
6869

6970
#else
70-
7171
#region Manual Logging (NetStandard2.1)
7272

7373
public static void SendingRequest(this ILogger logger, string method, string requestUri)

0 commit comments

Comments
 (0)