public string GetCode(MetadataTypes metadata, IRequest request, INativeTypesMetadata nativeTypes)
{
var typeNamespaces = new HashSet<string>();
metadata.RemoveIgnoredTypes(Config);
metadata.Types.Each(x => typeNamespaces.Add(x.Namespace));
metadata.Operations.Each(x => typeNamespaces.Add(x.Request.Namespace));
var defaultImports = !Config.DefaultImports.IsEmpty()
? Config.DefaultImports
: DefaultImports;
var globalNamespace = Config.GlobalNamespace;
Func<string, string> defaultValue = k =>
request.QueryString[k].IsNullOrEmpty() ? "//" : "";
var sbInner = StringBuilderCache.Allocate();
var sb = new StringBuilderWrapper(sbInner);
sb.AppendLine("/* Options:");
sb.AppendLine("Date: {0}".Fmt(DateTime.Now.ToString("s").Replace("T", " ")));
sb.AppendLine("Version: {0}".Fmt(Env.ServiceStackVersion));
sb.AppendLine("Tip: {0}".Fmt(HelpMessages.NativeTypesDtoOptionsTip.Fmt("//")));
sb.AppendLine("BaseUrl: {0}".Fmt(Config.BaseUrl));
sb.AppendLine();
sb.AppendLine("{0}GlobalNamespace: {1}".Fmt(defaultValue("GlobalNamespace"), Config.GlobalNamespace));
//sb.AppendLine("{0}ExportAsTypes: {1}".Fmt(defaultValue("ExportAsTypes"), Config.ExportAsTypes));
sb.AppendLine("{0}MakePropertiesOptional: {1}".Fmt(defaultValue("MakePropertiesOptional"), Config.MakePropertiesOptional));
sb.AppendLine("{0}AddServiceStackTypes: {1}".Fmt(defaultValue("AddServiceStackTypes"), Config.AddServiceStackTypes));
sb.AppendLine("{0}AddResponseStatus: {1}".Fmt(defaultValue("AddResponseStatus"), Config.AddResponseStatus));
sb.AppendLine("{0}AddImplicitVersion: {1}".Fmt(defaultValue("AddImplicitVersion"), Config.AddImplicitVersion));
sb.AppendLine("{0}AddDescriptionAsComments: {1}".Fmt(defaultValue("AddDescriptionAsComments"), Config.AddDescriptionAsComments));
sb.AppendLine("{0}IncludeTypes: {1}".Fmt(defaultValue("IncludeTypes"), Config.IncludeTypes.Safe().ToArray().Join(",")));
sb.AppendLine("{0}ExcludeTypes: {1}".Fmt(defaultValue("ExcludeTypes"), Config.ExcludeTypes.Safe().ToArray().Join(",")));
sb.AppendLine("{0}DefaultImports: {1}".Fmt(defaultValue("DefaultImports"), defaultImports.Join(",")));
sb.AppendLine("*/");
sb.AppendLine();
string lastNS = null;
var existingTypes = new HashSet<string>();
var requestTypes = metadata.Operations.Select(x => x.Request).ToHashSet();
var requestTypesMap = metadata.Operations.ToSafeDictionary(x => x.Request);
var responseTypes = metadata.Operations
.Where(x => x.Response != null)
.Select(x => x.Response).ToHashSet();
// Base Types need to be written first
var types = CreateSortedTypeList(metadata.Types);
allTypes = new List<MetadataType>();
allTypes.AddRange(types);
allTypes.AddRange(responseTypes);
allTypes.AddRange(requestTypes);
allTypes.RemoveAll(x => x.IgnoreType(Config));
allTypes = FilterTypes(allTypes);
//TypeScript doesn't support reusing same type name with different generic airity
var conflictPartialNames = allTypes.Map(x => x.Name).Distinct()
.GroupBy(g => g.LeftPart('`'))
.Where(g => g.Count() > 1)
.Select(g => g.Key)
.ToList();
this.conflictTypeNames = allTypes
.Where(x => conflictPartialNames.Any(name => x.Name.StartsWith(name)))
.Map(x => x.Name);
defaultImports.Each(x => sb.AppendLine("import {0};".Fmt(x)));
if (!string.IsNullOrEmpty(globalNamespace))
{
var moduleDef = Config.ExportAsTypes ? "" : "declare ";
sb.AppendLine();
sb.AppendLine("{0}module {1}".Fmt(moduleDef, globalNamespace.SafeToken()));
sb.AppendLine("{");
sb = sb.Indent();
}
//ServiceStack core interfaces
foreach (var type in allTypes)
{
var fullTypeName = type.GetFullName();
if (requestTypes.Contains(type))
{
if (!existingTypes.Contains(fullTypeName))
{
MetadataType response = null;
MetadataOperationType operation;
if (requestTypesMap.TryGetValue(type, out operation))
{
response = operation.Response;
}
lastNS = AppendType(ref sb, type, lastNS,
new CreateTypeOptions
{
ImplementsFn = () =>
{
if (!Config.AddReturnMarker
&& !type.ReturnVoidMarker
&& type.ReturnMarkerTypeName == null)
return null;
if (type.ReturnVoidMarker)
return "IReturnVoid";
if (type.ReturnMarkerTypeName != null)
return Type("IReturn`1", new[] { Type(type.ReturnMarkerTypeName).InDeclarationType() });
return response != null
? Type("IReturn`1", new[] { Type(response.Name, response.GenericArgs).InDeclarationType() })
: null;
},
IsRequest = true,
});
existingTypes.Add(fullTypeName);
}
}
else if (responseTypes.Contains(type))
{
if (!existingTypes.Contains(fullTypeName)
&& !Config.IgnoreTypesInNamespaces.Contains(type.Namespace))
{
lastNS = AppendType(ref sb, type, lastNS,
new CreateTypeOptions
{
IsResponse = true,
});
existingTypes.Add(fullTypeName);
}
}
else if (types.Contains(type) && !existingTypes.Contains(fullTypeName))
{
lastNS = AppendType(ref sb, type, lastNS,
new CreateTypeOptions { IsType = true });
existingTypes.Add(fullTypeName);
}
}
if (!string.IsNullOrEmpty(globalNamespace))
{
sb = sb.UnIndent();
sb.AppendLine();
sb.AppendLine("}");
}
return StringBuilderCache.ReturnAndFree(sbInner);
}