Skip to content

Commit

Permalink
Merge pull request #5 from allegro/feature/identifiers
Browse files Browse the repository at this point in the history
Feature/identifiers
  • Loading branch information
ppiwow-apay authored Nov 7, 2022
2 parents 7fdde4b + 5245d65 commit e2ced83
Show file tree
Hide file tree
Showing 21 changed files with 570 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Build Allegro.Extensions.Identifiers.Abstractions

on:
push:
branches: [ main ]
paths:
- 'src/Allegro.Extensions.Identifiers/*'
- 'src/Allegro.Extensions.Identifiers/Allegro.Extensions.Identifiers.Abstractions/**'
- 'src/*'
pull_request:
branches: [ main ]
paths:
- 'src/Allegro.Extensions.Identifiers/*'
- 'src/Allegro.Extensions.Identifiers/Allegro.Extensions.Identifiers.Abstractions/**'
- 'src/*'

jobs:
ci:
uses: ./.github/workflows/template.yml
with:
projectName: Allegro.Extensions.Identifiers.Abstractions
solutionName: Allegro.Extensions.Identifiers
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Publish Allegro.Extensions.Identifiers.Abstractions

on:
push:
tags:
- 'Allegro.Extensions.Identifiers.Abstractions_*'

jobs:
publish:
uses: ./.github/workflows/template.yml
with:
projectName: Allegro.Extensions.Identifiers.Abstractions
solutionName: Allegro.Extensions.Identifiers
publish: true
tagName: ${{ github.ref_name }}
secrets:
nugetCertificate: ${{ secrets.NUGET_PRIVATE_KEY_P12 }}
nugetCertificatePassword: ${{ secrets.GPG_PRIVATE_KEY_PASSWORD }}
nugetApiKey: ${{ secrets.NUGET_API_KEY }}
22 changes: 22 additions & 0 deletions .github/workflows/Allegro.Extensions.Identifiers.AspNetCore.ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Build Allegro.Extensions.Identifiers.AspNetCore

on:
push:
branches: [ main ]
paths:
- 'src/Allegro.Extensions.Identifiers/*'
- 'src/Allegro.Extensions.Identifiers/Allegro.Extensions.Identifiers.AspNetCore/**'
- 'src/*'
pull_request:
branches: [ main ]
paths:
- 'src/Allegro.Extensions.Identifiers/*'
- 'src/Allegro.Extensions.Identifiers/Allegro.Extensions.Identifiers.AspNetCore/**'
- 'src/*'

jobs:
ci:
uses: ./.github/workflows/template.yml
with:
projectName: Allegro.Extensions.Identifiers.AspNetCore
solutionName: Allegro.Extensions.Identifiers
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Publish Allegro.Extensions.Identifiers.AspNetCore

on:
push:
tags:
- 'Allegro.Extensions.Identifiers.AspNetCore_*'

jobs:
publish:
uses: ./.github/workflows/template.yml
with:
projectName: Allegro.Extensions.Identifiers.AspNetCore
solutionName: Allegro.Extensions.Identifiers
publish: true
tagName: ${{ github.ref_name }}
secrets:
nugetCertificate: ${{ secrets.NUGET_PRIVATE_KEY_P12 }}
nugetCertificatePassword: ${{ secrets.GPG_PRIVATE_KEY_PASSWORD }}
nugetApiKey: ${{ secrets.NUGET_API_KEY }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageId>Allegro.Extensions.Identifiers.Abstractions</PackageId>
<PackageDescription>Contains strongly typed identifiers abstractions.</PackageDescription>
<NoWarn>CS1574</NoWarn><!-- Caused by Meziantou generator and some cref issues related to partial classes -->
</PropertyGroup>
<Import Project="..\..\Package.Build.props" />
<ItemGroup>
<PackageReference Include="AsyncFixer" Version="1.5.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Asyncify" Version="0.9.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Meziantou.Analyzer" Version="1.0.676">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.0.64">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.354">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Meziantou.Framework.StronglyTypedId" Version="1.0.22" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace Allegro.Extensions.Identifiers.Abstractions;

/// <summary>
/// Marker interface for strongly typed entities
/// </summary>
public interface IStronglyTypedEntity<out T, Tu>
where T : IStronglyTypedId<Tu>
{
/// <summary>
/// Strongly typed entity id
/// </summary>
public T Id { get; }
}

/// <summary>
/// Marker interface for strongly typed identifiers
/// </summary>
public interface IStronglyTypedEntity<out T> : IStronglyTypedEntity<T, string>
where T : IStronglyTypedId<string>
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Allegro.Extensions.Identifiers.Abstractions;

/// <summary>
/// Marker interface. Indicates if type should be treated as a strongly typed identifier.
/// Meziantou.Framework.StronglyTypedId that is recommended as a code generator implements this interface by default and provides common JSON serializers.
/// </summary>
public interface IStronglyTypedId<out T>
{
/// <summary>
/// Value of identifier
/// </summary>
public T Value { get; }

/// <summary>
/// String value of identifier
/// </summary>
public string ValueAsString { get; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageId>Allegro.Extensions.Identifiers.AspNetCore</PackageId>
<PackageDescription>Contains strongly typed identifiers extensions for swagger.</PackageDescription>
<NoWarn>CS1574</NoWarn><!-- Caused by Meziantou generator and some cref issues related to partial classes -->
</PropertyGroup>
<Import Project="..\..\Package.Build.props" />
<ItemGroup>
<PackageReference Include="AsyncFixer" Version="1.5.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Asyncify" Version="0.9.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Meziantou.Analyzer" Version="1.0.676">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.0.64">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.354">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Allegro.Extensions.Identifiers.Abstractions\Allegro.Extensions.Identifiers.Abstractions.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System;
using System.Linq;
using Allegro.Extensions.Identifiers.Abstractions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace Allegro.Extensions.Identifiers.AspNetCore.Swagger;

/// <summary>
/// Asp extensions related to strongly typed identifiers
/// </summary>
public static class StronglyTypedIdsSwaggerExtensions
{
private const string IdentifiersAssemblyNameSuffix = "Identifiers";

/// <summary>
/// Add swagger support for strongly typed identifiers
/// </summary>
public static IServiceCollection AddStronglyTypedIds(this IServiceCollection services)
{
services.Configure<SwaggerGenOptions>(options =>
{
var types = AppDomain.CurrentDomain.GetAssemblies()
.Where(x => x.FullName != null && x.FullName.Contains(IdentifiersAssemblyNameSuffix))
.SelectMany(x => x.GetTypes())
.Where(x => IsAssignableToGenericType(x, typeof(IStronglyTypedId<>)) && !x.IsInterface && !x.IsAbstract)
.ToList();

foreach (var type in types)
{
var valueType = type.GetProperty(nameof(IStronglyTypedId<string>.Value))!.PropertyType;

var openApiSchema = valueType.Name switch
{
nameof(Int32) => new OpenApiSchema
{
Type = "integer",
Example = new OpenApiString(string.Empty)
},
nameof(Guid) => new OpenApiSchema
{
Type = "string",
Format = "uuid",
Example = new OpenApiString(string.Empty)
},
_ => new OpenApiSchema
{
Type = "string",
Example = new OpenApiString(string.Empty)
},
};

options.MapType(type, () => openApiSchema);
}
});

return services;
}

private static bool IsAssignableToGenericType(Type givenType, Type genericType)
{
var interfaceTypes = givenType.GetInterfaces();

foreach (var it in interfaceTypes)
{
if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
{
return true;
}
}

if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
{
return true;
}

var baseType = givenType.BaseType;
if (baseType == null)
{
return false;
}

return IsAssignableToGenericType(baseType, genericType);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AsyncFixer" Version="1.5.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Asyncify" Version="0.9.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Meziantou.Analyzer" Version="1.0.676">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.0.64">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.354">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Allegro.Extensions.Identifiers.Abstractions\Allegro.Extensions.Identifiers.Abstractions.csproj" />
<ProjectReference Include="..\Allegro.Extensions.Identifiers.AspNetCore\Allegro.Extensions.Identifiers.AspNetCore.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using Allegro.Extensions.Identifiers.Demo.Identifiers;
using Microsoft.AspNetCore.Mvc;

namespace Allegro.Extensions.Identifiers.Demo.Controllers
{
[ApiController]
[Route("strongly-typed")]
public class StronglyTypedExamples : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok(new { UserId = UserId.Generate(), PaymentId = PaymentId.Parse("123"), OrderId = OrderId.FromGuid(Guid.NewGuid()) });
}

[HttpPost]
public IActionResult Post([FromQuery] UserId userId, [FromQuery] PaymentId paymentId, [FromQuery] OrderId orderId)
{
return Ok(new { UserId = userId, PaymentId = paymentId, OrderId = orderId });
}

[HttpGet("{userId}")]
public IActionResult Post([FromRoute] UserId userId)
{
return Ok(new { UserId = userId });
}

[HttpPost("body")]
public IActionResult Post([FromBody] Dto dto)
{
return Ok(dto);
}

public record Dto(UserId UserId, PaymentId PaymentId, OrderId OrderId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) PlaceholderCompany. All rights reserved.
#pragma warning disable 1591

using System;
using Allegro.Extensions.Identifiers.Abstractions;

namespace Allegro.Extensions.Identifiers.Demo.Identifiers;

[StronglyTypedId(typeof(Guid))]
public partial class OrderId : IStronglyTypedId<Guid>
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) PlaceholderCompany. All rights reserved.

using Allegro.Extensions.Identifiers.Abstractions;

namespace Allegro.Extensions.Identifiers.Demo.Identifiers;

[StronglyTypedId(typeof(int))]
public partial class PaymentId : IStronglyTypedId<int>
{
}
Loading

0 comments on commit e2ced83

Please sign in to comment.