public void WriteHubs(SignalRHubDesc[] hubs, TypeConverter converter, CustomIndentedTextWriter writer) { var hubList = hubs.ToList(); var scriptBuilder = new ScriptBuilder(" "); // Output signalR style promise interface: scriptBuilder.AppendLine("interface ISignalRPromise<T> {"); using (scriptBuilder.IncreaseIndentation()) { scriptBuilder.AppendLineIndented("done(cb: (result: T) => any): ISignalRPromise<T>;"); scriptBuilder.AppendLineIndented("error(cb: (error: any) => any): ISignalRPromise<T>;"); } scriptBuilder.AppendLineIndented("}"); scriptBuilder.AppendLine(); hubList.ForEach(h => GenerateHubInterfaces(h, scriptBuilder, converter)); // Generate client connection interfaces scriptBuilder.AppendLineIndented("interface SignalR {"); using (scriptBuilder.IncreaseIndentation()) { hubList.ForEach(h => scriptBuilder.AppendLineIndented(h.HubClassName.ToCamelCase() + ": I" + h.HubClassName + "Proxy;")); } scriptBuilder.AppendLineIndented("}"); scriptBuilder.AppendLine(); writer.WriteLine(scriptBuilder.ToString()); }
protected virtual void WriteController(ApiControllerDesc controller, CustomIndentedTextWriter writer) { var actions = controller.Actions.Select(a => ParseAction(controller, a)).ToArray(); var duplicateRoute = actions.GroupBy(a => a.Action.Method + a.Template).FirstOrDefault(g => g.Count() > 1); if (duplicateRoute != null) { throw new Exception($"Two actions ('{duplicateRoute.First().Action.ActionName}', '{duplicateRoute.Skip(1).First().Action.ActionName}') " + $"in controller '{controller.ControllerName}' share the same route '{duplicateRoute.First().Template}' and method '{duplicateRoute.First().Action.Method}'."); } var baseClass = String.IsNullOrWhiteSpace(_options.ControllerBaseClass) ? "" : $" extends {_options.ControllerBaseClass}"; var controllerName = $"{controller.ControllerName}Service"; writer.WriteLine($"export class {controllerName}{baseClass} {{"); writer.Indent++; writer.WriteLine("protected _basePath: string;"); writer.WriteLine($"protected {ajaxVariableName}: {_options.AjaxClassName};"); writer.WriteLine(); writer.WriteLine($"public endpoints = {{"); foreach (var a in actions) { writer.Indent++; WriteEndpoint(a, writer); writer.Indent--; } writer.WriteLine($"}}"); writer.WriteLine(); writer.WriteLine($"public constructor(basePath?: string, {optionsVariableName}?: {_options.OptionsClassName}) {{"); writer.Indent++; if (!String.IsNullOrEmpty(baseClass)) { writer.WriteLine("super();"); } writer.WriteLine("basePath = (basePath || \"\");"); writer.WriteLine("this._basePath = (basePath.substr(-1) == \"/\") ? basePath.substr(0, basePath.length - 1) : basePath;"); writer.WriteLine($"this.{ajaxVariableName} = new {_options.AjaxClassName}({optionsVariableName});"); foreach (var a in actions) { writer.WriteLine($"this.{a.NameString} = this.{a.NameString}.bind(this);"); } writer.Indent--; writer.WriteLine("}"); foreach (var a in actions) { writer.WriteLine(); WriteMethod(a, writer); } writer.Indent--; writer.WriteLine("}"); }
public void WriteEnums(CustomIndentedTextWriter enumsWriter, CustomIndentedTextWriter globalsWriter, CustomIndentedTextWriter definitionsWriter, ISet <TsEnum> enums, TypeConverter converter) { var enumGroup = enums .Select(e => new { Original = e, Path = converter.GetTypeScriptName(e.Type).Split('.') }) .Select(e => new EnumGroup { Enum = e.Original, Name = e.Path.Last(), Namespace = String.Join(".", e.Path.Take(e.Path.Length - 1)) }) .GroupBy(e => e.Namespace) .ToArray(); Dictionary <string, EnumGroup> globals = new Dictionary <string, EnumGroup>(); foreach (var grp in enumGroup) { enumsWriter.WriteLine(); enumsWriter.WriteLine($"namespace {grp.Key} {{"); enumsWriter.Indent++; definitionsWriter.WriteLine(); definitionsWriter.WriteLine($"namespace {grp.Key} {{"); definitionsWriter.Indent++; foreach (var e in grp) { GenerateEnum(enumsWriter, definitionsWriter, e, out var globalTypeName); if (!String.IsNullOrWhiteSpace(globalTypeName)) { globals.Add(globalTypeName, e); } } enumsWriter.Indent--; enumsWriter.WriteLine("}"); definitionsWriter.Indent--; definitionsWriter.WriteLine("}"); } if (globals.Any()) { var namespaces = globals.Select(g => g.Value.Namespace) .Distinct() .ToArray(); globalsWriter.WriteLine("const wnd: any = window;"); foreach (var space in namespaces) { globalsWriter.WriteLine($"wnd.{space} = wnd.{space} || {{}};"); } foreach (var n_gr in globals) { globalsWriter.WriteLine($"wnd.{n_gr.Value.Namespace}.{n_gr.Key} = {n_gr.Value.Namespace}.{n_gr.Key};"); } } }
public string Build(GapApiGeneratorOptions options = null) { var services = new StringWriter(); var servicesWriter = new CustomIndentedTextWriter(services, _indent); var enums = new StringWriter(); var enumsWriter = new CustomIndentedTextWriter(enums, _indent); var globals = new StringWriter(); var globalsWriter = new CustomIndentedTextWriter(globals, _indent); var definitions = new StringWriter(); var definitionsWriter = new CustomIndentedTextWriter(definitions, _indent); TypeScriptFluent fluent = new TypeScriptFluent(); fluent.WithConvertor <Guid>(c => "string"); fluent.WithIndentation(_indent); fluent.WithModelVisitor(_modelVisitor); var converter = new TypeConverter(_namespace, fluent); fluent.WithDictionaryMemberFormatter(converter); if (!string.IsNullOrEmpty(_namespace)) { fluent.WithModuleNameFormatter(m => _namespace); } ProcessTypes(_general, fluent); fluent.ModelBuilder.Build(); // this is to fix up manually added types before GapApiGenerator var apiGen = new GapApiGenerator(converter, _indent, options ?? new GapApiGeneratorOptions()); apiGen.WriteServices(_apis.ToArray(), servicesWriter); var signalr = new SignalRGenerator(); signalr.WriteHubs(_hubs.ToArray(), converter, servicesWriter); var tsClassDefinitions = fluent.Generate(TsGeneratorOutput.Properties | TsGeneratorOutput.Fields); definitionsWriter.Write(tsClassDefinitions); _enumGenerator.WriteEnums(enumsWriter, globalsWriter, definitionsWriter, fluent.ModelBuilder.Build().Enums, converter); string prepended = _generateNotice ? Resx.GeneratedNotice + "\r\n\r\n" : ""; prepended += services.GetStringBuilder() + Environment.NewLine + "declare global {" + (definitions.GetStringBuilder().ToString() + enums.GetStringBuilder()).Replace("declare namespace", "namespace").Replace("\n", "\n ").TrimEnd() + Environment.NewLine + "}" + Environment.NewLine + globals.GetStringBuilder(); return(prepended); }
public override void GenerateEnum(CustomIndentedTextWriter enumWriter, CustomIndentedTextWriter definitionsWriter, EnumGroup e, out string globalTypeName) { enumWriter.WriteLine($"{(ConstEnums ? "const " : "")}enum {e.Name} {{"); foreach (var value in e.Enum.Values) { enumWriter.Indent++; enumWriter.WriteLine($"{value.Name} = {GetEnumValue(value)},"); enumWriter.Indent--; } enumWriter.WriteLine("}"); globalTypeName = ConstEnums ? null : e.Name; }
public virtual void WriteServices(ApiControllerDesc[] controllers, CustomIndentedTextWriter writer) { var controllerNames = controllers.Select(d => d.ControllerName).ToArray(); var baseClass = String.IsNullOrWhiteSpace(_options.ControllerBaseClass) ? "" : $", {_options.ControllerBaseClass}"; writer.WriteLine($"import {{ {_options.AjaxClassName}, {_options.OptionsClassName}{baseClass} }} from \"{_options.EssentialsImportPath}\";"); if (!String.IsNullOrEmpty(_options.HeaderText)) { writer.WriteLine("// === BEGIN CUSTOM HEADER CODE ==="); writer.WriteLine(_options.HeaderText); writer.WriteLine("// === END CUSTOM HEADER CODE ==="); } writer.WriteLine(); WriteStaticHelper(controllerNames, writer); writer.WriteLine(); foreach (var d in controllers) { WriteController(d, writer); writer.WriteLine(); } writer.WriteLine(Resx.AjaxHelpers); writer.WriteLine(); if (bodyLookup.Values.Any()) { writer.WriteLine(); writer.WriteLine("// ======================================================================================"); writer.WriteLine("// The code below is generated by the chosen type initializer settings. It will serialize"); writer.WriteLine("// and deserialize types as described when they cross the http boundry."); writer.WriteLine("// ======================================================================================"); writer.WriteLine(); foreach (var helper in bodyLookup.Values.SelectMany(v => v.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries))) { writer.WriteLine(helper); } } if (!String.IsNullOrEmpty(_options.FooterText)) { writer.WriteLine("// === BEGIN CUSTOM FOOTER CODE ==="); writer.WriteLine(_options.FooterText); writer.WriteLine("// === END CUSTOM FOOTER CODE ==="); } }
protected virtual void WriteStaticHelper(string[] names, CustomIndentedTextWriter writer) { writer.WriteLine($"export class Services {{"); writer.Indent++; foreach (var n in names) { writer.WriteLine($"public readonly {n}: {n}Service;"); } writer.WriteLine($"public constructor(hostname: string, {optionsVariableName}?: {_options.OptionsClassName}) {{"); writer.Indent++; foreach (var n in names) { writer.WriteLine($"this.{n} = new {n}Service(hostname, {optionsVariableName});"); } writer.Indent--; writer.WriteLine("}"); writer.Indent--; writer.WriteLine("}"); }
protected virtual void WriteMethod(ParsedApiDesc desc, CustomIndentedTextWriter writer) { string returnString; if (desc.Action.ReturnType == null) { returnString = "any"; } else { returnString = _converter.GetTypeScriptName(desc.Action.ReturnType); } var paramString = desc.ParamString; if (!string.IsNullOrWhiteSpace(paramString)) { paramString += ", "; } string filesString = ""; if (desc.PostParameter != null && desc.PostParameter.ParameterType.Name == "IFormCollection") { filesString = "_files?: File[], "; } var modifier = "public"; if (_options.HideActionsWithNoReturn && returnString.StartsWith("any")) { writer.WriteLine("// This method is hidden because it's return type is not specified and HideActionsWithNoReturn=True"); writer.WriteLine("// Either add a return type (check [ProducesResponseType]) or set HideActionsWithNoReturn to False"); modifier = "protected"; } writer.WriteLine($"{modifier} {desc.NameString}({paramString}{filesString}{optionsVariableName}?: {_options.OptionsClassName}): {_options.PromiseType}<{returnString}> {{"); writer.Indent++; if (desc.PostParameter != null) { if (String.IsNullOrWhiteSpace(filesString)) { var pinit = this.CreateTypeInitializerMethod(desc.PostParameter.ParameterType); if (!String.IsNullOrWhiteSpace(pinit)) { writer.WriteLine($"{desc.PostParameter.ParameterName} = from_{pinit}({desc.PostParameter.ParameterName});"); } } else { writer.WriteLine($"if ({checkRealFn}(_files))"); writer.Indent++; writer.WriteLine($"for (const _f of _files) {{ {desc.PostParameter.ParameterName}.append(\"files[]\", _f); }}"); writer.Indent--; } } var excParams = desc.ModelParameter == null ? desc.GetParameters : new[] { desc.ModelParameter }; writer.WriteLine($"var url = this.endpoints.{desc.NameString}({String.Join(", ", excParams.Select(p => p.ParameterName))});"); var ajaxCtx = new AjaxExecContext { Ajax = ajaxVariableName, HttpMethod = desc.Action.Method.ToString().ToLower(), Options = optionsVariableName, Post = desc.PostParameter?.ParameterName ?? "null", Url = "url" }; writer.Write("return " + _options.FnAjaxExecute(ajaxCtx).TrimEnd(';')); var initializer = this.CreateTypeInitializerMethod(desc.Action.ReturnType); if (String.IsNullOrWhiteSpace(initializer)) { writer.WriteLine(";"); } else { writer.WriteLine($".then(to_{initializer});"); } writer.Indent--; writer.WriteLine("}"); }
protected virtual void WriteEndpoint(ParsedApiDesc desc, CustomIndentedTextWriter writer) { var line = $"{desc.NameString}: ({desc.EndpointParamString}): string => {desc.PathString},"; writer.WriteLine(line.Replace(" + \"\",", ",")); }
public abstract void GenerateEnum(CustomIndentedTextWriter enumWriter, CustomIndentedTextWriter definitionsWriter, EnumGroup enumObj, out string globalTypeName);
public override void GenerateEnum(CustomIndentedTextWriter enumWriter, CustomIndentedTextWriter definitionsWriter, EnumGroup e, out string globalTypeName) { enumWriter.WriteLine($"type {e.Name} = {String.Join(" | ", e.Enum.Values.Select(GetEnumValue))};"); globalTypeName = null; }