Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

typescript-fetch: Fix compile error #6538

Merged
merged 5 commits into from
Jun 29, 2020
Merged

Conversation

ffMathy
Copy link
Contributor

@ffMathy ffMathy commented Jun 4, 2020

Fixes an compile error that happens when a .NET Core 3.1 Swashbuckle generated swagger.json has a Controller with a request class.

Type 'ApproveBrandRequest[]' is not assignable to type 'string | number | boolean | HTTPQuery | (string | number | boolean)[]'.
Type 'ApproveBrandRequest[]' is not assignable to type '(string | number | boolean)[]'.
Type 'ApproveBrandRequest' is not assignable to type 'string | number | boolean'.
Type 'ApproveBrandRequest' is not assignable to type 'true'.

PR checklist

  • Read the contribution guidelines.
  • If contributing template-only or documentation-only changes which will change sample output, build the project before.
  • Run the shell script(s) under ./bin/ (or Windows batch scripts under.\bin\windows) to update Petstore samples related to your fix. This is important, as CI jobs will verify all generator outputs of your HEAD commit, and these must match the expectations made by your contribution. You only need to run ./bin/{LANG}-petstore.sh, ./bin/openapi3/{LANG}-petstore.sh if updating the code or mustache templates for a language ({LANG}) (e.g. php, ruby, python, etc).
  • File the PR against the correct branch: master, 4.3.x, 5.0.x. Default: master.
  • Copy the technical committee to review the pull request if your PR is targeting a particular programming language.

Fixes an annoying compile error that happens when a .NET Core 3.1 Swashbuckle generated `swagger.json` has a Controller with a request class.

> Type 'ApproveBrandRequest[]' is not assignable to type 'string | number | boolean | HTTPQuery | (string | number | boolean)[]'.
  Type 'ApproveBrandRequest[]' is not assignable to type '(string | number | boolean)[]'.
    Type 'ApproveBrandRequest' is not assignable to type 'string | number | boolean'.
      Type 'ApproveBrandRequest' is not assignable to type 'true'.
@ffMathy
Copy link
Contributor Author

ffMathy commented Jun 4, 2020

The build failure seems to be transient from the description, and should be able to be ignored.

@wing328
Copy link
Member

wing328 commented Jun 10, 2020

cc @TiFu (2017/07) @taxpon (2017/07) @sebastianhaas (2017/07) @kenisteward (2017/07) @Vrolijkx (2017/09) @macjohnny (2018/01) @topce (2018/10) @akehir (2019/07) @petejohansonxo (2019/11) @amakhrov (2020/02)

@wing328
Copy link
Member

wing328 commented Jun 10, 2020

@ffMathy please merge the latest master to address some of the CI errors.

@wing328
Copy link
Member

wing328 commented Jun 10, 2020

Please also run ./bin/generate-samples.sh ./bin/configs/typescript-fetch-* to update TS Fetch samples so that the CI can verify the change.

@ffMathy
Copy link
Contributor Author

ffMathy commented Jun 10, 2020

I re-merged master into my patch-2 branch now. However, I can't find the file ./bin/generate-samples.sh - also, I am on Windows.

@wing328
Copy link
Member

wing328 commented Jun 10, 2020

You will need to install Git BASH (https://gitforwindows.org/) in order to run the script on Windows.

@macjohnny
Copy link
Member

the typing should be ok,

export type HTTPQuery = { [key: string]: string | number | null | boolean | Array<string | number | null | boolean> | HTTPQuery };

maybe it is an object that doesn't fit that type that gets assigned?
maybe here?

{{#vendorExtensions.x-codegen-isDeepObject}}
queryParameters['{{baseName}}'] = runtime.querystring(requestParameters.{{paramName}} as unknown as runtime.HTTPQuery, '{{baseName}}');
{{/vendorExtensions.x-codegen-isDeepObject}}
{{^vendorExtensions.x-codegen-isDeepObject}}
queryParameters['{{baseName}}'] = requestParameters.{{paramName}};
{{/vendorExtensions.x-codegen-isDeepObject}}

@ffMathy could you please provide the generated code of the service and an example of the the input parameter?

@ffMathy
Copy link
Contributor Author

ffMathy commented Jun 24, 2020

@macjohnny I have shown the bad code below.

The generated ApproveBrandRequest looks like this:

export interface ApproveBrandRequest {
    /**
     * 
     * @type {string}
     * @memberof ApproveBrandRequest
     */
    brand?: string | null;
    /**
     * 
     * @type {string}
     * @memberof ApproveBrandRequest
     */
    category?: string | null;
    /**
     * 
     * @type {string}
     * @memberof ApproveBrandRequest
     */
    country?: string | null;
}

export interface BrandsApprovePostRequest {
    requests?: Array<ApproveBrandRequest> | null;
}

The C# class looks like this:

    public class ApproveBrandRequest
    {
        public string Brand { get; set; } = null!;
        public string Category { get; set; } = null!;
        public string Country { get; set; } = null!;
    }

The controller method looks like this:

        [Route("brands/approve")]
        [HttpPost]
        public async Task<IActionResult> ApproveBrand(ApproveBrandRequest[] requests)
        {
            //...

            return Ok();
        }

The violating TypeScript code that was generated (and fails compilation) is this:

    async brandsApprovePostRaw(requestParameters: BrandsApprovePostRequest): Promise<runtime.ApiResponse<void>> {
        const queryParameters: runtime.HTTPQuery = {};

        if (requestParameters.requests) {
            queryParameters['requests'] = requestParameters.requests; // <-- this line gives the error.
        }

        const headerParameters: runtime.HTTPHeaders = {};

        const response = await this.request({
            path: `<relative URL removed for obscurity>/brands/approve`,
            method: 'POST',
            headers: headerParameters,
            query: queryParameters,
        });

        return new runtime.VoidApiResponse(response);
    }

@ffMathy
Copy link
Contributor Author

ffMathy commented Jun 24, 2020

@wing328 thanks, but my problem is that the given file is not present. ./bin/generate-samples.sh simply doesn't exist.

@ffMathy
Copy link
Contributor Author

ffMathy commented Jun 24, 2020

But @macjohnny why insist on having typing within a method where that is not used in the first place? The typings inside that file are not necessary 🙂

We're basically adding unnecessary strictness that (at best) can't do anything positive, and (at worst) can only make things worse.

Typings are present to help the developer catching type errors - right? But since we're using Mustache, there's absolutely no reason for it IMO.

I get that the typings are present towards the consumer of the method. But internal variables inside the method should jus the any, because they can't help us either way.

@macjohnny
Copy link
Member

@ffMathy the typings in the .mustache file help to identify problems in the generated code, so they can be considered useful.
But you are right, sometimes it is difficult to determine the correct type for all possible branches, so any can be a solution to this.

please merge the current master into your branch, so you can run bin/generate-samples.sh

@ffMathy
Copy link
Contributor Author

ffMathy commented Jun 24, 2020

@macjohnny at what point do they identify the issues though?

Is it because openapi-generator has a test suite running that generates some TypeScript and then checks if it is valid? Because then it would totally make sense (and then I should also add a test-case for this scenario). If not, then I consider the typings generated as "too late in the process" for the identification of issues 🙂

As you can see in the GitHub history, I already merged master into my branch, and the file is still not there. I'll try doing it again though, and report back.

@ffMathy
Copy link
Contributor Author

ffMathy commented Jun 24, 2020

Alright, that worked - the file is there now. I must have missed something or pulled too early.

Now I can't build the project though. I'm running mvn clean install and get the following error:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:3.0.0-M3:test (default-test) on project openapi-generator: There are test failures.
[ERROR]
[ERROR] Please refer to C:\Users\Reshopper\source\repos\openapi-generator\modules\openapi-generator\target\surefire-reports for the individual test results.
[ERROR] Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
[ERROR] The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was cmd.exe /X /C ""C:\Program Files (x86)\Java\jdk1.8.0_201\jre\bin\java" -javaagent:C:\\Users\\Reshopper\\.m2\\repository\\org\\jacoco\\org.jacoco.agent\\0.8.5\\org.jacoco.agent-0.8.5-runtime.jar=destfile=C:\\Users\\Reshopper\\source\\repos\\openapi-generator\\modules\\openapi-generator\\target\\jacoco.exec,excludes=**/gradle-wrapper.jar -XX:+StartAttachListener org.apache.maven.surefire.booter.ForkedBooter C:\Users\Reshopper\AppData\Local\Temp\surefire789845850923632446 2020-06-24T10-05-25_294-jvmRun1 surefire7020443301389458439tmp surefire_05129994305474195284tmp"
[ERROR] Process Exit Code: 0
[ERROR] Crashed tests:
[ERROR] org.openapitools.codegen.java.JavaModelTest
[ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was cmd.exe /X /C ""C:\Program Files (x86)\Java\jdk1.8.0_201\jre\bin\java" -javaagent:C:\\Users\\Reshopper\\.m2\\repository\\org\\jacoco\\org.jacoco.agent\\0.8.5\\org.jacoco.agent-0.8.5-runtime.jar=destfile=C:\\Users\\Reshopper\\source\\repos\\openapi-generator\\modules\\openapi-generator\\target\\jacoco.exec,excludes=**/gradle-wrapper.jar -XX:+StartAttachListener org.apache.maven.surefire.booter.ForkedBooter C:\Users\Reshopper\AppData\Local\Temp\surefire789845850923632446 2020-06-24T10-05-25_294-jvmRun1 surefire7020443301389458439tmp surefire_05129994305474195284tmp"
[ERROR] Process Exit Code: 0
[ERROR] Crashed tests:
[ERROR] org.openapitools.codegen.java.JavaModelTest
[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:670)
[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:283)
[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:246)
[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1161)
[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1002)
[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:848)
[ERROR]         at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
[ERROR]         at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
[ERROR]         at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
[ERROR]         at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
[ERROR]         at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
[ERROR]         at org.apache.maven.cli.MavenCli.execute(MavenCli.java:957)
[ERROR]         at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:289)
[ERROR]         at org.apache.maven.cli.MavenCli.main(MavenCli.java:193)
[ERROR]         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR]         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ERROR]         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR]         at java.lang.reflect.Method.invoke(Method.java:498)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)

@macjohnny
Copy link
Member

try running mvn clean package -DskipTests=true

@ffMathy
Copy link
Contributor Author

ffMathy commented Jun 24, 2020

Thank you so much. That helped. It has been updated now! 🙂

@ffMathy ffMathy changed the title Fix annoying compile error Fix compile error Jun 24, 2020
@macjohnny macjohnny added this to the 5.0.0 milestone Jun 24, 2020
docs\AdditionalPropertiesBoolean.md
docs\AdditionalPropertiesClass.md
docs\AdditionalPropertiesInteger.md
docs\AdditionalPropertiesNumber.md
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the file path separator seems to differ between windows and linux, please revert this
cc @wing328

Copy link
Contributor Author

@ffMathy ffMathy Jun 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I'm gonna make a whole different PR to fix this because it has left such a big mess 🙁

Some hard honest feedback: I must say, the experience of contributing to this PR has been a nightmare so far. I think more people would contribute if it was easier. This bug has existed for 5+ months, and I am sure many people have it - yet no one has contributed a fix yet. I suspect that's because it's very difficult.

The project is great though! 🙂

But which parts do I remove, and which parts do I keep? I have no idea.

Copy link
Member

@wing328 wing328 Jun 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ffMathy sorry for hear that. We're in transition to a new process to update the samples.

Please PM me via https://join.slack.com/t/openapi-generator/shared_invite/enQtNzAyNDMyOTU0OTE1LTY5ZDBiNDI5NzI5ZjQ1Y2E5OWVjMjZkYzY1ZGM2MWQ4YWFjMzcyNDY5MGI4NjQxNDBiMTlmZTc5NjY2ZTQ5MGM tomorrow (Thur) when you've time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ffMathy I agree it is not straightforward to implement changes in this project. re-generating the samples was re-factored recently, so apparently there are still some issues with windows support.

please list the issues you have faced when contributing, possibly with a suggestion how to improve them

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I can't contribute much to anything else than solving this issue, since I am a consultant and I am being paid to work for a company. They allowed me to fix the bug that causes them to be stuck, but not more than that.

I hope you understand. Can you let me know when the Windows build script has been fixed, so I can regenerate using that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just updated the samples via 5a754e3. Let's see how it goes.

@macjohnny
Copy link
Member

@ffMathy I just noticed that this should fix your issue:

change

export type HTTPQuery = { [key: string]: string | number | null | boolean | Array<string | number | null | boolean> | HTTPQuery };

to

export type HTTPQuery = { [key: string]: string | number | null | boolean | Array<string | number | null | boolean | HTTPQuery> | HTTPQuery }; 

could you please test that and change your PR accordingly?

@akehir
Copy link
Contributor

akehir commented Jun 24, 2020

@ffMathy I just noticed that this should fix your issue:

change

export type HTTPQuery = { [key: string]: string | number | null | boolean | Array<string | number | null | boolean> | HTTPQuery };

to

export type HTTPQuery = { [key: string]: string | number | null | boolean | Array<string | number | null | boolean | HTTPQuery> | HTTPQuery }; 

could you please test that and change your PR accordingly?

I think it might need a generic type, something along the lines of:

// runtime.mustache#L187
export type HTTPQuery<T = void> = { [key: string]: string | number | null | boolean | T | Array<string | number | null | boolean | T> | HTTPQuery}; 
 
// apis.mustache#L101
const queryParameters: HTTPQuery<typeof requestParameters.['{{paramName}}']> = {};

That should hopefully result in the following ts code:

export type HTTPQuery<T = void> = { [key: string]: string | number | null | boolean | T | Array<string | number | null | boolean | T> | HTTPQuery}; 


export interface ApproveBrandRequest {
    /**
     * 
     * @type {string}
     * @memberof ApproveBrandRequest
     */
    brand?: string | null;
    /**
     * 
     * @type {string}
     * @memberof ApproveBrandRequest
     */
    category?: string | null;
    /**
     * 
     * @type {string}
     * @memberof ApproveBrandRequest
     */
    country?: string | null;
}

export interface BrandsApprovePostRequest {
    requests?: Array<ApproveBrandRequest> | null;
}


export class ApproveBrandRequest {
  async brandsApprovePostRaw(requestParameters: BrandsApprovePostRequest): Promise<void> {
      const queryParameters: HTTPQuery<typeof requestParameters['requests']> = {};

        if (requestParameters.requests) {
            queryParameters['requests'] = requestParameters.requests; // <-- this line gives the error.
        }
    }

}

@ffMathy
Copy link
Contributor Author

ffMathy commented Jun 24, 2020

@macjohnny I left a comment to your review question.

@macjohnny macjohnny merged commit d9a6f4d into OpenAPITools:master Jun 29, 2020
@macjohnny
Copy link
Member

macjohnny commented Jun 29, 2020

I merge this now to have a working fix for the issue, but the typing should be fixed properly in a separate PR. The solution proposed by @akehir sounds good.

@macjohnny macjohnny changed the title Fix compile error typescript-fetch: Fix compile error Jun 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants