From 65d12ca183431d13763d2c92b017d944aadc7b6e Mon Sep 17 00:00:00 2001 From: Chris Haines Date: Thu, 15 Sep 2016 18:05:58 +0100 Subject: [PATCH 1/9] Refactor forked project and split up console into library and console app --- LICENSE | 21 -- Signalr.Hubs.TypescriptGenerator.sln | 48 ++++ SignalrTypescriptGenerator.sln | 22 -- icon.png | Bin 19506 -> 0 bytes src/SampleUsage/App.config | 27 ++ .../DataContracts/InnerSomethingDto.cs | 18 ++ .../DataContracts/OtherSomethingDto.cs | 21 ++ src/SampleUsage/DataContracts/SomethingDto.cs | 18 ++ .../DataContracts/SomethingEnum.cs | 15 + src/SampleUsage/GenerateHubTypeScript.cs | 16 ++ src/SampleUsage/Hubs/HubA.cs | 23 ++ src/SampleUsage/Hubs/HubB.cs | 22 ++ .../Hubs/HubCWithNoClientInterface.cs | 11 + src/SampleUsage/Properties/AssemblyInfo.cs | 36 +++ src/SampleUsage/SampleUsage.csproj | 96 +++++++ src/SampleUsage/packages.config | 9 + .../App.config | 27 ++ .../AssemblyLoader.cs | 29 ++ .../CommandLineOptions.cs | 31 +- .../Program.cs | 63 ++++ .../Properties/AssemblyInfo.cs | 36 +++ ...lr.Hubs.TypeScriptGenerator.Console.csproj | 101 +++++++ ...lr.Hubs.TypeScriptGenerator.Console.nuspec | 17 ++ .../packages.config | 11 + .../AssemblyLoader.cs | 29 ++ .../Helpers/HubHelper.cs | 121 ++++++++ .../Helpers}/TypeHelper.cs | 272 +++++++++--------- .../HubTypeScriptGenerator.cs | 66 +++++ .../Models/ClientInfo.cs | 23 ++ .../Models/DataContractInfo.cs | 23 ++ .../Models/EnumInfo.cs | 23 ++ .../Models/FunctionDetails.cs | 21 ++ .../Models/ServiceInfo.cs | 30 ++ .../Models/TypeInfo.cs | 19 ++ .../Models/TypesModel.cs | 25 ++ .../Properties/AssemblyInfo.cs | 72 ++--- .../Signalr.Hubs.TypescriptGenerator.csproj} | 213 +++++++------- .../Signalr.Hubs.TypescriptGenerator.nuspec | 17 ++ .../app.config | 19 ++ .../packages.config | 10 + .../template.cshtml | 170 +++++------ src/SignalrTypescriptGenerator/App.config | 19 -- .../Models/ClientInfo.cs | 16 -- .../Models/DataContractInfo.cs | 16 -- .../Models/EnumInfo.cs | 16 -- .../Models/FunctionDetails.cs | 9 - .../Models/ServiceInfo.cs | 20 -- .../Models/TypeInfo.cs | 8 - .../Models/TypesModel.cs | 28 -- src/SignalrTypescriptGenerator/Program.cs | 138 --------- .../SignalrHubinator.cs | 191 ------------ .../SignalrTypescriptGenerator.nuspec | 20 -- .../build-nuget.ps1 | 7 - .../packages.config | 11 - 54 files changed, 1450 insertions(+), 920 deletions(-) delete mode 100644 LICENSE create mode 100644 Signalr.Hubs.TypescriptGenerator.sln delete mode 100644 SignalrTypescriptGenerator.sln delete mode 100644 icon.png create mode 100644 src/SampleUsage/App.config create mode 100644 src/SampleUsage/DataContracts/InnerSomethingDto.cs create mode 100644 src/SampleUsage/DataContracts/OtherSomethingDto.cs create mode 100644 src/SampleUsage/DataContracts/SomethingDto.cs create mode 100644 src/SampleUsage/DataContracts/SomethingEnum.cs create mode 100644 src/SampleUsage/GenerateHubTypeScript.cs create mode 100644 src/SampleUsage/Hubs/HubA.cs create mode 100644 src/SampleUsage/Hubs/HubB.cs create mode 100644 src/SampleUsage/Hubs/HubCWithNoClientInterface.cs create mode 100644 src/SampleUsage/Properties/AssemblyInfo.cs create mode 100644 src/SampleUsage/SampleUsage.csproj create mode 100644 src/SampleUsage/packages.config create mode 100644 src/Signalr.Hubs.TypeScriptGenerator.Console/App.config create mode 100644 src/Signalr.Hubs.TypeScriptGenerator.Console/AssemblyLoader.cs rename src/{SignalrTypescriptGenerator/Models => Signalr.Hubs.TypeScriptGenerator.Console}/CommandLineOptions.cs (56%) create mode 100644 src/Signalr.Hubs.TypeScriptGenerator.Console/Program.cs create mode 100644 src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs create mode 100644 src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.csproj create mode 100644 src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.nuspec create mode 100644 src/Signalr.Hubs.TypeScriptGenerator.Console/packages.config create mode 100644 src/Signalr.Hubs.TypescriptGenerator/AssemblyLoader.cs create mode 100644 src/Signalr.Hubs.TypescriptGenerator/Helpers/HubHelper.cs rename src/{SignalrTypescriptGenerator => Signalr.Hubs.TypescriptGenerator/Helpers}/TypeHelper.cs (76%) create mode 100644 src/Signalr.Hubs.TypescriptGenerator/HubTypeScriptGenerator.cs create mode 100644 src/Signalr.Hubs.TypescriptGenerator/Models/ClientInfo.cs create mode 100644 src/Signalr.Hubs.TypescriptGenerator/Models/DataContractInfo.cs create mode 100644 src/Signalr.Hubs.TypescriptGenerator/Models/EnumInfo.cs create mode 100644 src/Signalr.Hubs.TypescriptGenerator/Models/FunctionDetails.cs create mode 100644 src/Signalr.Hubs.TypescriptGenerator/Models/ServiceInfo.cs create mode 100644 src/Signalr.Hubs.TypescriptGenerator/Models/TypeInfo.cs create mode 100644 src/Signalr.Hubs.TypescriptGenerator/Models/TypesModel.cs rename src/{SignalrTypescriptGenerator => Signalr.Hubs.TypescriptGenerator}/Properties/AssemblyInfo.cs (97%) rename src/{SignalrTypescriptGenerator/SignalrTypescriptGenerator.csproj => Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.csproj} (72%) create mode 100644 src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.nuspec create mode 100644 src/Signalr.Hubs.TypescriptGenerator/app.config create mode 100644 src/Signalr.Hubs.TypescriptGenerator/packages.config rename src/{SignalrTypescriptGenerator => Signalr.Hubs.TypescriptGenerator}/template.cshtml (81%) delete mode 100644 src/SignalrTypescriptGenerator/App.config delete mode 100644 src/SignalrTypescriptGenerator/Models/ClientInfo.cs delete mode 100644 src/SignalrTypescriptGenerator/Models/DataContractInfo.cs delete mode 100644 src/SignalrTypescriptGenerator/Models/EnumInfo.cs delete mode 100644 src/SignalrTypescriptGenerator/Models/FunctionDetails.cs delete mode 100644 src/SignalrTypescriptGenerator/Models/ServiceInfo.cs delete mode 100644 src/SignalrTypescriptGenerator/Models/TypeInfo.cs delete mode 100644 src/SignalrTypescriptGenerator/Models/TypesModel.cs delete mode 100644 src/SignalrTypescriptGenerator/Program.cs delete mode 100644 src/SignalrTypescriptGenerator/SignalrHubinator.cs delete mode 100644 src/SignalrTypescriptGenerator/SignalrTypescriptGenerator.nuspec delete mode 100644 src/SignalrTypescriptGenerator/build-nuget.ps1 delete mode 100644 src/SignalrTypescriptGenerator/packages.config diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 80214b7..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Chris S. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Signalr.Hubs.TypescriptGenerator.sln b/Signalr.Hubs.TypescriptGenerator.sln new file mode 100644 index 0000000..3ecdea2 --- /dev/null +++ b/Signalr.Hubs.TypescriptGenerator.sln @@ -0,0 +1,48 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Signalr.Hubs.TypescriptGenerator", "src\Signalr.Hubs.TypescriptGenerator\Signalr.Hubs.TypescriptGenerator.csproj", "{C90F8C7B-213B-4CD0-A9F0-3A39634CECDE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Signalr.Hubs.TypeScriptGenerator.Console", "src\Signalr.Hubs.TypeScriptGenerator.Console\Signalr.Hubs.TypeScriptGenerator.Console.csproj", "{B68600AA-F2AE-4EBF-9AF5-DEF252E71142}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "App", "App", "{AE98D3B3-6832-4544-A021-3C32156F971B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".sln", ".sln", "{6C40DD74-1C6E-4292-9252-252D1573C321}" + ProjectSection(SolutionItems) = preProject + README.md = README.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sample", "Sample", "{5522BF7C-CC56-45CA-8C07-A735916CC2BE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleUsage", "src\SampleUsage\SampleUsage.csproj", "{668072BF-5142-4796-BA67-8CB676C7196C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C90F8C7B-213B-4CD0-A9F0-3A39634CECDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C90F8C7B-213B-4CD0-A9F0-3A39634CECDE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C90F8C7B-213B-4CD0-A9F0-3A39634CECDE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C90F8C7B-213B-4CD0-A9F0-3A39634CECDE}.Release|Any CPU.Build.0 = Release|Any CPU + {B68600AA-F2AE-4EBF-9AF5-DEF252E71142}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B68600AA-F2AE-4EBF-9AF5-DEF252E71142}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B68600AA-F2AE-4EBF-9AF5-DEF252E71142}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B68600AA-F2AE-4EBF-9AF5-DEF252E71142}.Release|Any CPU.Build.0 = Release|Any CPU + {668072BF-5142-4796-BA67-8CB676C7196C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {668072BF-5142-4796-BA67-8CB676C7196C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {668072BF-5142-4796-BA67-8CB676C7196C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {668072BF-5142-4796-BA67-8CB676C7196C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {C90F8C7B-213B-4CD0-A9F0-3A39634CECDE} = {AE98D3B3-6832-4544-A021-3C32156F971B} + {B68600AA-F2AE-4EBF-9AF5-DEF252E71142} = {AE98D3B3-6832-4544-A021-3C32156F971B} + {668072BF-5142-4796-BA67-8CB676C7196C} = {5522BF7C-CC56-45CA-8C07-A735916CC2BE} + EndGlobalSection +EndGlobal diff --git a/SignalrTypescriptGenerator.sln b/SignalrTypescriptGenerator.sln deleted file mode 100644 index 4fa3942..0000000 --- a/SignalrTypescriptGenerator.sln +++ /dev/null @@ -1,22 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SignalrTypescriptGenerator", "src\SignalrTypescriptGenerator\SignalrTypescriptGenerator.csproj", "{C90F8C7B-213B-4CD0-A9F0-3A39634CECDE}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C90F8C7B-213B-4CD0-A9F0-3A39634CECDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C90F8C7B-213B-4CD0-A9F0-3A39634CECDE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C90F8C7B-213B-4CD0-A9F0-3A39634CECDE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C90F8C7B-213B-4CD0-A9F0-3A39634CECDE}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/icon.png b/icon.png deleted file mode 100644 index f8e0350b4725ddb5d2f9636f0fec6f7ba77f4056..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19506 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 V|KYNMA*}!a002ovPDHLkV1nmIZ+-v( diff --git a/src/SampleUsage/App.config b/src/SampleUsage/App.config new file mode 100644 index 0000000..d92337c --- /dev/null +++ b/src/SampleUsage/App.config @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/SampleUsage/DataContracts/InnerSomethingDto.cs b/src/SampleUsage/DataContracts/InnerSomethingDto.cs new file mode 100644 index 0000000..6372f8e --- /dev/null +++ b/src/SampleUsage/DataContracts/InnerSomethingDto.cs @@ -0,0 +1,18 @@ +using System; +using System.Runtime.Serialization; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.DataContracts +{ + [DataContract] + public class InnerSomethingDto + { + [DataMember] + public int InnerProperty1 { get; set; } + + [DataMember] + public DateTime InnerProperty2 { get; set; } + + [DataMember] + public SomethingEnum InnerProperty3 { get; set; } + } +} \ No newline at end of file diff --git a/src/SampleUsage/DataContracts/OtherSomethingDto.cs b/src/SampleUsage/DataContracts/OtherSomethingDto.cs new file mode 100644 index 0000000..fa4e9a4 --- /dev/null +++ b/src/SampleUsage/DataContracts/OtherSomethingDto.cs @@ -0,0 +1,21 @@ +using System; +using System.Runtime.Serialization; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.DataContracts +{ + [DataContract] + public class OtherSomethingDto + { + [DataMember] + public string Property1 { get; set; } + + [DataMember] + public DateTime Property2 { get; set; } + + [DataMember] + public InnerSomethingDto Property3 { get; set; } + + [DataMember] + public InnerSomethingDto Property4 { get; set; } + } +} \ No newline at end of file diff --git a/src/SampleUsage/DataContracts/SomethingDto.cs b/src/SampleUsage/DataContracts/SomethingDto.cs new file mode 100644 index 0000000..4230e46 --- /dev/null +++ b/src/SampleUsage/DataContracts/SomethingDto.cs @@ -0,0 +1,18 @@ +using System; +using System.Runtime.Serialization; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.DataContracts +{ + [DataContract] + public class SomethingDto + { + [DataMember] + public string Property1 { get; set; } + + [DataMember] + public Guid Property2 { get; set; } + + [DataMember] + public InnerSomethingDto Property3 { get; set; } + } +} \ No newline at end of file diff --git a/src/SampleUsage/DataContracts/SomethingEnum.cs b/src/SampleUsage/DataContracts/SomethingEnum.cs new file mode 100644 index 0000000..329ef73 --- /dev/null +++ b/src/SampleUsage/DataContracts/SomethingEnum.cs @@ -0,0 +1,15 @@ +using System.Runtime.Serialization; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.DataContracts +{ + [DataContract] + public enum SomethingEnum + { + [EnumMember] + One, + [EnumMember] + Two, + [EnumMember] + Three, + } +} \ No newline at end of file diff --git a/src/SampleUsage/GenerateHubTypeScript.cs b/src/SampleUsage/GenerateHubTypeScript.cs new file mode 100644 index 0000000..8478b54 --- /dev/null +++ b/src/SampleUsage/GenerateHubTypeScript.cs @@ -0,0 +1,16 @@ +using NUnit.Framework; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage +{ + [TestFixture] + public class GenerateHubTypeScript + { + [Test] + public void Generate() + { + var hubTypeScriptGenerator = new HubTypeScriptGenerator(); + var typeScript = hubTypeScriptGenerator.Generate(); + System.Console.WriteLine(typeScript); + } + } +} \ No newline at end of file diff --git a/src/SampleUsage/Hubs/HubA.cs b/src/SampleUsage/Hubs/HubA.cs new file mode 100644 index 0000000..3207f81 --- /dev/null +++ b/src/SampleUsage/Hubs/HubA.cs @@ -0,0 +1,23 @@ +using GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.DataContracts; +using Microsoft.AspNet.SignalR; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.Hubs +{ + public interface IHubAClient + { + void Pong(); + void TakeThis(SomethingDto somethingDto); + } + + public class HubA : Hub + { + public SomethingDto GetSomething() + { + return new SomethingDto(); + } + + public void Ping() + { + } + } +} \ No newline at end of file diff --git a/src/SampleUsage/Hubs/HubB.cs b/src/SampleUsage/Hubs/HubB.cs new file mode 100644 index 0000000..144ed0f --- /dev/null +++ b/src/SampleUsage/Hubs/HubB.cs @@ -0,0 +1,22 @@ +using GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.DataContracts; +using Microsoft.AspNet.SignalR; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.Hubs +{ + public interface IHubBClient + { + void TakeOtherThis(OtherSomethingDto otherSomethingDto); + } + + public class HubB : Hub + { + public OtherSomethingDto GetOtherSomething() + { + return new OtherSomethingDto(); + } + + public void DoOtherSomethingElse() + { + } + } +} \ No newline at end of file diff --git a/src/SampleUsage/Hubs/HubCWithNoClientInterface.cs b/src/SampleUsage/Hubs/HubCWithNoClientInterface.cs new file mode 100644 index 0000000..1f021c8 --- /dev/null +++ b/src/SampleUsage/Hubs/HubCWithNoClientInterface.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNet.SignalR; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.Hubs +{ + public class HubC : Hub + { + public void AServerSideMethod() + { + } + } +} \ No newline at end of file diff --git a/src/SampleUsage/Properties/AssemblyInfo.cs b/src/SampleUsage/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8b27b17 --- /dev/null +++ b/src/SampleUsage/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SampleUsage")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SampleUsage")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("668072bf-5142-4796-ba67-8cb676c7196c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/SampleUsage/SampleUsage.csproj b/src/SampleUsage/SampleUsage.csproj new file mode 100644 index 0000000..5f4b01a --- /dev/null +++ b/src/SampleUsage/SampleUsage.csproj @@ -0,0 +1,96 @@ + + + + + Debug + AnyCPU + {668072BF-5142-4796-BA67-8CB676C7196C} + Library + Properties + GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage + GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\packages\Microsoft.AspNet.SignalR.Core.2.2.1\lib\net45\Microsoft.AspNet.SignalR.Core.dll + True + + + ..\..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll + True + + + ..\..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll + True + + + ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + True + + + ..\..\packages\NUnit.3.4.1\lib\net45\nunit.framework.dll + True + + + ..\..\packages\Owin.1.0\lib\net40\Owin.dll + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {C90F8C7B-213B-4CD0-A9F0-3A39634CECDE} + Signalr.Hubs.TypescriptGenerator + + + + + \ No newline at end of file diff --git a/src/SampleUsage/packages.config b/src/SampleUsage/packages.config new file mode 100644 index 0000000..a562550 --- /dev/null +++ b/src/SampleUsage/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/App.config b/src/Signalr.Hubs.TypeScriptGenerator.Console/App.config new file mode 100644 index 0000000..d92337c --- /dev/null +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/App.config @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/AssemblyLoader.cs b/src/Signalr.Hubs.TypeScriptGenerator.Console/AssemblyLoader.cs new file mode 100644 index 0000000..ea411c2 --- /dev/null +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/AssemblyLoader.cs @@ -0,0 +1,29 @@ +using System; +using System.IO; +using System.Reflection; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Console +{ + internal class AssemblyLoader + { + public void LoadAssemblyIntoAppDomain(string assemblyPath) + { + var currentDomain = AppDomain.CurrentDomain; + currentDomain.AssemblyResolve += LoadFromSameFolder; + Assembly.LoadFile(assemblyPath); + } + + private static Assembly LoadFromSameFolder(object sender, ResolveEventArgs args) + { + var directoryName = Path.GetDirectoryName(args.RequestingAssembly.Location); + var assemblyPath = Path.Combine(directoryName, new AssemblyName(args.Name).Name + ".dll"); + if (!File.Exists(assemblyPath)) + { + return null; + } + + var assembly = Assembly.LoadFrom(assemblyPath); + return assembly; + } + } +} \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/Models/CommandLineOptions.cs b/src/Signalr.Hubs.TypeScriptGenerator.Console/CommandLineOptions.cs similarity index 56% rename from src/SignalrTypescriptGenerator/Models/CommandLineOptions.cs rename to src/Signalr.Hubs.TypeScriptGenerator.Console/CommandLineOptions.cs index 6137711..1e3a474 100644 --- a/src/SignalrTypescriptGenerator/Models/CommandLineOptions.cs +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/CommandLineOptions.cs @@ -1,13 +1,20 @@ -using CommandLine; - -namespace SignalrTypescriptGenerator.Models -{ - public class CommandLineOptions - { - [Option('a', "assembly", HelpText = "The path to the assembly (.dll/.exe)", Required = true)] - public string AssemblyPath { get; set; } - - [Option('o', "outfile", HelpText = "The path to the file to generate. If this is empty, the output is written to stdout.")] - public string OutFile { get; set; } - } +using CommandLine; +using CommandLine.Text; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Console +{ + public class CommandLineOptions + { + [Option('a', "assembly", HelpText = "The path to the assembly (.dll/.exe)", Required = true)] + public string AssemblyPath { get; set; } + + [Option('o', "outfile", HelpText = "The path to the file to generate. If this is empty, the output is written to stdout.")] + public string OutFile { get; set; } + + [HelpOption] + public string GetUsage() + { + return HelpText.AutoBuild(this, current => HelpText.DefaultParsingErrorsHandler(this, current)); + } + } } \ No newline at end of file diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/Program.cs b/src/Signalr.Hubs.TypeScriptGenerator.Console/Program.cs new file mode 100644 index 0000000..e54369f --- /dev/null +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/Program.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; +using System.Reflection; +using CommandLine; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Console +{ + public class Program + { + public static int Main(string[] args) + { + if (AppDomain.CurrentDomain.IsDefaultAppDomain()) + { + return RunInNewAppDomainToAllowRazorEngineToCleanup(args); + } + + try + { + var options = new CommandLineOptions(); + if (Parser.Default.ParseArguments(args, options)) + { + Run(options); + return 0; + } + + System.Console.WriteLine("Error parsing command line options"); + System.Console.WriteLine(options.GetUsage()); + System.Console.ReadKey(); + return 1; + } + catch (Exception e) + { + System.Console.WriteLine("Error generating TypeScript"); + System.Console.WriteLine(e); + return 1; + } + } + + private static int RunInNewAppDomainToAllowRazorEngineToCleanup(string[] args) + { + var appDomain = AppDomain.CreateDomain("RazorEngine", null, AppDomain.CurrentDomain.SetupInformation); + var exitCode = appDomain.ExecuteAssembly(Assembly.GetExecutingAssembly().Location, args); + AppDomain.Unload(appDomain); + return exitCode; + } + + private static void Run(CommandLineOptions commandLineOptions) + { + LoadAssemblies(commandLineOptions); + + var hubTypeScriptGenerator = new HubTypeScriptGenerator(); + var outputText = hubTypeScriptGenerator.Generate(); + File.WriteAllText(commandLineOptions.OutFile, outputText); + } + + + private static void LoadAssemblies(CommandLineOptions commandLineOptions) + { + var assemblyLoader = new AssemblyLoader(); + assemblyLoader.LoadAssemblyIntoAppDomain(commandLineOptions.AssemblyPath); + } + } +} diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs b/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0d9ff4d --- /dev/null +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Signalr.Hubs.TypeScriptGenerator.Console")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Signalr.Hubs.TypeScriptGenerator.Console")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("b68600aa-f2ae-4ebf-9af5-def252e71142")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.csproj b/src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.csproj new file mode 100644 index 0000000..b5d1c6d --- /dev/null +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.csproj @@ -0,0 +1,101 @@ + + + + + Debug + AnyCPU + {B68600AA-F2AE-4EBF-9AF5-DEF252E71142} + Exe + Properties + GeniusSports.Signalr.Hubs.TypescriptGenerator.Console + GeniusSports.Signalr.Hubs.TypescriptGenerator.Console + v4.5 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll + True + + + ..\..\packages\Microsoft.AspNet.SignalR.Core.2.2.1\lib\net45\Microsoft.AspNet.SignalR.Core.dll + True + + + ..\..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll + True + + + ..\..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll + True + + + ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + True + + + ..\..\packages\Owin.1.0\lib\net40\Owin.dll + True + + + ..\..\packages\RazorEngine.3.9.0\lib\net45\RazorEngine.dll + True + + + + + ..\..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll + True + + + + + + + + + + + + + + + + + + + + + + {c90f8c7b-213b-4cd0-a9f0-3a39634cecde} + Signalr.Hubs.TypescriptGenerator + + + + + \ No newline at end of file diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.nuspec b/src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.nuspec new file mode 100644 index 0000000..18067e0 --- /dev/null +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.nuspec @@ -0,0 +1,17 @@ + + + + Signalr.Hubs.TypescriptGenerator.Console + $version$ + Signalr Typescript Hub Generator + Genius Sports + Genius Sports + https://github.com/geniussportsgroup/Signalr.Hubs.TypescriptGenerator + false + Command line tool for generating Typescript hub definitions for a Signalr assembly. + typescript signalr hubs + + + + + \ No newline at end of file diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/packages.config b/src/Signalr.Hubs.TypeScriptGenerator.Console/packages.config new file mode 100644 index 0000000..1d495d5 --- /dev/null +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/packages.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/AssemblyLoader.cs b/src/Signalr.Hubs.TypescriptGenerator/AssemblyLoader.cs new file mode 100644 index 0000000..b522695 --- /dev/null +++ b/src/Signalr.Hubs.TypescriptGenerator/AssemblyLoader.cs @@ -0,0 +1,29 @@ +using System; +using System.IO; +using System.Reflection; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator +{ + internal class AssemblyLoader + { + public void LoadAssemblyIntoAppDomain(string assemblyPath) + { + var currentDomain = AppDomain.CurrentDomain; + currentDomain.AssemblyResolve += LoadFromSameFolder; + Assembly.LoadFile(assemblyPath); + } + + private static Assembly LoadFromSameFolder(object sender, ResolveEventArgs args) + { + var directoryName = Path.GetDirectoryName(args.RequestingAssembly.Location); + var assemblyPath = Path.Combine(directoryName, new AssemblyName(args.Name).Name + ".dll"); + if (!File.Exists(assemblyPath)) + { + return null; + } + + var assembly = Assembly.LoadFrom(assemblyPath); + return assembly; + } + } +} \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/Helpers/HubHelper.cs b/src/Signalr.Hubs.TypescriptGenerator/Helpers/HubHelper.cs new file mode 100644 index 0000000..5868a99 --- /dev/null +++ b/src/Signalr.Hubs.TypescriptGenerator/Helpers/HubHelper.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using GeniusSports.Signalr.Hubs.TypescriptGenerator.Models; +using Microsoft.AspNet.SignalR; +using Microsoft.AspNet.SignalR.Hubs; +using TypeInfo = GeniusSports.Signalr.Hubs.TypescriptGenerator.Models.TypeInfo; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Helpers +{ + internal class HubHelper + { + private readonly DefaultHubManager hubmanager; + private readonly TypeHelper typeHelper; + + public HubHelper() + { + typeHelper = new TypeHelper(); + + var defaultDependencyResolver = new DefaultDependencyResolver(); + hubmanager = new DefaultHubManager(defaultDependencyResolver); + } + + public List GetHubs() + { + return hubmanager + .GetHubs() + .Select(hub => new TypeInfo(name: hub.NameSpecified ? hub.Name : typeHelper.FirstCharLowered(hub.Name), typescriptType: hub.HubType.FullName)) + .ToList(); + } + + public List GetServiceContracts() + { + var list = new List(); + + foreach (var hub in hubmanager.GetHubs()) + { + var hubMethods = hubmanager + .GetHubMethods(hub.Name) + .Select(method => + { + var methodParametersString = method.Parameters.Select(x => x.Name + " : " + typeHelper.GetTypeContractName(x.ParameterType)); + return new FunctionDetails( + name: typeHelper.FirstCharLowered(method.Name), + arguments: $"({string.Join(", ", methodParametersString)})", + returnType: $"JQueryPromise<{typeHelper.GetTypeContractName(method.ReturnType)}>"); + }) + .ToList(); + + var hubType = hub.HubType; + var clientType = typeHelper.ClientType(hubType); + list.Add(new ServiceInfo( + moduleName: hubType.Namespace, + interfaceName: hubType.Name, + clientType: clientType != null ? clientType.FullName : "any", + serverType: hubType.Name + "Server", + serverTypeFullNamespace: hubType.FullName + "Server", + serverFunctions: hubMethods)); + } + + return list; + } + + public List GetClients() + { + var list = new List(); + + foreach (var hub in hubmanager.GetHubs()) + { + var hubType = hub.HubType; + var clientType = typeHelper.ClientType(hubType); + + if (clientType != null) + { + list.Add(new ClientInfo(moduleName: clientType.Namespace, interfaceName: clientType.Name, functionDetails: typeHelper.GetClientFunctions(hubType))); + } + } + + return list; + } + + public List GetDataContracts() + { + var list = new List(); + + while (typeHelper.InterfaceTypes.Count != 0) + { + var type = typeHelper.InterfaceTypes.Pop(); + + var properties = type + .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly) + .Select(prop => new TypeInfo(name: prop.Name, typescriptType: typeHelper.GetTypeContractName(prop.PropertyType))) + .ToList(); + + list.Add(new DataContractInfo(moduleName: type.Namespace, interfaceName: typeHelper.GenericSpecificName(type, false), properties: properties)); + } + + return list; + } + + public List GetEnums() + { + var list = new List(); + + while (typeHelper.EnumTypes.Count != 0) + { + var type = typeHelper.EnumTypes.Pop(); + + var enumProperties = + Enum.GetNames(type) + .Select(propertyName => new TypeInfo(name: propertyName, typescriptType: $"{Enum.Parse(type, propertyName):D}")) + .ToList(); + + list.Add(new EnumInfo(moduleName: type.Namespace, interfaceName: typeHelper.GenericSpecificName(type, false), properties: enumProperties)); + } + + return list; + } + } +} \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/TypeHelper.cs b/src/Signalr.Hubs.TypescriptGenerator/Helpers/TypeHelper.cs similarity index 76% rename from src/SignalrTypescriptGenerator/TypeHelper.cs rename to src/Signalr.Hubs.TypescriptGenerator/Helpers/TypeHelper.cs index d934935..28b1a7a 100644 --- a/src/SignalrTypescriptGenerator/TypeHelper.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Helpers/TypeHelper.cs @@ -1,139 +1,135 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Microsoft.AspNet.SignalR; -using SignalrTypescriptGenerator.Models; - -namespace SignalrTypescriptGenerator -{ - internal class TypeHelper - { - private readonly HashSet _doneTypes; - public readonly Stack InterfaceTypes; - public readonly Stack EnumTypes; - - public TypeHelper() - { - _doneTypes = new HashSet(); - InterfaceTypes = new Stack(); - EnumTypes = new Stack(); - } - - public List GetClientFunctions(Type hubType) - { - var list = new List(); - - Type clientType = ClientType(hubType); - if (clientType != null) - { - foreach (var method in clientType.GetMethods()) - { - var functionDetails = new FunctionDetails(); - IEnumerable ps = method.GetParameters().Select(x => x.Name + " : " + GetTypeContractName(x.ParameterType)); - string functionName = FirstCharLowered(method.Name); - string functionArgs = "(" + string.Join(", ", ps) + ")"; - - functionDetails.Name = functionName; - functionDetails.Arguments = functionArgs; - - list.Add(functionDetails); - } - } - - return list; - } - - public string FirstCharLowered(string s) - { - return Regex.Replace(s, "^.", x => x.Value.ToLowerInvariant()); - } - - public Type ClientType(Type hubType) - { - while (hubType != null && hubType != typeof(Hub)) - { - if (hubType.IsGenericType && hubType.GetGenericTypeDefinition() == typeof(Hub<>)) - { - return hubType.GetGenericArguments().Single(); - } - hubType = hubType.BaseType; - } - return null; - } - - public string GetTypeContractName(Type type) - { - if (type == typeof(Task)) - { - return "void"; - } - - if (type.IsArray) - { - return GetTypeContractName(type.GetElementType()) + "[]"; - } - - if (type.IsGenericType) - { - if (typeof(Task<>).IsAssignableFrom(type.GetGenericTypeDefinition())) - { - return GetTypeContractName(type.GetGenericArguments()[0]); - } - - if (typeof(Nullable<>).IsAssignableFrom(type.GetGenericTypeDefinition())) - { - return GetTypeContractName(type.GetGenericArguments()[0]); - } - - if (typeof(List<>).IsAssignableFrom(type.GetGenericTypeDefinition())) - { - return GetTypeContractName(type.GetGenericArguments()[0]) + "[]"; - } - } - - switch (type.Name.ToLowerInvariant()) - { - - case "datetime": - return "Date"; - case "int16": - case "int32": - case "int64": - case "single": - case "double": - return "number"; - case "boolean": - return "boolean"; - case "void": - case "string": - return type.Name.ToLowerInvariant(); - } - - if (!_doneTypes.Contains(type)) - { - _doneTypes.Add(type); - if (type.IsEnum) - { - EnumTypes.Push(type); - } - else - { - InterfaceTypes.Push(type); - } - } - return GenericSpecificName(type, true); - } - - public string GenericSpecificName(Type type, bool referencing) - { - string name = (referencing ? type.FullName : type.Name).Split('`').First(); - if (type.IsGenericType) - { - name += "_" + string.Join("_", type.GenericTypeArguments.Select(a => GenericSpecificName(a, false))) + "_"; - } - return name; - } - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using GeniusSports.Signalr.Hubs.TypescriptGenerator.Models; +using Microsoft.AspNet.SignalR; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Helpers +{ + internal class TypeHelper + { + private readonly HashSet doneTypes; + + public readonly Stack InterfaceTypes; + public readonly Stack EnumTypes; + + public TypeHelper() + { + doneTypes = new HashSet(); + InterfaceTypes = new Stack(); + EnumTypes = new Stack(); + } + + public List GetClientFunctions(Type hubType) + { + var list = new List(); + + var clientType = ClientType(hubType); + if (clientType != null) + { + foreach (var method in clientType.GetMethods()) + { + var ps = method.GetParameters().Select(x => x.Name + " : " + GetTypeContractName(x.ParameterType)); + var functionName = FirstCharLowered(method.Name); + var functionArgs = "(" + string.Join(", ", ps) + ")"; + list.Add(new FunctionDetails(name: functionName, arguments: functionArgs, returnType: null)); + } + } + + return list; + } + + public string FirstCharLowered(string s) + { + return Regex.Replace(s, "^.", x => x.Value.ToLowerInvariant()); + } + + public Type ClientType(Type hubType) + { + while (hubType != null && hubType != typeof(Hub)) + { + if (hubType.IsGenericType && hubType.GetGenericTypeDefinition() == typeof(Hub<>)) + { + return hubType.GetGenericArguments().Single(); + } + hubType = hubType.BaseType; + } + return null; + } + + public string GetTypeContractName(Type type) + { + if (type == typeof(Task)) + { + return "void"; + } + + if (type.IsArray) + { + return GetTypeContractName(type.GetElementType()) + "[]"; + } + + if (type.IsGenericType) + { + if (typeof(Task<>).IsAssignableFrom(type.GetGenericTypeDefinition())) + { + return GetTypeContractName(type.GetGenericArguments()[0]); + } + + if (typeof(Nullable<>).IsAssignableFrom(type.GetGenericTypeDefinition())) + { + return GetTypeContractName(type.GetGenericArguments()[0]); + } + + if (typeof(List<>).IsAssignableFrom(type.GetGenericTypeDefinition())) + { + return GetTypeContractName(type.GetGenericArguments()[0]) + "[]"; + } + } + + switch (type.Name.ToLowerInvariant()) + { + + case "datetime": + return "Date"; + case "int16": + case "int32": + case "int64": + case "single": + case "double": + return "number"; + case "boolean": + return "boolean"; + case "void": + case "string": + return type.Name.ToLowerInvariant(); + } + + if (!doneTypes.Contains(type)) + { + doneTypes.Add(type); + if (type.IsEnum) + { + EnumTypes.Push(type); + } + else + { + InterfaceTypes.Push(type); + } + } + return GenericSpecificName(type, true); + } + + public string GenericSpecificName(Type type, bool referencing) + { + string name = (referencing ? type.FullName : type.Name).Split('`').First(); + if (type.IsGenericType) + { + name += "_" + string.Join("_", type.GenericTypeArguments.Select(a => GenericSpecificName(a, false))) + "_"; + } + return name; + } + } } \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/HubTypeScriptGenerator.cs b/src/Signalr.Hubs.TypescriptGenerator/HubTypeScriptGenerator.cs new file mode 100644 index 0000000..1376ee8 --- /dev/null +++ b/src/Signalr.Hubs.TypescriptGenerator/HubTypeScriptGenerator.cs @@ -0,0 +1,66 @@ +using System; +using System.IO; +using System.Reflection; +using GeniusSports.Signalr.Hubs.TypescriptGenerator.Helpers; +using GeniusSports.Signalr.Hubs.TypescriptGenerator.Models; +using RazorEngine; +using RazorEngine.Templating; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator +{ + public class HubTypeScriptGenerator + { + public string Generate() + { + //if (AppDomain.CurrentDomain.IsDefaultAppDomain()) + //{ + // RunInNewAppDomainToAllowRazorEngineToCleanup(); + //} + return Run(); + } + + //private static void RunInNewAppDomainToAllowRazorEngineToCleanup() + //{ + // var appDomain = AppDomain.CreateDomain("RazorEngine", null, AppDomain.CurrentDomain.SetupInformation); + // appDomain.ExecuteAssembly(Assembly.GetExecutingAssembly().Location); + // AppDomain.Unload(appDomain); + //} + + private static string Run() + { + var model = GenerateTypeScriptModel(); + var template = ReadEmbeddedFile("template.cshtml"); + var outputText = Engine.Razor.RunCompile(template, "templateKey", null, model); + return outputText; + } + + private static TypesModel GenerateTypeScriptModel() + { + var signalrHelper = new HubHelper(); + return new TypesModel( + hubs: signalrHelper.GetHubs(), + serviceContracts: signalrHelper.GetServiceContracts(), + clients: signalrHelper.GetClients(), + dataContracts: signalrHelper.GetDataContracts(), + enums: signalrHelper.GetEnums()); + } + + private static string ReadEmbeddedFile(string file) + { + string resourcePath = $"{typeof(HubTypeScriptGenerator).Namespace}.{file}"; + + using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourcePath)) + { + if (stream == null) throw new InvalidOperationException($"Unable to find '{resourcePath}' as an embedded resource"); + + string textContent; + using (var reader = new StreamReader(stream)) + { + textContent = reader.ReadToEnd(); + } + + return textContent; + } + } + } +} diff --git a/src/Signalr.Hubs.TypescriptGenerator/Models/ClientInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Models/ClientInfo.cs new file mode 100644 index 0000000..bd55cbd --- /dev/null +++ b/src/Signalr.Hubs.TypescriptGenerator/Models/ClientInfo.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Models +{ + public class ClientInfo + { + public string ModuleName { get; } + public string InterfaceName { get; } + public List FunctionDetails { get; } + + public ClientInfo(string moduleName, string interfaceName, List functionDetails) + { + ModuleName = moduleName; + InterfaceName = interfaceName; + FunctionDetails = functionDetails; + } + + public override string ToString() + { + return $"ModuleName:{ModuleName},InterfaceName:{InterfaceName}"; + } + } +} \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/Models/DataContractInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Models/DataContractInfo.cs new file mode 100644 index 0000000..fa74a50 --- /dev/null +++ b/src/Signalr.Hubs.TypescriptGenerator/Models/DataContractInfo.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Models +{ + public class DataContractInfo + { + public string ModuleName { get; } + public string InterfaceName { get; } + public List Properties { get; } + + public DataContractInfo(string moduleName, string interfaceName, List properties) + { + ModuleName = moduleName; + InterfaceName = interfaceName; + Properties = properties; + } + + public override string ToString() + { + return $"ModuleName:{ModuleName},InterfaceName:{InterfaceName};Properties:[{string.Join(",", Properties)}]"; + } + } +} \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/Models/EnumInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Models/EnumInfo.cs new file mode 100644 index 0000000..e796456 --- /dev/null +++ b/src/Signalr.Hubs.TypescriptGenerator/Models/EnumInfo.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Models +{ + public class EnumInfo + { + public string ModuleName { get; } + public string InterfaceName { get; } + public List Properties { get; } + + public EnumInfo(string moduleName, string interfaceName, List properties) + { + ModuleName = moduleName; + InterfaceName = interfaceName; + Properties = properties; + } + + public override string ToString() + { + return $"ModuleName:{ModuleName},InterfaceName:{InterfaceName};Properties:[{string.Join(",", Properties)}]"; + } + } +} \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/Models/FunctionDetails.cs b/src/Signalr.Hubs.TypescriptGenerator/Models/FunctionDetails.cs new file mode 100644 index 0000000..7487492 --- /dev/null +++ b/src/Signalr.Hubs.TypescriptGenerator/Models/FunctionDetails.cs @@ -0,0 +1,21 @@ +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Models +{ + public class FunctionDetails + { + public string Name { get; } + public string Arguments { get; } + public string ReturnType { get; } + + public FunctionDetails(string name, string arguments, string returnType) + { + Name = name; + Arguments = arguments; + ReturnType = returnType; + } + + public override string ToString() + { + return $"Name:{Name},Arguments:{Arguments};ReturnType:[{string.Join(",", ReturnType)}]"; + } + } +} \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/Models/ServiceInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Models/ServiceInfo.cs new file mode 100644 index 0000000..ccea9db --- /dev/null +++ b/src/Signalr.Hubs.TypescriptGenerator/Models/ServiceInfo.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Models +{ + public class ServiceInfo + { + public string ModuleName { get; } + public string InterfaceName { get; } + public string ClientType { get; } + + public string ServerType { get; } + public string ServerTypeFullNamespace { get; } + public List ServerFunctions { get; } + + public ServiceInfo(string moduleName, string interfaceName, string clientType, string serverType, string serverTypeFullNamespace, List serverFunctions) + { + ModuleName = moduleName; + InterfaceName = interfaceName; + ClientType = clientType; + ServerType = serverType; + ServerTypeFullNamespace = serverTypeFullNamespace; + ServerFunctions = serverFunctions; + } + + public override string ToString() + { + return $"ModuleName:{ModuleName},InterfaceName:{InterfaceName},ClientType:{ClientType}"; + } + } +} \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/Models/TypeInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Models/TypeInfo.cs new file mode 100644 index 0000000..3be2ada --- /dev/null +++ b/src/Signalr.Hubs.TypescriptGenerator/Models/TypeInfo.cs @@ -0,0 +1,19 @@ +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Models +{ + public class TypeInfo + { + public string Name { get; } + public string TypescriptType { get; } + + public TypeInfo(string name, string typescriptType) + { + Name = name; + TypescriptType = typescriptType; + } + + public override string ToString() + { + return $"Name:{Name},TypescriptType:{TypescriptType}]"; + } + } +} \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/Models/TypesModel.cs b/src/Signalr.Hubs.TypescriptGenerator/Models/TypesModel.cs new file mode 100644 index 0000000..2c73d2d --- /dev/null +++ b/src/Signalr.Hubs.TypescriptGenerator/Models/TypesModel.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; + +namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Models +{ + public class TypesModel + { + public List Hubs { get; } + public List ServiceContracts { get; } + public List Clients { get; } + public List DataContracts { get; } + public List Enums { get; } + + public DateTime LastGenerated => DateTime.UtcNow; + + public TypesModel(List hubs, List serviceContracts, List clients, List dataContracts, List enums) + { + Hubs = hubs; + ServiceContracts = serviceContracts; + Clients = clients; + DataContracts = dataContracts; + Enums = enums; + } + } +} \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/Properties/AssemblyInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs similarity index 97% rename from src/SignalrTypescriptGenerator/Properties/AssemblyInfo.cs rename to src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs index 3538b3b..a547c0c 100644 --- a/src/SignalrTypescriptGenerator/Properties/AssemblyInfo.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SignalrTypescriptGenerator")] -[assembly: AssemblyDescription("Command line tool for generating Typescript hub definitions for a Signalr assembly.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("C.Small")] -[assembly: AssemblyProduct("SignalrTypescriptGenerator")] -[assembly: AssemblyCopyright("Copyright © C.Small 2016")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("c90f8c7b-213b-4cd0-a9f0-3a39634cecde")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.13.0")] -[assembly: AssemblyFileVersion("1.0.13.0")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SignalrTypescriptGenerator")] +[assembly: AssemblyDescription("Command line tool for generating Typescript hub definitions for a Signalr assembly.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("C.Small")] +[assembly: AssemblyProduct("SignalrTypescriptGenerator")] +[assembly: AssemblyCopyright("Copyright © C.Small 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c90f8c7b-213b-4cd0-a9f0-3a39634cecde")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.13.0")] +[assembly: AssemblyFileVersion("1.0.13.0")] diff --git a/src/SignalrTypescriptGenerator/SignalrTypescriptGenerator.csproj b/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.csproj similarity index 72% rename from src/SignalrTypescriptGenerator/SignalrTypescriptGenerator.csproj rename to src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.csproj index e53d5f4..aeb2765 100644 --- a/src/SignalrTypescriptGenerator/SignalrTypescriptGenerator.csproj +++ b/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.csproj @@ -1,108 +1,107 @@ - - - - - Debug - AnyCPU - {C90F8C7B-213B-4CD0-A9F0-3A39634CECDE} - Exe - Properties - SignalrTypescriptGenerator - SignalrTypescriptGenerator - v4.5.1 - 512 - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\..\packages\CommandLineParser.2.0.275-beta\lib\net45\CommandLine.dll - True - - - ..\..\packages\Microsoft.AspNet.SignalR.Core.2.2.0\lib\net45\Microsoft.AspNet.SignalR.Core.dll - True - - - ..\..\packages\Microsoft.Owin.2.1.0\lib\net45\Microsoft.Owin.dll - True - - - ..\..\packages\Microsoft.Owin.Security.2.1.0\lib\net45\Microsoft.Owin.Security.dll - True - - - ..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll - True - - - ..\..\packages\Owin.1.0\lib\net40\Owin.dll - True - - - ..\..\packages\RazorEngine.3.7.7\lib\net45\RazorEngine.dll - True - - - - - ..\..\packages\Microsoft.AspNet.Razor.3.0.0\lib\net45\System.Web.Razor.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + AnyCPU + {C90F8C7B-213B-4CD0-A9F0-3A39634CECDE} + Library + Properties + GeniusSports.Signalr.Hubs.TypescriptGenerator + GeniusSports.Signalr.Hubs.TypescriptGenerator + v4.5 + 512 + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + ..\..\packages\Microsoft.AspNet.SignalR.Core.2.2.1\lib\net45\Microsoft.AspNet.SignalR.Core.dll + True + + + ..\..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll + True + + + ..\..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll + True + + + ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + True + + + ..\..\packages\Owin.1.0\lib\net40\Owin.dll + True + + + ..\..\packages\RazorEngine.3.9.0\lib\net45\RazorEngine.dll + True + + + + + ..\..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.nuspec b/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.nuspec new file mode 100644 index 0000000..732d308 --- /dev/null +++ b/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.nuspec @@ -0,0 +1,17 @@ + + + + Signalr.Hubs.TypescriptGenerator + $version$ + Signalr Typescript Hub Generator + Genius Sports + Genius Sports + https://github.com/geniussportsgroup/Signalr.Hubs.TypescriptGenerator + false + Utility library for generating Typescript hub definitions for a Signalr assembly. + typescript signalr hubs + + + + + \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/app.config b/src/Signalr.Hubs.TypescriptGenerator/app.config new file mode 100644 index 0000000..d973905 --- /dev/null +++ b/src/Signalr.Hubs.TypescriptGenerator/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/packages.config b/src/Signalr.Hubs.TypescriptGenerator/packages.config new file mode 100644 index 0000000..9e590c9 --- /dev/null +++ b/src/Signalr.Hubs.TypescriptGenerator/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/template.cshtml b/src/Signalr.Hubs.TypescriptGenerator/template.cshtml similarity index 81% rename from src/SignalrTypescriptGenerator/template.cshtml rename to src/Signalr.Hubs.TypescriptGenerator/template.cshtml index 6ff2307..41dc491 100644 --- a/src/SignalrTypescriptGenerator/template.cshtml +++ b/src/Signalr.Hubs.TypescriptGenerator/template.cshtml @@ -1,86 +1,86 @@ -@using System -@using SignalrTypescriptGenerator.Models -@*Model is a TypesModel*@ -// Get signalr.d.ts.ts from https://github.com/borisyankov/DefinitelyTyped (or delete the reference) -/// -/// - -// Hubs -interface SignalR -{ - @foreach (TypeInfo type in Model.Hubs) - { - @(type.Name) : @(type.TypescriptType); - } -} - -// Service contracts -@foreach (ServiceInfo serviceInfo in Model.ServiceContracts){ - -declare module @serviceInfo.ModuleName -{ - - interface @serviceInfo.InterfaceName - { - server : @Raw(serviceInfo.ServerTypeFullNamespace); - client : @Raw(serviceInfo.ClientType); - } - - interface @serviceInfo.ServerType - { - @foreach (FunctionDetails functionDetails in serviceInfo.ServerFunctions) - { - @Raw(functionDetails.Name + functionDetails.Arguments) : @Raw(functionDetails.ReturnType); - } - } -} - -} - -// Clients -@foreach (ClientInfo clientInfo in Model.Clients){ - -declare module @clientInfo.ModuleName -{ - interface @clientInfo.InterfaceName - { - @foreach (FunctionDetails functionDetails in clientInfo.FunctionDetails) - { - @Raw(functionDetails.Name) : @Raw(functionDetails.Arguments) => void; - } - } -} - -} - -// Data contracts -@foreach (DataContractInfo dataContractInfo in Model.DataContracts){ - -declare module @dataContractInfo.ModuleName -{ - interface @dataContractInfo.InterfaceName - { - @foreach (TypeInfo property in dataContractInfo.Properties) - { - @Raw(property.Name) : @Raw(property.TypescriptType); - } - } -} - -} - -// Enums -@foreach (EnumInfo enumInfo in Model.Enums){ - -declare module @enumInfo.ModuleName -{ - enum @enumInfo.InterfaceName - { - @foreach (TypeInfo property in enumInfo.Properties) - { - @Raw(property.Name) = @Raw(property.TypescriptType), - } - } -} - +@using GeniusSports.Signalr.Hubs.TypescriptGenerator.Models +@model TypesModel + +/// Autogenerated at @Model.LastGenerated by https://github.com/geniussportsgroup/Signalr.Hubs.TypescriptGenerator +/// +/// + +// Hubs +interface SignalR +{ + @foreach (TypeInfo type in Model.Hubs) + { + @(type.Name) : @(type.TypescriptType); + } +} + +// Service contracts +@foreach (ServiceInfo serviceInfo in Model.ServiceContracts){ + +declare module @serviceInfo.ModuleName +{ + + interface @serviceInfo.InterfaceName + { + server : @Raw(serviceInfo.ServerTypeFullNamespace); + client : @Raw(serviceInfo.ClientType); + } + + interface @serviceInfo.ServerType + { + @foreach (FunctionDetails functionDetails in serviceInfo.ServerFunctions) + { + @Raw(functionDetails.Name + functionDetails.Arguments) : @Raw(functionDetails.ReturnType); + } + } +} + +} + +// Clients +@foreach (ClientInfo clientInfo in Model.Clients){ + +declare module @clientInfo.ModuleName +{ + interface @clientInfo.InterfaceName + { + @foreach (FunctionDetails functionDetails in clientInfo.FunctionDetails) + { + @Raw(functionDetails.Name) : @Raw(functionDetails.Arguments) => void; + } + } +} + +} + +// Data contracts +@foreach (DataContractInfo dataContractInfo in Model.DataContracts){ + +declare module @dataContractInfo.ModuleName +{ + interface @dataContractInfo.InterfaceName + { + @foreach (TypeInfo property in dataContractInfo.Properties) + { + @Raw(property.Name) : @Raw(property.TypescriptType); + } + } +} + +} + +// Enums +@foreach (EnumInfo enumInfo in Model.Enums){ + +declare module @enumInfo.ModuleName +{ + enum @enumInfo.InterfaceName + { + @foreach (TypeInfo property in enumInfo.Properties) + { + @Raw(property.Name) = @Raw(property.TypescriptType), + } + } +} + } \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/App.config b/src/SignalrTypescriptGenerator/App.config deleted file mode 100644 index 8c18ddd..0000000 --- a/src/SignalrTypescriptGenerator/App.config +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/Models/ClientInfo.cs b/src/SignalrTypescriptGenerator/Models/ClientInfo.cs deleted file mode 100644 index d1ebd14..0000000 --- a/src/SignalrTypescriptGenerator/Models/ClientInfo.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; - -namespace SignalrTypescriptGenerator.Models -{ - public class ClientInfo - { - public string ModuleName { get; set; } - public string InterfaceName { get; set; } - public List FunctionDetails { get; set; } - - public ClientInfo() - { - FunctionDetails = new List(); - } - } -} \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/Models/DataContractInfo.cs b/src/SignalrTypescriptGenerator/Models/DataContractInfo.cs deleted file mode 100644 index 5b341b6..0000000 --- a/src/SignalrTypescriptGenerator/Models/DataContractInfo.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; - -namespace SignalrTypescriptGenerator.Models -{ - public class DataContractInfo - { - public string ModuleName { get; set; } - public string InterfaceName { get; set; } - public List Properties { get; set; } - - public DataContractInfo() - { - Properties = new List(); - } - } -} \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/Models/EnumInfo.cs b/src/SignalrTypescriptGenerator/Models/EnumInfo.cs deleted file mode 100644 index 6031165..0000000 --- a/src/SignalrTypescriptGenerator/Models/EnumInfo.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; - -namespace SignalrTypescriptGenerator.Models -{ - public class EnumInfo - { - public string ModuleName { get; set; } - public string InterfaceName { get; set; } - public List Properties { get; set; } - - public EnumInfo() - { - Properties = new List(); - } - } -} \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/Models/FunctionDetails.cs b/src/SignalrTypescriptGenerator/Models/FunctionDetails.cs deleted file mode 100644 index 3e13d6e..0000000 --- a/src/SignalrTypescriptGenerator/Models/FunctionDetails.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace SignalrTypescriptGenerator.Models -{ - public class FunctionDetails - { - public string Name { get; set; } - public string Arguments { get; set; } - public string ReturnType { get; set; } - } -} \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/Models/ServiceInfo.cs b/src/SignalrTypescriptGenerator/Models/ServiceInfo.cs deleted file mode 100644 index f0d8214..0000000 --- a/src/SignalrTypescriptGenerator/Models/ServiceInfo.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Collections.Generic; - -namespace SignalrTypescriptGenerator.Models -{ - public class ServiceInfo - { - public string ModuleName { get; set; } - public string InterfaceName { get; set; } - public string ClientType { get; set; } - - public string ServerType { get; set; } - public string ServerTypeFullNamespace { get; set; } - public List ServerFunctions { get; set; } - - public ServiceInfo() - { - ServerFunctions = new List(); - } - } -} \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/Models/TypeInfo.cs b/src/SignalrTypescriptGenerator/Models/TypeInfo.cs deleted file mode 100644 index 6b3906a..0000000 --- a/src/SignalrTypescriptGenerator/Models/TypeInfo.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace SignalrTypescriptGenerator.Models -{ - public class TypeInfo - { - public string Name { get; set; } - public string TypescriptType { get; set; } - } -} \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/Models/TypesModel.cs b/src/SignalrTypescriptGenerator/Models/TypesModel.cs deleted file mode 100644 index 6961be0..0000000 --- a/src/SignalrTypescriptGenerator/Models/TypesModel.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace SignalrTypescriptGenerator.Models -{ - public class TypesModel - { - public List Hubs { get; set; } - public List ServiceContracts { get; set; } - public List Clients { get; set; } - public List DataContracts { get; set; } - public List Enums { get; set; } - - public string LastGenerated - { - get - { - return $"// Autogenerated by SignalrTypescriptGenerator.exe at {DateTime.Now}"; - } - } - - public TypesModel() - { - Hubs = new List(); - ServiceContracts = new List(); - } - } -} \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/Program.cs b/src/SignalrTypescriptGenerator/Program.cs deleted file mode 100644 index 5fbfd7f..0000000 --- a/src/SignalrTypescriptGenerator/Program.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Security.Cryptography; -using System.Text; -using CommandLine; -using RazorEngine; -using RazorEngine.Templating; -using SignalrTypescriptGenerator.Models; -using Encoding = System.Text.Encoding; - -namespace SignalrTypescriptGenerator -{ - class Program - { - static int Main(string[] args) - { - if (AppDomain.CurrentDomain.IsDefaultAppDomain()) - { - return RunInNewAppDomainToAllowRazorEngineToCleanup(args); - } - - try - { - return Parser.Default.ParseArguments(args) - .MapResult(options => - { - Run(options); - return 0; - }, - errors => 1); - } - catch (Exception e) - { - Console.WriteLine(e); - return 1; - } - } - - static int RunInNewAppDomainToAllowRazorEngineToCleanup(string[] args) - { - var appDomain = AppDomain.CreateDomain("RazorEngine", null, AppDomain.CurrentDomain.SetupInformation); - var exitCode = appDomain.ExecuteAssembly(Assembly.GetExecutingAssembly().Location, args); - AppDomain.Unload(appDomain); - return exitCode; - } - - static void Run(CommandLineOptions commandLineOptions) - { - var signalrHelper = new SignalrHubinator(commandLineOptions.AssemblyPath); - - var model = new TypesModel(); - model.Hubs = signalrHelper.GetHubs(); - model.ServiceContracts = signalrHelper.GetServiceContracts(); - model.Clients = signalrHelper.GetClients(); - model.DataContracts = signalrHelper.GetDataContracts(); - model.Enums = signalrHelper.GetEnums(); - - string template = ReadEmbeddedFile("template.cshtml"); - string outputText = Engine.Razor.RunCompile(template, "templateKey", null, model); - - if (!string.IsNullOrEmpty(commandLineOptions.OutFile)) - { - if (FileHasChanged(commandLineOptions.OutFile, outputText)) - { - outputText = model.LastGenerated + Environment.NewLine + outputText; - File.WriteAllText(commandLineOptions.OutFile, outputText); - } - } - else - { - outputText = model.LastGenerated + Environment.NewLine + outputText; - Console.WriteLine(outputText); - } - } - - static bool FileHasChanged(string filename, string contents) - { - string currentContents = File.Exists(filename) ? File.ReadAllText(filename) : string.Empty; - - // Remove the timestamp - int startIndex = currentContents.IndexOf("// Autogenerated", StringComparison.Ordinal); - if (startIndex > -1) - { - int endIndex = currentContents.IndexOf(Environment.NewLine, startIndex, StringComparison.Ordinal); - if (endIndex > startIndex) - { - currentContents = currentContents.Substring(endIndex + Environment.NewLine.Length); - } - } - - string currentHash = GetMd5(currentContents); - string newHash = GetMd5(contents); - Console.WriteLine("[SignalrTypescriptGenerator] Existing MD5 for {0}: {1}", filename, currentHash); - Console.WriteLine("[SignalrTypescriptGenerator] New MD5: {0}", newHash); - - bool hashesAreDifferent = (currentHash != newHash); - Console.WriteLine("[SignalrTypescriptGenerator] (content is {0})", hashesAreDifferent ? "different - generating new file" : "the same - skipping file generation."); - - return hashesAreDifferent; - } - - static string GetMd5(string contents) - { - using (var md5 = MD5.Create()) - { - using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(contents))) - { - var hash = md5.ComputeHash(memoryStream); - - StringBuilder result = new StringBuilder(); - foreach (byte b in hash) - result = result.Append(b.ToString("x2")); - - return result.ToString(); - } - } - } - - static string ReadEmbeddedFile(string file) - { - string resourcePath = string.Format("{0}.{1}", typeof(Program).Namespace, file); - - Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourcePath); - if (stream == null) - throw new InvalidOperationException(string.Format("Unable to find '{0}' as an embedded resource", resourcePath)); - - string textContent = ""; - using (StreamReader reader = new StreamReader(stream)) - { - textContent = reader.ReadToEnd(); - } - - return textContent; - } - } -} diff --git a/src/SignalrTypescriptGenerator/SignalrHubinator.cs b/src/SignalrTypescriptGenerator/SignalrHubinator.cs deleted file mode 100644 index c29333c..0000000 --- a/src/SignalrTypescriptGenerator/SignalrHubinator.cs +++ /dev/null @@ -1,191 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using Microsoft.AspNet.SignalR; -using Microsoft.AspNet.SignalR.Hubs; -using SignalrTypescriptGenerator.Models; -using TypeInfo = SignalrTypescriptGenerator.Models.TypeInfo; - -namespace SignalrTypescriptGenerator -{ - internal class SignalrHubinator - { - private static string _assemblyRootFolder; - private readonly TypeHelper _typeHelper; - private DefaultHubManager _hubmanager; - - public SignalrHubinator(string assemblyPath) - { - _assemblyRootFolder = Path.GetDirectoryName(assemblyPath); - LoadAssemblyIntoAppDomain(assemblyPath); - - _typeHelper = new TypeHelper(); - - var defaultDependencyResolver = new DefaultDependencyResolver(); - _hubmanager = new DefaultHubManager(defaultDependencyResolver); - } - - public TypeHelper TypeHelper - { - get { return _typeHelper; } - } - - private static Assembly LoadFromSameFolder(object sender, ResolveEventArgs args) - { - string assemblyPath = Path.Combine(_assemblyRootFolder, new AssemblyName(args.Name).Name + ".dll"); - if (File.Exists(assemblyPath) == false) - return null; - - Assembly assembly = Assembly.LoadFrom(assemblyPath); - return assembly; - } - - private void LoadAssemblyIntoAppDomain(string assemblyPath) - { - AppDomain currentDomain = AppDomain.CurrentDomain; - currentDomain.AssemblyResolve += new ResolveEventHandler(LoadFromSameFolder); - Assembly.LoadFile(assemblyPath); - } - - public List GetHubs() - { - var items = new List(); - foreach (var hub in _hubmanager.GetHubs()) - { - string name = hub.NameSpecified ? hub.Name : _typeHelper.FirstCharLowered(hub.Name); - string typename = hub.HubType.FullName; - - items.Add(new TypeInfo() { Name = name, TypescriptType = typename }); - } - - return items; - } - - public List GetServiceContracts() - { - var list = new List(); - var serviceInfo = new ServiceInfo(); - - foreach (var hub in _hubmanager.GetHubs()) - { - Type hubType = hub.HubType; - - string moduleName = hubType.Namespace; - string interfaceName = hubType.Name; - serviceInfo.ModuleName = moduleName; - serviceInfo.InterfaceName = interfaceName; - - Type clientType = TypeHelper.ClientType(hubType); - string clientTypeName = clientType != null ? clientType.FullName : "any"; - serviceInfo.ClientType = clientTypeName; - - // Server type and functions - string serverType = hubType.Name + "Server"; - string serverFullNamespace = hubType.FullName + "Server"; - serviceInfo.ServerType = serverType; - serviceInfo.ServerTypeFullNamespace = serverFullNamespace; - foreach (var method in _hubmanager.GetHubMethods(hub.Name)) - { - var ps = method.Parameters.Select(x => x.Name + " : " + TypeHelper.GetTypeContractName(x.ParameterType)); - var functionDetails = new FunctionDetails() - { - Name = _typeHelper.FirstCharLowered(method.Name), - Arguments = "(" + string.Join(", ", ps) + ")", - ReturnType = "JQueryPromise<" +TypeHelper.GetTypeContractName(method.ReturnType)+ ">" - }; - - serviceInfo.ServerFunctions.Add(functionDetails); - } - - list.Add(serviceInfo); - } - - return list; - } - - public List GetClients() - { - var list = new List(); - - foreach (var hub in _hubmanager.GetHubs()) - { - Type hubType = hub.HubType; - Type clientType = TypeHelper.ClientType(hubType); - - if (clientType != null) - { - string moduleName = clientType.Namespace; - string interfaceName = clientType.Name; - var clientInfo = new ClientInfo(); - - clientInfo.ModuleName = moduleName; - clientInfo.InterfaceName = interfaceName; - clientInfo.FunctionDetails = TypeHelper.GetClientFunctions(hubType); - list.Add(clientInfo); - } - } - - return list; - } - - public List GetDataContracts() - { - var list = new List(); - - while (_typeHelper.InterfaceTypes.Count != 0) - { - var type = _typeHelper.InterfaceTypes.Pop(); - var dataContractInfo = new DataContractInfo(); - - string moduleName = type.Namespace; - string interfaceName = _typeHelper.GenericSpecificName(type, false); - - dataContractInfo.ModuleName = moduleName; - dataContractInfo.InterfaceName = interfaceName; - - foreach (var property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)) - { - string propertyName = property.Name; - string typeName = _typeHelper.GetTypeContractName(property.PropertyType); - - dataContractInfo.Properties.Add(new TypeInfo() { Name = propertyName, TypescriptType = typeName }); - } - - list.Add(dataContractInfo); - } - - return list; - } - - public List GetEnums() - { - var list = new List(); - - while (_typeHelper.EnumTypes.Count != 0) - { - var type = _typeHelper.EnumTypes.Pop(); - var enuminfo = new EnumInfo(); - - string moduleName = type.Namespace; - string interfaceName = _typeHelper.GenericSpecificName(type, false); - - enuminfo.ModuleName = moduleName; - enuminfo.InterfaceName = interfaceName; - - foreach (string name in Enum.GetNames(type)) - { - string propertyName = name; - string typeName = string.Format("{0:D}", Enum.Parse(type, name)); - - enuminfo.Properties.Add(new TypeInfo() { Name = propertyName, TypescriptType = typeName }); - } - - list.Add(enuminfo); - } - - return list; - } - } -} \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/SignalrTypescriptGenerator.nuspec b/src/SignalrTypescriptGenerator/SignalrTypescriptGenerator.nuspec deleted file mode 100644 index ca0e722..0000000 --- a/src/SignalrTypescriptGenerator/SignalrTypescriptGenerator.nuspec +++ /dev/null @@ -1,20 +0,0 @@ - - - - SignalrTypescriptGenerator - $version$ - Signalr Typescript Hub Generator - C.Small - >C.Small - https://github.com/yetanotherchris/SignalrTypescriptGenerator - https://raw.githubusercontent.com/yetanotherchris/SignalrTypescriptGenerator/master/icon.png - false - Command line tool for generating Typescript hub definitions for a Signalr assembly. - Breaking change: now use -a for the assembly, and -o for the file to write. See the Github project page for examples. - C.Small Copyright 2016 - typescript signalr hubs - - - - - \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/build-nuget.ps1 b/src/SignalrTypescriptGenerator/build-nuget.ps1 deleted file mode 100644 index 195b099..0000000 --- a/src/SignalrTypescriptGenerator/build-nuget.ps1 +++ /dev/null @@ -1,7 +0,0 @@ -# This could be automated via appveyor -Write-Host "Make sure you have updated the assemblyinfo file and compiled in release mode first." -$version = Read-Host "What is the version number?" -$apikey = Read-Host "Enter a nuget.org API key" - -nuget pack .\SignalrTypescriptGenerator.nuspec -Prop Configuration=Release -Version $version -nuget push ".\SignalrTypescriptGenerator.$version.nupkg" $apikey -Source https://www.nuget.org/api/v2/package \ No newline at end of file diff --git a/src/SignalrTypescriptGenerator/packages.config b/src/SignalrTypescriptGenerator/packages.config deleted file mode 100644 index b2b7d4e..0000000 --- a/src/SignalrTypescriptGenerator/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file From 4a2a1e3f8e43d800e90e536a03c5eb564353d785 Mon Sep 17 00:00:00 2001 From: Chris Haines Date: Thu, 15 Sep 2016 18:20:50 +0100 Subject: [PATCH 2/9] Use DataMember name for TypeScript property name if available --- .../DataContracts/InnerSomethingDto.cs | 4 ++-- .../Helpers/HubHelper.cs | 2 +- .../Helpers/TypeHelper.cs | 8 ++++++++ .../HubTypeScriptGenerator.cs | 18 +----------------- .../Signalr.Hubs.TypescriptGenerator.csproj | 1 + 5 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/SampleUsage/DataContracts/InnerSomethingDto.cs b/src/SampleUsage/DataContracts/InnerSomethingDto.cs index 6372f8e..df5f0af 100644 --- a/src/SampleUsage/DataContracts/InnerSomethingDto.cs +++ b/src/SampleUsage/DataContracts/InnerSomethingDto.cs @@ -9,10 +9,10 @@ public class InnerSomethingDto [DataMember] public int InnerProperty1 { get; set; } - [DataMember] + [DataMember(Name = "innerProperty2")] public DateTime InnerProperty2 { get; set; } - [DataMember] + [DataMember(Name = "innerProperty3WithCrazyCustomName")] public SomethingEnum InnerProperty3 { get; set; } } } \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/Helpers/HubHelper.cs b/src/Signalr.Hubs.TypescriptGenerator/Helpers/HubHelper.cs index 5868a99..7c0c3e5 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Helpers/HubHelper.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Helpers/HubHelper.cs @@ -90,7 +90,7 @@ public List GetDataContracts() var properties = type .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly) - .Select(prop => new TypeInfo(name: prop.Name, typescriptType: typeHelper.GetTypeContractName(prop.PropertyType))) + .Select(prop => new TypeInfo(name: typeHelper.GetPropertyName(prop), typescriptType: typeHelper.GetTypeContractName(prop.PropertyType))) .ToList(); list.Add(new DataContractInfo(moduleName: type.Namespace, interfaceName: typeHelper.GenericSpecificName(type, false), properties: properties)); diff --git a/src/Signalr.Hubs.TypescriptGenerator/Helpers/TypeHelper.cs b/src/Signalr.Hubs.TypescriptGenerator/Helpers/TypeHelper.cs index 28b1a7a..bd589ac 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Helpers/TypeHelper.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Helpers/TypeHelper.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; +using System.Runtime.Serialization; using System.Text.RegularExpressions; using System.Threading.Tasks; using GeniusSports.Signalr.Hubs.TypescriptGenerator.Models; @@ -131,5 +133,11 @@ public string GenericSpecificName(Type type, bool referencing) } return name; } + + public string GetPropertyName(PropertyInfo prop) + { + var dataMemberAttribute = prop.GetCustomAttribute(); + return !string.IsNullOrWhiteSpace(dataMemberAttribute?.Name) ? dataMemberAttribute.Name : prop.Name; + } } } \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/HubTypeScriptGenerator.cs b/src/Signalr.Hubs.TypescriptGenerator/HubTypeScriptGenerator.cs index 1376ee8..5f1b638 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/HubTypeScriptGenerator.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/HubTypeScriptGenerator.cs @@ -11,22 +11,6 @@ namespace GeniusSports.Signalr.Hubs.TypescriptGenerator public class HubTypeScriptGenerator { public string Generate() - { - //if (AppDomain.CurrentDomain.IsDefaultAppDomain()) - //{ - // RunInNewAppDomainToAllowRazorEngineToCleanup(); - //} - return Run(); - } - - //private static void RunInNewAppDomainToAllowRazorEngineToCleanup() - //{ - // var appDomain = AppDomain.CreateDomain("RazorEngine", null, AppDomain.CurrentDomain.SetupInformation); - // appDomain.ExecuteAssembly(Assembly.GetExecutingAssembly().Location); - // AppDomain.Unload(appDomain); - //} - - private static string Run() { var model = GenerateTypeScriptModel(); var template = ReadEmbeddedFile("template.cshtml"); @@ -63,4 +47,4 @@ private static string ReadEmbeddedFile(string file) } } } -} +} \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.csproj b/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.csproj index aeb2765..cbf4ca6 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.csproj +++ b/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.csproj @@ -63,6 +63,7 @@ + ..\..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll True From a06b5b8982c8e50b085fe897b44881b7a823c129 Mon Sep 17 00:00:00 2001 From: Chris Haines Date: Thu, 15 Sep 2016 18:39:46 +0100 Subject: [PATCH 3/9] Update version numbers and readme file --- README.md | 28 ++++++++------ .../Properties/AssemblyInfo.cs | 38 ++++--------------- .../Properties/AssemblyInfo.cs | 38 ++++--------------- 3 files changed, 30 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index 090d621..18ef25f 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,26 @@ -[![Nuget.org](https://img.shields.io/nuget/v/SignalrTypescriptGenerator.svg?style=flat)](https://www.nuget.org/packages/SignalrTypescriptGenerator) +[![Build status](https://ci.appveyor.com/api/projects/status/uwhg9nwo62kx2fif?svg=true)](https://ci.appveyor.com/project/cjbhaines/signalr-hubs-typescriptgenerator) -# SignalrTypescriptGenerator -A command line tool for generating typescript definitions for Signalr +# Signalr.Hubs.TypescriptGenerator +Utility library for generating typescript definitions for Signalr Hubs. This is a fork of [https://github.com/yetanotherchris/SignalrTypescriptGenerator](https://github.com/yetanotherchris/SignalrTypescriptGenerator "SignalrTypescriptGenerator") by [https://github.com/yetanotherchris](https://github.com/yetanotherchris "yetanotherchris"). I have split the packages up into a referenced library and a console app. -This tool is based off this gist: https://gist.github.com/robfe/4583549. It works using the same C# logic, but skips the need for a T4 template which can be fiddly to get working on build servers. +Our usage at Genius Sports is to generate the Hub proxies at build time using our [https://github.com/geniussportsgroup/SignalR.ProxyGenerator](https://github.com/geniussportsgroup/SignalR.ProxyGenerator "Proxy Generator") publishing them to our internal NPM feed. We then use this tool to generate TypeScript definitions our those proxies again publishing them to our internal NPM feed. This allows our UI developers to get strongly typed Hub APIs and allows us to do proper Continous Integrtaion between the back end and front end. Move quickly and break fast. -### Nuget - install-package SignalrTypescriptGenerator +## Installation - Nuget -### Usage +- [Signalr.Hubs.TypescriptGenerator](https://www.nuget.org/packages/Signalr.Hubs.TypescriptGenerator "Signalr.Hubs.TypeScriptGenerator") +- [Signalr.Hubs.TypescriptGenerator.Console](https://www.nuget.org/packages/Signalr.Hubs.TypescriptGenerator.Console "Signalr.Hubs.TypeScriptGenerator.Console") - .\SignalrTypescriptGenerator.exe -a "c:\etc\path-to-myassembly.dll" +## Usage -This will print the Typescript to the console window. You can write to a file, which automatically checks if the file has changed: +### Signalr.Hubs.TypescriptGenerator +The utility library is simple to use, load any assemblies required and then create a HubTypeScriptGenerator and call Generate. It returns the TypeScript as a string. We can't pick a specific assembly to scan because we are using the SignalR DefaultHubManager which looks in all loaded assemblies. - .\SignalrTypescriptGenerator.exe -a "c:\etc\path-to-myassembly.dll" -o "C:\temp\.myfile.d.ts" + var generator = new HubTypeScriptGenerator(); + var typeScript = generator.Generate(); -If you don't specify an output file, the typescript output is written to the console window. A post-build command line in Visual Studio might look like this: - $(SolutionDir)\packages\SignalrTypescriptGenerator.1.0.11\tools\SignalrTypescriptGenerator.exe -a "$(TargetPath)" -o "$(SolutionDir)src\MyProject.Web\Scripts\typings\Hubs.d.ts" \ No newline at end of file +### Signalr.Hubs.TypescriptGenerator.Console +This will output the Typescript to the specified file path + + .\Signalr.Hubs.TypescriptGenerator.Console.exe -a "c:\etc\path-to-myassembly.dll" -o "C:\temp\.myfile.d.ts" \ No newline at end of file diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs b/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs index 0d9ff4d..add6515 100644 --- a/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs @@ -1,36 +1,12 @@ using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Signalr.Hubs.TypeScriptGenerator.Console")] -[assembly: AssemblyDescription("")] +[assembly: AssemblyTitle("Signalr.Hubs.TypescriptGenerator.Console")] +[assembly: AssemblyDescription("Command line tool for generating Typescript hub definitions for a Signalr assembly.")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Signalr.Hubs.TypeScriptGenerator.Console")] -[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyCompany("Genius Sports")] +[assembly: AssemblyProduct("Signalr.Hubs.TypescriptGenerator.Console")] +[assembly: AssemblyCopyright("Copyright © Genius Sports 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("b68600aa-f2ae-4ebf-9af5-def252e71142")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("1.0.1.0")] +[assembly: AssemblyFileVersion("1.0.1.0")] diff --git a/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs index a547c0c..6031b57 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs @@ -1,36 +1,12 @@ using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SignalrTypescriptGenerator")] -[assembly: AssemblyDescription("Command line tool for generating Typescript hub definitions for a Signalr assembly.")] +[assembly: AssemblyTitle("Signalr.Hubs.TypescriptGenerator")] +[assembly: AssemblyDescription("Utility library for generating Typescript hub definitions for a Signalr assembly.")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("C.Small")] -[assembly: AssemblyProduct("SignalrTypescriptGenerator")] -[assembly: AssemblyCopyright("Copyright © C.Small 2016")] +[assembly: AssemblyCompany("Genius Sports")] +[assembly: AssemblyProduct("Signalr.Hubs.TypescriptGenerator")] +[assembly: AssemblyCopyright("Copyright © Genius Sports 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("c90f8c7b-213b-4cd0-a9f0-3a39634cecde")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.13.0")] -[assembly: AssemblyFileVersion("1.0.13.0")] +[assembly: AssemblyVersion("1.0.1.0")] +[assembly: AssemblyFileVersion("1.0.1.0")] From 97050f2d4e7ef587ba6c48522dd1db368398e668 Mon Sep 17 00:00:00 2001 From: Chris Haines Date: Thu, 15 Sep 2016 18:46:00 +0100 Subject: [PATCH 4/9] Fix casing in package names - OCD! --- .../Properties/AssemblyInfo.cs | 4 ++-- .../Signalr.Hubs.TypeScriptGenerator.Console.nuspec | 8 ++++---- .../Properties/AssemblyInfo.cs | 4 ++-- .../Signalr.Hubs.TypescriptGenerator.nuspec | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs b/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs index add6515..8150383 100644 --- a/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs @@ -8,5 +8,5 @@ [assembly: AssemblyCopyright("Copyright © Genius Sports 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("1.0.1.0")] -[assembly: AssemblyFileVersion("1.0.1.0")] +[assembly: AssemblyVersion("1.0.2.0")] +[assembly: AssemblyFileVersion("1.0.2.0")] diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.nuspec b/src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.nuspec index 18067e0..c758b19 100644 --- a/src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.nuspec +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.nuspec @@ -1,14 +1,14 @@ - Signalr.Hubs.TypescriptGenerator.Console + Signalr.Hubs.TypeScriptGenerator.Console $version$ - Signalr Typescript Hub Generator + Signalr TypeScript Hub Generator Genius Sports Genius Sports - https://github.com/geniussportsgroup/Signalr.Hubs.TypescriptGenerator + https://github.com/geniussportsgroup/Signalr.Hubs.TypeScriptGenerator false - Command line tool for generating Typescript hub definitions for a Signalr assembly. + Command line tool for generating TypeScript hub definitions for a Signalr assembly. typescript signalr hubs diff --git a/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs index 6031b57..0e27ae6 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs @@ -8,5 +8,5 @@ [assembly: AssemblyCopyright("Copyright © Genius Sports 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("1.0.1.0")] -[assembly: AssemblyFileVersion("1.0.1.0")] +[assembly: AssemblyVersion("1.0.2.0")] +[assembly: AssemblyFileVersion("1.0.2.0")] diff --git a/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.nuspec b/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.nuspec index 732d308..1fa1015 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.nuspec +++ b/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.nuspec @@ -1,17 +1,17 @@ - Signalr.Hubs.TypescriptGenerator + Signalr.Hubs.TypeScriptGenerator $version$ - Signalr Typescript Hub Generator + Signalr TypeScript Hub Generator Genius Sports Genius Sports - https://github.com/geniussportsgroup/Signalr.Hubs.TypescriptGenerator + https://github.com/geniussportsgroup/Signalr.Hubs.TypeScriptGenerator false - Utility library for generating Typescript hub definitions for a Signalr assembly. + Utility library for generating TypeScript hub definitions for a Signalr assembly. typescript signalr hubs - + \ No newline at end of file From ec92721742f00958192acaca2b325f0967e3491c Mon Sep 17 00:00:00 2001 From: Chris Haines Date: Fri, 16 Sep 2016 14:23:47 +0100 Subject: [PATCH 5/9] Rename Typescript to TypeScript and update ReadMe --- README.md | 189 +++++++++++++++++- Signalr.Hubs.TypescriptGenerator.sln | 2 +- .../DataContracts/InnerSomethingDto.cs | 2 +- .../DataContracts/OtherSomethingDto.cs | 2 +- src/SampleUsage/DataContracts/SomethingDto.cs | 4 +- .../DataContracts/SomethingEnum.cs | 2 +- src/SampleUsage/GenerateHubTypeScript.cs | 2 +- src/SampleUsage/Hubs/HubA.cs | 4 +- src/SampleUsage/Hubs/HubB.cs | 4 +- .../Hubs/HubCWithNoClientInterface.cs | 2 +- src/SampleUsage/SampleUsage.csproj | 8 +- .../AssemblyLoader.cs | 2 +- .../CommandLineOptions.cs | 2 +- .../Program.cs | 2 +- .../Properties/AssemblyInfo.cs | 10 +- ...lr.Hubs.TypeScriptGenerator.Console.csproj | 8 +- .../AssemblyLoader.cs | 2 +- .../Helpers/HubHelper.cs | 6 +- .../Helpers/TypeHelper.cs | 4 +- .../HubTypeScriptGenerator.cs | 6 +- .../Models/ClientInfo.cs | 2 +- .../Models/DataContractInfo.cs | 2 +- .../Models/EnumInfo.cs | 2 +- .../Models/FunctionDetails.cs | 2 +- .../Models/ServiceInfo.cs | 2 +- .../Models/TypeInfo.cs | 8 +- .../Models/TypesModel.cs | 2 +- .../Properties/AssemblyInfo.cs | 10 +- .../Signalr.Hubs.TypescriptGenerator.csproj | 6 +- .../template.cshtml | 23 ++- 30 files changed, 249 insertions(+), 73 deletions(-) diff --git a/README.md b/README.md index 18ef25f..eb0b1ca 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,197 @@ [![Build status](https://ci.appveyor.com/api/projects/status/uwhg9nwo62kx2fif?svg=true)](https://ci.appveyor.com/project/cjbhaines/signalr-hubs-typescriptgenerator) -# Signalr.Hubs.TypescriptGenerator -Utility library for generating typescript definitions for Signalr Hubs. This is a fork of [https://github.com/yetanotherchris/SignalrTypescriptGenerator](https://github.com/yetanotherchris/SignalrTypescriptGenerator "SignalrTypescriptGenerator") by [https://github.com/yetanotherchris](https://github.com/yetanotherchris "yetanotherchris"). I have split the packages up into a referenced library and a console app. +# Signalr.Hubs.TypeScriptGenerator +Utility library for generating typescript definitions for Signalr Hubs. This is a fork of [yetanotherchris/SignalrTypeScriptGenerator](https://github.com/yetanotherchris/SignalrTypeScriptGenerator "SignalrTypeScriptGenerator") by [yetanotherchris](https://github.com/yetanotherchris "yetanotherchris"). I have split the packages up into a referenced library and a console app. -Our usage at Genius Sports is to generate the Hub proxies at build time using our [https://github.com/geniussportsgroup/SignalR.ProxyGenerator](https://github.com/geniussportsgroup/SignalR.ProxyGenerator "Proxy Generator") publishing them to our internal NPM feed. We then use this tool to generate TypeScript definitions our those proxies again publishing them to our internal NPM feed. This allows our UI developers to get strongly typed Hub APIs and allows us to do proper Continous Integrtaion between the back end and front end. Move quickly and break fast. +Our usage at Genius Sports is to generate the Hub proxies at build time using our [geniussportsgroup/SignalR.ProxyGenerator](https://github.com/geniussportsgroup/SignalR.ProxyGenerator "Proxy Generator") publishing them to our internal NPM feed. We then use this tool to generate TypeScript definitions our those proxies again publishing them to our internal NPM feed. This allows our UI developers to get strongly typed Hub APIs and allows us to do proper Continous Integrtaion between the back end and front end. Move quickly and break fast. ## Installation - Nuget -- [Signalr.Hubs.TypescriptGenerator](https://www.nuget.org/packages/Signalr.Hubs.TypescriptGenerator "Signalr.Hubs.TypeScriptGenerator") -- [Signalr.Hubs.TypescriptGenerator.Console](https://www.nuget.org/packages/Signalr.Hubs.TypescriptGenerator.Console "Signalr.Hubs.TypeScriptGenerator.Console") +- [Signalr.Hubs.TypeScriptGenerator](https://www.nuget.org/packages/Signalr.Hubs.TypeScriptGenerator "Signalr.Hubs.TypeScriptGenerator") +- [Signalr.Hubs.TypeScriptGenerator.Console](https://www.nuget.org/packages/Signalr.Hubs.TypeScriptGenerator.Console "Signalr.Hubs.TypeScriptGenerator.Console") ## Usage -### Signalr.Hubs.TypescriptGenerator +### Signalr.Hubs.TypeScriptGenerator The utility library is simple to use, load any assemblies required and then create a HubTypeScriptGenerator and call Generate. It returns the TypeScript as a string. We can't pick a specific assembly to scan because we are using the SignalR DefaultHubManager which looks in all loaded assemblies. var generator = new HubTypeScriptGenerator(); var typeScript = generator.Generate(); -### Signalr.Hubs.TypescriptGenerator.Console -This will output the Typescript to the specified file path +### Signalr.Hubs.TypeScriptGenerator.Console +This will output the TypeScript to the specified file path - .\Signalr.Hubs.TypescriptGenerator.Console.exe -a "c:\etc\path-to-myassembly.dll" -o "C:\temp\.myfile.d.ts" \ No newline at end of file + .\Signalr.Hubs.TypeScriptGenerator.Console.exe -a "c:\etc\path-to-myassembly.dll" -o "C:\temp\.myfile.d.ts" + +### Data Contract Property Name +Sometimes the serialized name of your data contract properties are changed from the actual C# property name. This is done through the DataMember property: + + [DataContract] + public class SomethingDto + { + [DataMember(Name = "iChangedTheName")] + public string Property1 { get; set; } + + [DataMember] + public Guid Property2 { get; set; } + } + +This library will respect the DataMember name and use this as the TypeScript property name: + + declare module GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts + { + interface SomethingDto + { + iChangedTheName : string; + Property2 : System.Guid; + } + } + +## Example Output + + + /// Autogenerated at 16/09/2016 13:22:56 by https://github.com/geniussportsgroup/Signalr.Hubs.TypeScriptGenerator + /// + /// + + // Hubs + interface SignalR + { + hubA : GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs.HubA; + hubC : GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs.HubC; + hubB : GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs.HubB; + } + + // Service contracts + + declare module GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs + { + + interface HubA + { + server : GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs.HubAServer; + client : GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs.IHubAClient; + } + + interface HubAServer + { + getSomething() : JQueryPromise; + ping() : JQueryPromise; + } + } + + + declare module GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs + { + + interface HubC + { + server : GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs.HubCServer; + // Hub does not have a Client Interface as a generic argument - it is recommend to add one + client : any; + } + + interface HubCServer + { + aServerSideMethod() : JQueryPromise; + } + } + + + declare module GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs + { + + interface HubB + { + server : GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs.HubBServer; + client : GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs.IHubBClient; + } + + interface HubBServer + { + getOtherSomething() : JQueryPromise; + doOtherSomethingElse() : JQueryPromise; + } + } + + + // Clients + + declare module GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs + { + interface IHubAClient + { + pong : () => void; + takeThis : (somethingDto : GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts.SomethingDto) => void; + } + } + + + declare module GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs + { + interface IHubBClient + { + takeOtherThis : (otherSomethingDto : GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts.OtherSomethingDto) => void; + } + } + + + // Data contracts + + declare module GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts + { + interface OtherSomethingDto + { + Property1 : string; + Property2 : Date; + Property3 : GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts.InnerSomethingDto; + Property4 : GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts.InnerSomethingDto; + } + } + + + declare module GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts + { + interface InnerSomethingDto + { + InnerProperty1 : number; + innerProperty2 : Date; + innerProperty3WithCrazyCustomName : GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts.SomethingEnum; + } + } + + + declare module GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts + { + interface SomethingDto + { + iChangedTheName : string; + Property2 : System.Guid; + Property3 : GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts.InnerSomethingDto; + } + } + + + declare module System + { + interface Guid + { + } + } + + + // Enums + + declare module GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts + { + enum SomethingEnum + { + One = 0, + Two = 1, + Three = 2, + } + } + + diff --git a/Signalr.Hubs.TypescriptGenerator.sln b/Signalr.Hubs.TypescriptGenerator.sln index 3ecdea2..118a93a 100644 --- a/Signalr.Hubs.TypescriptGenerator.sln +++ b/Signalr.Hubs.TypescriptGenerator.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Signalr.Hubs.TypescriptGenerator", "src\Signalr.Hubs.TypescriptGenerator\Signalr.Hubs.TypescriptGenerator.csproj", "{C90F8C7B-213B-4CD0-A9F0-3A39634CECDE}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Signalr.Hubs.TypeScriptGenerator", "src\Signalr.Hubs.TypeScriptGenerator\Signalr.Hubs.TypeScriptGenerator.csproj", "{C90F8C7B-213B-4CD0-A9F0-3A39634CECDE}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Signalr.Hubs.TypeScriptGenerator.Console", "src\Signalr.Hubs.TypeScriptGenerator.Console\Signalr.Hubs.TypeScriptGenerator.Console.csproj", "{B68600AA-F2AE-4EBF-9AF5-DEF252E71142}" EndProject diff --git a/src/SampleUsage/DataContracts/InnerSomethingDto.cs b/src/SampleUsage/DataContracts/InnerSomethingDto.cs index df5f0af..8d34c83 100644 --- a/src/SampleUsage/DataContracts/InnerSomethingDto.cs +++ b/src/SampleUsage/DataContracts/InnerSomethingDto.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.Serialization; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.DataContracts +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts { [DataContract] public class InnerSomethingDto diff --git a/src/SampleUsage/DataContracts/OtherSomethingDto.cs b/src/SampleUsage/DataContracts/OtherSomethingDto.cs index fa4e9a4..e651bfb 100644 --- a/src/SampleUsage/DataContracts/OtherSomethingDto.cs +++ b/src/SampleUsage/DataContracts/OtherSomethingDto.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.Serialization; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.DataContracts +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts { [DataContract] public class OtherSomethingDto diff --git a/src/SampleUsage/DataContracts/SomethingDto.cs b/src/SampleUsage/DataContracts/SomethingDto.cs index 4230e46..725b401 100644 --- a/src/SampleUsage/DataContracts/SomethingDto.cs +++ b/src/SampleUsage/DataContracts/SomethingDto.cs @@ -1,12 +1,12 @@ using System; using System.Runtime.Serialization; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.DataContracts +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts { [DataContract] public class SomethingDto { - [DataMember] + [DataMember(Name = "iChangedTheName")] public string Property1 { get; set; } [DataMember] diff --git a/src/SampleUsage/DataContracts/SomethingEnum.cs b/src/SampleUsage/DataContracts/SomethingEnum.cs index 329ef73..decec97 100644 --- a/src/SampleUsage/DataContracts/SomethingEnum.cs +++ b/src/SampleUsage/DataContracts/SomethingEnum.cs @@ -1,6 +1,6 @@ using System.Runtime.Serialization; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.DataContracts +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts { [DataContract] public enum SomethingEnum diff --git a/src/SampleUsage/GenerateHubTypeScript.cs b/src/SampleUsage/GenerateHubTypeScript.cs index 8478b54..1d54d37 100644 --- a/src/SampleUsage/GenerateHubTypeScript.cs +++ b/src/SampleUsage/GenerateHubTypeScript.cs @@ -1,6 +1,6 @@ using NUnit.Framework; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage { [TestFixture] public class GenerateHubTypeScript diff --git a/src/SampleUsage/Hubs/HubA.cs b/src/SampleUsage/Hubs/HubA.cs index 3207f81..a159584 100644 --- a/src/SampleUsage/Hubs/HubA.cs +++ b/src/SampleUsage/Hubs/HubA.cs @@ -1,7 +1,7 @@ -using GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.DataContracts; +using GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts; using Microsoft.AspNet.SignalR; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.Hubs +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs { public interface IHubAClient { diff --git a/src/SampleUsage/Hubs/HubB.cs b/src/SampleUsage/Hubs/HubB.cs index 144ed0f..56a0f0d 100644 --- a/src/SampleUsage/Hubs/HubB.cs +++ b/src/SampleUsage/Hubs/HubB.cs @@ -1,7 +1,7 @@ -using GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.DataContracts; +using GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts; using Microsoft.AspNet.SignalR; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.Hubs +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs { public interface IHubBClient { diff --git a/src/SampleUsage/Hubs/HubCWithNoClientInterface.cs b/src/SampleUsage/Hubs/HubCWithNoClientInterface.cs index 1f021c8..befafbf 100644 --- a/src/SampleUsage/Hubs/HubCWithNoClientInterface.cs +++ b/src/SampleUsage/Hubs/HubCWithNoClientInterface.cs @@ -1,6 +1,6 @@ using Microsoft.AspNet.SignalR; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage.Hubs +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.Hubs { public class HubC : Hub { diff --git a/src/SampleUsage/SampleUsage.csproj b/src/SampleUsage/SampleUsage.csproj index 5f4b01a..7244e31 100644 --- a/src/SampleUsage/SampleUsage.csproj +++ b/src/SampleUsage/SampleUsage.csproj @@ -7,8 +7,8 @@ {668072BF-5142-4796-BA67-8CB676C7196C} Library Properties - GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage - GeniusSports.Signalr.Hubs.TypescriptGenerator.SampleUsage + GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage + GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage v4.5 512 @@ -80,9 +80,9 @@ - + {C90F8C7B-213B-4CD0-A9F0-3A39634CECDE} - Signalr.Hubs.TypescriptGenerator + Signalr.Hubs.TypeScriptGenerator diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/AssemblyLoader.cs b/src/Signalr.Hubs.TypeScriptGenerator.Console/AssemblyLoader.cs index ea411c2..3f8db7f 100644 --- a/src/Signalr.Hubs.TypeScriptGenerator.Console/AssemblyLoader.cs +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/AssemblyLoader.cs @@ -2,7 +2,7 @@ using System.IO; using System.Reflection; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Console +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.Console { internal class AssemblyLoader { diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/CommandLineOptions.cs b/src/Signalr.Hubs.TypeScriptGenerator.Console/CommandLineOptions.cs index 1e3a474..51d6e0b 100644 --- a/src/Signalr.Hubs.TypeScriptGenerator.Console/CommandLineOptions.cs +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/CommandLineOptions.cs @@ -1,7 +1,7 @@ using CommandLine; using CommandLine.Text; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Console +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.Console { public class CommandLineOptions { diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/Program.cs b/src/Signalr.Hubs.TypeScriptGenerator.Console/Program.cs index e54369f..c8d11d8 100644 --- a/src/Signalr.Hubs.TypeScriptGenerator.Console/Program.cs +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/Program.cs @@ -3,7 +3,7 @@ using System.Reflection; using CommandLine; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Console +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.Console { public class Program { diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs b/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs index 8150383..e1409e6 100644 --- a/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs @@ -1,12 +1,12 @@ using System.Reflection; -[assembly: AssemblyTitle("Signalr.Hubs.TypescriptGenerator.Console")] -[assembly: AssemblyDescription("Command line tool for generating Typescript hub definitions for a Signalr assembly.")] +[assembly: AssemblyTitle("Signalr.Hubs.TypeScriptGenerator.Console")] +[assembly: AssemblyDescription("Command line tool for generating TypeScript hub definitions for a Signalr assembly.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Genius Sports")] -[assembly: AssemblyProduct("Signalr.Hubs.TypescriptGenerator.Console")] +[assembly: AssemblyProduct("Signalr.Hubs.TypeScriptGenerator.Console")] [assembly: AssemblyCopyright("Copyright © Genius Sports 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("1.0.2.0")] -[assembly: AssemblyFileVersion("1.0.2.0")] +[assembly: AssemblyVersion("1.0.3.0")] +[assembly: AssemblyFileVersion("1.0.3.0")] diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.csproj b/src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.csproj index b5d1c6d..5f2bc2e 100644 --- a/src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.csproj +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/Signalr.Hubs.TypeScriptGenerator.Console.csproj @@ -7,8 +7,8 @@ {B68600AA-F2AE-4EBF-9AF5-DEF252E71142} Exe Properties - GeniusSports.Signalr.Hubs.TypescriptGenerator.Console - GeniusSports.Signalr.Hubs.TypescriptGenerator.Console + GeniusSports.Signalr.Hubs.TypeScriptGenerator.Console + GeniusSports.Signalr.Hubs.TypeScriptGenerator.Console v4.5 512 @@ -85,9 +85,9 @@ - + {c90f8c7b-213b-4cd0-a9f0-3a39634cecde} - Signalr.Hubs.TypescriptGenerator + Signalr.Hubs.TypeScriptGenerator diff --git a/src/Signalr.Hubs.TypescriptGenerator/AssemblyLoader.cs b/src/Signalr.Hubs.TypescriptGenerator/AssemblyLoader.cs index b522695..4a51ff4 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/AssemblyLoader.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/AssemblyLoader.cs @@ -2,7 +2,7 @@ using System.IO; using System.Reflection; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator { internal class AssemblyLoader { diff --git a/src/Signalr.Hubs.TypescriptGenerator/Helpers/HubHelper.cs b/src/Signalr.Hubs.TypescriptGenerator/Helpers/HubHelper.cs index 7c0c3e5..075c08d 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Helpers/HubHelper.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Helpers/HubHelper.cs @@ -2,12 +2,12 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using GeniusSports.Signalr.Hubs.TypescriptGenerator.Models; +using GeniusSports.Signalr.Hubs.TypeScriptGenerator.Models; using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; -using TypeInfo = GeniusSports.Signalr.Hubs.TypescriptGenerator.Models.TypeInfo; +using TypeInfo = GeniusSports.Signalr.Hubs.TypeScriptGenerator.Models.TypeInfo; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Helpers +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.Helpers { internal class HubHelper { diff --git a/src/Signalr.Hubs.TypescriptGenerator/Helpers/TypeHelper.cs b/src/Signalr.Hubs.TypescriptGenerator/Helpers/TypeHelper.cs index bd589ac..aca425a 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Helpers/TypeHelper.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Helpers/TypeHelper.cs @@ -5,10 +5,10 @@ using System.Runtime.Serialization; using System.Text.RegularExpressions; using System.Threading.Tasks; -using GeniusSports.Signalr.Hubs.TypescriptGenerator.Models; +using GeniusSports.Signalr.Hubs.TypeScriptGenerator.Models; using Microsoft.AspNet.SignalR; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Helpers +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.Helpers { internal class TypeHelper { diff --git a/src/Signalr.Hubs.TypescriptGenerator/HubTypeScriptGenerator.cs b/src/Signalr.Hubs.TypescriptGenerator/HubTypeScriptGenerator.cs index 5f1b638..2342cf6 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/HubTypeScriptGenerator.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/HubTypeScriptGenerator.cs @@ -1,12 +1,12 @@ using System; using System.IO; using System.Reflection; -using GeniusSports.Signalr.Hubs.TypescriptGenerator.Helpers; -using GeniusSports.Signalr.Hubs.TypescriptGenerator.Models; +using GeniusSports.Signalr.Hubs.TypeScriptGenerator.Helpers; +using GeniusSports.Signalr.Hubs.TypeScriptGenerator.Models; using RazorEngine; using RazorEngine.Templating; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator { public class HubTypeScriptGenerator { diff --git a/src/Signalr.Hubs.TypescriptGenerator/Models/ClientInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Models/ClientInfo.cs index bd55cbd..dcc879d 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Models/ClientInfo.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Models/ClientInfo.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Models +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.Models { public class ClientInfo { diff --git a/src/Signalr.Hubs.TypescriptGenerator/Models/DataContractInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Models/DataContractInfo.cs index fa74a50..3bddcee 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Models/DataContractInfo.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Models/DataContractInfo.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Models +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.Models { public class DataContractInfo { diff --git a/src/Signalr.Hubs.TypescriptGenerator/Models/EnumInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Models/EnumInfo.cs index e796456..3bfe745 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Models/EnumInfo.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Models/EnumInfo.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Models +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.Models { public class EnumInfo { diff --git a/src/Signalr.Hubs.TypescriptGenerator/Models/FunctionDetails.cs b/src/Signalr.Hubs.TypescriptGenerator/Models/FunctionDetails.cs index 7487492..1ecfca2 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Models/FunctionDetails.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Models/FunctionDetails.cs @@ -1,4 +1,4 @@ -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Models +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.Models { public class FunctionDetails { diff --git a/src/Signalr.Hubs.TypescriptGenerator/Models/ServiceInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Models/ServiceInfo.cs index ccea9db..e57e5bb 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Models/ServiceInfo.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Models/ServiceInfo.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Models +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.Models { public class ServiceInfo { diff --git a/src/Signalr.Hubs.TypescriptGenerator/Models/TypeInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Models/TypeInfo.cs index 3be2ada..8d37e69 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Models/TypeInfo.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Models/TypeInfo.cs @@ -1,19 +1,19 @@ -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Models +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.Models { public class TypeInfo { public string Name { get; } - public string TypescriptType { get; } + public string TypeScriptType { get; } public TypeInfo(string name, string typescriptType) { Name = name; - TypescriptType = typescriptType; + TypeScriptType = typescriptType; } public override string ToString() { - return $"Name:{Name},TypescriptType:{TypescriptType}]"; + return $"Name:{Name},TypeScriptType:{TypeScriptType}]"; } } } \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/Models/TypesModel.cs b/src/Signalr.Hubs.TypescriptGenerator/Models/TypesModel.cs index 2c73d2d..21f9d31 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Models/TypesModel.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Models/TypesModel.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace GeniusSports.Signalr.Hubs.TypescriptGenerator.Models +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.Models { public class TypesModel { diff --git a/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs index 0e27ae6..f8167c4 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs @@ -1,12 +1,12 @@ using System.Reflection; -[assembly: AssemblyTitle("Signalr.Hubs.TypescriptGenerator")] -[assembly: AssemblyDescription("Utility library for generating Typescript hub definitions for a Signalr assembly.")] +[assembly: AssemblyTitle("Signalr.Hubs.TypeScriptGenerator")] +[assembly: AssemblyDescription("Utility library for generating TypeScript hub definitions for a Signalr assembly.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Genius Sports")] -[assembly: AssemblyProduct("Signalr.Hubs.TypescriptGenerator")] +[assembly: AssemblyProduct("Signalr.Hubs.TypeScriptGenerator")] [assembly: AssemblyCopyright("Copyright © Genius Sports 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("1.0.2.0")] -[assembly: AssemblyFileVersion("1.0.2.0")] +[assembly: AssemblyVersion("1.0.3.0")] +[assembly: AssemblyFileVersion("1.0.3.0")] diff --git a/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.csproj b/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.csproj index cbf4ca6..c57c41c 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.csproj +++ b/src/Signalr.Hubs.TypescriptGenerator/Signalr.Hubs.TypescriptGenerator.csproj @@ -7,8 +7,8 @@ {C90F8C7B-213B-4CD0-A9F0-3A39634CECDE} Library Properties - GeniusSports.Signalr.Hubs.TypescriptGenerator - GeniusSports.Signalr.Hubs.TypescriptGenerator + GeniusSports.Signalr.Hubs.TypeScriptGenerator + GeniusSports.Signalr.Hubs.TypeScriptGenerator v4.5 512 true @@ -92,7 +92,7 @@ - + diff --git a/src/Signalr.Hubs.TypescriptGenerator/template.cshtml b/src/Signalr.Hubs.TypescriptGenerator/template.cshtml index 41dc491..2db6c89 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/template.cshtml +++ b/src/Signalr.Hubs.TypescriptGenerator/template.cshtml @@ -1,7 +1,8 @@ -@using GeniusSports.Signalr.Hubs.TypescriptGenerator.Models -@model TypesModel +@using System +@using GeniusSports.Signalr.Hubs.TypeScriptGenerator.Models +@model GeniusSports.Signalr.Hubs.TypeScriptGenerator.Models.TypesModel -/// Autogenerated at @Model.LastGenerated by https://github.com/geniussportsgroup/Signalr.Hubs.TypescriptGenerator +/// Autogenerated at @Model.LastGenerated by https://github.com/geniussportsgroup/Signalr.Hubs.TypeScriptGenerator /// /// @@ -10,7 +11,7 @@ interface SignalR { @foreach (TypeInfo type in Model.Hubs) { - @(type.Name) : @(type.TypescriptType); + @(type.Name) : @(type.TypeScriptType); } } @@ -22,9 +23,13 @@ declare module @serviceInfo.ModuleName interface @serviceInfo.InterfaceName { - server : @Raw(serviceInfo.ServerTypeFullNamespace); - client : @Raw(serviceInfo.ClientType); - } + server : @Raw(serviceInfo.ServerTypeFullNamespace); + @if (serviceInfo.ClientType == "any") + { + @Raw(" // Hub does not have a Client Interface as a generic argument - it is recommend to add one" + Environment.NewLine); + } + client : @Raw(serviceInfo.ClientType); + } interface @serviceInfo.ServerType { @@ -62,7 +67,7 @@ declare module @dataContractInfo.ModuleName { @foreach (TypeInfo property in dataContractInfo.Properties) { - @Raw(property.Name) : @Raw(property.TypescriptType); + @Raw(property.Name) : @Raw(property.TypeScriptType); } } } @@ -78,7 +83,7 @@ declare module @enumInfo.ModuleName { @foreach (TypeInfo property in enumInfo.Properties) { - @Raw(property.Name) = @Raw(property.TypescriptType), + @Raw(property.Name) = @Raw(property.TypeScriptType), } } } From e7ba1778f80a080d831a917390373fbbe613482b Mon Sep 17 00:00:00 2001 From: Chris Haines Date: Fri, 16 Sep 2016 14:58:22 +0100 Subject: [PATCH 6/9] Write result to standard out if no output file is specified --- README.md | 2 ++ .../Program.cs | 12 ++++++++++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index eb0b1ca..ffbcc2c 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ This will output the TypeScript to the specified file path .\Signalr.Hubs.TypeScriptGenerator.Console.exe -a "c:\etc\path-to-myassembly.dll" -o "C:\temp\.myfile.d.ts" +If the output file is not specified the result is written to standard out. + ### Data Contract Property Name Sometimes the serialized name of your data contract properties are changed from the actual C# property name. This is done through the DataMember property: diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/Program.cs b/src/Signalr.Hubs.TypeScriptGenerator.Console/Program.cs index c8d11d8..195517c 100644 --- a/src/Signalr.Hubs.TypeScriptGenerator.Console/Program.cs +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/Program.cs @@ -50,7 +50,15 @@ private static void Run(CommandLineOptions commandLineOptions) var hubTypeScriptGenerator = new HubTypeScriptGenerator(); var outputText = hubTypeScriptGenerator.Generate(); - File.WriteAllText(commandLineOptions.OutFile, outputText); + + if (string.IsNullOrWhiteSpace(commandLineOptions.OutFile)) + { + System.Console.WriteLine(outputText); + } + else + { + File.WriteAllText(commandLineOptions.OutFile, outputText); + } } @@ -60,4 +68,4 @@ private static void LoadAssemblies(CommandLineOptions commandLineOptions) assemblyLoader.LoadAssemblyIntoAppDomain(commandLineOptions.AssemblyPath); } } -} +} \ No newline at end of file diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs b/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs index e1409e6..87c4964 100644 --- a/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs @@ -8,5 +8,5 @@ [assembly: AssemblyCopyright("Copyright © Genius Sports 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("1.0.3.0")] -[assembly: AssemblyFileVersion("1.0.3.0")] +[assembly: AssemblyVersion("1.0.4.0")] +[assembly: AssemblyFileVersion("1.0.4.0")] diff --git a/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs index f8167c4..4431383 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs @@ -8,5 +8,5 @@ [assembly: AssemblyCopyright("Copyright © Genius Sports 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("1.0.3.0")] -[assembly: AssemblyFileVersion("1.0.3.0")] +[assembly: AssemblyVersion("1.0.4.0")] +[assembly: AssemblyFileVersion("1.0.4.0")] From cf6047cd41f9e1ef6c25e76251475263eabd9060 Mon Sep 17 00:00:00 2001 From: Chris Haines Date: Fri, 16 Sep 2016 17:32:05 +0100 Subject: [PATCH 7/9] Use assembly redirect to ensure we can generate hubs for different versions of SignalR --- README.md | 9 ++ .../App.config | 4 + .../Properties/AssemblyInfo.cs | 4 +- .../Helpers/HubDescriptorProvider.cs | 138 ++++++++++++++++++ .../Properties/AssemblyInfo.cs | 4 +- 5 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 src/Signalr.Hubs.TypeScriptGenerator/Helpers/HubDescriptorProvider.cs diff --git a/README.md b/README.md index ffbcc2c..f5e347b 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,15 @@ This will output the TypeScript to the specified file path If the output file is not specified the result is written to standard out. +**# ONLY COMBATIBLE WITH SIGNALR VERSIONS AT 2.2.1.0 OR EARLIER #** + +We have compiled this at verison 2.2.1.0 so in order for the HubManager to recognise your hubs we are using an assembly redirect. If Microsoft release a new version we will need to update this. + + + + + + ### Data Contract Property Name Sometimes the serialized name of your data contract properties are changed from the actual C# property name. This is done through the DataMember property: diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/App.config b/src/Signalr.Hubs.TypeScriptGenerator.Console/App.config index d92337c..df8577d 100644 --- a/src/Signalr.Hubs.TypeScriptGenerator.Console/App.config +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/App.config @@ -10,6 +10,10 @@ + + + + diff --git a/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs b/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs index 87c4964..457b94f 100644 --- a/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs +++ b/src/Signalr.Hubs.TypeScriptGenerator.Console/Properties/AssemblyInfo.cs @@ -8,5 +8,5 @@ [assembly: AssemblyCopyright("Copyright © Genius Sports 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("1.0.4.0")] -[assembly: AssemblyFileVersion("1.0.4.0")] +[assembly: AssemblyVersion("1.0.5.0")] +[assembly: AssemblyFileVersion("1.0.5.0")] diff --git a/src/Signalr.Hubs.TypeScriptGenerator/Helpers/HubDescriptorProvider.cs b/src/Signalr.Hubs.TypeScriptGenerator/Helpers/HubDescriptorProvider.cs new file mode 100644 index 0000000..63822d9 --- /dev/null +++ b/src/Signalr.Hubs.TypeScriptGenerator/Helpers/HubDescriptorProvider.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Reflection; +using Microsoft.AspNet.SignalR; +using Microsoft.AspNet.SignalR.Hubs; + +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.Helpers +{ + public class HubDescriptorProvider : IHubDescriptorProvider + { + private readonly IDependencyResolver resolver; + + public HubDescriptorProvider(IDependencyResolver resolver) + { + this.resolver = resolver; + } + + public IList GetHubs() + { + return GetHubsInternal().Values.ToList(); + } + + private IDictionary GetHubsInternal() + { + // Getting all IHub-implementing types that apply + var assemblyLocator = (IAssemblyLocator)resolver.GetService(typeof(IAssemblyLocator)); + var types = assemblyLocator.GetAssemblies() + .SelectMany(GetTypesSafe) + .Where(IsHubType) + .ToList(); + + // Building cache entries for each descriptor + // Each descriptor is stored in dictionary under a key + // that is it's name or the name provided by an attribute + var hubDescriptors = types + .Select(type => new HubDescriptor + { + NameSpecified = (type.GetHubAttributeName() != null), + Name = type.GetHubName(), + HubType = type + }); + + var cacheEntries = new Dictionary(StringComparer.OrdinalIgnoreCase); + + foreach (var descriptor in hubDescriptors) + { + HubDescriptor oldDescriptor = null; + if (!cacheEntries.TryGetValue(descriptor.Name, out oldDescriptor)) + { + cacheEntries[descriptor.Name] = descriptor; + } + else + { + throw new InvalidOperationException(); + } + } + + return cacheEntries; + } + + public bool TryGetHub(string hubName, out HubDescriptor descriptor) + { + return GetHubsInternal().TryGetValue(hubName, out descriptor); + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "If we throw then it's not a hub type")] + private static bool IsHubType(Type type) + { + try + { + return typeof(Hub).IsAssignableFrom(type) && + !type.IsAbstract && + (type.Attributes.HasFlag(TypeAttributes.Public) || + type.Attributes.HasFlag(TypeAttributes.NestedPublic)); + } + catch + { + return false; + } + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "If we throw then we have an empty type")] + private IEnumerable GetTypesSafe(Assembly a) + { + try + { + return a.GetTypes(); + } + catch (ReflectionTypeLoadException ex) + { + return ex.Types.Where(t => t != null); + } + catch (Exception ex) + { + return Enumerable.Empty(); + } + } + } + + internal static class HubTypeExtensions + { + internal static string GetHubName(this Type type) + { + if (!typeof(IHub).IsAssignableFrom(type)) + { + return null; + } + + return GetHubAttributeName(type) ?? GetHubTypeName(type); + } + + internal static string GetHubAttributeName(this Type type) + { + if (!typeof(IHub).IsAssignableFrom(type)) + { + return null; + } + + // We can still return null if there is no attribute name + return ReflectionHelper.GetAttributeValue(type, attr => attr.HubName); + } + + private static string GetHubTypeName(Type type) + { + var lastIndexOfBacktick = type.Name.LastIndexOf('`'); + if (lastIndexOfBacktick == -1) + { + return type.Name; + } + else + { + return type.Name.Substring(0, lastIndexOfBacktick); + } + } + } +} \ No newline at end of file diff --git a/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs b/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs index 4431383..bf24f5d 100644 --- a/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs +++ b/src/Signalr.Hubs.TypescriptGenerator/Properties/AssemblyInfo.cs @@ -8,5 +8,5 @@ [assembly: AssemblyCopyright("Copyright © Genius Sports 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("1.0.4.0")] -[assembly: AssemblyFileVersion("1.0.4.0")] +[assembly: AssemblyVersion("1.0.5.0")] +[assembly: AssemblyFileVersion("1.0.5.0")] From 43a2ebf3d624a5eb235f06f1a624e0dcb0de37f1 Mon Sep 17 00:00:00 2001 From: Kiril Djakov Date: Tue, 25 Oct 2016 08:25:18 +0300 Subject: [PATCH 8/9] Support for inherited dto's --- .../DataContracts/InheritedSomethingDto.cs | 11 +++++++++++ src/SampleUsage/Hubs/HubA.cs | 5 +++++ src/SampleUsage/SampleUsage.csproj | 4 ++++ .../Helpers/HubHelper.cs | 16 ++++++++-------- 4 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 src/SampleUsage/DataContracts/InheritedSomethingDto.cs diff --git a/src/SampleUsage/DataContracts/InheritedSomethingDto.cs b/src/SampleUsage/DataContracts/InheritedSomethingDto.cs new file mode 100644 index 0000000..639de57 --- /dev/null +++ b/src/SampleUsage/DataContracts/InheritedSomethingDto.cs @@ -0,0 +1,11 @@ +using System.Runtime.Serialization; + +namespace GeniusSports.Signalr.Hubs.TypeScriptGenerator.SampleUsage.DataContracts +{ + [DataContract] + public class InheritedSomethingDto : SomethingDto + { + [DataMember] + public int InheritedSomethingDtoProperty1 { get; set; } + } +} \ No newline at end of file diff --git a/src/SampleUsage/Hubs/HubA.cs b/src/SampleUsage/Hubs/HubA.cs index a159584..64697bf 100644 --- a/src/SampleUsage/Hubs/HubA.cs +++ b/src/SampleUsage/Hubs/HubA.cs @@ -16,6 +16,11 @@ public SomethingDto GetSomething() return new SomethingDto(); } + public InheritedSomethingDto GetInheritedSomething() + { + return new InheritedSomethingDto(); + } + public void Ping() { } diff --git a/src/SampleUsage/SampleUsage.csproj b/src/SampleUsage/SampleUsage.csproj index 7244e31..2072867 100644 --- a/src/SampleUsage/SampleUsage.csproj +++ b/src/SampleUsage/SampleUsage.csproj @@ -65,6 +65,7 @@ + @@ -85,6 +86,9 @@ Signalr.Hubs.TypeScriptGenerator + + +