예제 #1
0
 void IDisposable.Dispose()
 {
     if (_owner != null && _indent)
     {
         _owner._indentLevel--;
     }
     _owner = null;
 }
예제 #2
0
 public Indenter(TypeScriptWriter owner, bool indent)
 {
     _owner  = owner;
     _indent = indent;
     if (indent)
     {
         _owner._indentLevel++;
     }
 }
예제 #3
0
        private void OutputTypeConversion(TypeScriptWriter writer, string lvalue, ApiTypeDesc type, bool toTypeScript)
        {
            var converter = getConverter(type);

            if (converter == null)
            {
                return;
            }
            MarkUsedConverters(converter, toTypeScript);
            writer.WriteLine($"if ({lvalue})");
            using (writer.Indent())
                writer.WriteLine($"{lvalue} = this.{converter.FunctionName(toTypeScript)}({lvalue});");
        }
예제 #4
0
 protected void OutputInterface(TypeScriptWriter writer, ApiInterfaceDesc i)
 {
     writer.Write($"interface {getName(i.TsName)}");
     if (i.Extends.Any())
     {
         writer.Write(" extends ");
         writer.Write(i.Extends.Select(e => getNamespace(e.TsName) == getNamespace(i.TsName) ? getName(e.TsName) : e.TsName).Order().JoinString(", "));
     }
     writer.WriteLine(" {");
     using (writer.Indent())
     {
         foreach (var prop in i.Properties.OrderBy(p => p.TsName))
         {
             writer.WriteLine($"{prop.TsName}: {prop.TsType.GetTypeScript()};");
         }
     }
     writer.WriteLine("}");
 }
예제 #5
0
 protected void OutputEnum(TypeScriptWriter writer, ApiEnumDesc e)
 {
     writer.WriteLine($"type {getName(e.TsName)} = {e.Values.Select(v => v.TsName).Order().JoinString(" | ", "\"", "\"")};");
 }
예제 #6
0
        public void Output(TypeScriptWriter writer, ApiDesc api)
        {
            writer.WriteLine("// AUTOGENERATED FILE - any manual changes will be lost");
            writer.WriteLine();
            if (api.Imports.Count > 0)
            {
                foreach (var import in api.Imports.Order())
                {
                    writer.WriteLine(import);
                }
                writer.WriteLine();
            }
            writer.WriteLine("declare global {");
            writer.WriteLine();
            using (writer.Indent())
            {
                var namespaces = api.Interfaces.Values.Select(i => getNamespace(i.TsName)).Concat(api.Enums.Values.Select(e => getNamespace(e.TsName))).Distinct().Order();
                foreach (var ns in new string[] { null }.Concat(namespaces))
                {
                    var enums      = api.Enums.Values.Where(e => getNamespace(e.TsName) == ns).OrderBy(e => e.TsName).ToList();
                    var interfaces = api.Interfaces.Values.Where(i => getNamespace(i.TsName) == ns).OrderBy(e => e.TsName).ToList();
                    if (enums.Count == 0 && interfaces.Count == 0)
                    {
                        continue;
                    }
                    if (ns != null)
                    {
                        writer.WriteLine($"namespace {ns} {{");
                        writer.WriteLine();
                    }
                    using (writer.Indent(ns != null))
                    {
                        foreach (var e in enums)
                        {
                            OutputEnum(writer, e);
                            writer.WriteLine();
                        }
                        foreach (var i in interfaces)
                        {
                            OutputInterface(writer, i);
                            writer.WriteLine();
                        }
                    }
                    if (ns != null)
                    {
                        writer.WriteLine("}");
                        writer.WriteLine();
                    }
                }
            }
            writer.WriteLine("}");
            writer.WriteLine();

            writer.WriteLine("export class Services {");
            using (writer.Indent())
            {
                foreach (var svc in api.Services.OrderBy(s => s.Name))
                {
                    writer.WriteLine($"public readonly {svc.Name}: {svc.Name}Service;");
                }
                writer.WriteLine();
                writer.WriteLine("public constructor(hostname: string) {");
                using (writer.Indent())
                {
                    foreach (var svc in api.Services.OrderBy(s => s.Name))
                    {
                        writer.WriteLine($"this.{svc.Name} = new {svc.Name}Service(hostname);");
                    }
                }
                writer.WriteLine("}");
            }
            writer.WriteLine("}");
            writer.WriteLine();
            foreach (var svc in api.Services.OrderBy(s => s.Name))
            {
                OutputService(writer, svc);
                writer.WriteLine();
            }
        }
예제 #7
0
        protected void OutputService(TypeScriptWriter writer, ApiServiceDesc s)
        {
            _convertersUsedFrom = new HashSet <TypeConverter>();
            _convertersUsedTo   = new HashSet <TypeConverter>();
            writer.WriteLine($"export class {s.Name}Service extends ApiServiceBase {{");
            writer.WriteLine();
            using (writer.Indent())
            {
                writer.WriteLine("private _hostname: string;");
                writer.WriteLine();
                writer.WriteLine("public constructor(hostname: string) {");
                using (writer.Indent())
                {
                    writer.WriteLine("super();");
                    writer.WriteLine("this._hostname = (hostname.substr(-1) == '/') ? hostname : hostname + '/';");
                }
                writer.WriteLine("}");
                writer.WriteLine();
                foreach (var method in s.Methods.OrderBy(m => m.TsName))
                {
                    foreach (var httpMethod in method.HttpMethods.Order())
                    {
                        bool canDirectReturn = getConverter(method.TsReturnType) == null;
                        writer.Write($"public {(canDirectReturn ? "" : "async ")}{getMethodName(method, httpMethod)}(");
                        bool first = true;
                        foreach (var p in method.Parameters)
                        {
                            if (!first)
                            {
                                writer.Write(", ");
                            }
                            writer.Write($"{p.TsName}: {p.TsType.GetTypeScript()}");
                            first = false;
                        }
                        writer.WriteLine($"): {string.Format(ReturnTypeTemplate, method.TsReturnType.GetTypeScript())} {{");
                        using (writer.Indent())
                        {
                            var  url    = method.UrlPath;
                            bool first2 = true;
                            foreach (var p in method.Parameters.Where(p => p.Location == ParameterLocation.QueryString).OrderBy(p => p.TsName))
                            {
                                url   += (first2 ? '?' : '&') + p.TsName + "=${encodeURIComponent('' + " + p.TsName + ")}";
                                first2 = false;
                            }
                            writer.WriteLine($"let url = this._hostname + `{url}`;");

                            // Output parameter type conversions
                            foreach (var p in method.Parameters)
                            {
                                OutputTypeConversion(writer, p.TsName, p.TsType, toTypeScript: false);
                            }

                            // Build request body
                            var bodyParams = method.Parameters.Where(p => p.Location == ParameterLocation.RequestBody).OrderBy(p => p.TsName).ToList();
                            if (bodyParams.Count > 0 && httpMethod == "GET")
                            {
                                throw new InvalidOperationException($"GET requests must not have any body parameters. Offending parameter: {bodyParams[0].TsName}, method {method.Method.Name}, controller {s.Controller.FullName}");
                            }
                            if (bodyParams.Count > 1 && (method.BodyEncoding == BodyEncoding.Raw || method.BodyEncoding == BodyEncoding.Json))
                            {
                                throw new InvalidOperationException($"The body encoding for this method allows for at most one body parameter. Offending parameters: [{bodyParams.Select(p => p.TsName).JoinString(", ")}], method {method.Method.Name}, controller {s.Controller.FullName}");
                            }
                            var bodyCode = "";
                            if (bodyParams.Count > 0)
                            {
                                if (method.BodyEncoding == BodyEncoding.Raw)
                                {
                                    bodyCode = $", body: {bodyParams[0].TsName}";
                                }
                                else if (method.BodyEncoding == BodyEncoding.Json)
                                {
                                    bodyCode = $", body: JSON.stringify({bodyParams[0].TsName}), headers: {{ 'Content-Type': 'application/json' }}";
                                }
                                else if (method.BodyEncoding == BodyEncoding.FormUrlEncoded)
                                {
                                    writer.WriteLine("let __body = new URLSearchParams();");
                                    foreach (var bp in bodyParams)
                                    {
                                        writer.WriteLine($"__body.append('{bp.TsName}', '' + {bp.TsName});");
                                    }
                                    bodyCode = ", body: __body";
                                }
                                else if (method.BodyEncoding == BodyEncoding.MultipartFormData)
                                {
                                    writer.WriteLine("let __body = new FormData();");
                                    foreach (var bp in bodyParams)
                                    {
                                        writer.WriteLine($"__body.append('{bp.TsName}', '' + {bp.TsName});");
                                    }
                                    bodyCode = ", body: __body";
                                    throw new NotImplementedException("FormData encoding is not fully implemented."); // no support for file name, parameter is always stringified with no support for Blob
                                }
                                else
                                {
                                    throw new Exception($"Unexpected {nameof(method.BodyEncoding)}: {method.BodyEncoding}");
                                }
                            }

                            // Output call
                            var sendCookies = s.SendCookies == SendCookies.Always ? "include" : s.SendCookies == SendCookies.SameOriginOnly ? "same-origin" : s.SendCookies == SendCookies.Never ? "omit" : throw new Exception();
                            if (canDirectReturn)
                            {
                                writer.Write("return ");
                            }
                            else
                            {
                                writer.Write("let result = await ");
                            }
                            writer.WriteLine($"this.{httpMethod}<{method.TsReturnType.GetTypeScript()}>(url, {{ credentials: '{sendCookies}'{bodyCode} }});");

                            if (!canDirectReturn)
                            {
                                // Output return type conversion
                                OutputTypeConversion(writer, "result", method.TsReturnType, toTypeScript: true);

                                writer.WriteLine("return result;");
                            }
                        }
                        writer.WriteLine("}");
                        writer.WriteLine();
                    }
                }

                // Output type converters
                foreach (var tc in _typeConverters.Values.Where(c => c != null).OrderBy(c => c.ForType.GetHash()))
                {
                    if (_convertersUsedFrom.Contains(tc))
                    {
                        writer.WriteLine($"private {tc.FunctionName(toTypeScript: false)}(val: {tc.ForType.GetTypeScript()}): any {{");
                        using (writer.Indent())
                            tc.WriteFunctionBody(writer, false);
                        writer.WriteLine("}");
                        writer.WriteLine();
                    }
                    if (_convertersUsedTo.Contains(tc))
                    {
                        writer.WriteLine($"private {tc.FunctionName(toTypeScript: true)}(val: any): {tc.ForType.GetTypeScript()} {{");
                        using (writer.Indent())
                            tc.WriteFunctionBody(writer, true);
                        writer.WriteLine("}");
                        writer.WriteLine();
                    }
                }
            }
            writer.WriteLine("}");
        }