Skip to content

Commit

Permalink
Merge pull request #41 from nenoNaninu/support_DateTimeOffset
Browse files Browse the repository at this point in the history
Support DateTimeOffset
  • Loading branch information
nenoNaninu committed Sep 17, 2022
2 parents 3b2c72d + 7294c18 commit fee62c3
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 8 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ When transpiling class, struct, and record, only `public` fields and properties
| string | string |
| Uri | string |
| Guid | string | Compatible with TypeScript's `crypto.randomUUID()`. |
| DateTime | (Date \| string) or Date | Json: `(Date \| string)`, MessagePack: `Date`. |
| DateTime | `(Date \| string)` or `Date` | Json: `(Date \| string)`, MessagePack: `Date`. |
| DateTimeOffset | `(Date \| string)` or `[Date, number]` | Json: `(Date \| string)`, MessagePack: `[Date, number]`. note [#41](https://github.com/nenoNaninu/Tapper/pull/41) |
| System.Nullable\<T\>| (T \| undefined) |
| byte[] | string or Uint8Array | JSON: `string` (base64), MessagePack `Uint8Array`. |
| T[] | T[] |
Expand Down
1 change: 1 addition & 0 deletions src/Tapper.Analyzer/TapperAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public override void Initialize(AnalysisContext context)
typeof(Uri),
typeof(Guid),
typeof(DateTime),
typeof(DateTimeOffset),
typeof(Nullable<>),
// Collection
typeof(Array),
Expand Down
3 changes: 2 additions & 1 deletion src/Tapper/DefaultTypeMapperProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public DefaultTypeMapperProvider(Compilation compilation, bool includeReferenced
_tupleTypeMapper = new TupleTypeMapper();

var dateTimeTypeMapper = new DateTimeTypeMapper(compilation);
var dateTimeOffsetTypeMapper = new DateTimeOffsetTypeMapper(compilation);
var nullableStructTypeMapper = new NullableStructTypeMapper(compilation);

var primitiveTypeMappers = PrimitiveTypeMappers.Create(compilation);
Expand All @@ -31,7 +32,7 @@ public DefaultTypeMapperProvider(Compilation compilation, bool includeReferenced
var typeMappers = sourceTypeMapper.Concat(primitiveTypeMappers)
.Concat(collectionTypeTypeMappers)
.Concat(dictionaryTypeMappers)
.Concat(new ITypeMapper[] { dateTimeTypeMapper, nullableStructTypeMapper });
.Concat(new ITypeMapper[] { dateTimeTypeMapper, dateTimeOffsetTypeMapper, nullableStructTypeMapper });

_mappers = typeMappers.ToDictionary<ITypeMapper, ITypeSymbol>(x => x.Assign, SymbolEqualityComparer.Default);
}
Expand Down
28 changes: 28 additions & 0 deletions src/Tapper/TypeMappers/DateTimeTypeMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,31 @@ public string MapTo(ITypeSymbol typeSymbol, ITranspilationOptions options)
throw new InvalidOperationException($"DateTimeTypeMapper is not support {typeSymbol.ToDisplayString()}.");
}
}

internal class DateTimeOffsetTypeMapper : ITypeMapper
{
public ITypeSymbol Assign { get; }

public DateTimeOffsetTypeMapper(Compilation compilation)
{
Assign = compilation.GetTypeByMetadataName("System.DateTimeOffset")!;
}

public string MapTo(ITypeSymbol typeSymbol, ITranspilationOptions options)
{
if (SymbolEqualityComparer.Default.Equals(typeSymbol, Assign))
{
if (options.SerializerOption == SerializerOption.MessagePack)
{
return "[Date, number]";
}
else
{
return "(Date | string)";
}
}

throw new InvalidOperationException($"DateTimeOffsetTypeMapper is not support {typeSymbol.ToDisplayString()}.");
}
}

13 changes: 13 additions & 0 deletions tests/Tapper.Tests.Server/Controllers/TapperController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,17 @@ public int Test0()

return null;
}

[HttpPost]
public Type7? Test7(Type7 type7)
{
var ans = DateTimeOffset.Parse("2022-09-17T16:29:55.2260000+09:00");

if (type7.DateTimeOffset == ans)
{
return new Type7(DateTimeOffset.Parse("2022-09-17T16:51:00.4600000+09:00"));
}

return null;
}
}
3 changes: 3 additions & 0 deletions tests/Tapper.Tests.Server/Models/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,6 @@ public record Type5(char Value);

[TranspilationSource]
public record Type6(byte[] Binary);

[TranspilationSource]
public record Type7(DateTimeOffset DateTimeOffset);
15 changes: 13 additions & 2 deletions tests/TypeScriptTest/src/fetch.json.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { fetchType2, fetchType3, fetchType4, fetchType5, fetchType6 } from './fetch.json'
import { MyEnum, Type2, Type3, Type4, Type5, Type6 } from './generated/json/Tapper.Tests.Server.Models'
import { fetchType2, fetchType3, fetchType4, fetchType5, fetchType6, fetchType7 } from './fetch.json'
import { MyEnum, Type2, Type3, Type4, Type5, Type6, Type7 } from './generated/json/Tapper.Tests.Server.Models'

test('fetch1.json', async () => {
const res = await fetchType2();
Expand Down Expand Up @@ -53,3 +53,14 @@ test('fetch6.json', async () => {

expect(res).toEqual(gt);
});

test('fetch7.json', async () => {
const res = await fetchType7();

const gt: Type7 =
{
dateTimeOffset: new Date("2022-09-17T16:51:00.4600000+09:00")
}

expect(res).toEqual(gt);
});
20 changes: 19 additions & 1 deletion tests/TypeScriptTest/src/fetch.json.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MyEnum, Type2, Type3, Type4, Type5, Type6 } from './generated/json/Tapper.Tests.Server.Models';
import { MyEnum, Type2, Type3, Type4, Type5, Type6, Type7 } from './generated/json/Tapper.Tests.Server.Models';
import { randomUUID } from 'crypto';
import fetch from 'node-fetch';

Expand Down Expand Up @@ -84,3 +84,21 @@ export const fetchType6 = async () => {

return ret;
}

export const fetchType7 = async () => {
const obj: Type7 = {
dateTimeOffset: new Date("2022-09-17T16:29:55.2260000+09:00")
}

const response = await fetch("http://localhost:5100/tapper/test7", {
method: "POST",
body: JSON.stringify(obj),
headers: { 'Content-Type': 'application/json' },
});

const ret = await response.json() as Type7;

ret.dateTimeOffset = typeof ret.dateTimeOffset === 'string' ? new Date(ret.dateTimeOffset) : ret.dateTimeOffset;

return ret;
}
15 changes: 13 additions & 2 deletions tests/TypeScriptTest/src/fetch.msgpack.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { fetchType2, fetchType3, fetchType4, fetchType5, fetchType6 } from './fetch.msgpack'
import { MyEnum, Type2, Type3, Type4, Type5, Type6 } from './generated/msgpack/Tapper.Tests.Server.Models'
import { fetchType2, fetchType3, fetchType4, fetchType5, fetchType6, fetchType7 } from './fetch.msgpack'
import { MyEnum, Type2, Type3, Type4, Type5, Type6, Type7 } from './generated/msgpack/Tapper.Tests.Server.Models'

test('fetch1.msgpack', async () => {
const res = await fetchType2();
Expand Down Expand Up @@ -56,3 +56,14 @@ test('fetch6.msgpack', async () => {

expect(res).toEqual(gt);
});

test('fetch7.msgpack', async () => {
const res = await fetchType7();

const gt: Type7 =
{
DateTimeOffset: [new Date("2022-09-17T16:51:00.46Z"), 540]
}

expect(res).toEqual(gt);
});
22 changes: 21 additions & 1 deletion tests/TypeScriptTest/src/fetch.msgpack.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MyEnum, Type2, Type3, Type4, Type5, Type6 } from './generated/msgpack/Tapper.Tests.Server.Models';
import { MyEnum, Type2, Type3, Type4, Type5, Type6, Type7 } from './generated/msgpack/Tapper.Tests.Server.Models';
import { randomUUID } from 'crypto';
import { encode, decode } from "@msgpack/msgpack";
import fetch from 'node-fetch';
Expand Down Expand Up @@ -108,3 +108,23 @@ export const fetchType6 = async () => {

return ret;
}

export const fetchType7 = async () => {
const obj: Type7 = {
DateTimeOffset: [new Date("2022-09-17T16:29:55.226Z"), 540],
}

const response = await fetch("http://localhost:5100/tapper/test7", {
method: "POST",
body: encode(obj),
headers: {
'Content-Type': 'application/x-msgpack',
'Accept': 'application/x-msgpack'
},
});

const buf = await response.buffer()
const ret = decode<Type7>(buf) as Type7;

return ret;
}

0 comments on commit fee62c3

Please sign in to comment.