Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
inputfalken committed Apr 2, 2024
0 parents commit ef98642
Show file tree
Hide file tree
Showing 22 changed files with 1,553 additions and 0 deletions.
36 changes: 36 additions & 0 deletions Dynatello.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EDABF10C-5499-442F-8BE1-9205EEE7E016}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dynatello", "src\Dynatello\Dynatello.csproj", "{892C771D-B39C-4221-B04D-FF59A061995C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{F0497192-D217-4A90-9C1C-E1A6DEDC4526}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dynatello.Tests", "tests\Dynatello.Tests\Dynatello.Tests.csproj", "{D0078AB2-F320-42BD-89C9-ED5491A35DE1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{892C771D-B39C-4221-B04D-FF59A061995C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{892C771D-B39C-4221-B04D-FF59A061995C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{892C771D-B39C-4221-B04D-FF59A061995C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{892C771D-B39C-4221-B04D-FF59A061995C}.Release|Any CPU.Build.0 = Release|Any CPU
{D0078AB2-F320-42BD-89C9-ED5491A35DE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D0078AB2-F320-42BD-89C9-ED5491A35DE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D0078AB2-F320-42BD-89C9-ED5491A35DE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D0078AB2-F320-42BD-89C9-ED5491A35DE1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{892C771D-B39C-4221-B04D-FF59A061995C} = {EDABF10C-5499-442F-8BE1-9205EEE7E016}
{D0078AB2-F320-42BD-89C9-ED5491A35DE1} = {F0497192-D217-4A90-9C1C-E1A6DEDC4526}
EndGlobalSection
EndGlobal
177 changes: 177 additions & 0 deletions src/Dynatello/Builders/Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
using Amazon.DynamoDBv2.Model;
using DynamoDBGenerator;
using Dynatello.Builders.Types;

namespace Dynatello.Builders;

/// <summary>
/// Contains extension methods to create builders.
/// </summary>
public static class Extensions
{
/// <summary>
///
/// </summary>
public static QueryRequestBuilder<TArg> ToQueryRequestBuilder<T, TArg, TReferences, TArgumentReferences>(
this KeyConditionedFilterExpression<T, TArg, TReferences, TArgumentReferences> source
)
where TReferences : IAttributeExpressionNameTracker
where TArgumentReferences : IAttributeExpressionValueTracker<TArg>
{
return new QueryRequestBuilder<TArg>(
source.TableAccess.Item.ComposeAttributeExpression(source.Condition, source.Filter),
source.TableAccess.TableName
);
}

/// <summary>
///
/// </summary>
public static QueryRequestBuilder<TArg> ToQueryRequestBuilder<T, TArg, TReferences, TArgumentReferences>(
this KeyConditionExpression<T, TArg, TReferences, TArgumentReferences> source
)
where TReferences : IAttributeExpressionNameTracker
where TArgumentReferences : IAttributeExpressionValueTracker<TArg>
{
return new QueryRequestBuilder<TArg>(
source.TableAccess.Item.ComposeAttributeExpression(source.Condition, null),
source.TableAccess.TableName
);
}

/// <summary>
///
/// </summary>
public static GetRequestBuilder<TArg> ToGetRequestBuilder<T, TArg, TReferences, TArgumentReferences>(
this TableAccess<T, TArg, TReferences, TArgumentReferences> source)
where TReferences : IAttributeExpressionNameTracker
where TArgumentReferences : IAttributeExpressionValueTracker<TArg>
where TArg : notnull
{
return new GetRequestBuilder<TArg>(
source.TableName,
source.Item.PrimaryKeyMarshaller.ComposeKeys<TArg>(y => y, null)
);
}

/// <summary>
///
/// </summary>
public static GetRequestBuilder<TArg> ToGetRequestBuilder<T, TArg, TReferences, TArgumentReferences,
TPartition>(
this TableAccess<T, TArg, TReferences, TArgumentReferences> source,
Func<TArg, TPartition> partitionKeySelector)
where TReferences : IAttributeExpressionNameTracker
where TArgumentReferences : IAttributeExpressionValueTracker<TArg>
where TPartition : notnull
{
return new GetRequestBuilder<TArg>(
source.TableName,
source.Item.PrimaryKeyMarshaller.ComposeKeys<TArg>(y => partitionKeySelector(y), null)
);
}

/// <summary>
///
/// </summary>
public static GetRequestBuilder<TArg> ToGetRequestBuilder<T, TArg,
TReferences, TArgumentReferences, TPartition, TRange>(
this TableAccess<T, TArg, TReferences, TArgumentReferences> source,
Func<TArg, TPartition> partitionKeySelector,
Func<TArg, TRange> rangeKeySelector)
where TReferences : IAttributeExpressionNameTracker
where TArgumentReferences : IAttributeExpressionValueTracker<TArg>
where TPartition : notnull
where TRange : notnull
{
return new GetRequestBuilder<TArg>(
source.TableName,
source.Item.PrimaryKeyMarshaller.ComposeKeys<TArg>(y => partitionKeySelector(y), y => rangeKeySelector(y))
);
}

/// <summary>
///
/// </summary>
public static UpdateRequestBuilder<TArg> ToUpdateItemRequestBuilder<T, TArg, TReferences, TArgumentReferences>(
this UpdateExpression<T, TArg, TReferences, TArgumentReferences> source,
Func<IDynamoDBKeyMarshaller, TArg, Dictionary<string, AttributeValue>> keySelector
)
where TReferences : IAttributeExpressionNameTracker
where TArgumentReferences : IAttributeExpressionValueTracker<TArg>
{
return new UpdateRequestBuilder<TArg>(
source.TableAccess.Item.ComposeAttributeExpression(source.Update, null),
source.TableAccess.TableName,
keySelector,
source.TableAccess.Item.PrimaryKeyMarshaller
);
}

/// <summary>
///
/// </summary>
public static UpdateRequestBuilder<TArg> ToUpdateItemRequestBuilder<T, TArg, TReferences, TArgumentReferences>(
this ConditionalUpdateExpression<T, TArg, TReferences, TArgumentReferences> source,
Func<IDynamoDBKeyMarshaller, TArg, Dictionary<string, AttributeValue>> keySelector
)
where TReferences : IAttributeExpressionNameTracker
where TArgumentReferences : IAttributeExpressionValueTracker<TArg>
{
return new UpdateRequestBuilder<TArg>(
source.TableAccess.Item.ComposeAttributeExpression(source.Update, source.Condition),
source.TableAccess.TableName,
keySelector,
source.TableAccess.Item.PrimaryKeyMarshaller
);
}

/// <summary>
///
/// </summary>
public static KeyConditionExpression<T, TArg, TReferences, TArgumentReferences> WithKeyConditionExpression<T, TArg,
TReferences, TArgumentReferences>(
this TableAccess<T, TArg, TReferences, TArgumentReferences> source,
Func<TReferences, TArgumentReferences, string> condition)
where TReferences : IAttributeExpressionNameTracker
where TArgumentReferences : IAttributeExpressionValueTracker<TArg>
{
return new KeyConditionExpression<T, TArg, TReferences, TArgumentReferences>(source, condition);
}

/// <summary>
///
/// </summary>
public static PutRequestBuilder<T> ToPutRequestBuilder<T, TReferences,
TArgumentReferences>(
this TableAccess<T, T, TReferences, TArgumentReferences> source
)
where TReferences : IAttributeExpressionNameTracker
where TArgumentReferences : IAttributeExpressionValueTracker<T>
{
return new PutRequestBuilder<T>
(
null,
source.Item.Marshall,
source.TableName
);
}

/// <summary>
///
/// </summary>
public static PutRequestBuilder<T> ToPutRequestBuilder<T, TReferences,
TArgumentReferences>(
this ConditionExpression<T, T, TReferences, TArgumentReferences> source
)
where TReferences : IAttributeExpressionNameTracker
where TArgumentReferences : IAttributeExpressionValueTracker<T>
{
return new PutRequestBuilder<T>
(
source.TableAccess.Item.ComposeAttributeExpression(null, source.Condition),
source.TableAccess.Item.Marshall,
source.TableAccess.TableName
);
}
}
63 changes: 63 additions & 0 deletions src/Dynatello/Builders/GetRequestBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;

namespace Dynatello.Builders;

/// <summary>
/// A <see cref="GetItemRequest"/> builder that can be configured through the record `with` syntax.
/// </summary>
/// <typeparam name="T">
/// The type you need to provide in you execution.
/// </typeparam>
public readonly record struct GetRequestBuilder<T>
{
private readonly Func<T, Dictionary<string, AttributeValue>> _keysSelector;

internal GetRequestBuilder(
string tableName,
Func<T, Dictionary<string, AttributeValue>> keysSelector)
{
_keysSelector = keysSelector;
TableName = tableName;
}

[Obsolete(Constants.ObsoleteConstructorMessage, true)]
public GetRequestBuilder()
{
throw Constants.InvalidConstructor();
}

/// <inheritdoc cref="GetItemRequest.TableName" />
public string TableName { get; init; }

/// <inheritdoc cref="GetItemRequest.ConsistentRead" />
public bool? ConsistentRead { get; init; } = null;

/// <inheritdoc cref="GetItemRequest.ReturnConsumedCapacity" />
public ReturnConsumedCapacity? ReturnConsumedCapacity { get; init; } = null;

/// <summary>
/// Creates a <see cref="GetItemRequest"/>.
/// </summary>
/// <param name="arg">
/// The argument required to extract the keys.
/// </param>
/// <returns>A <see cref="GetItemRequest"/></returns>
public GetItemRequest Build(T arg)
{
var request = new GetItemRequest
{
ReturnConsumedCapacity = ReturnConsumedCapacity,
TableName = TableName,
Key = _keysSelector(arg)
};

if (ConsistentRead is { } consistentRead)
request.ConsistentRead = consistentRead;

if (ReturnConsumedCapacity is not null)
request.ReturnConsumedCapacity = ReturnConsumedCapacity;

return request;
}
}
89 changes: 89 additions & 0 deletions src/Dynatello/Builders/PutRequestBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using DynamoDBGenerator;

namespace Dynatello.Builders;

/// <summary>
/// A <see cref="PutItemRequest"/> builder that can be configured through the record `with` syntax.
/// </summary>
/// <typeparam name="T">
/// The type you need to provide in you execution.
/// </typeparam>
public readonly record struct PutRequestBuilder<T>
{
private readonly Func<T, IAttributeExpression>? _attributeExpressionSelector;
private readonly Func<T, Dictionary<string, AttributeValue>> _marshall;

private readonly string _tableName;


internal PutRequestBuilder(
Func<T, IAttributeExpression>? attributeExpressionSelector,
Func<T, Dictionary<string, AttributeValue>> marshall,
string tableName
)
{
_attributeExpressionSelector = attributeExpressionSelector;
_marshall = marshall;
_tableName = tableName;
}

[Obsolete(Constants.ObsoleteConstructorMessage, true)]
public PutRequestBuilder()
{
throw Constants.InvalidConstructor();
}

/// <inheritdoc cref="PutItemRequest.TableName" />
public string TableName
{
get => _tableName;
init => _tableName = value ?? throw new ArgumentNullException(nameof(value));
}

/// <inheritdoc cref="PutItemRequest.ReturnValues" />
public ReturnValue? ReturnValues { get; init; } = null;

/// <inheritdoc cref="PutItemRequest.ReturnConsumedCapacity" />
public ReturnConsumedCapacity? ReturnConsumedCapacity { get; init; } = null;

/// <inheritdoc cref="PutItemRequest.ReturnItemCollectionMetrics" />
public ReturnItemCollectionMetrics? ReturnItemCollectionMetrics { get; init; } = null;

/// <inheritdoc cref="PutItemRequest.ReturnValuesOnConditionCheckFailure" />
public ReturnValuesOnConditionCheckFailure? ReturnValuesOnConditionCheckFailure { get; init; } = null;


public PutItemRequest Build(T element)
{
var request = new PutItemRequest
{
TableName = TableName,
Item = _marshall(element),
Expected = null,
ConditionalOperator = null,
ConditionExpression = null,
ExpressionAttributeNames = null,
ExpressionAttributeValues = null
};

if (ReturnValues is not null)
request.ReturnValues = ReturnValues;
if (ReturnConsumedCapacity is not null)
request.ReturnConsumedCapacity = ReturnConsumedCapacity;
if (ReturnItemCollectionMetrics is not null)
request.ReturnItemCollectionMetrics = ReturnItemCollectionMetrics;
if (ReturnValuesOnConditionCheckFailure is not null)
request.ReturnValuesOnConditionCheckFailure = ReturnValuesOnConditionCheckFailure;

if (_attributeExpressionSelector is null) return request;
var attributeExpression = _attributeExpressionSelector(element);

request.ExpressionAttributeNames = attributeExpression.Names;
request.ExpressionAttributeValues = attributeExpression.Values;
request.ConditionExpression = attributeExpression.Expressions[0];

return request;
}
}
Loading

0 comments on commit ef98642

Please sign in to comment.