diff --git a/Directory.Build.props b/Directory.Build.props index 219d40d..f4e8d07 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,8 +1,8 @@ - 3.4.0 - 3.3.0 + 3.5.0 + 3.4.0 12.0 enable enable diff --git a/ReleaseNotes.md b/ReleaseNotes.md index ae0400a..d725b95 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -2,6 +2,10 @@ These are the NuGet package releases. See also [npm Release Notes](ReleaseNotesNpm.md). +## 3.5.0 + +* Add option to omit generated HTTP client. + ## 3.4.0 * Export generated HttpClient class, allowing the class to be extended. diff --git a/src/Facility.CodeGen.JavaScript/JavaScriptGenerator.cs b/src/Facility.CodeGen.JavaScript/JavaScriptGenerator.cs index 02a1665..7fb8837 100644 --- a/src/Facility.CodeGen.JavaScript/JavaScriptGenerator.cs +++ b/src/Facility.CodeGen.JavaScript/JavaScriptGenerator.cs @@ -39,6 +39,11 @@ public static int GenerateJavaScript(JavaScriptGeneratorSettings settings) => /// public bool TypeScript { get; set; } + /// + /// True to omit generated HTTP code. + /// + public bool NoHttp { get; set; } + /// /// True to generate Express service. /// @@ -137,248 +142,251 @@ public override CodeGenOutput GenerateOutput(ServiceInfo service) })); } - namedTexts.Add(CreateFile(clientFileName, code => + if (!NoHttp) { - WriteFileHeader(code); - - if (!TypeScript) - code.WriteLine("'use strict';"); - - code.WriteLine(); - var facilityImports = new List { "HttpClientUtility" }; - if (TypeScript) + namedTexts.Add(CreateFile(clientFileName, code => { - if (httpServiceInfo.Methods.Any()) - facilityImports.Add("IServiceResult"); - facilityImports.Add("IHttpClientOptions"); - } - WriteImports(code, facilityImports, "facility-core"); + WriteFileHeader(code); - if (TypeScript) - { - WriteImports(code, typeNames, $"./{typesFileNameNoExt}"); - code.WriteLine($"export * from './{typesFileNameNoExt}';"); - } + if (!TypeScript) + code.WriteLine("'use strict';"); - code.WriteLine(); - WriteJsDoc(code, $"Provides access to {capModuleName} over HTTP via fetch."); - using (code.Block("export function createHttpClient(options" + IfTypeScript(": IHttpClientOptions") + ")" + IfTypeScript($": I{capModuleName}") + " {", "}")) - code.WriteLine($"return new {capModuleName}HttpClient(options);"); + code.WriteLine(); + var facilityImports = new List { "HttpClientUtility" }; + if (TypeScript) + { + if (httpServiceInfo.Methods.Any()) + facilityImports.Add("IServiceResult"); + facilityImports.Add("IHttpClientOptions"); + } + WriteImports(code, facilityImports, "facility-core"); - code.WriteLine(); - code.WriteLine("const { fetchResponse, createResponseError, createRequiredRequestFieldError } = HttpClientUtility;"); - if (TypeScript) - { - code.WriteLine("type IFetch = HttpClientUtility.IFetch;"); - code.WriteLine("type IFetchRequest = HttpClientUtility.IFetchRequest;"); - } + if (TypeScript) + { + WriteImports(code, typeNames, $"./{typesFileNameNoExt}"); + code.WriteLine($"export * from './{typesFileNameNoExt}';"); + } + + code.WriteLine(); + WriteJsDoc(code, $"Provides access to {capModuleName} over HTTP via fetch."); + using (code.Block("export function createHttpClient(options" + IfTypeScript(": IHttpClientOptions") + ")" + IfTypeScript($": I{capModuleName}") + " {", "}")) + code.WriteLine($"return new {capModuleName}HttpClient(options);"); - // TODO: export this from facility-core? - if (httpServiceInfo.Methods.Any(x => x.RequestHeaderFields.Any(y => service.GetFieldType(y.ServiceField)!.Kind == ServiceTypeKind.Boolean))) - { code.WriteLine(); - using (code.Block("function parseBoolean(value" + IfTypeScript(": string | undefined") + ") {", "}")) + code.WriteLine("const { fetchResponse, createResponseError, createRequiredRequestFieldError } = HttpClientUtility;"); + if (TypeScript) { - using (code.Block("if (typeof value === 'string') {", "}")) - { - code.WriteLine("const lowerValue = value.toLowerCase();"); - using (code.Block("if (lowerValue === 'true') {", "}")) - code.WriteLine("return true;"); - using (code.Block("if (lowerValue === 'false') {", "}")) - code.WriteLine("return false;"); - } - code.WriteLine("return undefined;"); + code.WriteLine("type IFetch = HttpClientUtility.IFetch;"); + code.WriteLine("type IFetchRequest = HttpClientUtility.IFetchRequest;"); } - } - code.WriteLine(); - WriteJsDoc(code, $"Provides access to {capModuleName} over HTTP via fetch."); - using (code.Block($"export class {capModuleName}HttpClient" + IfTypeScript($" implements I{capModuleName}") + " {", "}")) - { - using (code.Block("constructor({ fetch, baseUri }" + IfTypeScript(": IHttpClientOptions") + ") {", "}")) + // TODO: export this from facility-core? + if (httpServiceInfo.Methods.Any(x => x.RequestHeaderFields.Any(y => service.GetFieldType(y.ServiceField)!.Kind == ServiceTypeKind.Boolean))) { - using (code.Block("if (typeof fetch !== 'function') {", "}")) - code.WriteLine("throw new TypeError('fetch must be a function.');"); - using (code.Block("if (typeof baseUri === 'undefined') {", "}")) - code.WriteLine($"baseUri = '{httpServiceInfo.Url ?? ""}';"); - using (code.Block(@"if (/[^\/]$/.test(baseUri)) {", "}")) - code.WriteLine("baseUri += '/';"); - - code.WriteLine("this._fetch = fetch;"); - code.WriteLine("this._baseUri = baseUri;"); + code.WriteLine(); + using (code.Block("function parseBoolean(value" + IfTypeScript(": string | undefined") + ") {", "}")) + { + using (code.Block("if (typeof value === 'string') {", "}")) + { + code.WriteLine("const lowerValue = value.toLowerCase();"); + using (code.Block("if (lowerValue === 'true') {", "}")) + code.WriteLine("return true;"); + using (code.Block("if (lowerValue === 'false') {", "}")) + code.WriteLine("return false;"); + } + code.WriteLine("return undefined;"); + } } - foreach (var httpMethodInfo in httpServiceInfo.Methods) + code.WriteLine(); + WriteJsDoc(code, $"Provides access to {capModuleName} over HTTP via fetch."); + using (code.Block($"export class {capModuleName}HttpClient" + IfTypeScript($" implements I{capModuleName}") + " {", "}")) { - var methodName = httpMethodInfo.ServiceMethod.Name; - var capMethodName = CodeGenUtility.Capitalize(methodName); + using (code.Block("constructor({ fetch, baseUri }" + IfTypeScript(": IHttpClientOptions") + ") {", "}")) + { + using (code.Block("if (typeof fetch !== 'function') {", "}")) + code.WriteLine("throw new TypeError('fetch must be a function.');"); + using (code.Block("if (typeof baseUri === 'undefined') {", "}")) + code.WriteLine($"baseUri = '{httpServiceInfo.Url ?? ""}';"); + using (code.Block(@"if (/[^\/]$/.test(baseUri)) {", "}")) + code.WriteLine("baseUri += '/';"); + + code.WriteLine("this._fetch = fetch;"); + code.WriteLine("this._baseUri = baseUri;"); + } - code.WriteLine(); - WriteJsDoc(code, httpMethodInfo.ServiceMethod); - using (code.Block(IfTypeScript("public ") + $"{methodName}(request" + IfTypeScript($": I{capMethodName}Request") + ", context" + IfTypeScript("?: unknown") + ")" + IfTypeScript($": Promise>") + " {", "}")) + foreach (var httpMethodInfo in httpServiceInfo.Methods) { - var hasPathFields = httpMethodInfo.PathFields.Count != 0; - var jsUriDelim = hasPathFields ? "`" : "'"; + var methodName = httpMethodInfo.ServiceMethod.Name; + var capMethodName = CodeGenUtility.Capitalize(methodName); + + code.WriteLine(); + WriteJsDoc(code, httpMethodInfo.ServiceMethod); + using (code.Block(IfTypeScript("public ") + $"{methodName}(request" + IfTypeScript($": I{capMethodName}Request") + ", context" + IfTypeScript("?: unknown") + ")" + IfTypeScript($": Promise>") + " {", "}")) + { + var hasPathFields = httpMethodInfo.PathFields.Count != 0; + var jsUriDelim = hasPathFields ? "`" : "'"; #if !NETSTANDARD2_0 - var jsUri = string.Concat(jsUriDelim, httpMethodInfo.Path.AsSpan(1), jsUriDelim); + var jsUri = string.Concat(jsUriDelim, httpMethodInfo.Path.AsSpan(1), jsUriDelim); #else - var jsUri = jsUriDelim + httpMethodInfo.Path.Substring(1) + jsUriDelim; + var jsUri = jsUriDelim + httpMethodInfo.Path.Substring(1) + jsUriDelim; #endif - if (hasPathFields) - { - foreach (var httpPathField in httpMethodInfo.PathFields) + if (hasPathFields) { - code.WriteLine($"const uriPart{CodeGenUtility.Capitalize(httpPathField.ServiceField.Name)} = request.{httpPathField.ServiceField.Name} != null && {RenderUriComponent(httpPathField.ServiceField, service)};"); - using (code.Block($"if (!uriPart{CodeGenUtility.Capitalize(httpPathField.ServiceField.Name)}) {{", "}")) - code.WriteLine($"return Promise.resolve(createRequiredRequestFieldError('{httpPathField.ServiceField.Name}'));"); + foreach (var httpPathField in httpMethodInfo.PathFields) + { + code.WriteLine($"const uriPart{CodeGenUtility.Capitalize(httpPathField.ServiceField.Name)} = request.{httpPathField.ServiceField.Name} != null && {RenderUriComponent(httpPathField.ServiceField, service)};"); + using (code.Block($"if (!uriPart{CodeGenUtility.Capitalize(httpPathField.ServiceField.Name)}) {{", "}")) + code.WriteLine($"return Promise.resolve(createRequiredRequestFieldError('{httpPathField.ServiceField.Name}'));"); + } + foreach (var httpPathField in httpMethodInfo.PathFields) + jsUri = ReplaceOrdinal(jsUri, "{" + httpPathField.Name + "}", $"${{uriPart{CodeGenUtility.Capitalize(httpPathField.ServiceField.Name)}}}"); } - foreach (var httpPathField in httpMethodInfo.PathFields) - jsUri = ReplaceOrdinal(jsUri, "{" + httpPathField.Name + "}", $"${{uriPart{CodeGenUtility.Capitalize(httpPathField.ServiceField.Name)}}}"); - } - - var hasQueryFields = httpMethodInfo.QueryFields.Count != 0; - code.WriteLine((hasQueryFields ? "let" : "const") + $" uri = {jsUri};"); - if (hasQueryFields) - { - code.WriteLine("const query" + IfTypeScript(": string[]") + " = [];"); - foreach (var httpQueryField in httpMethodInfo.QueryFields) - code.WriteLine($"request.{httpQueryField.ServiceField.Name} == null || query.push('{httpQueryField.Name}=' + {RenderUriComponent(httpQueryField.ServiceField, service)});"); - using (code.Block("if (query.length) {", "}")) - code.WriteLine("uri = uri + '?' + query.join('&');"); - } - if (httpMethodInfo.RequestBodyField != null) - { - using (code.Block($"if (!request.{httpMethodInfo.RequestBodyField.ServiceField.Name}) {{", "}")) - code.WriteLine($"return Promise.resolve(createRequiredRequestFieldError('{httpMethodInfo.RequestBodyField.ServiceField.Name}'));"); - } - - using (code.Block("const fetchRequest" + IfTypeScript(": IFetchRequest") + " = {", "};")) - { - if (httpMethodInfo.RequestBodyField == null && httpMethodInfo.RequestNormalFields.Count == 0) + var hasQueryFields = httpMethodInfo.QueryFields.Count != 0; + code.WriteLine((hasQueryFields ? "let" : "const") + $" uri = {jsUri};"); + if (hasQueryFields) { - code.WriteLine($"method: '{httpMethodInfo.Method}',"); - if (httpMethodInfo.RequestHeaderFields.Count != 0) - code.WriteLine("headers: {},"); + code.WriteLine("const query" + IfTypeScript(": string[]") + " = [];"); + foreach (var httpQueryField in httpMethodInfo.QueryFields) + code.WriteLine($"request.{httpQueryField.ServiceField.Name} == null || query.push('{httpQueryField.Name}=' + {RenderUriComponent(httpQueryField.ServiceField, service)});"); + using (code.Block("if (query.length) {", "}")) + code.WriteLine("uri = uri + '?' + query.join('&');"); } - else + + if (httpMethodInfo.RequestBodyField != null) { - code.WriteLine($"method: '{httpMethodInfo.Method}',"); - code.WriteLine("headers: { 'Content-Type': 'application/json' },"); + using (code.Block($"if (!request.{httpMethodInfo.RequestBodyField.ServiceField.Name}) {{", "}")) + code.WriteLine($"return Promise.resolve(createRequiredRequestFieldError('{httpMethodInfo.RequestBodyField.ServiceField.Name}'));"); + } - if (httpMethodInfo.RequestBodyField != null) - { - code.WriteLine($"body: JSON.stringify(request.{httpMethodInfo.RequestBodyField.ServiceField.Name})"); - } - else if (httpMethodInfo.ServiceMethod.RequestFields.Count == httpMethodInfo.RequestNormalFields.Count) + using (code.Block("const fetchRequest" + IfTypeScript(": IFetchRequest") + " = {", "};")) + { + if (httpMethodInfo.RequestBodyField == null && httpMethodInfo.RequestNormalFields.Count == 0) { - code.WriteLine("body: JSON.stringify(request)"); + code.WriteLine($"method: '{httpMethodInfo.Method}',"); + if (httpMethodInfo.RequestHeaderFields.Count != 0) + code.WriteLine("headers: {},"); } else { - using (code.Block("body: JSON.stringify({", "})")) + code.WriteLine($"method: '{httpMethodInfo.Method}',"); + code.WriteLine("headers: { 'Content-Type': 'application/json' },"); + + if (httpMethodInfo.RequestBodyField != null) + { + code.WriteLine($"body: JSON.stringify(request.{httpMethodInfo.RequestBodyField.ServiceField.Name})"); + } + else if (httpMethodInfo.ServiceMethod.RequestFields.Count == httpMethodInfo.RequestNormalFields.Count) { - for (var httpFieldIndex = 0; httpFieldIndex < httpMethodInfo.RequestNormalFields.Count; httpFieldIndex++) + code.WriteLine("body: JSON.stringify(request)"); + } + else + { + using (code.Block("body: JSON.stringify({", "})")) { - var httpFieldInfo = httpMethodInfo.RequestNormalFields[httpFieldIndex]; - var isLastField = httpFieldIndex == httpMethodInfo.RequestNormalFields.Count - 1; - var fieldName = httpFieldInfo.ServiceField.Name; - code.WriteLine(fieldName + ": request." + fieldName + (isLastField ? "" : ",")); + for (var httpFieldIndex = 0; httpFieldIndex < httpMethodInfo.RequestNormalFields.Count; httpFieldIndex++) + { + var httpFieldInfo = httpMethodInfo.RequestNormalFields[httpFieldIndex]; + var isLastField = httpFieldIndex == httpMethodInfo.RequestNormalFields.Count - 1; + var fieldName = httpFieldInfo.ServiceField.Name; + code.WriteLine(fieldName + ": request." + fieldName + (isLastField ? "" : ",")); + } } } } } - } - if (httpMethodInfo.RequestHeaderFields.Count != 0) - { - foreach (var httpHeaderField in httpMethodInfo.RequestHeaderFields) + if (httpMethodInfo.RequestHeaderFields.Count != 0) { - using (code.Block($"if (request.{httpHeaderField.ServiceField.Name} != null) {{", "}")) - code.WriteLine("fetchRequest.headers" + IfTypeScript("!") + $"['{httpHeaderField.Name}'] = {RenderFieldValue(httpHeaderField.ServiceField, service, $"request.{httpHeaderField.ServiceField.Name}")};"); + foreach (var httpHeaderField in httpMethodInfo.RequestHeaderFields) + { + using (code.Block($"if (request.{httpHeaderField.ServiceField.Name} != null) {{", "}")) + code.WriteLine("fetchRequest.headers" + IfTypeScript("!") + $"['{httpHeaderField.Name}'] = {RenderFieldValue(httpHeaderField.ServiceField, service, $"request.{httpHeaderField.ServiceField.Name}")};"); + } } - } - code.WriteLine("return fetchResponse(this._fetch, this._baseUri + uri, fetchRequest, context)"); - using (code.Indent()) - using (code.Block(".then(result => {", "});")) - { - code.WriteLine("const status = result.response.status;"); - var responseValueType = $"I{capMethodName}Response"; - code.WriteLine("let value" + IfTypeScript($": {responseValueType} | null") + " = null;"); - var validResponses = httpMethodInfo.ValidResponses; - var elsePrefix = ""; - foreach (var validResponse in validResponses) + code.WriteLine("return fetchResponse(this._fetch, this._baseUri + uri, fetchRequest, context)"); + using (code.Indent()) + using (code.Block(".then(result => {", "});")) { - var statusCodeAsString = ((int) validResponse.StatusCode).ToString(CultureInfo.InvariantCulture); - code.WriteLine($"{elsePrefix}if (status === {statusCodeAsString}) {{"); - elsePrefix = "else "; - - using (code.Indent()) + code.WriteLine("const status = result.response.status;"); + var responseValueType = $"I{capMethodName}Response"; + code.WriteLine("let value" + IfTypeScript($": {responseValueType} | null") + " = null;"); + var validResponses = httpMethodInfo.ValidResponses; + var elsePrefix = ""; + foreach (var validResponse in validResponses) { - var bodyField = validResponse.BodyField; - if (bodyField != null) - { - var responseBodyFieldName = bodyField.ServiceField.Name; + var statusCodeAsString = ((int) validResponse.StatusCode).ToString(CultureInfo.InvariantCulture); + code.WriteLine($"{elsePrefix}if (status === {statusCodeAsString}) {{"); + elsePrefix = "else "; - var bodyFieldType = service.GetFieldType(bodyField.ServiceField)!; - if (bodyFieldType.Kind == ServiceTypeKind.Boolean) - { - code.WriteLine($"value = {{ {responseBodyFieldName}: true }};"); - } - else + using (code.Indent()) + { + var bodyField = validResponse.BodyField; + if (bodyField != null) { - using (code.Block("if (result.json) {", "}")) + var responseBodyFieldName = bodyField.ServiceField.Name; + + var bodyFieldType = service.GetFieldType(bodyField.ServiceField)!; + if (bodyFieldType.Kind == ServiceTypeKind.Boolean) { - code.WriteLine($"value = {{ {responseBodyFieldName}: result.json }}" + IfTypeScript($" as {responseValueType}") + ";"); + code.WriteLine($"value = {{ {responseBodyFieldName}: true }};"); + } + else + { + using (code.Block("if (result.json) {", "}")) + { + code.WriteLine($"value = {{ {responseBodyFieldName}: result.json }}" + IfTypeScript($" as {responseValueType}") + ";"); + } } - } - } - else - { - if (validResponse.NormalFields!.Count == 0) - { - code.WriteLine("value = {};"); } else { - using (code.Block("if (result.json) {", "}")) + if (validResponse.NormalFields!.Count == 0) + { + code.WriteLine("value = {};"); + } + else { - code.WriteLine("value = result.json" + IfTypeScript($" as {responseValueType} | null") + ";"); + using (code.Block("if (result.json) {", "}")) + { + code.WriteLine("value = result.json" + IfTypeScript($" as {responseValueType} | null") + ";"); + } } } } + code.WriteLine("}"); } - code.WriteLine("}"); - } - using (code.Block("if (!value) {", "}")) - code.WriteLine("return createResponseError(status, result.json)" + IfTypeScript($" as IServiceResult") + ";"); + using (code.Block("if (!value) {", "}")) + code.WriteLine("return createResponseError(status, result.json)" + IfTypeScript($" as IServiceResult") + ";"); - if (httpMethodInfo.ResponseHeaderFields.Count != 0) - { - code.WriteLine("let headerValue" + IfTypeScript(": string | null | undefined") + ";"); - foreach (var httpHeaderField in httpMethodInfo.ResponseHeaderFields) + if (httpMethodInfo.ResponseHeaderFields.Count != 0) { - code.WriteLine($"headerValue = result.response.headers.get('{httpHeaderField.Name}');"); - using (code.Block("if (headerValue != null) {", "}")) - code.WriteLine($"value.{httpHeaderField.ServiceField.Name} = {ParseFieldValue(httpHeaderField.ServiceField, service, "headerValue")};"); + code.WriteLine("let headerValue" + IfTypeScript(": string | null | undefined") + ";"); + foreach (var httpHeaderField in httpMethodInfo.ResponseHeaderFields) + { + code.WriteLine($"headerValue = result.response.headers.get('{httpHeaderField.Name}');"); + using (code.Block("if (headerValue != null) {", "}")) + code.WriteLine($"value.{httpHeaderField.ServiceField.Name} = {ParseFieldValue(httpHeaderField.ServiceField, service, "headerValue")};"); + } } - } - code.WriteLine("return { value: value };"); + code.WriteLine("return { value: value };"); + } } } - } - if (TypeScript) - { - code.WriteLine(); - code.WriteLine("private _fetch: IFetch;"); - code.WriteLine("private _baseUri: string;"); + if (TypeScript) + { + code.WriteLine(); + code.WriteLine("private _fetch: IFetch;"); + code.WriteLine("private _baseUri: string;"); + } } - } - })); + })); + } if (Express) { @@ -548,6 +556,7 @@ public override void ApplySettings(FileGeneratorSettings settings) Fastify = ourSettings.Fastify; DisableESLint = ourSettings.DisableESLint; FileNameSuffix = ourSettings.FileNameSuffix; + NoHttp = ourSettings.NoHttp; } /// diff --git a/src/Facility.CodeGen.JavaScript/JavaScriptGeneratorSettings.cs b/src/Facility.CodeGen.JavaScript/JavaScriptGeneratorSettings.cs index 6261b86..02867b4 100644 --- a/src/Facility.CodeGen.JavaScript/JavaScriptGeneratorSettings.cs +++ b/src/Facility.CodeGen.JavaScript/JavaScriptGeneratorSettings.cs @@ -17,6 +17,11 @@ public sealed class JavaScriptGeneratorSettings : FileGeneratorSettings /// public bool TypeScript { get; set; } + /// + /// True to omit generated HTTP client code. + /// + public bool NoHttp { get; set; } + /// /// True to generate Express service. /// diff --git a/src/fsdgenjs/FsdGenJavaScriptApp.cs b/src/fsdgenjs/FsdGenJavaScriptApp.cs index 7f12b28..e00a215 100644 --- a/src/fsdgenjs/FsdGenJavaScriptApp.cs +++ b/src/fsdgenjs/FsdGenJavaScriptApp.cs @@ -27,6 +27,8 @@ public sealed class FsdGenJavaScriptApp : CodeGeneratorApp " Generates a Fastify plugin. When specified, only the server plugin is generated, not the client. EXPERIMENTAL: This option is subject to change/removal without a major version bump.", " --disable-eslint", " Disables ESLint via code comment.", + " --no-http", + " Omits generated HTTP client code.", " --file-name-suffix", " Suffix to append to generated file names before the file extension.", ]; @@ -40,6 +42,7 @@ protected override FileGeneratorSettings CreateSettings(ArgsReader args) => { ModuleName = args.ReadOption("module"), TypeScript = args.ReadFlag("typescript"), + NoHttp = args.ReadFlag("no-http"), Express = args.ReadFlag("express"), Fastify = args.ReadFlag("fastify"), DisableESLint = args.ReadFlag("disable-eslint"), diff --git a/tests/Facility.CodeGen.JavaScript.UnitTests/JavaScriptGeneratorTests.cs b/tests/Facility.CodeGen.JavaScript.UnitTests/JavaScriptGeneratorTests.cs index c68c861..1f2482a 100644 --- a/tests/Facility.CodeGen.JavaScript.UnitTests/JavaScriptGeneratorTests.cs +++ b/tests/Facility.CodeGen.JavaScript.UnitTests/JavaScriptGeneratorTests.cs @@ -140,6 +140,58 @@ public void GenerateExampleApiTypeScript_ExternDataWithNameAndModuel() Assert.That(typesFile.Text, Does.Contain("thing?: IThing;")); } + [Test] + public void GenerateExampleApiTypeScript_OmitHttpClient() + { + ServiceInfo service; + const string fileName = "Facility.CodeGen.JavaScript.UnitTests.ExampleApi.fsd"; + var parser = CreateParser(); + var stream = GetType().GetTypeInfo().Assembly.GetManifestResourceStream(fileName)!; + Assert.That(stream, Is.Not.Null); + using (var reader = new StreamReader(stream)) + service = parser.ParseDefinition(new ServiceDefinitionText(Path.GetFileName(fileName), reader.ReadToEnd())); + + var generator = new JavaScriptGenerator + { + GeneratorName = "JavaScriptGeneratorTests", + TypeScript = true, + NoHttp = true, + NewLine = "\n", + }; + var result = generator.GenerateOutput(service); + Assert.That(result, Is.Not.Null); + + var files = result.Files.Select(x => x.Name).ToList(); + Assert.That(files, Does.Not.Contain("exampleApi.ts")); + Assert.That(files, Does.Contain("exampleApiTypes.ts")); + } + + [Test] + public void GenerateExampleApiTypeScript_OmitHttpClientWithExpress() + { + ServiceInfo service; + const string fileName = "Facility.CodeGen.JavaScript.UnitTests.ExampleApi.fsd"; + var parser = CreateParser(); + var stream = GetType().GetTypeInfo().Assembly.GetManifestResourceStream(fileName)!; + Assert.That(stream, Is.Not.Null); + using (var reader = new StreamReader(stream)) + service = parser.ParseDefinition(new ServiceDefinitionText(Path.GetFileName(fileName), reader.ReadToEnd())); + + var generator = new JavaScriptGenerator + { + GeneratorName = "JavaScriptGeneratorTests", + TypeScript = true, + NoHttp = true, + Express = true, + NewLine = "\n", + }; + var result = generator.GenerateOutput(service); + Assert.That(result, Is.Not.Null); + + var expressServerContents = result.Files.Single(x => x.Name == "exampleApiServer.ts"); + Assert.That(expressServerContents.Text, Does.Not.Contain("from 'exampleApi';")); + } + [Test] public void GenerateExampleApiTypeScript_ExternDataWithoutJsAttribute() {