Skip to content

Commit

Permalink
StrawberryShake: Add dual store support
Browse files Browse the repository at this point in the history
  • Loading branch information
repne committed Dec 27, 2024
1 parent a265c91 commit 54563c8
Show file tree
Hide file tree
Showing 33 changed files with 11,701 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using StrawberryShake.CodeGeneration.Analyzers;
using StrawberryShake.CodeGeneration.Analyzers.Models;
using StrawberryShake.CodeGeneration.CSharp.Generators;
using StrawberryShake.CodeGeneration.Descriptors;
using StrawberryShake.CodeGeneration.Mappers;
using StrawberryShake.CodeGeneration.Utilities;
using StrawberryShake.Properties;
Expand Down Expand Up @@ -129,17 +130,36 @@ public static async Task<CSharpGeneratorResult> GenerateAsync(
var clientModel = await analyzer.AnalyzeAsync();

// With the client model we finally can create CSharp code.
return Generate(clientModel, settings);
return !settings.NoStore && settings.DualStore
? GenerateWithDualStore(clientModel, settings)
: Generate(clientModel, settings, secondaryStore: false);
}
catch (GraphQLException ex)
{
return new CSharpGeneratorResult(ex.Errors);
}
}

public static CSharpGeneratorResult Generate(
public static CSharpGeneratorResult GenerateWithDualStore(
ClientModel clientModel,
CSharpGeneratorSettings settings)
{
var result1 = Generate(clientModel, settings, secondaryStore: false);

settings.NoStore = true;
settings.RazorComponents = false;

var result2 = Generate(clientModel, settings, secondaryStore: true);

return new CSharpGeneratorResult(
[..result1.Documents, ..result2.Documents],
result1.OperationTypes);
}

public static CSharpGeneratorResult Generate(
ClientModel clientModel,
CSharpGeneratorSettings settings,
bool secondaryStore)
{
if (clientModel is null)
{
Expand Down Expand Up @@ -195,24 +215,28 @@ public static CSharpGeneratorResult Generate(
DependencyInjectionMapper.Map(context);

// Last we execute all our generators with the descriptors.
var results = GenerateCSharpDocuments(context, settings);
var results = GenerateCSharpDocuments(context, settings, secondaryStore);

var documents = new List<SourceDocument>();

if (settings.SingleCodeFile)
{
var fileName = secondaryStore
? $"{settings.SecondaryStorePrefix}{settings.ClientName}"
: settings.ClientName;

GenerateSingleCSharpDocument(
results.Where(t => t.Result.IsCSharpDocument),
SourceDocumentKind.CSharp,
settings.ClientName,
fileName,
documents);

if (results.Any(t => t.Result.IsRazorComponent))
{
GenerateSingleCSharpDocument(
results.Where(t => t.Result.IsRazorComponent),
SourceDocumentKind.Razor,
settings.ClientName,
fileName,
documents);
}
}
Expand Down Expand Up @@ -306,25 +330,32 @@ private static void GenerateSingleCSharpDocument(

private static IReadOnlyList<GeneratorResult> GenerateCSharpDocuments(
MapperContext context,
CSharpGeneratorSettings settings)
CSharpGeneratorSettings settings,
bool secondaryStore)
{
var generatorSettings = new CSharpSyntaxGeneratorSettings(
settings.AccessModifier,
settings.NoStore,
settings.InputRecords,
settings.EntityRecords,
settings.RazorComponents);
settings.RazorComponents,
secondaryStore,
settings.SecondaryStorePrefix);

var results = new List<GeneratorResult>();

foreach (var descriptor in context.GetAllDescriptors())
{
foreach (var generator in _generators)
{
if (generator.CanHandle(descriptor, generatorSettings))
var newDescriptor = secondaryStore
? OverrideDescriptor(descriptor, settings.SecondaryStorePrefix)
: descriptor;

if (generator.CanHandle(newDescriptor, generatorSettings))
{
var result =
generator.Generate(descriptor, generatorSettings);
generator.Generate(newDescriptor, generatorSettings);
results.Add(new(generator.GetType(), result));
}
}
Expand All @@ -333,6 +364,27 @@ private static IReadOnlyList<GeneratorResult> GenerateCSharpDocuments(
return results;
}

private static ICodeDescriptor OverrideDescriptor(ICodeDescriptor descriptor, string prefix)
=> descriptor switch
{
DependencyInjectionDescriptor dependencyInjection
when OverrideDescriptor(dependencyInjection.StoreAccessor, prefix) is StoreAccessorDescriptor storeAccessor
=> new DependencyInjectionDescriptor(
dependencyInjection.ClientDescriptor,
dependencyInjection.Entities,
dependencyInjection.Operations,
dependencyInjection.TypeDescriptors,
dependencyInjection.TransportProfiles,
dependencyInjection.EntityIdFactoryDescriptor,
storeAccessor,
dependencyInjection.ResultFromEntityMappers),
StoreAccessorDescriptor storeAccessor
=> new StoreAccessorDescriptor(
$"{prefix}{storeAccessor.Name}",
storeAccessor.RuntimeType.Namespace),
_ => descriptor
};

private static void GenerateMultipleCSharpDocuments(
IEnumerable<GeneratorResult> results,
SourceDocumentKind kind,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ public class CSharpGeneratorSettings
/// </summary>
public bool NoStore { get; set; }

/// <summary>
/// Generates the client with and without a store
/// </summary>
public bool DualStore { get; set; }

/// <summary>
/// The prefix of the additional store when dual store generation is enabled
/// </summary>
public string SecondaryStorePrefix { get; set; } = "ServerSide";

/// <summary>
/// Generates input types as records.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ namespace StrawberryShake.CodeGeneration.CSharp.Generators;

public class ClientGenerator : ClassBaseGenerator<ClientDescriptor>
{
protected override bool CanHandle(
ClientDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings)
=> !settings.SecondaryStore;

protected override void Generate(
ClientDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ namespace StrawberryShake.CodeGeneration.CSharp.Generators;

public class ClientInterfaceGenerator : ClassBaseGenerator<ClientDescriptor>
{
protected override bool CanHandle(
ClientDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings)
=> !settings.SecondaryStore;

protected override void Generate(ClientDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings,
CodeWriter writer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ namespace StrawberryShake.CodeGeneration.CSharp.Generators;

public class DataTypeGenerator : CSharpSyntaxGenerator<DataTypeDescriptor>
{
protected override bool CanHandle(
DataTypeDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings)
=> !settings.SecondaryStore;

protected override CSharpSyntaxGeneratorResult Generate(
DataTypeDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ protected override void Generate(
out string? path,
out string ns)
{
fileName = CreateServiceCollectionExtensions(descriptor.Name);
fileName = CreateServiceCollectionExtensions(descriptor.Name)
.Prefix(settings);
path = DependencyInjection;
ns = DependencyInjectionNamespace;

Expand All @@ -71,7 +72,7 @@ protected override void Generate(
.SetAccessModifier(settings.AccessModifier);

var addClientMethod = factory
.AddMethod($"Add{descriptor.Name}")
.AddMethod($"Add{descriptor.Name.Prefix(settings)}")
.SetPublic()
.SetStatic()
.SetReturnType(IClientBuilder.WithGeneric(descriptor.StoreAccessor.RuntimeType))
Expand Down Expand Up @@ -552,9 +553,12 @@ private static ICode GenerateInternalMethodBody(

var factoryName =
CreateResultFactoryName(
typeDescriptor.ImplementedBy.First().RuntimeType.Name);
typeDescriptor.ImplementedBy.First().RuntimeType.Name)
.Prefix(settings);

var builderName = CreateResultBuilderName(operationName)
.Prefix(settings);

var builderName = CreateResultBuilderName(operationName);
body.AddCode(
RegisterOperation(
settings,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ namespace StrawberryShake.CodeGeneration.CSharp.Generators;

public class EnumGenerator : CodeGenerator<EnumTypeDescriptor>
{
protected override bool CanHandle(
EnumTypeDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings)
=> !settings.SecondaryStore;

protected override void Generate(EnumTypeDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings,
CodeWriter writer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ namespace StrawberryShake.CodeGeneration.CSharp.Generators;

public class EnumParserGenerator : CodeGenerator<EnumTypeDescriptor>
{
protected override bool CanHandle(
EnumTypeDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings)
=> !settings.SecondaryStore;

protected override void Generate(EnumTypeDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings,
CodeWriter writer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ namespace StrawberryShake.CodeGeneration.CSharp.Generators;

public class InputTypeGenerator : CSharpSyntaxGenerator<InputObjectTypeDescriptor>
{
protected override bool CanHandle(
InputObjectTypeDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings)
=> !settings.SecondaryStore;

protected override CSharpSyntaxGeneratorResult Generate(
InputObjectTypeDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ namespace StrawberryShake.CodeGeneration.CSharp.Generators;

public class InputTypeStateInterfaceGenerator : CSharpSyntaxGenerator<InputObjectTypeDescriptor>
{
protected override bool CanHandle(
InputObjectTypeDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings)
=> !settings.SecondaryStore;

protected override CSharpSyntaxGeneratorResult Generate(
InputObjectTypeDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ public class InputValueFormatterGenerator : CodeGenerator<InputObjectTypeDescrip
TypeNames.String,
TypeNames.Object.MakeNullable());

protected override bool CanHandle(
InputObjectTypeDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings)
=> !settings.SecondaryStore;

protected override void Generate(
InputObjectTypeDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ resultBuilderDescriptor.ResultNamedType as InterfaceTypeDescriptor ??
throw new InvalidOperationException(
"A result type can only be generated for complex types");

fileName = resultBuilderDescriptor.RuntimeType.Name;
fileName = resultBuilderDescriptor.RuntimeType.Name
.Prefix(settings);
path = State;
ns = resultBuilderDescriptor.RuntimeType.NamespaceWithoutGlobal;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ private void AddBuildDataMethod(
{
var concreteType =
CreateResultInfoName(
resultNamedType.ImplementedBy.First().RuntimeType.Name);
resultNamedType.ImplementedBy.First().RuntimeType.Name)
.Prefix(settings);

// protected override IOperationResultDataInfo BuildData(JsonElement dataProp)
var buildDataMethod = classBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ namespace StrawberryShake.CodeGeneration.CSharp.Generators;

public class OperationDocumentGenerator : ClassBaseGenerator<OperationDescriptor>
{
protected override bool CanHandle(
OperationDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings)
=> !settings.SecondaryStore;

protected override void Generate(OperationDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings,
CodeWriter writer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public class OperationServiceGenerator : ClassBaseGenerator<OperationDescriptor>
private static readonly string _filesType =
TypeNames.Dictionary.WithGeneric(TypeNames.String, TypeNames.Upload.MakeNullable());

protected override bool CanHandle(
OperationDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings)
=> !settings.SecondaryStore;

protected override void Generate(
OperationDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ public class OperationServiceInterfaceGenerator : ClassBaseGenerator<OperationDe
private const string _strategy = "strategy";
private const string _cancellationToken = "cancellationToken";

protected override bool CanHandle(
OperationDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings)
=> !settings.SecondaryStore;

protected override void Generate(OperationDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings,
CodeWriter writer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ typeDescriptor as ComplexTypeDescriptor ??
throw new InvalidOperationException(
"A result data factory can only be generated for complex types");

fileName = CreateResultFactoryName(descriptor.RuntimeType.Name);
fileName = CreateResultFactoryName(descriptor.RuntimeType.Name)
.Prefix(settings);
path = State;
ns = CreateStateNamespace(descriptor.RuntimeType.NamespaceWithoutGlobal);

Expand Down Expand Up @@ -72,7 +73,7 @@ typeDescriptor as ComplexTypeDescriptor ??
var ifHasCorrectType = IfBuilder
.New()
.SetCondition(
$"{_dataInfo} is {CreateResultInfoName(descriptor.RuntimeType.Name)} {_info}")
$"{_dataInfo} is {CreateResultInfoName(descriptor.RuntimeType.Name).Prefix(settings)} {_info}")
.AddCode(returnStatement);

var createMethod = classBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ typeDescriptor as ComplexTypeDescriptor ??
throw new InvalidOperationException(
"A result entity mapper can only be generated for complex types");

var className = CreateResultInfoName(complexTypeDescriptor.RuntimeType.Name);
var className = CreateResultInfoName(complexTypeDescriptor.RuntimeType.Name)
.Prefix(settings);
fileName = className;
path = State;
ns = CreateStateNamespace(complexTypeDescriptor.RuntimeType.NamespaceWithoutGlobal);
Expand All @@ -45,7 +46,7 @@ typeDescriptor as ComplexTypeDescriptor ??

var constructorBuilder = classBuilder
.AddConstructor()
.SetTypeName(complexTypeDescriptor.RuntimeType.Name);
.SetTypeName(complexTypeDescriptor.RuntimeType.Name.Prefix(settings));

foreach (var prop in complexTypeDescriptor.Properties)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ namespace StrawberryShake.CodeGeneration.CSharp.Generators;

public class ResultInterfaceGenerator : CodeGenerator<InterfaceTypeDescriptor>
{
protected override bool CanHandle(
InterfaceTypeDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings)
=> !settings.SecondaryStore;

protected override void Generate(InterfaceTypeDescriptor descriptor,
CSharpSyntaxGeneratorSettings settings,
CodeWriter writer,
Expand Down
Loading

0 comments on commit 54563c8

Please sign in to comment.