Example #1
0
        public string GetCode(MetadataTypes metadata, IRequest request, INativeTypesMetadata nativeTypes)
        {
            var typeNamespaces = new HashSet <string>();
            var includeList    = 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;

            string defaultValue(string 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.VersionString));
            sb.AppendLine("Tip: {0}".Fmt(HelpMessages.NativeTypesDtoOptionsTip.Fmt("//")));
            sb.AppendLine("BaseUrl: {0}".Fmt(Config.BaseUrl));
            if (Config.UsePath != null)
            {
                sb.AppendLine("UsePath: {0}".Fmt(Config.UsePath));
            }

            sb.AppendLine();
            sb.AppendLine("{0}GlobalNamespace: {1}".Fmt(defaultValue("GlobalNamespace"), Config.GlobalNamespace));

            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();
            var types = metadata.Types.CreateSortedTypeList();

            AllTypes = metadata.GetAllTypesOrdered();
            AllTypes.RemoveAll(x => x.IgnoreType(Config, includeList));
            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);

            foreach (var import in defaultImports)
            {
                var pos = import.IndexOf(':');
                sb.AppendLine(pos == -1
                    ? $"import {import};"
                    : $"import {{ {import.Substring(0, pos)} }} from \"{import.Substring(pos + 1).StripQuotes()}\";");
            }

            if (!string.IsNullOrEmpty(globalNamespace))
            {
                var moduleDef = Config.ExportAsTypes ? "export " : "declare ";
                sb.AppendLine();
                sb.AppendLine("{0}module {1}".Fmt(moduleDef, globalNamespace.SafeToken()));
                sb.AppendLine("{");

                sb = sb.Indent();
            }

            var insertCode = InsertCodeFilter?.Invoke(AllTypes, Config);

            if (insertCode != null)
            {
                sb.AppendLine(insertCode);
            }

            //ServiceStack core interfaces
            foreach (var type in AllTypes)
            {
                var fullTypeName = type.GetFullName();
                if (requestTypes.Contains(type))
                {
                    if (!existingTypes.Contains(fullTypeName))
                    {
                        MetadataType response = null;
                        if (requestTypesMap.TryGetValue(type, out var operation))
                        {
                            response = operation.Response;
                        }

                        lastNS = AppendType(ref sb, type, lastNS,
                                            new CreateTypeOptions
                        {
                            Routes       = metadata.Operations.GetRoutes(type),
                            ImplementsFn = () =>
                            {
                                if (!Config.AddReturnMarker &&
                                    operation?.ReturnsVoid != true &&
                                    operation?.ReturnType == null)
                                {
                                    return(null);
                                }

                                if (operation?.ReturnsVoid == true)
                                {
                                    return(nameof(IReturnVoid));
                                }
                                if (operation?.ReturnType != null)
                                {
                                    return(Type("IReturn`1", new[] { Type(operation.ReturnType) }));
                                }
                                return(response != null
                                        ? Type("IReturn`1", new[] { Type(response.Name, response.GenericArgs) })
                                        : 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);
                }
            }

            var addCode = AddCodeFilter?.Invoke(AllTypes, Config);

            if (addCode != null)
            {
                sb.AppendLine(addCode);
            }

            if (!string.IsNullOrEmpty(globalNamespace))
            {
                sb = sb.UnIndent();
                sb.AppendLine();
                sb.AppendLine("}");
            }

            sb.AppendLine(); //tslint

            return(StringBuilderCache.ReturnAndFree(sbInner));
        }