├── tools
└── NuGet.exe
├── src
├── TypeScriptType.cs
├── _Program.cs
├── SignalRModule.cs
├── ServiceTypes.cs
└── DataTypes.cs
├── .gitignore
├── NuGet
├── Package.proj
└── SRTS.nuspec
├── Properties
└── AssemblyInfo.cs
├── SRTS.csproj
├── Content
└── signalr.d.ts
├── README.md
└── LICENSE.md
/tools/NuGet.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muratg/SRTS/HEAD/tools/NuGet.exe
--------------------------------------------------------------------------------
/src/TypeScriptType.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace SRTS
8 | {
9 | public class TypeScriptType
10 | {
11 | public string Name { get; set; }
12 | public string Declaration { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | [Oo]bj/
2 | [Bb]in/
3 | *.user
4 | *.suo
5 | *.cache
6 | _ReSharper.*
7 | *.csproj.user
8 | *[Rr]e[Ss]harper.user
9 | packages/*
10 | *.vsp
11 | *.pidb
12 | *.userprefs
13 | *DS_Store
14 | *.ncrunchsolution
15 | *.log
16 | *.vspx
17 | /.symbols
18 | README.html
19 | *.sdf
20 | *.ipch
21 | *.opensdf
22 | /Debug
23 | /.nuget/nuget.exe
24 | /TestResults
25 |
--------------------------------------------------------------------------------
/NuGet/Package.proj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/_Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace SRTS
8 | {
9 | class _Program
10 | {
11 | static int Main(string[] args)
12 | {
13 | if (args.Count() != 1)
14 | {
15 | Console.WriteLine("Usage: SRTS AssemblyName");
16 | return 1;
17 | }
18 |
19 | var path = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), args[0]);
20 | var asm = System.Reflection.Assembly.LoadFile(path);
21 |
22 | Console.WriteLine(SignalRModule.Create(asm));
23 |
24 | return 0;
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/NuGet/SRTS.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SRTS
5 | 0.1.1-beta
6 | Murat Girgin
7 | Murat Gitgin
8 | http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE
9 | http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE
10 | http://ICON_URL_HERE_OR_DELETE_THIS_LINE
11 | false
12 | Package description
13 | Summary of changes made in this release of the package.
14 | Copyright 2013
15 | Tag1 Tag2
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("SRTS")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("SRTS")]
13 | [assembly: AssemblyCopyright("Copyright © 2013")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("362e4453-f28f-4b94-b0fb-2723114d8ce0")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/SRTS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {62BF269B-6F67-4C84-936D-7CC0CE365C3E}
8 | Exe
9 | Properties
10 | SRTS
11 | SRTS
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
63 |
--------------------------------------------------------------------------------
/src/SignalRModule.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using System.Reflection;
3 |
4 | namespace SRTS
5 | {
6 | public class SignalRModule
7 | {
8 | public static string Create(Assembly assembly)
9 | {
10 | ServiceTypes.AddHubsFromAssembly(assembly);
11 |
12 | var dec = "";
13 |
14 | dec += "/*\n Client interfaces:\n These are to be implemented by the user.\n These are for Hub -> Client calls.\n */ \n\n";
15 | foreach (var k in ServiceTypes.ClientCache.Keys)
16 | {
17 | var dt = ServiceTypes.ClientCache[k];
18 | if (dt.Declaration != "")
19 | {
20 | dec += dt.Declaration + "\n";
21 | }
22 | }
23 |
24 | dec += "\n//Promise interface\n";
25 | dec += "interface IPromise {\n";
26 | dec += " done(cb: (result: T) => any): IPromise;\n";
27 | dec += " error(cb: (error: any) => any): IPromise;\n";
28 | dec += "}\n";
29 | if (DataTypes.HasDictionary)
30 | {
31 | dec += "\n//Generic dictionary interface\n";
32 | dec += "interface IDictionary {\n [key: any]: T;\n}\n";
33 | }
34 | if (DataTypes.TupleTypesByCount.Count() > 0)
35 | {
36 | dec += "\n// Tuple types\n";
37 | DataTypes.TupleTypesByCount.ForEach(c =>
38 | {
39 | dec += "interface Tuple" + c + "<";
40 | for (var i = 0; i < c; i++)
41 | {
42 | dec += "T" + i + (i == c - 1 ? "" : ", ");
43 | }
44 | dec += "> {\n";
45 | for (var i = 0; i < c; i++)
46 | {
47 | dec += " Item" + i + ": T" + i + ";\n";
48 | }
49 | dec += "}\n";
50 | });
51 | }
52 |
53 | dec += "\n// Data interfaces \n";
54 | foreach (var k in DataTypes.Cache.Keys)
55 | {
56 | var dt = DataTypes.Cache[k];
57 | if (dt.Declaration != "")
58 | {
59 | dec += dt.Declaration + "\n";
60 | }
61 | }
62 |
63 | dec += "\n// Hub interfaces \n";
64 | foreach (var k in ServiceTypes.HubCache.Keys)
65 | {
66 | var dt = ServiceTypes.HubCache[k];
67 | if (dt.Declaration != "")
68 | {
69 | dec += dt.Declaration + "\n";
70 | }
71 | }
72 |
73 | dec += "\n// Generetated proxies \n";
74 |
75 | foreach (var k in ServiceTypes.HubCache.Keys)
76 | {
77 | var dt = ServiceTypes.HubCache[k];
78 | var hubName = ServiceTypes.HubAliasesCache[k];
79 | var hubAttribute = ServiceTypes.HubAliasesCache[k];
80 |
81 | dec += "interface " + dt.Name + "Proxy {\n";
82 | dec += " server: " + dt.Name + ";\n";
83 | dec += " client: " + dt.Name + "Client;\n";
84 | dec += "}\n";
85 |
86 | }
87 | return dec;
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/ServiceTypes.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text.RegularExpressions;
6 |
7 | namespace SRTS
8 | {
9 | public class ServiceTypes
10 | {
11 | static Dictionary hubCache;
12 | static Dictionary hubAliasesCache;
13 | static Dictionary clientCache;
14 |
15 | public static Dictionary HubCache { get { return hubCache; } }
16 | public static Dictionary ClientCache { get { return clientCache; } }
17 | public static Dictionary HubAliasesCache { get { return hubAliasesCache; } }
18 |
19 | static ServiceTypes()
20 | {
21 | hubCache = new Dictionary();
22 | clientCache = new Dictionary();
23 | hubAliasesCache = new Dictionary();
24 | }
25 |
26 | static string CamelCase(string s)
27 | {
28 | return s[0].ToString().ToLower() + s.Substring(1);
29 | }
30 |
31 | static TypeScriptType MakeHubInterface(Type hubType)
32 | {
33 | var name = "I" + hubType.Name;
34 | var cName = name + "Client";
35 |
36 | var declaration = "interface " + name + " {\n";
37 | var count = 0;
38 | var sep = "";
39 | var hubAttribute = "";
40 | hubType.GetMethods()
41 | .Where(mi => mi.DeclaringType.Name == hubType.Name).ToList()
42 | .ForEach(mi =>
43 | {
44 | declaration += " " + CamelCase(mi.Name) + "(";
45 |
46 | var retTS = DataTypes.GetTypeScriptType(mi.ReturnType);
47 | var retType = retTS.Name == "System.Void" ? "void" : "IPromise<" + retTS.Name + ">";
48 | mi.GetParameters().ToList()
49 | .ForEach((pi) =>
50 | {
51 | sep = (count != 0 ? ", " : "");
52 | count++;
53 | var tst = DataTypes.GetTypeScriptType(pi.ParameterType);
54 | declaration += sep + pi.Name + ": " + tst.Name;
55 | });
56 |
57 | declaration += "): "+ retType + ";\n";
58 | count = 0;
59 | });
60 |
61 | declaration += "}";
62 |
63 | hubAttribute = hubType.CustomAttributes
64 | .Where(ad => ad.AttributeType.Name == "HubNameAttribute")
65 | .Select(ad => ad.ConstructorArguments.FirstOrDefault().Value.ToString())
66 | .FirstOrDefault();
67 |
68 | var ret = new TypeScriptType
69 | {
70 | Name = name,
71 | Declaration = declaration
72 | };
73 |
74 | hubCache.Add(name, ret);
75 |
76 | hubAliasesCache.Add(name, hubAttribute);
77 |
78 | clientCache.Add(cName, new TypeScriptType {
79 | Name = cName,
80 | Declaration = "interface " + cName + " { \n /* Not implemented */ \n}"
81 | });
82 |
83 | return ret;
84 | }
85 |
86 | /*
87 | declare var client: IClient // To be filled by the user...
88 | declare var server: IServer
89 |
90 | */
91 |
92 | public static void AddHubsFromAssembly(Assembly assembly)
93 | {
94 | assembly.GetTypes()
95 | .Where(t => t.BaseType != null && t.BaseType.Name == "Hub").ToList()
96 | .ForEach(t => MakeHubInterface(t) );
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/Content/signalr.d.ts:
--------------------------------------------------------------------------------
1 | // Code from DefinitelyTyped Project. https://github.com/borisyankov/DefinitelyTyped (MIT license)
2 | // JQueryPromise & JQueryDeferred definitions (c) Microsoft
3 | // SignalR definitions (c) Boris Yankov https://github.com/borisyankov/
4 | // Updated by Murat Girgin
5 |
6 | /*
7 | Copyrights are respective of each contributor listed at the beginning of each definition file.
8 |
9 | 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:
10 |
11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12 |
13 | 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.
14 | */
15 |
16 | // Simplified JQueryPromise and JQueryDefered, renamed to prevent name potential clashes with jquery
17 | interface IPromise {
18 | always(...alwaysCallbacks: any[]): IPromise;
19 | done(...doneCallbacks: any[]): IPromise;
20 | fail(...failCallbacks: any[]): IPromise;
21 | progress(...progressCallbacks: any[]): IPromise;
22 | then(onFulfill: (...values: any[]) => U, onReject?: (...reasons: any[]) => U, onProgress?: (...progression: any[]) => any): IPromise;
23 | }
24 | interface IDeferred extends IPromise {
25 | always(...alwaysCallbacks: any[]): IDeferred;
26 | done(...doneCallbacks: any[]): IDeferred;
27 | fail(...failCallbacks: any[]): IDeferred;
28 | progress(...progressCallbacks: any[]): IDeferred;
29 | notify(...args: any[]): IDeferred;
30 | notifyWith(context: any, ...args: any[]): IDeferred;
31 | reject(...args: any[]): IDeferred;
32 | rejectWith(context: any, ...args: any[]): IDeferred;
33 | resolve(val: T): IDeferred;
34 | resolve(...args: any[]): IDeferred;
35 | resolveWith(context: any, ...args: any[]): IDeferred;
36 | state(): string;
37 | promise(target?: any): IPromise;
38 | }
39 |
40 | interface HubMethod {
41 | (callback: (data: string) => void);
42 | }
43 |
44 | interface SignalREvents {
45 | onStart: string;
46 | onStarting: string;
47 | onReceived: string;
48 | onError: string;
49 | onConnectionSlow: string;
50 | onReconnect: string;
51 | onStateChanged: string;
52 | onDisconnect: string;
53 | }
54 |
55 | interface SignalRStateChange {
56 | oldState: number;
57 | newState: number;
58 | }
59 |
60 | interface SignalR {
61 | events: SignalREvents;
62 | connectionState: any;
63 | transports: any;
64 |
65 | hub: HubConnection;
66 | id: string;
67 | logging: boolean;
68 | messageId: string;
69 | url: string;
70 |
71 | (url: string, queryString?: any, logging?: boolean): SignalR;
72 | hubConnection(url?: string): SignalR;
73 |
74 | log(msg: string, logging: boolean): void;
75 | isCrossDomain(url: string): boolean;
76 | changeState(connection: SignalR, expectedState: number, newState: number): boolean;
77 | isDisconnecting(connection: SignalR): boolean;
78 |
79 | // createHubProxy(hubName: string): SignalR;
80 |
81 | start(): IPromise;
82 | start(callback: () => void): IPromise;
83 | start(settings: ConnectionSettings): IPromise;
84 | start(settings: ConnectionSettings, callback: () => void): IPromise;
85 |
86 | send(data: string): void;
87 | stop(async?: boolean, notifyServer?: boolean): void;
88 |
89 | starting(handler: () => void): SignalR;
90 | received(handler: (data: any) => void): SignalR;
91 | error(handler: (error: string) => void): SignalR;
92 | stateChanged(handler: (change: SignalRStateChange) => void): SignalR;
93 | disconnected(handler: () => void): SignalR;
94 | connectionSlow(handler: () => void): SignalR;
95 | sending(handler: () => void): SignalR;
96 | reconnecting(handler: () => void): SignalR;
97 | reconnected(handler: () => void): SignalR;
98 | }
99 |
100 | interface HubProxy {
101 | (connection: HubConnection, hubName: string): HubProxy;
102 | state: any;
103 | connection: HubConnection;
104 | hubName: string;
105 | init(connection: HubConnection, hubName: string): void;
106 | hasSubscriptions(): boolean;
107 | on(eventName: string, callback: (...msg) => void): HubProxy;
108 | off(eventName: string, callback: (msg) => void): HubProxy;
109 | invoke(methodName: string, ...args: any[]): any; // IDeferred;
110 | }
111 |
112 | interface HubConnectionSettings {
113 | queryString?: string;
114 | logging?: boolean;
115 | useDefaultPath?: boolean;
116 | }
117 |
118 | interface HubConnection extends SignalR {
119 | //(url?: string, queryString?: any, logging?: boolean): HubConnection;
120 | proxies;
121 | received(callback: (data: { Id; Method; Hub; State; Args; }) => void): HubConnection;
122 | createHubProxy(hubName: string): HubProxy;
123 | }
124 |
125 | interface SignalRfn {
126 | init(url, qs, logging);
127 | }
128 |
129 | interface ConnectionSettings {
130 | transport? ;
131 | callback? ;
132 | waitForPageLoad?: boolean;
133 | jsonp?: boolean;
134 | }
135 |
136 |
137 | interface JQueryStatic {
138 | signalR: SignalR;
139 | connection: SignalR;
140 | hubConnection(url?: string, queryString?: any, logging?: boolean): HubConnection;
141 | }
142 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SRTS
2 |
3 | SignalR-TypeScript declarations generator
4 |
5 | ## WHAT
6 |
7 | This tool generates TypeScript declarations files for your SignalR hubs
8 |
9 | ## WHY
10 |
11 | You might want to write your SignalR client code in TypeScript instead of JavaScript for obvious reasons. Some of the benefits are:
12 |
13 | * Dev/build time type checking. This is especially helpful when the churn in your code is high
14 | * Better tooling support. While intellisense for JavaScript is getting better, it's not on par with TypeScript
15 |
16 | ## HOW
17 |
18 | ### Using NuGet
19 |
20 | * Install SRTS NuGet package
21 | * types.tt and signalr.d.ts files are generated in your project. You can move them / rename them if you want
22 | * Definition of your types will be generated in types.d.ts file. You can reference this file from your .ts files
23 | * A basic piece "starter" code is provided on top of types.d.ts file. You can copy paste this code to your .ts file
24 |
25 | ### Using command line tool
26 |
27 | * srts.exe installed in project packages folder (installed with the srts NuGet package,) and can be taken from there
28 | * Copy srts.exe to the folder where your assembly is in
29 | * Run "srts.exe ASSEMBLYNAME.DLL > myTypes.d.ts"
30 |
31 | ## FEATURES
32 |
33 | In addition to supporting all basic types, SRTS also supports:
34 |
35 | * Tuple
36 | * Nullable types
37 | * Task results
38 | * List and Array like types (IEnumerable, etc...)
39 | * Dictionary like types
40 | * Enums
41 | * Custom classes/interfaces
42 |
43 | ### SAMPLE OUTPUT
44 |
45 | ## Sample output from StockTicker
46 |
47 | /* Sample code -- create a .ts file, and paste the following to get started
48 |
49 | ///
50 | ///
51 |
52 | // ---- Change the name name of d.ts file above based on your .tt file ----
53 | var stockTicker: IStockTickerHubProxy = ($.connection).stockTicker;
54 | $.connection.hub.start().done((a) => {
55 | alert('connected.'); // ....
56 | });
57 |
58 | */
59 |
60 | // Client interfaces
61 | // These are expected to be defined by the user elsewhere
62 | // (This file is auto-generated)
63 | interface IStockTickerHubClient { /* To be defined elsewhere... */ }
64 |
65 | // Promise interface
66 | interface IPromise {
67 | done(cb: (result: T) => any): IPromise;
68 | error(cb: (error: any) => any): IPromise;
69 | }
70 |
71 | // Data interfaces
72 | interface Stock {
73 | Symbol: string;
74 | DayOpen: number;
75 | DayLow: number;
76 | DayHigh: number;
77 | LastChange: number;
78 | Change: number;
79 | PercentChange: number;
80 | Price: number;
81 | }
82 |
83 | // Hub interfaces
84 | interface IStockTickerHub {
85 | getAllStocks(): IPromise>;
86 | getMarketState(): IPromise;
87 | openMarket(): IPromise;
88 | closeMarket(): IPromise;
89 | reset(): IPromise;
90 | }
91 |
92 | // Generetated proxies
93 | interface IStockTickerHubProxy {
94 | server: IStockTickerHub;
95 | client: IStockTickerHubClient;
96 | }
97 |
98 | ## Sample output from JabbR
99 |
100 | // Client interfaces
101 | // These are expected to be defined by the user elsewhere
102 | // (This file is auto-generated)
103 | interface IMonitorClient { /* To be defined elsewhere... */ }
104 | interface IChatClient { /* To be defined elsewhere... */ }
105 |
106 | // Promise interface
107 | interface IPromise {
108 | done(cb: (result: T) => any): IPromise;
109 | error(cb: (error: any) => any): IPromise;
110 | }
111 |
112 | // Data interfaces
113 | interface ClientMessage {
114 | Id: string;
115 | Content: string;
116 | Room: string;
117 | }
118 | interface UserViewModel {
119 | Name: string;
120 | Hash: string;
121 | Active: boolean;
122 | Status: string;
123 | Note: string;
124 | AfkNote: string;
125 | IsAfk: boolean;
126 | Flag: string;
127 | Country: string;
128 | LastActivity: string;
129 | IsAdmin: boolean;
130 | }
131 | interface LobbyRoomViewModel {
132 | Name: string;
133 | Count: number;
134 | Private: boolean;
135 | Closed: boolean;
136 | Topic: string;
137 | }
138 | interface MessageViewModel {
139 | HtmlEncoded: boolean;
140 | Id: string;
141 | Content: string;
142 | HtmlContent: string;
143 | When: string;
144 | User: UserViewModel;
145 | MessageType: number;
146 | ImageUrl: string;
147 | Source: string;
148 | }
149 | interface RoomViewModel {
150 | Name: string;
151 | Count: number;
152 | Private: boolean;
153 | Topic: string;
154 | Closed: boolean;
155 | Welcome: string;
156 | Users: Array;
157 | Owners: Array;
158 | RecentMessages: Array;
159 | }
160 | interface ClientNotification {
161 | Room: string;
162 | ImageUrl: string;
163 | Source: string;
164 | Content: string;
165 | }
166 |
167 | // Hub interfaces
168 | interface IMonitor {
169 | }
170 | interface IChat {
171 | onConnected(): IPromise;
172 | join(): IPromise;
173 | join(reconnecting: boolean): IPromise;
174 | send(content: string, roomName: string): IPromise;
175 | send(clientMessage: ClientMessage): IPromise;
176 | getUserInfo(): IPromise;
177 | onReconnected(): IPromise;
178 | onDisconnected(): IPromise;
179 | getCommands(): IPromise;
180 | getShortcuts(): IPromise;
181 | getRooms(): IPromise>;
182 | getPreviousMessages(messageId: string): IPromise>;
183 | getRoomInfo(roomName: string): IPromise;
184 | postNotification(notification: ClientNotification): IPromise;
185 | postNotification(notification: ClientNotification, executeContentProviders: boolean): IPromise;
186 | typing(roomName: string): IPromise;
187 | updateActivity(): IPromise;
188 | }
189 |
190 | // Generetated proxies
191 | interface IMonitorProxy {
192 | server: IMonitor;
193 | client: IMonitorClient;
194 | }
195 | interface IChatProxy {
196 | server: IChat;
197 | client: IChatClient;
198 | }
199 |
200 | ## Sample output from ShootR
201 |
202 | /* Sample code -- create a .ts file, and paste the following to get started
203 |
204 | ///
205 | ///
206 |
207 | // ---- Change the name name of d.ts file above based on your .tt file ----
208 | var h: IGameHubProxy = ($.connection).h;
209 | $.connection.hub.start().done((a) => {
210 | alert('connected.'); // ....
211 | });
212 |
213 | */
214 |
215 | // Client interfaces
216 | // These are expected to be defined by the user elsewhere
217 | // (This file is auto-generated)
218 | interface IGameHubClient { /* To be defined elsewhere... */ }
219 |
220 | // Promise interface
221 | interface IPromise {
222 | done(cb: (result: T) => any): IPromise;
223 | error(cb: (error: any) => any): IPromise;
224 | }
225 |
226 | // Data interfaces
227 |
228 | // Hub interfaces
229 | interface IGameHub {
230 | onConnected(): IPromise;
231 | onReconnected(): IPromise;
232 | onDisconnected(): IPromise;
233 | ping(): IPromise;
234 | fire(): IPromise;
235 | startFire(): IPromise;
236 | stopFire(): IPromise;
237 | initializeClient(registrationID: string): IPromise;
238 | initializeController(registrationID: string): IPromise;
239 | readyForPayloads(): IPromise;
240 | resetMovement(movementList: Array, pingBack: boolean, commandID: number): IPromise;
241 | startAndStopMovement(toStop: string, toStart: string, pingBack: boolean, commandID: number): IPromise;
242 | registerMoveStart(movement: string, pingBack: boolean, commandID: number): IPromise;
243 | registerMoveStop(movement: string, pingBack: boolean, commandID: number): IPromise;
244 | registerAbilityStart(abilityName: string, pingBack: boolean, commandID: number): IPromise;
245 | registerAbilityStop(abilityName: string, pingBack: boolean, commandID: number): IPromise;
246 | registerAbilityStop(ability: string): IPromise;
247 | changeViewport(viewportWidth: number, viewportHeight: number): IPromise;
248 | readyForLeaderboardPayloads(): IPromise;
249 | stopLeaderboardPayloads(): IPromise;
250 | }
251 |
252 | // Generetated proxies
253 | interface IGameHubProxy {
254 | server: IGameHub;
255 | client: IGameHubClient;
256 | }
257 |
--------------------------------------------------------------------------------
/src/DataTypes.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | namespace SRTS
6 | {
7 | public class DataTypes
8 | {
9 | static Dictionary cache;
10 |
11 | public static Dictionary Cache { get { return cache; } }
12 |
13 | public static List TupleTypesByCount { get; set; }
14 | public static bool HasDictionary { get; set; }
15 |
16 | static DataTypes()
17 | {
18 | cache = new Dictionary();
19 | TupleTypesByCount = new List();
20 | HasDictionary = false;
21 |
22 | // Integral types
23 | cache.Add("System.Object", new TypeScriptType { Name = "any", Declaration = "" });
24 | cache.Add("System.Boolean", new TypeScriptType { Name = "boolean", Declaration = "" });
25 |
26 | cache.Add("System.Byte", new TypeScriptType { Name = "number", Declaration = "" });
27 | cache.Add("System.SByte", new TypeScriptType { Name = "number", Declaration = "" });
28 | cache.Add("System.Short", new TypeScriptType { Name = "number", Declaration = "" });
29 | cache.Add("System.UShort", new TypeScriptType { Name = "number", Declaration = "" });
30 | cache.Add("System.Int32", new TypeScriptType { Name = "number", Declaration = "" });
31 | cache.Add("System.UInt32", new TypeScriptType { Name = "number", Declaration = "" });
32 | cache.Add("System.Int64", new TypeScriptType { Name = "number", Declaration = "" });
33 | cache.Add("System.UInt64", new TypeScriptType { Name = "number", Declaration = "" });
34 | cache.Add("System.Single", new TypeScriptType { Name = "number", Declaration = "" });
35 | cache.Add("System.Double", new TypeScriptType { Name = "number", Declaration = "" });
36 | cache.Add("System.Decimal", new TypeScriptType { Name = "number", Declaration = "" });
37 |
38 | cache.Add("System.String", new TypeScriptType { Name = "string", Declaration = "" });
39 | cache.Add("System.Char", new TypeScriptType { Name = "string", Declaration = "" });
40 | cache.Add("System.DateTime", new TypeScriptType { Name = "string", Declaration = "" });
41 | cache.Add("System.DateTimeOffset", new TypeScriptType { Name = "string", Declaration = "" });
42 | cache.Add("System.Byte[]", new TypeScriptType { Name = "string", Declaration = "" });
43 | cache.Add("System.Type", new TypeScriptType { Name = "string", Declaration = "" });
44 | cache.Add("System.Guid", new TypeScriptType { Name = "string", Declaration = "" });
45 |
46 | cache.Add("System.Exception", new TypeScriptType { Name = "string", Declaration = "" });
47 | cache.Add("System.Collections.IDictionary", new TypeScriptType { Name = "Dictionary", Declaration = "" });
48 |
49 | }
50 |
51 | // Types that have implicit declarations
52 | public static TypeScriptType MakeFromNullable(Type type)
53 | {
54 | if (type.GenericTypeArguments.Count() == 1)
55 | {
56 | var name = GetTypeScriptType(type.GenericTypeArguments[0]).Name;
57 | return new TypeScriptType
58 | {
59 | Name = name + "?",
60 | Declaration = ""
61 | };
62 | }
63 | throw new ArgumentException("Can't make a Nullable type from: " + type);
64 | }
65 |
66 | public static TypeScriptType MakeFromTask(Type type)
67 | {
68 | var name = "void";
69 |
70 | if (type.GenericTypeArguments.Count() == 1)
71 | {
72 | name = GetTypeScriptType(type.GenericTypeArguments[0]).Name;
73 | }
74 | return new TypeScriptType
75 | {
76 | Name = name,
77 | Declaration = ""
78 | };
79 | }
80 |
81 | public static TypeScriptType MakeArray(Type type)
82 | {
83 | if (type.GenericTypeArguments.Count() != 1)
84 | {
85 | throw new ArgumentException("Can't convert " + type.FullName + " to an Array type. Invalid number of generic type arguments");
86 | }
87 |
88 | var elementType = type.GenericTypeArguments[0];
89 | var tst = GetTypeScriptType(elementType);
90 |
91 | return new TypeScriptType
92 | {
93 | Name = "Array<" + tst.Name + ">",
94 | Declaration = ""
95 | };
96 | }
97 |
98 | // TODO: create a generic Dictionary type interface.. such as IDictionary (excepts number or string) in []
99 | static TypeScriptType MakeDictionary(Type type)
100 | {
101 | if (type.GenericTypeArguments.Count() != 2)
102 | {
103 | throw new ArgumentException("Can't convert " + type.FullName + " to a Dictionary type. Invalid number of generic type arguments");
104 | }
105 |
106 | var keyType = type.GenericTypeArguments[0];
107 | var valueType = type.GenericTypeArguments[1];
108 | var keyTypeScriptType = GetTypeScriptType(keyType);
109 | if (keyTypeScriptType.Name != "string" && keyTypeScriptType.Name != "number")
110 | {
111 | throw new ArgumentException("Can't convert " + type.FullName
112 | + " to a collection type. TypeScript type of the key is "
113 | + keyTypeScriptType.Name + ". Should be number or string");
114 | }
115 |
116 | var valueTypeScriptType = GetTypeScriptType(valueType);
117 | HasDictionary = true;
118 |
119 | return new TypeScriptType
120 | {
121 | Name = "IDictionary<" + valueTypeScriptType.Name + ">",
122 | Declaration = ""
123 | };
124 | }
125 |
126 | // TODO: for each count of tuples, create a corresponding interface with number of Tuples..
127 | static TypeScriptType MakeTuple(Type type)
128 | {
129 | var count = type.GenericTypeArguments.Count();
130 | var name = "Tuple" + count + "<";
131 |
132 | TupleTypesByCount.Add(count);
133 |
134 | type.GenericTypeArguments.ToList().ForEach(t => name += GetTypeScriptType(t).Name + ", ");
135 |
136 | name = name.Substring(0, name.Length - ", ".Length);
137 | name += ">";
138 |
139 | return new TypeScriptType
140 | {
141 | Name = name,
142 | Declaration = ""
143 | };
144 | }
145 |
146 | // Types that have exlplicit declarations
147 |
148 | static TypeScriptType MakeEnum(Type type)
149 | {
150 | var name = type.Name;
151 | var declaration = "enum " + name + " {";
152 | var count = 0;
153 |
154 | type.GetEnumNames().ToList().ForEach(n =>
155 | {
156 | var sep = (count != 0 ? ", " : "") + "\n ";
157 | count++;
158 | declaration += sep + n;
159 | });
160 |
161 | declaration += "\n}";
162 |
163 | return new TypeScriptType
164 | {
165 | Name = name,
166 | Declaration = declaration
167 | };
168 | }
169 |
170 | static TypeScriptType MakeClassOrInterface(Type type)
171 | {
172 | var declaration = "";
173 | var name = type.Name;
174 |
175 | var members = type.GetMembers().ToList()
176 | .Select((mi, x) => Tuple.Create(mi.MemberType.ToString(), mi))
177 | .Where(mt => (mt.Item1 == "Property" || mt.Item1 == "Field"))
178 | .ToList();
179 |
180 | // TODO: Consider differentiating between classes and interfaces...
181 | declaration += "interface " + name + " {\n";
182 |
183 | members.ForEach(mt =>
184 | {
185 | var mem = mt.Item2;
186 |
187 | var fieldName = mem.Name;
188 | var typeName = "";
189 |
190 | if (mt.Item1 == "Property")
191 | {
192 | var prop = type.GetProperty(fieldName);
193 | typeName = GetTypeScriptType(prop.PropertyType).Name;
194 | }
195 | else if (mt.Item1 == "Field")
196 | {
197 | var prop = type.GetField(fieldName);
198 | typeName = GetTypeScriptType(prop.FieldType).Name;
199 | }
200 | else
201 | {
202 | // Shouldn't happen
203 | throw new ArgumentException("Unknown kind of class or interface element: " + fieldName + " is not expected....");
204 | }
205 |
206 | declaration += " " + mem.Name + ": " + typeName + ";\n";
207 | });
208 |
209 | declaration += "}";
210 |
211 | return new TypeScriptType
212 | {
213 | Name = name,
214 | Declaration = declaration
215 | };
216 | }
217 |
218 | public static TypeScriptType GetTypeScriptType(Type type)
219 | {
220 | TypeScriptType value;
221 | var typeName = type.FullName;
222 |
223 | if (cache.TryGetValue(typeName, out value))
224 | {
225 | return value;
226 | }
227 |
228 |
229 | // Nullables..
230 | if (type.FullName.Contains("Nullable"))
231 | {
232 | value = MakeFromNullable(type);
233 | }
234 | // Tasks..
235 | else if (type.FullName.Contains("Task") || type.GetInterfaces().Any(X => X.FullName.Contains("Task")))
236 | {
237 | value = MakeFromTask(type);
238 | }
239 | // Dictionaries -- these should come before IEnumerables, because they also implement IEnumerable
240 | else if (type.GetInterfaces().Any(X => X.FullName.Contains("IDictionary")))
241 | {
242 | value = MakeDictionary(type);
243 | }
244 | // Arrays
245 | else if (typeName.Contains("[]"))
246 | {
247 | value = MakeArray(typeof(List