diff --git a/CHANGELOG.md b/CHANGELOG.md
index bfdda50..e31d965 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
diff --git a/README.md b/README.md
index 02033b5..c51200d 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/TypeContractor.Annotations/TypeContractorIgnoreAttribute.cs b/TypeContractor.Annotations/TypeContractorIgnoreAttribute.cs
index 03dacd2..f520890 100644
--- a/TypeContractor.Annotations/TypeContractorIgnoreAttribute.cs
+++ b/TypeContractor.Annotations/TypeContractorIgnoreAttribute.cs
@@ -3,11 +3,11 @@
namespace TypeContractor.Annotations
{
///
- /// 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.
///
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class TypeContractorIgnoreAttribute : Attribute
{
}
diff --git a/TypeContractor.Tests/TypeScript/TypeScriptConverterTests.cs b/TypeContractor.Tests/TypeScript/TypeScriptConverterTests.cs
index 12221ab..2cd229f 100644
--- a/TypeContractor.Tests/TypeScript/TypeScriptConverterTests.cs
+++ b/TypeContractor.Tests/TypeScript/TypeScriptConverterTests.cs
@@ -1,5 +1,6 @@
using System.Reflection;
using System.Runtime.InteropServices;
+using TypeContractor.Annotations;
using TypeContractor.TypeScript;
namespace TypeContractor.Tests.TypeScript;
@@ -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);
@@ -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()
diff --git a/TypeContractor.Tool/ConsoleLogger.cs b/TypeContractor.Tool/ConsoleLogger.cs
index f446fe4..bc7d59e 100644
--- a/TypeContractor.Tool/ConsoleLogger.cs
+++ b/TypeContractor.Tool/ConsoleLogger.cs
@@ -4,6 +4,7 @@ namespace TypeContractor.Tool;
public enum LogLevel
{
+ Trace,
Debug,
Info,
Warning,
@@ -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}");
+ }
}
diff --git a/TypeContractor/Logger/ILog.cs b/TypeContractor/Logger/ILog.cs
index c0d5d9c..59734ae 100644
--- a/TypeContractor/Logger/ILog.cs
+++ b/TypeContractor/Logger/ILog.cs
@@ -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);
diff --git a/TypeContractor/Logger/NullLogger.cs b/TypeContractor/Logger/NullLogger.cs
index 5557503..d4e75bb 100644
--- a/TypeContractor/Logger/NullLogger.cs
+++ b/TypeContractor/Logger/NullLogger.cs
@@ -2,6 +2,10 @@ namespace TypeContractor.Logger;
public class NullLogger : ILog
{
+ public void LogTrace(string message)
+ {
+ }
+
public void LogDebug(string message)
{
}
diff --git a/TypeContractor/TypeScript/TypeScriptConverter.cs b/TypeContractor/TypeScript/TypeScriptConverter.cs
index 2ec0fb6..24b16e9 100644
--- a/TypeContractor/TypeScript/TypeScriptConverter.cs
+++ b/TypeContractor/TypeScript/TypeScriptConverter.cs
@@ -1,5 +1,7 @@
using System.Reflection;
+using TypeContractor.Annotations;
using TypeContractor.Helpers;
+using TypeContractor.Logger;
using TypeContractor.Output;
namespace TypeContractor.TypeScript;
@@ -62,6 +64,12 @@ private List 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;