RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.76k stars 1.29k forks source link

Typescript Generator Generating return _observableOf(null); -- failing typescript build #3575

Closed mbrennan376 closed 3 years ago

mbrennan376 commented 3 years ago

ASP.NET Core 3.1 NSwag 13.12.1 Angular 11 Typescript 4.1 Rxjs 6.6

I am generating typescript only via MSBuild referring to the project file

All of my generated process methods end with return _observableOf(null);

`

    let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }}
    let _mappings: { source: any, target: any }[] = [];
    if (status === 200) {
        return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => {
        let result200: any = null;
        let resultData200 = _responseText === "" ? null : jsonParse(_responseText, this.jsonParseReviver);
        result200 = Foo.fromJS(resultData200, _mappings);
        return _observableOf(result200);
        }));
    } else if (status === 404) {
        return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => {
        let result404: any = null;
        let resultData404 = _responseText === "" ? null : jsonParse(_responseText, this.jsonParseReviver);
        result404 = ProblemDetails.fromJS(resultData404, _mappings);
        return throwException("A server side error occurred.", status, _responseText, _headers, result404);
        }));
    } else if (status === 500) {
        return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => {
        return throwException("A server side error occurred.", status, _responseText, _headers);
        }));
    } else if (status !== 200 && status !== 204) {
        return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => {
        return throwException("An unexpected server error occurred.", status, _responseText, _headers);
        }));
    }
    return _observableOf(null);     **<--- THIS LINE HERE**
}`

so my ng build fails

An example of how I defined my API method:

[ProducesResponseType(typeof(Foo), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [HttpGet("{ID}")] public async Task<ActionResult<Foo>> GetFooAsync(int ID) { Do STUFF }

IF I edit my generated file to be return _observableOf(new Foo); ng build works. I would be happy to throw an exception if it gets to this part of the code, as the path will likely never be hit.

All other searches on this topic seem to indicate that I am not defining my service correctly, but I can not see what I am missing. How do I tell NSwag that my return DTO can not be set to null?

attached is my nswag.json

` { "runtime": "NetCore31", "defaultVariables": "key1=1,key2=2", "documentGenerator": { "aspNetCoreToOpenApi": { "project": "../BAR.csproj", "msBuildProjectExtensionsPath": null, "configuration": null, "runtime": "", "targetFramework": "", "noBuild": true, "verbose": true, "workingDirectory": null, "requireParametersWithoutDefault": true, "apiGroupNames": null, "defaultPropertyNameHandling": "CamelCase", "defaultReferenceTypeNullHandling": "Null", "defaultDictionaryValueReferenceTypeNullHandling": "NotNull", "defaultResponseReferenceTypeNullHandling": "NotNull", "defaultEnumHandling": "Integer", "flattenInheritanceHierarchy": false, "generateKnownTypes": true, "generateEnumMappingDescription": false, "generateXmlObjects": false, "generateAbstractProperties": true, "generateAbstractSchemas": true, "ignoreObsoleteProperties": false, "allowReferencesWithProperties": false, "excludedTypeNames": [], "serviceHost": null, "serviceBasePath": null, "serviceSchemes": [], "infoTitle": "My Title", "infoDescription": null, "infoVersion": "1.0.0", "documentTemplate": null, "documentProcessorTypes": [], "operationProcessorTypes": [], "typeNameGeneratorType": null, "schemaNameGeneratorType": null, "contractResolverType": null, "serializerSettingsType": null, "useDocumentProvider": false, "documentName": "v1", "aspNetCoreEnvironment": null, "createWebHostBuilderMethod": null, "startupType": null, "allowNullableBodyParameters": true, "output": null, "outputType": "OpenApi3", "newLineBehavior": "Auto", "assemblyPaths": [], "assemblyConfig": null, "referencePaths": [], "useNuGetCache": false } }, "codeGenerators": { "openApiToTypeScriptClient": { "className": "{controller}Client", "moduleName": "", "namespace": "", "typeScriptVersion": 3.1, "template": "Angular", "promiseType": "Promise", "httpClass": "HttpClient", "useSingletonProvider": false, "injectionTokenType": "InjectionToken", "rxJsVersion": 6.0, "dateTimeType": "OffsetMomentJS", "nullValue": "Undefined", "generateClientClasses": true, "generateClientInterfaces": true, "generateOptionalParameters": true, "exportTypes": true, "wrapDtoExceptions": false, "exceptionClass": "ApiException", "clientBaseClass": "", "wrapResponses": false, "wrapResponseMethods": [], "generateResponseClasses": true, "responseClass": "ApiResponse", "protectedMethods": [], "configurationClass": null, "useTransformOptionsMethod": false, "useTransformResultMethod": false, "generateDtoTypes": true, "operationGenerationMode": "MultipleClientsFromPathSegments", "markOptionalProperties": false, "generateCloneMethod": false, "typeStyle": "Class", "classTypes": [], "extendedClasses": [], "extensionCode": "", "generateDefaultValues": true, "excludedTypeNames": [], "excludedParameterNames": [], "handleReferences": true, "generateConstructorInterface": true, "convertConstructorInterfaceData": false, "importRequiredTypes": true, "useGetBaseUrlMethod": false, "baseUrlTokenName": "API_BASE_URL", "queryNullValue": "", "inlineNamedDictionaries": false, "inlineNamedAny": false, "templateDirectory": null, "typeNameGeneratorType": null, "propertyNameGeneratorType": null, "enumNameGeneratorType": null, "serviceHost": null, "serviceSchemes": null, "output": "src/api/api.generated.clients.ts" } } }

`

leonandroid commented 3 years ago

I can add that I have the same issue, a few months back my generated code was not the same as today, it seems a new feature prints "return _observableOf(null);" instead of "return _observableOf<MyClassData>(<any>null);"

If you use Angular 9, this is not a problem because Angular9 is not strict, but starting in other versions like 11 or 12, this becomes an issue, and you can confirm it by turning off the "Strict" option from angular, which of course is not a valid solution.

I hope code can be rolled back to the version that was printing: "return _observableOf<MyClassData>(<any>null);"

This version was valid for angular 11.

vaceslav commented 3 years ago

I have the same problem. Looking for a solution.

rhegner commented 3 years ago

Same here. A workaround is to set strictNullChecks to false in tsconfig.json.

RicoSuter commented 3 years ago

I think the only solution is to revert the previous PRs:

3567

3544

Also see original issue: https://github.com/RicoSuter/NSwag/issues/3506

Or can anyone propose a change/PR which works for everyone?

/cc @wratho @dolphinsd

RicoSuter commented 3 years ago

Reverted to previous code. Please overwrite this in a custom template (@wratho @dolphinsd).

Any idea how we can solve this so that it works for everyone?

Thomas-Lederer commented 3 years ago

@RicoSuter Unfortunately we are facing the same issue with rxjs 7 (#3506 ) and would have an appropriate idea to solve the problem for everyone. Based on the pull request of my colleague (#3482 ) one could use the introduced setting for the rxjs version in the config file to decide if the typecast for the "of"-function of rxjs should be used or not. (Similar to the decision for the ResponseTextProperty in the above mentioned PR)

wratho commented 3 years ago

Sorry for delay, i only just noticed my tag in this thread. Are there any updates in the proposal from Thomas? Or when you mention an override in a custom template what exactly do you mean here? I have a feeling that this isn't a specific issue for just the 2 of us? I assumed this was an Angular 12 + 7.X issue no matter what?