Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Simplified response for generated API clients using the React template (#203)
- Add default maps for unsigned numbers (#180)
- Apply `TypeContractorIgnore` to properties

### Fixed

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,8 @@ Available annotations:
If you have a controller that doesn't need a client
generated, you can annotate that controller using `TypeContractorIgnore`
and it will be automatically skipped.

Also works on properties that shouldn't be included in generated DTOs.
* `TypeContractorName`:
If you have a badly named controller that you can't rename,
you want something custom, or just don't like the default naming
Expand Down
8 changes: 4 additions & 4 deletions TypeContractor.Annotations/TypeContractorIgnoreAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
namespace TypeContractor.Annotations
{
/// <summary>
/// Tells TypeContractor to ignore the given controller when generating
/// automatic API clients. For example a controller that serves static
/// assets for the HTML templates.
/// Tells TypeContractor to ignore the target when generating TypeScript.
/// For example a controller that serves static assets for HTML templates.
/// Can also be used for properties that don't need to be exposed.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class TypeContractorIgnoreAttribute : Attribute
{
}
Expand Down
20 changes: 20 additions & 0 deletions TypeContractor.Tests/TypeScript/TypeScriptConverterTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Reflection;
using System.Runtime.InteropServices;
using TypeContractor.Annotations;
using TypeContractor.TypeScript;

namespace TypeContractor.Tests.TypeScript;
Expand Down Expand Up @@ -416,6 +417,18 @@ public void Handles_Arrays()
list.IsArray.Should().BeTrue();
}

[Fact]
public void Ignores_Properties_With_IgnoreAttribute()
{
var result = Sut.Convert(typeof(ResponseWithIgnoredProperties));

result.Should().NotBeNull();
result.Properties.Should()
.NotBeNull()
.And.ContainSingle()
.And.Contain(x => x.DestinationName == "dontIgnoreMeBro");
}

#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
private record TopLevelRecord(string Name, SecondStoryRecord? SecondStoryRecord);
private record SecondStoryRecord(string Description, SomeOtherDeeplyNestedRecord? SomeOtherDeeplyNestedRecord);
Expand Down Expand Up @@ -559,6 +572,13 @@ private class ResponseWithArrayDto
public DateOnlyResponse[] DateOnlyResponses { get; set; }
}

private class ResponseWithIgnoredProperties
{
public string DontIgnoreMeBro { get; set; }
[TypeContractorIgnore]
public string FeelFreeToIgnoreMe { get; set; }
}

#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.

private MetadataLoadContext BuildMetadataLoadContext()
Expand Down
7 changes: 7 additions & 0 deletions TypeContractor.Tool/ConsoleLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace TypeContractor.Tool;

public enum LogLevel
{
Trace,
Debug,
Info,
Warning,
Expand Down Expand Up @@ -42,4 +43,10 @@ public void LogDebug(string message)
if (logLevel <= LogLevel.Debug)
Console.WriteLine($"[ DBG] {message}");
}

public void LogTrace(string message)
{
if (logLevel <= LogLevel.Trace)
Console.WriteLine($"[TRC] {message}");
}
}
1 change: 1 addition & 0 deletions TypeContractor/Logger/ILog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ namespace TypeContractor.Logger;

public interface ILog
{
void LogTrace(string message);
void LogDebug(string message);
void LogError(Exception exception, string message);
void LogError(string message);
Expand Down
4 changes: 4 additions & 0 deletions TypeContractor/Logger/NullLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ namespace TypeContractor.Logger;

public class NullLogger : ILog
{
public void LogTrace(string message)
{
}

public void LogDebug(string message)
{
}
Expand Down
8 changes: 8 additions & 0 deletions TypeContractor/TypeScript/TypeScriptConverter.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Reflection;
using TypeContractor.Annotations;
using TypeContractor.Helpers;
using TypeContractor.Logger;
using TypeContractor.Output;

namespace TypeContractor.TypeScript;
Expand Down Expand Up @@ -62,6 +64,12 @@ private List<OutputProperty> GetProperties(Type type)
// Evaluate type of property
foreach (var property in properties)
{
if (property.HasCustomAttribute(typeof(TypeContractorIgnoreAttribute).FullName!))
{
Log.Instance.LogTrace($"Property {type.FullName ?? type.Name}.{property.Name} is ignored by attribute");
continue;
}

// Need to have a getter
if (!property.CanRead) continue;

Expand Down
Loading