/// <summary> /// Generates structurally typed TypeScript API /// /// <param name="opts">Options for the generation</param> /// </summary> public bool Generate(GenSdkOptions opts) { var allDefinitions = new DictItem() as IItem; foreach (var grp in _apiDescriptionsProvider.ApiDescriptionGroups.Items) { foreach (var act in grp.Items) { var apiFunction = new ApiFunctionItem(); apiFunction.HttpMethod = act.HttpMethod; apiFunction.RelativePath = act.RelativePath; // [FromBody] or [FromForm] act.ParameterDescriptions.ToList().ForEach(p => { if (p.Source.Id.ToLower() == "body") { _tsGen.Generate(p.Type); apiFunction.InputBodyType = p.Type; } else if (p.Source.Id.ToLower() == "form") { // Not tested since ASP.NET Core 1.0 _tsGen.Generate(p.Type); apiFunction.InputFormType = p.Type; } else if (p.Source.Id.ToLower() == "path") { apiFunction.InputPathTypes.Add((p.Name, p.Type)); } else { _logger.LogWarning($"Unhandled type of method {p.Name} with source {p.Source.Id}, ignoring."); } }); // Get result type if (act.SupportedResponseTypes.Count >= 1) { var responseType = act.SupportedResponseTypes.First(); _tsGen.Generate(responseType.Type); // registry.GetOrRegister(responseType.Type); apiFunction.ResultType = responseType.Type; } var currDef = allDefinitions; // Namespaced controllers E.g. // AccountController.LoggedIn -> // Account.LoggedIn() var groupName = opts.GroupActionsBy(act); if (groupName != null) { var groups = groupName.Split('.'); // Step in to the nesting given in groups foreach (var g in groups) { if (!currDef.Children.ContainsKey(g)) { currDef.Children[g] = new DictItem(); } currDef = currDef.Children[g]; } } var nameRegex = new Regex(@".([^.]+) "); var nameMatch = nameRegex.Match(act.ActionDescriptor.DisplayName); if (!nameMatch.Success) { break; } var name = nameMatch.Groups[1].Value; currDef.Children[name] = apiFunction; } } // var apiObject = allDefinitions.GenTypescript(opts, registry); var apiObject = allDefinitions.GenTypescript(opts, _tsGen); var output = new List <string>(); output.AddRange(opts.Headers); output.AddRange(opts.Imports); output.Add(getApiErrors(opts, _tsGen)); output.Add(opts.GetApiRootFormat(apiObject)); output.AddRange(opts.Footers); // Write only if changed or does not exist var outputText = string.Join("\r\n", output); var write = true; if (File.Exists(opts.OutputFile)) { var fileContents = File.ReadAllText(opts.OutputFile); write = fileContents != outputText; } if (write) { File.WriteAllText(opts.OutputFile, outputText); return(true); } return(false); }
/// <summary> /// Generates structurally typed TypeScript API /// /// <param name="opts">Options for the generation</param> /// </summary> public bool Generate(GenSdkOptions opts) { var allDefinitions = new DictItem() as IItem; foreach (var grp in _apiDescriptionsProvider.ApiDescriptionGroups.Items) { foreach (var act in grp.Items) { var apiFunction = new ApiFunctionItem(); apiFunction.HttpMethod = act.HttpMethod; apiFunction.RelativePath = act.RelativePath; // Supports at most one parameter if (act.ParameterDescriptions.Count > 1) { var p = act.ParameterDescriptions.First(); if (p.Source.Id.ToLower() == "form") { apiFunction.InputFormType = typeof(object); } else { continue; } } // [FromBody] or [FromForm] if (act.ParameterDescriptions.Count == 1) { var p = act.ParameterDescriptions.First(); if (p.Source.Id.ToLower() == "body") { _tsGen.Generate(p.Type); apiFunction.InputBodyType = p.Type; } else { _logger.LogWarning($"Skipping SDK generation for {act.ActionDescriptor.DisplayName}. Only [FromBody] parameters are supported."); continue; } if (p.Source.Id.ToLower() == "form") { _tsGen.Generate(p.Type); apiFunction.InputFormType = p.Type; } } // Get result type if (act.SupportedResponseTypes.Count >= 1) { var responseType = act.SupportedResponseTypes.First(); _tsGen.Generate(responseType.Type); // registry.GetOrRegister(responseType.Type); apiFunction.ResultType = responseType.Type; } var groupName = opts.GroupActionsBy(act); if (groupName == null) { _logger.LogWarning($"Skipping SDK generation for {act.ActionDescriptor.DisplayName}. Group name can't be parsed."); break; } var groups = groupName.Split('.'); // Step in to the nesting given in groups var currDef = allDefinitions; foreach (var g in groups) { if (!currDef.Children.ContainsKey(g)) { currDef.Children[g] = new DictItem(); } currDef = currDef.Children[g]; } var nameRegex = new Regex(@".([^.]+) "); var nameMatch = nameRegex.Match(act.ActionDescriptor.DisplayName); if (!nameMatch.Success) { break; } var name = nameMatch.Groups[1].Value; currDef.Children[name] = apiFunction; } } // var apiObject = allDefinitions.GenTypescript(opts, registry); var apiObject = allDefinitions.GenTypescript(opts, _tsGen); var output = new List <string>(); output.AddRange(opts.Headers); output.AddRange(opts.Imports); output.Add(getApiErrors(opts, _tsGen)); output.Add(opts.GetApiRootFormat(apiObject)); output.AddRange(opts.Footers); // Write only if changed or does not exist var outputText = string.Join("\r\n", output); var write = true; if (File.Exists(opts.OutputFile)) { var fileContents = File.ReadAllText(opts.OutputFile); write = fileContents != outputText; } if (write) { File.WriteAllText(opts.OutputFile, outputText); return(true); } return(false); }